summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-11 19:23:56 +0200
committerwm4 <wm4@nowhere>2013-07-11 19:23:56 +0200
commit4cda1d113e0d9d34d7c39cf3d8861c7079f965d8 (patch)
treeea99adb009514eb5518caf81d0c611089050adfe /demux
parent86cc3bd9be80c433cbf4c65aebc52ca69628cc8a (diff)
downloadmpv-4cda1d113e0d9d34d7c39cf3d8861c7079f965d8.tar.bz2
mpv-4cda1d113e0d9d34d7c39cf3d8861c7079f965d8.tar.xz
core: completely change handling of attached picture pseudo video
Before this commit, we tried to play along with libavformat and tried to pretend that attached pictures are video streams with a single frame, and that the frame magically appeared at the seek position when seeking. The playback core would then switch to a mode where the video has ended, and the "remaining" audio is played. This didn't work very well: - we needed a hack in demux.c, because we tried to read more packets in order to find the "next" video frame (libavformat doesn't tell us if a stream has ended) - switching the video stream didn't work, because we can't tell libavformat to send the packet again - seeking and resuming after was hacky (for some reason libavformat sets the returned packet's PTS to that of the previously returned audio packet in generic code not related to attached pictures, and this happened to work) - if the user did something stupid and e.g. inserted a deinterlacer by default, a picture was never displayed, only an inactive VO window) - same when using a command that reconfigured the VO (like switching aspect or video filters) - hr-seek didn't work For this reason, handle attached pictures as separate case with a separate video decoding function, which doesn't read packets. Also, do not synchronize audio to video start in this case.
Diffstat (limited to 'demux')
-rw-r--r--demux/demux.c28
-rw-r--r--demux/demux_lavf.c13
-rw-r--r--demux/stheader.h4
3 files changed, 11 insertions, 34 deletions
diff --git a/demux/demux.c b/demux/demux.c
index f0652fba4d..1ae4137e62 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -92,7 +92,6 @@ const demuxer_desc_t *const demuxer_list[] = {
struct demux_stream {
int selected; // user wants packets from this stream
int eof; // end of demuxed stream? (true if all buffer empty)
- 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
struct demux_packet *head;
@@ -441,16 +440,6 @@ overflow:
return true;
}
-static bool need_coverart_hack(struct demuxer *demux)
-{
- for (int n = 0; n < demux->num_streams; n++) {
- struct sh_stream *sh = demux->streams[n];
- if (sh->attached_picture && sh->ds->selected)
- return true;
- }
- return false;
-}
-
// return value:
// 0 = EOF or no stream found or invalid type
// 1 = successfully read a packet
@@ -476,31 +465,14 @@ static void ds_get_packets(struct sh_stream *sh)
* despite the eof flag then it's better to clear it to avoid
* weird behavior. */
ds->eof = 0;
- ds->fill_count = 0;
return;
}
- // 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;
if (demux_check_queue_full(demux))
break;
- int apacks = count_packs(demux, STREAM_AUDIO);
- int vpacks = count_packs(demux, STREAM_VIDEO);
-
if (!demux_fill_buffer(demux))
break; // EOF
-
- if (need_coverart_hack(demux)) {
- ds->fill_count += count_packs(demux, STREAM_AUDIO) - apacks;
- ds->fill_count += count_packs(demux, STREAM_VIDEO) - vpacks;
- }
}
mp_msg(MSGT_DEMUXER, MSGL_V, "ds_get_packets: EOF reached (stream: %s)\n",
stream_type_name(sh->type));
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 385cd23006..3f330332e3 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -351,7 +351,8 @@ static void select_tracks(struct demuxer *demuxer, int start)
for (int n = start; n < priv->num_streams; n++) {
struct sh_stream *stream = priv->streams[n];
AVStream *st = priv->avfc->streams[n];
- bool selected = stream && demuxer_stream_is_selected(demuxer, stream);
+ bool selected = stream && demuxer_stream_is_selected(demuxer, stream) &&
+ !stream->attached_picture;
st->discard = selected ? AVDISCARD_DEFAULT : AVDISCARD_ALL;
}
}
@@ -388,8 +389,12 @@ static void handle_stream(demuxer_t *demuxer, int i)
break;
sh_video_t *sh_video = sh->video;
- if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
- sh_video->gsh->attached_picture = true;
+ if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
+ sh->attached_picture = new_demux_packet_from(st->attached_pic.data,
+ st->attached_pic.size);
+ sh->attached_picture->pts = 0;
+ talloc_steal(sh, sh->attached_picture);
+ }
sh_video->format = codec->codec_tag;
sh_video->disp_w = codec->width;
@@ -679,8 +684,6 @@ static int demux_lavf_fill_buffer(demuxer_t *demux)
dp->avpacket = pkt;
int64_t ts = priv->use_dts ? pkt->dts : pkt->pts;
- if (ts == AV_NOPTS_VALUE && (st->disposition & AV_DISPOSITION_ATTACHED_PIC))
- ts = 0;
if (ts != AV_NOPTS_VALUE) {
dp->pts = ts * av_q2d(st->time_base);
priv->last_pts = dp->pts * AV_TIME_BASE;
diff --git a/demux/stheader.h b/demux/stheader.h
index 0d94607fa2..2ca4bd0bae 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -61,7 +61,9 @@ struct sh_stream {
char *title;
char *lang; // language code
bool default_track; // container default track flag
- bool attached_picture; // stream is a picture (such as album art)
+
+ // stream is a picture (such as album art)
+ struct demux_packet *attached_picture;
// Human readable description of the running decoder, or NULL
char *decoder_desc;