summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-11 19:10:33 +0200
committerwm4 <wm4@nowhere>2013-07-11 19:10:33 +0200
commita5224836293ac02bd13f688cfc848aae6818e963 (patch)
treec67c9a61505583a0614ccc2c7cdbdb4e1deffda2
parent07c5327fa0c3411bcb8caad17d70b014d6b022dd (diff)
downloadmpv-a5224836293ac02bd13f688cfc848aae6818e963.tar.bz2
mpv-a5224836293ac02bd13f688cfc848aae6818e963.tar.xz
demux: remove facility for partial packet reads
Partial packet reads were needed because the video/audio parsers were working on top of them. So it could happen that a parser read a part of a packet, and returned that to the decoder. With libavformat/libavcodec, packets are already parsed, and everything is much simpler. Most of the simplifications in ad_spdif could have been done earlier. Remove some other stuff as well, like the questionable slave mode start time reporting (could be replaced by proper code, but we don't bother). Remove the unused skip_audio_frame() functionality as well (it was used by old demuxers). Some functions become private to demux.c, like demux_fill_buffer(). Introduce new packet read functions, which have simpler semantics. Packets returned from them are owned by the caller, and all packets in the demux.c packet queue are considered unread. Remove special code that dropped subtitle packets with size 0. This used to be needed because it caused special cases in the old code.
-rw-r--r--audio/decode/ad.h3
-rw-r--r--audio/decode/ad_lavc.c7
-rw-r--r--audio/decode/ad_mpg123.c16
-rw-r--r--audio/decode/ad_spdif.c59
-rw-r--r--audio/decode/dec_audio.c11
-rw-r--r--core/mplayer.c86
-rw-r--r--demux/demux.c178
-rw-r--r--demux/demux.h28
-rw-r--r--demux/demux_mng.c15
-rw-r--r--demux/demux_rawvideo.c1
-rw-r--r--sub/dec_sub.c5
11 files changed, 126 insertions, 283 deletions
diff --git a/audio/decode/ad.h b/audio/decode/ad.h
index 1f45e88f98..1c8a211f5b 100644
--- a/audio/decode/ad.h
+++ b/audio/decode/ad.h
@@ -44,7 +44,4 @@ extern const ad_functions_t * const mpcodecs_ad_drivers[];
#define ADCTRL_RESYNC_STREAM 1 // resync, called after seeking
-// fallback if ADCTRL_SKIP not implemented: ds_fill_buffer(sh_audio->ds);
-#define ADCTRL_SKIP_FRAME 2 // skip block/frame, called while seeking
-
#endif /* MPLAYER_AD_H */
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index c311bc2cb8..d197bed072 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -372,10 +372,12 @@ static int decode_new_packet(struct sh_audio *sh)
{
struct priv *priv = sh->context;
AVCodecContext *avctx = priv->avctx;
- struct demux_packet *mpkt = ds_get_packet2(sh->ds, false);
+ struct demux_packet *mpkt = demux_read_packet(sh->gsh);
if (!mpkt)
return -1; // error or EOF
+ int in_len = mpkt->len;
+
AVPacket pkt;
mp_set_av_packet(&pkt, mpkt);
@@ -385,6 +387,7 @@ static int decode_new_packet(struct sh_audio *sh)
}
int got_frame = 0;
int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt);
+ talloc_free(mpkt);
// LATM may need many packets to find mux info
if (ret == AVERROR(EAGAIN))
return 0;
@@ -408,7 +411,7 @@ static int decode_new_packet(struct sh_audio *sh)
} else {
priv->output = priv->avframe->data[0];
}
- mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", mpkt->len,
+ mp_dbg(MSGT_DECAUDIO, MSGL_DBG2, "Decoded %d -> %d \n", in_len,
priv->output_left);
return 0;
}
diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c
index 08739b7f4b..8d97468e06 100644
--- a/audio/decode/ad_mpg123.c
+++ b/audio/decode/ad_mpg123.c
@@ -217,27 +217,25 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count)
/* Feed the decoder. This will only fire from the second round on. */
if (ret == MPG123_NEED_MORE) {
- int incount;
- double pts;
- unsigned char *inbuf;
/* Feed more input data. */
- incount = ds_get_packet_pts(sh->ds, &inbuf, &pts);
- if (incount <= 0)
+ struct demux_packet *pkt = demux_read_packet(sh->gsh);
+ if (!pkt)
break; /* Apparently that's it. EOF. */
/* Next bytes from that presentation time. */
- if (pts != MP_NOPTS_VALUE) {
- sh->pts = pts;
+ if (pkt->pts != MP_NOPTS_VALUE) {
+ sh->pts = pkt->pts;
sh->pts_bytes = 0;
}
#ifdef AD_MPG123_FRAMEWISE
/* Have to use mpg123_feed() to avoid decoding here. */
- ret = mpg123_feed(con->handle, inbuf, incount);
+ ret = mpg123_feed(con->handle, pkt->buffer, pkt->len);
#else
/* Do not use mpg123_feed(), added in later libmpg123 versions. */
- ret = mpg123_decode(con->handle, inbuf, incount, NULL, 0, NULL);
+ ret = mpg123_decode(con->handle, pkt->buffer, pkt->len, NULL, 0, NULL);
#endif
+ talloc_free(pkt);
if (ret == MPG123_ERR)
break;
}
diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
index 49b7d9a0d8..f4fc430208 100644
--- a/audio/decode/ad_spdif.c
+++ b/audio/decode/ad_spdif.c
@@ -84,9 +84,7 @@ static int codecs[] = {
static int init(sh_audio_t *sh, const char *decoder)
{
- int x, in_size, srate, bps, *dtshd_rate;
- unsigned char *start;
- double pts;
+ int srate, bps, *dtshd_rate;
AVFormatContext *lavf_ctx = NULL;
AVStream *stream = NULL;
const AVOption *opt = NULL;
@@ -125,16 +123,8 @@ static int init(sh_audio_t *sh, const char *decoder)
goto fail;
}
- // get sample_rate & bitrate from parser
- x = ds_get_packet_pts(sh->ds, &start, &pts);
- in_size = x;
- if (x <= 0) {
- pts = MP_NOPTS_VALUE;
- x = 0;
- }
srate = 48000; //fake value
bps = 768000/8; //fake value
- sh->ds->buffer_pos -= in_size;
int num_channels = 0;
switch (lavf_ctx->streams[0]->codec->codec_id) {
@@ -214,42 +204,24 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf,
struct spdifContext *spdif_ctx = sh->context;
AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx;
AVPacket pkt;
- double pts;
- int ret, in_size, consumed, x;
- unsigned char *start = NULL;
- consumed = spdif_ctx->out_buffer_len = 0;
+ spdif_ctx->out_buffer_len = 0;
spdif_ctx->out_buffer_size = maxlen;
spdif_ctx->out_buffer = buf;
while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen
&& spdif_ctx->out_buffer_len < minlen) {
- if (sh->ds->eof)
+ struct demux_packet *mpkt = demux_read_packet(sh->gsh);
+ if (!mpkt)
break;
- x = ds_get_packet_pts(sh->ds, &start, &pts);
- if (x <= 0) {
- continue; // END_NOT_FOUND
- } else {
- in_size = x;
- consumed = x;
- if (x == 0) {
- mp_msg(MSGT_DECAUDIO,MSGL_V,
- "start[%p] in_size[%d] consumed[%d] x[%d].\n",
- start, in_size, consumed, x);
- continue; // END_NOT_FOUND
- }
- sh->ds->buffer_pos -= in_size - consumed;
- }
- av_init_packet(&pkt);
- pkt.data = start;
- pkt.size = x;
- mp_msg(MSGT_DECAUDIO,MSGL_V,
- "start[%p] pkt.size[%d] in_size[%d] consumed[%d] x[%d].\n",
- start, pkt.size, in_size, consumed, x);
- if (pts != MP_NOPTS_VALUE) {
- sh->pts = pts;
+ mp_set_av_packet(&pkt, mpkt);
+ mp_msg(MSGT_DECAUDIO,MSGL_V, "pkt.data[%p] pkt.size[%d]\n",
+ pkt.data, pkt.size);
+ if (mpkt->pts != MP_NOPTS_VALUE) {
+ sh->pts = mpkt->pts;
sh->pts_bytes = 0;
}
- ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt);
+ int ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt);
+ talloc_free(mpkt);
if (ret < 0)
break;
}
@@ -259,15 +231,6 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf,
static int control(sh_audio_t *sh, int cmd, void *arg)
{
- unsigned char *start;
- double pts;
-
- switch (cmd) {
- case ADCTRL_RESYNC_STREAM:
- case ADCTRL_SKIP_FRAME:
- ds_get_packet_pts(sh->ds, &start, &pts);
- return CONTROL_TRUE;
- }
return CONTROL_UNKNOWN;
}
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c
index 1bf217de80..8c80a0b119 100644
--- a/audio/decode/dec_audio.c
+++ b/audio/decode/dec_audio.c
@@ -365,14 +365,3 @@ void resync_audio_stream(sh_audio_t *sh_audio)
return;
sh_audio->ad_driver->control(sh_audio, ADCTRL_RESYNC_STREAM, NULL);
}
-
-void skip_audio_frame(sh_audio_t *sh_audio)
-{
- if (!sh_audio->initialized)
- return;
- if (sh_audio->ad_driver->control(sh_audio, ADCTRL_SKIP_FRAME, NULL)
- == CONTROL_TRUE)
- return;
- // default skip code:
- ds_fill_buffer(sh_audio->ds); // skip block
-}
diff --git a/core/mplayer.c b/core/mplayer.c
index 217e99ed5c..0d07b518d8 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -288,8 +288,6 @@ static void print_stream(struct MPContext *mpctx, struct track *t)
static void print_file_properties(struct MPContext *mpctx, const char *filename)
{
- double start_pts = MP_NOPTS_VALUE;
- double video_start_pts = MP_NOPTS_VALUE;
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILENAME=%s\n",
filename);
if (mpctx->sh_video) {
@@ -310,7 +308,6 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename)
"ID_VIDEO_FPS=%5.3f\n", mpctx->sh_video->fps);
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
"ID_VIDEO_ASPECT=%1.4f\n", mpctx->sh_video->aspect);
- video_start_pts = ds_get_next_pts(mpctx->sh_video->ds);
}
if (mpctx->sh_audio) {
/* Assume FOURCC if all bytes >= 0x20 (' ') */
@@ -326,17 +323,7 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename)
"ID_AUDIO_RATE=%d\n", mpctx->sh_audio->samplerate);
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
"ID_AUDIO_NCH=%d\n", mpctx->sh_audio->channels.num);
- start_pts = ds_get_next_pts(mpctx->sh_audio->ds);
}
- if (video_start_pts != MP_NOPTS_VALUE) {
- if (start_pts == MP_NOPTS_VALUE || !mpctx->sh_audio ||
- (mpctx->sh_video && video_start_pts < start_pts))
- start_pts = video_start_pts;
- }
- if (start_pts != MP_NOPTS_VALUE)
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=%.2f\n", start_pts);
- else
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=unknown\n");
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
"ID_LENGTH=%.2f\n", get_time_length(mpctx));
int chapter_count = get_chapter_count(mpctx);
@@ -375,11 +362,8 @@ static double get_main_demux_pts(struct MPContext *mpctx)
if (mpctx->demuxer) {
for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
struct demux_stream *ds = mpctx->demuxer->ds[type];
- if (ds->gsh && main_new_pos == MP_NOPTS_VALUE) {
- demux_fill_buffer(mpctx->demuxer, ds);
- if (ds->first)
- main_new_pos = ds->first->pts;
- }
+ if (ds->gsh && main_new_pos == MP_NOPTS_VALUE)
+ main_new_pos = demux_get_next_pts(ds->gsh);
}
}
return main_new_pos;
@@ -1703,14 +1687,14 @@ static double written_audio_pts(struct MPContext *mpctx)
// ratio is not constant for every audio packet or if it is constant
// but not accurately known in sh_audio->i_bps.
- a_pts = d_audio->pts;
+ a_pts = d_audio->last_pts;
if (a_pts == MP_NOPTS_VALUE)
return a_pts;
// ds_tell_pts returns bytes read after last timestamp from
// demuxing layer
if (sh_audio->i_bps)
- a_pts += ds_tell_pts(d_audio) / (double)sh_audio->i_bps;
+ a_pts += d_audio->last_pts_bytes / (double)sh_audio->i_bps;
}
// Now a_pts hopefully holds the pts for end of audio from decoder.
// Substract data in buffers between decoder and audio out.
@@ -1783,15 +1767,14 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
double curpts_s = refpts_s + opts->sub_delay;
if (!track->preloaded) {
- struct demux_stream *d_sub = sh_sub->ds;
bool non_interleaved = is_non_interleaved(mpctx, track);
while (1) {
- if (non_interleaved)
- ds_get_next_pts(d_sub);
- if (!d_sub->first)
+ if (!non_interleaved && !demux_has_packet(sh_sub->gsh))
+ break;
+ double subpts_s = demux_get_next_pts(sh_sub->gsh);
+ if (!demux_has_packet(sh_sub->gsh))
break;
- double subpts_s = ds_get_next_pts(d_sub);
if (subpts_s > curpts_s) {
mp_dbg(MSGT_CPLAYER, MSGL_DBG2,
"Sub early: c_pts=%5.3f s_pts=%5.3f\n",
@@ -1803,11 +1786,12 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
if (non_interleaved && subpts_s > curpts_s + 1)
break;
}
- struct demux_packet *pkt = ds_get_packet_sub(d_sub);
+ struct demux_packet *pkt = demux_read_packet(sh_sub->gsh);
mp_dbg(MSGT_CPLAYER, MSGL_V, "Sub: c_pts=%5.3f s_pts=%5.3f "
"duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration,
pkt->len);
sub_decode(dec_sub, pkt);
+ talloc_free(pkt);
}
}
@@ -2465,28 +2449,24 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame)
}
-static int video_read_frame(sh_video_t *sh_video,
- unsigned char **start, int force_fps)
+static struct demux_packet *video_read_frame(struct MPContext *mpctx)
{
+ sh_video_t *sh_video = mpctx->sh_video;
demux_stream_t *d_video = sh_video->ds;
demuxer_t *demuxer = d_video->demuxer;
- float pts1 = d_video->pts;
- int in_size = 0;
-
- *start = NULL;
+ float pts1 = d_video->last_pts;
- // frame-based file formats: (AVI,ASF,MOV)
- in_size = ds_get_packet(d_video, start);
- if (in_size < 0)
- return -1; // EOF
+ struct demux_packet *pkt = demux_read_packet(sh_video->gsh);
+ if (!pkt)
+ return NULL; // EOF
float frame_time = sh_video->frametime;
// override frame_time for variable/unknown FPS formats:
- if (!force_fps) {
- double next_pts = ds_get_next_pts(d_video);
- double d = next_pts == MP_NOPTS_VALUE ? d_video->pts - pts1
- : next_pts - d_video->pts;
+ if (!mpctx->opts.force_fps) {
+ double next_pts = demux_get_next_pts(sh_video->gsh);
+ double d = next_pts == MP_NOPTS_VALUE ? d_video->last_pts - pts1
+ : next_pts - d_video->last_pts;
if (d >= 0) {
if (demuxer->file_format == DEMUXER_TYPE_TV) {
if (d > 0) {
@@ -2501,10 +2481,10 @@ static int video_read_frame(sh_video_t *sh_video,
}
}
- sh_video->pts = d_video->pts;
+ sh_video->pts = d_video->last_pts;
sh_video->next_frame_time = frame_time;
- return in_size;
+ return pkt;
}
static double update_video_nocorrect_pts(struct MPContext *mpctx)
@@ -2518,15 +2498,11 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
break;
if (filter_output_queued_frame(mpctx))
break;
- unsigned char *packet = NULL;
frame_time = sh_video->next_frame_time;
if (mpctx->restart_playback)
frame_time = 0;
- int in_size = 0;
- while (!in_size)
- in_size = video_read_frame(sh_video,
- &packet, mpctx->opts.force_fps);
- if (in_size < 0)
+ struct demux_packet *pkt = video_read_frame(mpctx);
+ if (!pkt)
return -1;
if (mpctx->sh_audio)
mpctx->delay -= frame_time;
@@ -2534,13 +2510,9 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
update_fps(mpctx);
int framedrop_type = check_framedrop(mpctx, frame_time);
- struct demux_packet pkt = {0};
- if (sh_video->ds->current)
- pkt = *sh_video->ds->current;
- pkt.buffer = packet;
- pkt.len = in_size;
- void *decoded_frame = decode_video(sh_video, &pkt, framedrop_type,
+ void *decoded_frame = decode_video(sh_video, pkt, framedrop_type,
sh_video->pts);
+ talloc_free(pkt);
if (decoded_frame) {
filter_video(mpctx, decoded_frame);
}
@@ -2599,12 +2571,13 @@ static double update_video(struct MPContext *mpctx, double endpts)
pts = MP_NOPTS_VALUE;
struct demux_packet *pkt;
while (1) {
- pkt = ds_get_packet2(mpctx->sh_video->ds, false);
+ pkt = demux_read_packet(mpctx->sh_video->gsh);
if (!pkt || pkt->len)
break;
/* Packets with size 0 are assumed to not correspond to frames,
* but to indicate the absence of a frame in formats like AVI
* that must have packets at fixed timecode intervals. */
+ talloc_free(pkt);
}
if (pkt)
pts = pkt->pts;
@@ -2616,6 +2589,7 @@ static double update_video(struct MPContext *mpctx, double endpts)
1 : check_framedrop(mpctx, sh_video->frametime);
struct mp_image *decoded_frame =
decode_video(sh_video, pkt, framedrop_type, pts);
+ talloc_free(pkt);
if (decoded_frame) {
determine_frame_pts(mpctx);
filter_video(mpctx, decoded_frame);
@@ -2773,7 +2747,7 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac)
// Not all demuxers set d_video->pts during seek, so this value
// (which was used by at least vobsub code below) may be completely
// wrong (probably 0).
- mpctx->sh_video->pts = mpctx->sh_video->ds->pts + mpctx->video_offset;
+ mpctx->sh_video->pts = mpctx->sh_video->ds->last_pts + mpctx->video_offset;
mpctx->video_pts = mpctx->sh_video->pts;
}
diff --git a/demux/demux.c b/demux/demux.c
index f0cb28ab1d..16adfeb795 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -375,26 +375,16 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream,
void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp)
{
- // demux API can't handle 0-sized packets, but at least some vobsubs
- // generate them. Skipping them seems to work fine. Not skipping them will
- // stop demuxing with external vobsubs. See FATE sub/vobsub.{idx,sub} at
- // pts=185.91.
- if (dp->len == 0 && ds->stream_type == STREAM_SUB) {
- mp_dbg(MSGT_DEMUXER, MSGL_INFO, "Discarding empty subtitle packet.\n");
- free_demux_packet(dp);
- return;
- }
-
// append packet to DS stream:
++ds->packs;
ds->bytes += dp->len;
- if (ds->last) {
+ if (ds->tail) {
// next packet in stream
- ds->last->next = dp;
- ds->last = dp;
+ ds->tail->next = dp;
+ ds->tail = dp;
} else {
// first packet in stream
- ds->first = ds->last = dp;
+ ds->head = ds->tail = dp;
}
mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
"DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%u [packs: A=%d V=%d]\n",
@@ -440,38 +430,18 @@ int demux_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
// return value:
// 0 = EOF
// 1 = successful
-int ds_fill_buffer(demux_stream_t *ds)
+static int ds_get_packets(demux_stream_t *ds)
{
+ if (!ds)
+ return 0;
demuxer_t *demux = ds->demuxer;
- if (ds->current)
- free_demux_packet(ds->current);
- ds->current = NULL;
- mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_fill_buffer (%s) called\n",
+ mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_get_packets (%s) called\n",
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 vpacks = demux->video ? demux->video->packs : 0;
if (ds->packs) {
- demux_packet_t *p = ds->first;
- // copy useful data:
- ds->buffer = p->buffer;
- ds->buffer_pos = 0;
- ds->buffer_size = p->len;
- if (p->pts != MP_NOPTS_VALUE) {
- ds->pts = p->pts;
- ds->pts_bytes = 0;
- }
- ds->pts_bytes += p->len; // !!!
- if (p->stream_pts != MP_NOPTS_VALUE)
- demux->stream_pts = p->stream_pts;
- // unlink packet:
- ds->bytes -= p->len;
- ds->current = p;
- ds->first = p->next;
- if (!ds->first)
- ds->last = NULL;
- --ds->packs;
/* The code below can set ds->eof to 1 when another stream runs
* out of buffer space. That makes sense because in that situation
* the calling code should not count on being able to demux more
@@ -497,7 +467,7 @@ int ds_fill_buffer(demux_stream_t *ds)
if (!demux_fill_buffer(demux, ds)) {
mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
- "ds_fill_buffer()->demux_fill_buffer() failed\n");
+ "ds_get_packets()->demux_fill_buffer() failed\n");
break; // EOF
}
@@ -508,10 +478,8 @@ int ds_fill_buffer(demux_stream_t *ds)
ds->fill_count++;
}
}
- ds->buffer_pos = ds->buffer_size = 0;
- ds->buffer = NULL;
mp_msg(MSGT_DEMUXER, MSGL_V,
- "ds_fill_buffer: EOF reached (stream: %s) \n",
+ "ds_get_packets: EOF reached (stream: %s) \n",
ds == demux->audio ? "audio" : "video");
ds->eof = 1;
return 0;
@@ -519,100 +487,76 @@ int ds_fill_buffer(demux_stream_t *ds)
void ds_free_packs(demux_stream_t *ds)
{
- demux_packet_t *dp = ds->first;
+ demux_packet_t *dp = ds->head;
while (dp) {
demux_packet_t *dn = dp->next;
free_demux_packet(dp);
dp = dn;
}
- ds->first = ds->last = NULL;
+ ds->head = ds->tail = NULL;
ds->packs = 0; // !!!!!
ds->bytes = 0;
- if (ds->current)
- free_demux_packet(ds->current);
- ds->current = NULL;
- ds->buffer = NULL;
- ds->buffer_pos = ds->buffer_size;
- ds->pts = MP_NOPTS_VALUE;
- ds->pts_bytes = 0;
-}
-
-int ds_get_packet(demux_stream_t *ds, unsigned char **start)
-{
- int len;
- if (ds->buffer_pos >= ds->buffer_size) {
- if (!ds_fill_buffer(ds)) {
- // EOF
- *start = NULL;
- return -1;
- }
- }
- len = ds->buffer_size - ds->buffer_pos;
- *start = &ds->buffer[ds->buffer_pos];
- ds->buffer_pos += len;
- return len;
+ ds->last_pts = MP_NOPTS_VALUE;
+ ds->last_pts_bytes = 0;
}
-int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts)
+static struct demux_stream *ds_from_sh(struct sh_stream *sh)
{
- int len;
- *pts = MP_NOPTS_VALUE;
- len = ds_get_packet(ds, start);
- if (len < 0)
- return len;
- // Return pts unless this read starts from the middle of a packet
- if (len == ds->buffer_pos)
- *pts = ds->current->pts;
- return len;
+ for (int n = 0; n < STREAM_TYPE_COUNT; n++) {
+ if (sh->demuxer->ds[n]->gsh == sh)
+ return sh->demuxer->ds[n];
+ }
+ return NULL;
}
-struct demux_packet *ds_get_packet_sub(demux_stream_t *ds)
-{
- if (ds->buffer_pos >= ds->buffer_size) {
- if (!ds->packs)
- return NULL; // no sub
- if (!ds_fill_buffer(ds))
- return NULL; // EOF
- }
- if (ds->buffer_pos < ds->buffer_size) {
- ds->current->buffer += ds->buffer_pos;
- ds->buffer_size -= ds->buffer_pos;
+// Read a packet from the given stream. The returned packet belongs to the
+// caller, who has to free it with talloc_free(). Might block. Returns NULL
+// on EOF.
+struct demux_packet *demux_read_packet(struct sh_stream *sh)
+{
+ struct demux_stream *ds = ds_from_sh(sh);
+ if (ds) {
+ ds_get_packets(ds);
+ struct demux_packet *pkt = ds->head;
+ if (pkt) {
+ ds->head = pkt->next;
+ pkt->next = NULL;
+ if (!ds->head)
+ ds->tail = NULL;
+ ds->bytes -= pkt->len;
+ ds->packs--;
+
+ if (pkt->pts != MP_NOPTS_VALUE) {
+ ds->last_pts = pkt->pts;
+ ds->last_pts_bytes = 0;
+ } else {
+ ds->last_pts_bytes += pkt->len;
+ }
+
+ if (pkt->stream_pts != MP_NOPTS_VALUE)
+ sh->demuxer->stream_pts = pkt->stream_pts;
+
+ return pkt;
+ }
}
- ds->buffer_pos = ds->buffer_size;
- return ds->current;
+ return NULL;
}
-struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last)
+// Return the pts of the next packet that demux_read_packet() would return.
+// Might block. Sometimes used to force a packet read, without removing any
+// packets from the queue.
+double demux_get_next_pts(struct sh_stream *sh)
{
- if (!repeat_last)
- ds_fill_buffer(ds);
- // This shouldn't get used together with partial reads
- // However, some old demuxers return parsed packets with an offset in
- // -correct-pts mode (at least mpegts).
- // Not all old demuxers will actually work.
- if (ds->buffer_pos < ds->buffer_size) {
- ds->current->buffer += ds->buffer_pos;
- ds->buffer_size -= ds->buffer_pos;
- }
- ds->buffer_pos = ds->buffer_size;
- return ds->current;
+ struct demux_stream *ds = ds_from_sh(sh);
+ ds_get_packets(ds);
+ return ds && ds->head ? ds->head->pts : MP_NOPTS_VALUE;
}
-double ds_get_next_pts(demux_stream_t *ds)
+// Return whether a packet is queued. Never blocks, never forces any reads.
+bool demux_has_packet(struct sh_stream *sh)
{
- demuxer_t *demux = ds->demuxer;
- // if we have not read from the "current" packet, consider it
- // as the next, otherwise we never get the pts for the first packet.
- while (!ds->first && (!ds->current || ds->buffer_pos)) {
- if (demux_check_queue_full(demux))
- return MP_NOPTS_VALUE;
- if (!demux_fill_buffer(demux, ds))
- return MP_NOPTS_VALUE;
- }
- // take pts from "current" if we never read from it.
- if (ds->current && !ds->buffer_pos)
- return ds->current->pts;
- return ds->first->pts;
+ struct demux_stream *ds = ds_from_sh(sh);
+ return ds && ds->head;
}
// ====================================================================
diff --git a/demux/demux.h b/demux/demux.h
index eb5de265b3..fade7533e9 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -90,19 +90,15 @@ enum timestamp_type {
typedef struct demux_stream {
enum stream_type stream_type;
- int buffer_pos; // current buffer position
- int buffer_size; // current buffer size
- unsigned char *buffer; // current buffer, never free() it, always use free_demux_packet(buffer_ref);
- double pts; // current buffer's pts
- int pts_bytes; // number of bytes read after last pts stamp
+ double last_pts; // pts of the last packet that was read
+ int last_pts_bytes; // number of bytes read after last pts stamp
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
- demux_packet_t *first; // read to current buffer from here
- demux_packet_t *last; // append new packets from input stream to here
- demux_packet_t *current; // needed for refcounting of the buffer
+ struct demux_packet *head;
+ struct demux_packet *tail;
struct demuxer *demuxer; // parent demuxer structure (stream handler)
// ---- stream header ----
struct sh_stream *gsh;
@@ -256,20 +252,12 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream,
void ds_add_packet(struct demux_stream *ds, struct demux_packet *dp);
int demux_fill_buffer(struct demuxer *demux, struct demux_stream *ds);
-int ds_fill_buffer(struct demux_stream *ds);
-
-static inline int ds_tell_pts(struct demux_stream *ds)
-{
- return (ds->pts_bytes - ds->buffer_size) + ds->buffer_pos;
-}
void ds_free_packs(struct demux_stream *ds);
-int ds_get_packet(struct demux_stream *ds, unsigned char **start);
-int ds_get_packet_pts(struct demux_stream *ds, unsigned char **start,
- double *pts);
-struct demux_packet *ds_get_packet_sub(demux_stream_t *ds);
-struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last);
-double ds_get_next_pts(struct demux_stream *ds);
+
+struct demux_packet *demux_read_packet(struct sh_stream *sh);
+double demux_get_next_pts(struct sh_stream *sh);
+bool demux_has_packet(struct sh_stream *sh);
struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream,
int file_format, char *filename);
diff --git a/demux/demux_mng.c b/demux/demux_mng.c
index 76b742f019..6dc0e352e8 100644
--- a/demux/demux_mng.c
+++ b/demux/demux_mng.c
@@ -38,14 +38,6 @@
#include <libmng.h>
/**
- * \brief some small fixed start time > 0
- *
- * Start time must be > 0 for the variable frame time mechanism
- * (GIF, MATROSKA, MNG) in video.c to work for the first frame.
- */
-#define MNG_START_PTS 0.01f
-
-/**
* \brief private context structure
*
* This structure is used as private data for MPlayer demuxer
@@ -346,7 +338,7 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer,
// Set position and timing information in demuxer video and demuxer packet.
// - Time must be time of next frame and always be > 0 for the variable
// frame time mechanism (GIF, MATROSKA, MNG) in video.c to work.
- dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f + MNG_START_PTS;
+ dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f;
dp->pos = stream_tell(demuxer->stream);
ds_add_packet(demuxer->video, dp);
@@ -447,11 +439,6 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer)
sh_video->bih->biBitCount = 32;
sh_video->bih->biPlanes = 1;
- // Set start time to something > 0.
- // - This is required for the variable frame time mechanism
- // (GIF, MATROSKA, MNG) in video.c to work for the first frame.
- sh_video->ds->pts = MNG_START_PTS;
-
// set private data in demuxer and return demuxer
demuxer->priv = mng_priv;
return demuxer;
diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c
index a4eaaa2a8c..787bd0c064 100644
--- a/demux/demux_rawvideo.c
+++ b/demux/demux_rawvideo.c
@@ -164,7 +164,6 @@ static void demux_rawvideo_seek(demuxer_t *demuxer,float rel_seek_secs,float aud
pos/=imgsize;
stream_seek(s,pos*imgsize);
//sh_video->timer=pos * sh_video->frametime;
- demuxer->video->pts = pos * sh_video->frametime;
// printf("demux_rawvideo: streamtell=%d\n",(int)stream_tell(demuxer->stream));
}
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index fb7e5e4a2a..4351cf60a0 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -380,12 +380,12 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh)
preprocess = 1;
for (;;) {
- ds_get_next_pts(sh->ds);
- struct demux_packet *pkt = ds_get_packet_sub(sh->ds);
+ struct demux_packet *pkt = demux_read_packet(sh->gsh);
if (!pkt)
break;
if (preprocess) {
decode_chain(sub->sd, preprocess, pkt);
+ talloc_free(pkt);
while (1) {
pkt = get_decoded_packet(sub->sd[preprocess - 1]);
if (!pkt)
@@ -394,6 +394,7 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh)
}
} else {
add_packet(subs, pkt);
+ talloc_free(pkt);
}
}