summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);
}
}