diff options
-rw-r--r-- | audio/decode/ad.h | 3 | ||||
-rw-r--r-- | audio/decode/ad_lavc.c | 7 | ||||
-rw-r--r-- | audio/decode/ad_mpg123.c | 16 | ||||
-rw-r--r-- | audio/decode/ad_spdif.c | 59 | ||||
-rw-r--r-- | audio/decode/dec_audio.c | 11 | ||||
-rw-r--r-- | core/mplayer.c | 86 | ||||
-rw-r--r-- | demux/demux.c | 178 | ||||
-rw-r--r-- | demux/demux.h | 28 | ||||
-rw-r--r-- | demux/demux_mng.c | 15 | ||||
-rw-r--r-- | demux/demux_rawvideo.c | 1 | ||||
-rw-r--r-- | sub/dec_sub.c | 5 |
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); } } |