summaryrefslogtreecommitdiff
path: root/src/combined
diff options
context:
space:
mode:
Diffstat (limited to 'src/combined')
-rw-r--r--src/combined/demux_flac.c10
-rw-r--r--src/combined/ffmpeg/Makefile.am2
-rw-r--r--src/combined/ffmpeg/ff_audio_decoder.c11
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c105
-rw-r--r--src/combined/ffmpeg/ffmpeg_decoder.h4
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;