diff options
-rw-r--r-- | demux/demux.c | 37 | ||||
-rw-r--r-- | demux/demux.h | 1 | ||||
-rw-r--r-- | demux/video.c | 1 |
3 files changed, 33 insertions, 6 deletions
diff --git a/demux/demux.c b/demux/demux.c index 23b01b22f4..af710131b9 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -623,8 +623,15 @@ int ds_fill_buffer(demux_stream_t *ds) ds == demux->audio ? "d_audio" : ds == demux->video ? "d_video" : ds == demux->sub ? "d_sub" : "unknown"); while (1) { + int apacks = demux->audio ? demux->audio->packs : 0; + int abytes = demux->audio ? demux->audio->bytes : 0; + int vpacks = demux->video ? demux->video->packs : 0; + int vbytes = demux->video ? demux->video->bytes : 0; if (ds->packs) { demux_packet_t *p = ds->first; + // obviously not yet EOF after all + ds->eof = 0; + ds->fill_count = 0; // copy useful data: ds->buffer = p->buffer; ds->buffer_pos = 0; @@ -657,21 +664,30 @@ int ds_fill_buffer(demux_stream_t *ds) ds->eof = 0; return 1; } + // avoid buffering too far ahead in e.g. badly interleaved files + // or when one stream is shorter, without breaking large audio + // delay with well interleaved files. + // This needs to be enough for at least 1 second of packets + // since libavformat mov demuxer does not try to interleave + // with more than 1s precision. + if (ds->fill_count > 80) + break; + // avoid printing the "too many ..." message over and over + if (ds->eof) + break; #define MaybeNI _("Maybe you are playing a non-interleaved stream/file or the codec failed?\n" \ "For AVI files, try to force non-interleaved mode with the --demuxer=avi --avi-ni options.\n") - if (demux->audio->packs >= MAX_PACKS - || demux->audio->bytes >= MAX_PACK_BYTES) { + if (apacks >= MAX_PACKS || abytes >= MAX_PACK_BYTES) { mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many audio packets in the buffer: (%d in %d bytes).\n", - demux->audio->packs, demux->audio->bytes); + apacks, abytes); mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI); break; } - if (demux->video->packs >= MAX_PACKS - || demux->video->bytes >= MAX_PACK_BYTES) { + if (vpacks >= MAX_PACKS || vbytes >= MAX_PACK_BYTES) { mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many video packets in the buffer: (%d in %d bytes).\n", - demux->video->packs, demux->video->bytes); + vpacks, vbytes); mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI); break; } @@ -680,6 +696,15 @@ int ds_fill_buffer(demux_stream_t *ds) "ds_fill_buffer()->demux_fill_buffer() failed\n"); break; // EOF } + if (demux->audio) + ds->fill_count += demux->audio->packs - apacks; + if (demux->video && demux->video->packs > vpacks && + // Empty packets or "skip" packets in e.g. AVI can cause issues. + demux->video->bytes > vbytes + 100 && + // when video needs parsing we will have lots of video packets + // in-between audio packets, so ignore them in that case. + demux->video->sh && !((sh_video_t *)demux->video->sh)->needs_parsing) + ds->fill_count++; } ds->buffer_pos = ds->buffer_size = 0; ds->buffer = NULL; diff --git a/demux/demux.h b/demux/demux.h index c2b8ce69c1..13500c0372 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -120,6 +120,7 @@ typedef struct demux_stream { int pack_no; // serial number of packet bool keyframe; // keyframe flag of current packet //--------------- + int fill_count; // number of unsuccessful tries to get a packet int packs; // number of packets in buffer int bytes; // total bytes of packets in buffer demux_packet_t *first; // read to current buffer from here diff --git a/demux/video.c b/demux/video.c index 6a9b6b370b..02ecf9d4a7 100644 --- a/demux/video.c +++ b/demux/video.c @@ -422,6 +422,7 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char** int picture_coding_type=0; int in_size=0; video_codec_t video_codec = find_video_codec(sh_video); + sh_video->needs_parsing = video_codec != VIDEO_OTHER; *start=NULL; |