diff options
Diffstat (limited to 'src/combined')
-rw-r--r-- | src/combined/demux_flac.c | 10 | ||||
-rw-r--r-- | src/combined/ffmpeg/Makefile.am | 2 | ||||
-rw-r--r-- | src/combined/ffmpeg/ff_audio_decoder.c | 11 | ||||
-rw-r--r-- | src/combined/ffmpeg/ff_video_decoder.c | 105 | ||||
-rw-r--r-- | src/combined/ffmpeg/ffmpeg_decoder.h | 4 |
5 files changed, 116 insertions, 16 deletions
diff --git a/src/combined/demux_flac.c b/src/combined/demux_flac.c index ebba63701..fc638fe35 100644 --- a/src/combined/demux_flac.c +++ b/src/combined/demux_flac.c @@ -583,7 +583,7 @@ open_plugin (demux_class_t *class_gen, } break; case METHOD_BY_EXTENSION: { - char *ending, *mrl; + const char *ending, *mrl; mrl = input->get_mrl (input); @@ -715,22 +715,22 @@ open_plugin (demux_class_t *class_gen, /* FLAC Demuxer class */ -static char * +static const char * get_description (demux_class_t *this_gen) { return "FLAC demux plugin"; } -static char * +static const char * get_identifier (demux_class_t *this_gen) { return "FLAC"; } -static char * +static const char * get_extensions (demux_class_t *this_gen) { return "flac"; } -static char * +static const char * get_mimetypes (demux_class_t *this_gen) { return "audio/x-flac: flac: FLAC Audio;" "audio/flac: flac: FLAC Audio;"; diff --git a/src/combined/ffmpeg/Makefile.am b/src/combined/ffmpeg/Makefile.am index 3c78fa9d3..4d7e70423 100644 --- a/src/combined/ffmpeg/Makefile.am +++ b/src/combined/ffmpeg/Makefile.am @@ -4,7 +4,7 @@ DEFAULT_INCLUDES = -I. if HAVE_FFMPEG ff_cppflags = $(FFMPEG_CFLAGS) $(FFMPEG_POSTPROC_CFLAGS) -link_ffmpeg = $(FFMPEG_LIBS) $(FFMPEG_POSTPROC_LIBS) +link_ffmpeg = $(FFMPEG_LIBS) $(FFMPEG_UTIL_LIBS) $(FFMPEG_POSTPROC_LIBS) else ff_cppflags = -I$(top_builddir)/src/libffmpeg -I$(top_srcdir)/src/libffmpeg/libavcodec -I$(top_srcdir)/src/libffmpeg/libavutil link_ffmpeg = \ diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c index a08c3ac35..a9f630506 100644 --- a/src/combined/ffmpeg/ff_audio_decoder.c +++ b/src/combined/ffmpeg/ff_audio_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2005 the xine project + * Copyright (C) 2001-2008 the xine project * * This file is part of xine, a free video player. * @@ -324,7 +324,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) if (!this->output_open) { if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) { - avcodec_decode_audio (this->context, + avcodec_decode_audio2 (this->context, (int16_t *)this->decode_buffer, &decode_buffer_size, &this->buf[0], @@ -369,6 +369,11 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* dispatch the decoded audio */ out = 0; while (out < decode_buffer_size) { + int stream_status = xine_get_status(this->stream); + + if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP) + return; + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); if (audio_buffer->mem_size == 0) { @@ -445,7 +450,7 @@ static void ff_audio_dispose (audio_decoder_t *this_gen) { free(this->context->extradata); if(this->context) - free(this->context); + av_free(this->context); free (this_gen); } diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index e643708df..a1ab3696c 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2007 the xine project + * Copyright (C) 2001-2008 the xine project * * This file is part of xine, a free video player. * @@ -78,6 +78,9 @@ struct ff_video_decoder_s { xine_stream_t *stream; int64_t pts; + uint64_t pts_tag_mask; + uint64_t pts_tag; + int pts_tag_counter; int video_step; uint8_t decoder_ok:1; @@ -1178,6 +1181,42 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu } } +static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts) +{ + return pts | this->pts_tag; +} + +static uint64_t ff_untag_pts(ff_video_decoder_t *this, uint64_t pts) +{ + if (this->pts_tag_mask == 0) + return pts; /* pts tagging inactive */ + + if (this->pts_tag != 0 && (pts & this->pts_tag_mask) != this->pts_tag) + return 0; /* reset pts if outdated while waiting for first pass (see below) */ + + return pts & ~this->pts_tag_mask; +} + +static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts) +{ + if (this->pts_tag_mask == 0) + return; /* pts tagging inactive */ + + if ((pts & this->pts_tag_mask) != this->pts_tag) + return; /* pts still outdated */ + + if (this->pts_tag != 0) { + /* first pass: reset pts_tag */ + this->pts_tag = 0; + } else if (pts == 0) + return; /* cannot detect second pass */ + else { + /* second pass: reset pts_tag_mask and pts_tag_counter */ + this->pts_tag_mask = 0; + this->pts_tag_counter = 0; + } +} + static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { uint8_t *chunk_buf = this->buf; AVRational avr00 = {0, 1}; @@ -1202,6 +1241,13 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->size = 0; } + if (this->size == 0) { + /* take over pts when we are about to buffer a frame */ + this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); + this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->pts = 0; + } + /* data accumulation */ if (buf->size > 0) { if ((this->size == 0) && @@ -1254,6 +1300,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { len = avcodec_decode_video (this->context, this->av_frame, &got_picture, &chunk_buf[offset], this->size); + + /* reset consumed pts value */ + this->context->reordered_opaque = ff_tag_pts(this, 0); + lprintf("consumed size: %d, got_picture: %d\n", len, got_picture); if ((len <= 0) || (len > this->size)) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, @@ -1269,6 +1319,11 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_check_bufsize(this, this->size); memmove (this->buf, &chunk_buf[offset], this->size); chunk_buf = this->buf; + + /* take over pts for next access unit */ + this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); + this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->pts = 0; } } } @@ -1363,8 +1418,9 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_convert_frame(this, img); } - img->pts = this->pts; - this->pts = 0; + img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); + ff_check_pts_tagging(this, this->av_frame->reordered_opaque); /* only check for valid frames */ + this->av_frame->reordered_opaque = 0; /* workaround for weird 120fps streams */ if( video_step_to_use == 750 ) { @@ -1404,8 +1460,8 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->output_format, VO_BOTH_FIELDS|this->frame_flags); /* set PTS to allow early syncing */ - img->pts = this->pts; - this->pts = 0; + img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); + this->av_frame->reordered_opaque = 0; img->duration = video_step_to_use; @@ -1490,6 +1546,10 @@ static void ff_reset (video_decoder_t *this_gen) { if (this->is_mpeg12) mpeg_parser_reset(this->mpeg_parser); + + this->pts_tag_mask = 0; + this->pts_tag = 0; + this->pts_tag_counter = 0; } static void ff_discontinuity (video_decoder_t *this_gen) { @@ -1497,6 +1557,37 @@ static void ff_discontinuity (video_decoder_t *this_gen) { lprintf ("ff_discontinuity\n"); this->pts = 0; + + /* + * there is currently no way to reset all the pts which are stored in the decoder. + * therefore, we add a unique tag (generated from pts_tag_counter) to pts (see + * ff_tag_pts()) and wait for it to appear on returned frames. + * until then, any retrieved pts value will be reset to 0 (see ff_untag_pts()). + * when we see the tag returned, pts_tag will be reset to 0. from now on, any + * untagged pts value is valid already. + * when tag 0 appears too, there are no tags left in the decoder so pts_tag_mask + * and pts_tag_counter will be reset to 0 too (see ff_check_pts_tagging()). + */ + this->pts_tag_counter++; + this->pts_tag_mask = 0; + this->pts_tag = 0; + { + /* pts values typically don't use the uppermost bits. therefore we put the tag there */ + int counter_mask = 1; + uint64_t tag_mask = 0x8000000000000000ull; + while (this->pts_tag_counter >= counter_mask) + { + /* + * mirror the counter into the uppermost bits. this allows us to enlarge mask as + * necessary and while previous taggings can still be detected to be outdated. + */ + if (this->pts_tag_counter & counter_mask) + this->pts_tag |= tag_mask; + this->pts_tag_mask |= tag_mask; + tag_mask >>= 1; + counter_mask <<= 1; + } + } } static void ff_dispose (video_decoder_t *this_gen) { @@ -1534,10 +1625,10 @@ static void ff_dispose (video_decoder_t *this_gen) { free_yuv_planes(&this->yuv); if( this->context ) - free( this->context ); + av_free( this->context ); if( this->av_frame ) - free( this->av_frame ); + av_free( this->av_frame ); if (this->buf) free(this->buf); diff --git a/src/combined/ffmpeg/ffmpeg_decoder.h b/src/combined/ffmpeg/ffmpeg_decoder.h index f47421253..0f4ff1f1e 100644 --- a/src/combined/ffmpeg/ffmpeg_decoder.h +++ b/src/combined/ffmpeg/ffmpeg_decoder.h @@ -33,6 +33,10 @@ # include "../../libffmpeg/libavcodec/avcodec.h" #endif +#if LIBAVCODEC_VERSION_MAJOR > 51 +#define bits_per_sample bits_per_coded_sample +#endif + typedef struct ff_codec_s { uint32_t type; enum CodecID id; |