0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02:00

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.
This commit is contained in:
wm4 2013-07-11 19:10:33 +02:00
parent 07c5327fa0
commit a522483629
11 changed files with 127 additions and 284 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;
float pts1 = d_video->last_pts;
*start = NULL;
// 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;
}

View File

@ -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;
ds->last_pts = MP_NOPTS_VALUE;
ds->last_pts_bytes = 0;
}
int ds_get_packet(demux_stream_t *ds, unsigned char **start)
static struct demux_stream *ds_from_sh(struct sh_stream *sh)
{
int len;
if (ds->buffer_pos >= ds->buffer_size) {
if (!ds_fill_buffer(ds)) {
// EOF
*start = NULL;
return -1;
for (int n = 0; n < STREAM_TYPE_COUNT; n++) {
if (sh->demuxer->ds[n]->gsh == sh)
return sh->demuxer->ds[n];
}
return NULL;
}
// 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;
}
}
len = ds->buffer_size - ds->buffer_pos;
*start = &ds->buffer[ds->buffer_pos];
ds->buffer_pos += len;
return len;
return NULL;
}
int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts)
// 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)
{
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;
struct demux_stream *ds = ds_from_sh(sh);
ds_get_packets(ds);
return ds && ds->head ? ds->head->pts : MP_NOPTS_VALUE;
}
struct demux_packet *ds_get_packet_sub(demux_stream_t *ds)
// Return whether a packet is queued. Never blocks, never forces any reads.
bool demux_has_packet(struct sh_stream *sh)
{
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;
}
ds->buffer_pos = ds->buffer_size;
return ds->current;
}
struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last)
{
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;
}
double ds_get_next_pts(demux_stream_t *ds)
{
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;
}
// ====================================================================

View File

@ -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);

View File

@ -37,14 +37,6 @@
#define MNG_SUPPORT_DISPLAY
#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
*
@ -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;

View File

@ -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));
}

View File

@ -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);
}
}