@@ -168,7 +168,7 @@ void MediaEngine::closeMedia() {
168
168
}
169
169
170
170
void MediaEngine::DoState (PointerWrap &p) {
171
- auto s = p.Section (" MediaEngine" , 1 , 4 );
171
+ auto s = p.Section (" MediaEngine" , 1 , 5 );
172
172
if (!s)
173
173
return ;
174
174
@@ -181,6 +181,11 @@ void MediaEngine::DoState(PointerWrap &p) {
181
181
} else {
182
182
m_mpegheaderSize = sizeof (m_mpegheader);
183
183
}
184
+ if (s >= 5 ) {
185
+ p.Do (m_mpegheaderReadPos);
186
+ } else {
187
+ m_mpegheaderReadPos = m_mpegheaderSize;
188
+ }
184
189
185
190
p.Do (m_ringbuffersize);
186
191
@@ -194,8 +199,6 @@ void MediaEngine::DoState(PointerWrap &p) {
194
199
u32 hasopencontext = false ;
195
200
#endif
196
201
p.Do (hasopencontext);
197
- if (hasopencontext && p.mode == p.MODE_READ )
198
- openContext ();
199
202
if (m_pdata)
200
203
m_pdata->DoState (p);
201
204
if (m_demux)
@@ -209,6 +212,10 @@ void MediaEngine::DoState(PointerWrap &p) {
209
212
p.Do (m_lastTimeStamp);
210
213
}
211
214
215
+ if (hasopencontext && p.mode == p.MODE_READ ) {
216
+ openContext (true );
217
+ }
218
+
212
219
p.Do (m_isVideoEnd);
213
220
bool noAudioDataRemoved;
214
221
p.Do (noAudioDataRemoved);
@@ -219,17 +226,14 @@ void MediaEngine::DoState(PointerWrap &p) {
219
226
}
220
227
}
221
228
222
- int _MpegReadbuffer (void *opaque, uint8_t *buf, int buf_size)
223
- {
229
+ static int MpegReadbuffer (void *opaque, uint8_t *buf, int buf_size) {
224
230
MediaEngine *mpeg = (MediaEngine *)opaque;
225
231
226
232
int size = buf_size;
227
233
if (mpeg->m_mpegheaderReadPos < mpeg->m_mpegheaderSize ) {
228
234
size = std::min (buf_size, mpeg->m_mpegheaderSize - mpeg->m_mpegheaderReadPos );
229
235
memcpy (buf, mpeg->m_mpegheader + mpeg->m_mpegheaderReadPos , size);
230
236
mpeg->m_mpegheaderReadPos += size;
231
- } else if (mpeg->m_mpegheaderReadPos == mpeg->m_mpegheaderSize ) {
232
- return 0 ;
233
237
} else {
234
238
size = mpeg->m_pdata ->pop_front (buf, buf_size);
235
239
if (size > 0 )
@@ -238,33 +242,73 @@ int _MpegReadbuffer(void *opaque, uint8_t *buf, int buf_size)
238
242
return size;
239
243
}
240
244
241
- bool MediaEngine::openContext () {
245
+ bool MediaEngine::SetupStreams () {
246
+ #ifdef USE_FFMPEG
247
+ const u32 magic = *(u32_le *)&m_mpegheader[0 ];
248
+ if (magic != PSMF_MAGIC) {
249
+ WARN_LOG_REPORT (ME, " Could not setup streams, bad magic: %08x" , magic);
250
+ return false ;
251
+ }
252
+ int numStreams = *(u16_be *)&m_mpegheader[0x80 ];
253
+ if (numStreams <= 0 || numStreams > 8 ) {
254
+ // Looks crazy. Let's bail out and let FFmpeg handle it.
255
+ WARN_LOG_REPORT (ME, " Could not setup streams, unexpected stream count: %d" , numStreams);
256
+ return false ;
257
+ }
258
+
259
+ // Looking good. Let's add those streams.
260
+ const AVCodec *h264_codec = avcodec_find_decoder (AV_CODEC_ID_H264);
261
+ for (int i = 0 ; i < numStreams; i++) {
262
+ const u8 *const currentStreamAddr = m_mpegheader + 0x82 + i * 16 ;
263
+ int streamId = currentStreamAddr[0 ];
264
+
265
+ // We only set video streams. We demux the audio stream separately.
266
+ if ((streamId & PSMF_VIDEO_STREAM_ID) == PSMF_VIDEO_STREAM_ID) {
267
+ AVStream *stream = avformat_new_stream (m_pFormatCtx, h264_codec);
268
+ stream->id = 0x00000100 | streamId;
269
+ stream->request_probe = 0 ;
270
+ stream->need_parsing = AVSTREAM_PARSE_FULL;
271
+ // We could set the width here, but we don't need to.
272
+ }
273
+ }
274
+
275
+ #endif
276
+ return true ;
277
+ }
278
+
279
+ bool MediaEngine::openContext (bool keepReadPos) {
242
280
#ifdef USE_FFMPEG
243
281
InitFFmpeg ();
244
282
245
283
if (m_pFormatCtx || !m_pdata)
246
284
return false ;
247
- m_mpegheaderReadPos = 0 ;
285
+ if (!keepReadPos) {
286
+ m_mpegheaderReadPos = 0 ;
287
+ }
248
288
m_decodingsize = 0 ;
249
289
250
- u8* tempbuf = (u8*)av_malloc (m_bufSize);
290
+ m_bufSize = std::max (m_bufSize, m_mpegheaderSize);
291
+ u8 *tempbuf = (u8*)av_malloc (m_bufSize);
251
292
252
293
m_pFormatCtx = avformat_alloc_context ();
253
- m_pIOContext = avio_alloc_context (tempbuf, m_bufSize, 0 , (void *)this , _MpegReadbuffer, NULL , 0 );
294
+ m_pIOContext = avio_alloc_context (tempbuf, m_bufSize, 0 , (void *)this , &MpegReadbuffer, nullptr , nullptr );
254
295
m_pFormatCtx->pb = m_pIOContext;
255
296
256
297
// Open video file
257
298
AVDictionary *open_opt = nullptr ;
258
299
av_dict_set_int (&open_opt, " probesize" , m_mpegheaderSize, 0 );
259
- if (avformat_open_input ((AVFormatContext**)&m_pFormatCtx, NULL , NULL , &open_opt) != 0 ) {
300
+ if (avformat_open_input ((AVFormatContext**)&m_pFormatCtx, nullptr , nullptr , &open_opt) != 0 ) {
260
301
av_dict_free (&open_opt);
261
302
return false ;
262
303
}
263
304
av_dict_free (&open_opt);
264
305
265
- if (avformat_find_stream_info (m_pFormatCtx, NULL ) < 0 ) {
266
- closeContext ();
267
- return false ;
306
+ if (!SetupStreams ()) {
307
+ // Fallback to old behavior.
308
+ if (avformat_find_stream_info (m_pFormatCtx, NULL ) < 0 ) {
309
+ closeContext ();
310
+ return false ;
311
+ }
268
312
}
269
313
270
314
if (m_videoStream >= (int )m_pFormatCtx->nb_streams ) {
@@ -290,8 +334,6 @@ bool MediaEngine::openContext() {
290
334
setVideoDim ();
291
335
m_audioContext = new SimpleAudio (m_audioType, 44100 , 2 );
292
336
m_isVideoEnd = false ;
293
- m_mpegheaderReadPos++;
294
- av_seek_frame (m_pFormatCtx, m_videoStream, 0 , 0 );
295
337
#endif // USE_FFMPEG
296
338
return true ;
297
339
}
@@ -354,8 +396,7 @@ int MediaEngine::addStreamData(const u8 *buffer, int addSize) {
354
396
#ifdef USE_FFMPEG
355
397
if (!m_pFormatCtx && m_pdata->getQueueSize () >= 2048 ) {
356
398
m_mpegheaderSize = m_pdata->get_front (m_mpegheader, sizeof (m_mpegheader));
357
- int mpegoffset = (int )(*(s32_be*)(m_mpegheader + 8 ));
358
- m_pdata->pop_front (0 , mpegoffset);
399
+ m_pdata->pop_front (0 , m_mpegheaderSize);
359
400
openContext ();
360
401
}
361
402
#endif // USE_FFMPEG
@@ -418,8 +459,7 @@ bool MediaEngine::setVideoStream(int streamNum, bool force) {
418
459
}
419
460
420
461
// Open codec
421
- AVDictionary *optionsDict = 0 ;
422
- if (avcodec_open2 (m_pCodecCtx, pCodec, &optionsDict) < 0 ) {
462
+ if (avcodec_open2 (m_pCodecCtx, pCodec, nullptr ) < 0 ) {
423
463
return false ; // Could not open codec
424
464
}
425
465
m_pCodecCtxs[streamNum] = m_pCodecCtx;
@@ -451,11 +491,19 @@ bool MediaEngine::setVideoDim(int width, int height)
451
491
}
452
492
453
493
// Allocate video frame
454
- m_pFrame = av_frame_alloc ();
494
+ if (!m_pFrame) {
495
+ m_pFrame = av_frame_alloc ();
496
+ }
455
497
456
498
sws_freeContext (m_sws_ctx);
457
499
m_sws_ctx = NULL ;
458
500
m_sws_fmt = -1 ;
501
+
502
+ if (m_desWidth == 0 || m_desHeight == 0 ) {
503
+ // Can't setup SWS yet, so stop for now.
504
+ return false ;
505
+ }
506
+
459
507
updateSwsFormat (GE_CMODE_32BIT_ABGR8888);
460
508
461
509
// Allocate video frame for RGB24
@@ -523,14 +571,9 @@ bool MediaEngine::stepVideo(int videoPixelMode, bool skipFrame) {
523
571
return false ;
524
572
if (!m_pCodecCtx)
525
573
return false ;
526
- if (( !m_pFrame)||(!m_pFrameRGB) )
574
+ if (!m_pFrame)
527
575
return false ;
528
576
529
- updateSwsFormat (videoPixelMode);
530
- // TODO: Technically we could set this to frameWidth instead of m_desWidth for better perf.
531
- // Update the linesize for the new format too. We started with the largest size, so it should fit.
532
- m_pFrameRGB->linesize [0 ] = getPixelFormatBytes (videoPixelMode) * m_desWidth;
533
-
534
577
AVPacket packet;
535
578
av_init_packet (&packet);
536
579
int frameFinished;
@@ -551,7 +594,15 @@ bool MediaEngine::stepVideo(int videoPixelMode, bool skipFrame) {
551
594
552
595
int result = avcodec_decode_video2 (m_pCodecCtx, m_pFrame, &frameFinished, &packet);
553
596
if (frameFinished) {
554
- if (!skipFrame) {
597
+ if (!m_pFrameRGB) {
598
+ setVideoDim ();
599
+ }
600
+ if (m_pFrameRGB && !skipFrame) {
601
+ updateSwsFormat (videoPixelMode);
602
+ // TODO: Technically we could set this to frameWidth instead of m_desWidth for better perf.
603
+ // Update the linesize for the new format too. We started with the largest size, so it should fit.
604
+ m_pFrameRGB->linesize [0 ] = getPixelFormatBytes (videoPixelMode) * m_desWidth;
605
+
555
606
sws_scale (m_sws_ctx, m_pFrame->data , m_pFrame->linesize , 0 ,
556
607
m_pCodecCtx->height , m_pFrameRGB->data , m_pFrameRGB->linesize );
557
608
}
0 commit comments