summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c37
-rw-r--r--demux/demux.h1
-rw-r--r--demux/video.c1
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;