summaryrefslogtreecommitdiff
path: root/src/combined/ffmpeg/ff_video_decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/combined/ffmpeg/ff_video_decoder.c')
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c89
1 files changed, 28 insertions, 61 deletions
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
index 8693f0e67..ca3e488fa 100644
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -22,7 +22,6 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
-#include "../../libffmpeg/ffmpeg_config.h"
#endif
#include <stdlib.h>
@@ -38,10 +37,10 @@
/*
#define LOG
*/
-#include "xine_internal.h"
+#include <xine/xine_internal.h>
#include "bswap.h"
-#include "buffer.h"
-#include "xineutils.h"
+#include <xine/buffer.h>
+#include <xine/xineutils.h>
#include "ffmpeg_decoder.h"
#include "ff_mpeg_parser.h"
@@ -69,6 +68,7 @@ typedef struct ff_video_class_s {
int thread_count;
int8_t skip_loop_filter_enum;
int8_t choose_speed_over_accuracy;
+ uint8_t enable_dri;
xine_t *xine;
} ff_video_class_t;
@@ -81,12 +81,10 @@ struct ff_video_decoder_s {
xine_stream_t *stream;
int64_t pts;
int64_t last_pts;
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
uint64_t pts_tag_mask;
uint64_t pts_tag;
int pts_tag_counter;
int pts_tag_stable_counter;
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
int video_step;
int reported_video_step;
@@ -95,7 +93,7 @@ struct ff_video_decoder_s {
uint8_t is_mpeg12:1;
uint8_t pp_available:1;
uint8_t yuv_init:1;
- uint8_t is_direct_rendering_disabled:1;
+ uint8_t is_direct_rendering_disabled:1; /* used only to avoid flooding log */
uint8_t cs_convert_init:1;
uint8_t assume_bad_field_picture:1;
@@ -241,6 +239,8 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){
}
}
+ this->is_direct_rendering_disabled = 0;
+
img = this->stream->video_out->get_frame (this->stream->video_out,
width,
height,
@@ -267,10 +267,8 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){
av_frame->type= FF_BUFFER_TYPE_USER;
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
/* take over pts for this frame to have it reordered */
av_frame->reordered_opaque = context->reordered_opaque;
-#endif
xine_list_push_back(this->dr1_frames, img);
@@ -360,7 +358,7 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
/* Some codecs (eg rv10) copy flags in init so it's necessary to set
* this flag here in case we are going to use direct rendering */
- if(this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264) {
+ if(this->codec->capabilities & CODEC_CAP_DR1 && this->class->enable_dri) {
this->context->flags |= CODEC_FLAG_EMU_EDGE;
}
@@ -440,7 +438,7 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
/* enable direct rendering by default */
this->output_format = XINE_IMGFMT_YV12;
#ifdef ENABLE_DIRECT_RENDERING
- if( this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264 ) {
+ if( this->codec->capabilities & CODEC_CAP_DR1 && this->class->enable_dri ) {
this->context->get_buffer = get_buffer;
this->context->release_buffer = release_buffer;
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
@@ -500,6 +498,12 @@ static void pp_quality_cb(void *user_data, xine_cfg_entry_t *entry) {
class->pp_quality = entry->num_value;
}
+static void dri_cb(void *user_data, xine_cfg_entry_t *entry) {
+ ff_video_class_t *class = (ff_video_class_t *) user_data;
+
+ class->enable_dri = entry->num_value;
+}
+
static void pp_change_quality (ff_video_decoder_t *this) {
this->pp_quality = this->class->pp_quality;
@@ -1165,7 +1169,6 @@ static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *b
}
}
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts)
{
return pts | this->pts_tag;
@@ -1211,7 +1214,6 @@ static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts)
}
}
}
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
@@ -1234,14 +1236,12 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
uint8_t *current;
int next_flush;
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
/* apply valid pts to first frame _starting_ thereafter only */
if (this->pts && !this->context->reordered_opaque) {
this->context->reordered_opaque =
this->av_frame->reordered_opaque = ff_tag_pts (this, this->pts);
this->pts = 0;
}
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
got_picture = 0;
if (!flush) {
@@ -1324,16 +1324,11 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu
free_img = 0;
}
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
/* get back reordered pts */
img->pts = ff_untag_pts (this, this->av_frame->reordered_opaque);
ff_check_pts_tagging (this, this->av_frame->reordered_opaque);
this->av_frame->reordered_opaque = 0;
this->context->reordered_opaque = 0;
-#else
- img->pts = this->pts;
- this->pts = 0;
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
if (this->av_frame->repeat_pict)
img->duration = this->video_step * 3 / 2;
@@ -1401,7 +1396,6 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
this->size = 0;
}
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
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);
@@ -1409,7 +1403,6 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
this->context->reordered_opaque = ff_tag_pts(this, this->pts);
this->pts = 0;
}
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
/* data accumulation */
if (buf->size > 0) {
@@ -1476,10 +1469,8 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
&got_picture, &chunk_buf[offset],
this->size);
#endif
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
/* reset consumed pts value */
this->context->reordered_opaque = ff_tag_pts(this, 0);
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
lprintf("consumed size: %d, got_picture: %d\n", len, got_picture);
if ((len <= 0) || (len > this->size)) {
@@ -1497,12 +1488,10 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
memmove (this->buf, &chunk_buf[offset], this->size);
chunk_buf = this->buf;
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
/* 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;
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
}
}
}
@@ -1511,11 +1500,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
video_step_to_use = (this->video_step || !this->context->time_base.den)
? this->video_step
: (int)(90000ll
-#if LIBAVCODEC_VERSION_INT >= 0x341400
* this->context->ticks_per_frame
-#elif LIBAVCODEC_VERSION_INT >= 0x340000
-# warning Building without avcodec ticks_per_frame support; you should upgrade your libavcodec and recompile
-#endif
* this->context->time_base.num / this->context->time_base.den);
/* aspect ratio provided by ffmpeg, override previous setting */
@@ -1605,14 +1590,9 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) {
ff_convert_frame(this, img);
}
-#ifndef AVCODEC_HAS_REORDERED_OPAQUE
- img->pts = this->pts;
- this->pts = 0;
-#else /* AVCODEC_HAS_REORDERED_OPAQUE */
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;
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
/* workaround for weird 120fps streams */
if( video_step_to_use == 750 ) {
@@ -1655,13 +1635,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 */
-#ifndef AVCODEC_HAS_REORDERED_OPAQUE
- img->pts = this->pts;
- this->pts = 0;
-#else /* AVCODEC_HAS_REORDERED_OPAQUE */
img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque);
this->av_frame->reordered_opaque = 0;
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
img->duration = video_step_to_use;
@@ -1715,6 +1690,8 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
}
} else {
+ if (this->decoder_init_mode && !this->is_mpeg12)
+ ff_handle_preview_buffer(this, buf);
/* decode */
/* PES: each valid pts shall be used only once */
@@ -1762,12 +1739,10 @@ static void ff_reset (video_decoder_t *this_gen) {
if (this->is_mpeg12)
mpeg_parser_reset(this->mpeg_parser);
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
this->pts_tag_mask = 0;
this->pts_tag = 0;
this->pts_tag_counter = 0;
this->pts_tag_stable_counter = 0;
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
}
static void ff_discontinuity (video_decoder_t *this_gen) {
@@ -1776,7 +1751,6 @@ static void ff_discontinuity (video_decoder_t *this_gen) {
lprintf ("ff_discontinuity\n");
this->pts = 0;
-#ifdef AVCODEC_HAS_REORDERED_OPAQUE
/*
* 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
@@ -1809,7 +1783,6 @@ static void ff_discontinuity (video_decoder_t *this_gen) {
counter_mask <<= 1;
}
}
-#endif /* AVCODEC_HAS_REORDERED_OPAQUE */
}
static void ff_dispose (video_decoder_t *this_gen) {
@@ -1917,18 +1890,6 @@ static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen,
return &this->video_decoder;
}
-static char *ff_video_get_identifier (video_decoder_class_t *this) {
- return "ffmpeg video";
-}
-
-static char *ff_video_get_description (video_decoder_class_t *this) {
- return "ffmpeg based video decoder plugin";
-}
-
-static void ff_video_dispose_class (video_decoder_class_t *this) {
- free (this);
-}
-
void *init_video_plugin (xine_t *xine, void *data) {
ff_video_class_t *this;
@@ -1937,9 +1898,9 @@ void *init_video_plugin (xine_t *xine, void *data) {
this = calloc(1, sizeof (ff_video_class_t));
this->decoder_class.open_plugin = ff_video_open_plugin;
- this->decoder_class.get_identifier = ff_video_get_identifier;
- this->decoder_class.get_description = ff_video_get_description;
- this->decoder_class.dispose = ff_video_dispose_class;
+ this->decoder_class.identifier = "ffmpeg video";
+ this->decoder_class.description = N_("ffmpeg based video decoder plugin");
+ this->decoder_class.dispose = default_video_decoder_class_dispose;
this->xine = xine;
pthread_once( &once_control, init_once_routine );
@@ -1985,15 +1946,21 @@ void *init_video_plugin (xine_t *xine, void *data) {
"A change of this setting will take effect with playing the next stream."),
10, choose_speed_over_accuracy_cb, this);
+ this->enable_dri = xine->config->register_bool(config, "video.processing.ffmpeg_direct_rendering", 1,
+ _("Enable direct rendering"),
+ _("Disable direct rendering if you are experiencing lock-ups with\n"
+ "streams with lot of reference frames."),
+ 10, dri_cb, this);
+
return this;
}
-static uint32_t wmv8_video_types[] = {
+static const uint32_t wmv8_video_types[] = {
BUF_VIDEO_WMV8,
0
};
-static uint32_t wmv9_video_types[] = {
+static const uint32_t wmv9_video_types[] = {
BUF_VIDEO_WMV9,
0
};