VAAPI regression test
Torsten Jager <[email protected]> Thu, 18 Apr 2013 15:55:57 +0200
| Newsgroups | gmane.comp.video.xine.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello! libavcodec 54 (ff 1.1.2) has a bug that ignores the EMU_EDGE flag for the "wmv2" and "mpeg4" decoders. It yields memory corruption and crashes when direct rendering is enabled. This patch does work around it. But I'm not sure whether it breaks VAAPI. I dont have suiable hardware so can you perform a test for me? PS. I just saw your "dont work" issue. Maybe test with 1.1.2? Thanks, Torsten ------------------------------------------------------------------------------ Precog is a next-generation analytics platform capable of advanced analytics on semi-structured data. The platform includes APIs for building apps and a phenomenal toolset for data science. Developers can use our toolset for easy data analysis & visualization. Get a free account! http://www2.precog.com/precogplatform/slashdotnewsletter _______________________________________________ xine-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/xine-devel
ff_no_emu_edge.diff
(text/x-patch, 8.7 KB)
--- xine-lib-1.2-20130130/src/combined/ffmpeg/ff_video_decoder.c 2013-01-30 21:58:57.000000000 +0100
+++ xine-lib-1.2-20130130/src/combined/ffmpeg/ff_video_decoder.c 2013-02-08 16:20:53.000000000 +0100
@@ -128,7 +128,7 @@ struct ff_video_decoder_s {
double aspect_ratio;
int aspect_ratio_prio;
int frame_flags;
- int crop_right, crop_bottom;
+ int edge;
int output_format;
@@ -219,6 +222,7 @@ static int get_buffer(AVCodecContext *co
vo_frame_t *img;
int width = context->width;
int height = context->height;
+ int crop_right = 0, crop_bottom = 0;
int guarded_render = 0;
ff_check_colorspace (this);
@@ -226,13 +230,13 @@ static int get_buffer(AVCodecContext *co
if (!this->bih.biWidth || !this->bih.biHeight) {
this->bih.biWidth = width;
this->bih.biHeight = height;
+ }
- if (this->aspect_ratio_prio == 0) {
- this->aspect_ratio = (double)width / (double)height;
- this->aspect_ratio_prio = 1;
- lprintf("default aspect ratio: %f\n", this->aspect_ratio);
- this->set_stream_info = 1;
- }
+ if (this->aspect_ratio_prio == 0) {
+ this->aspect_ratio = (double)width / (double)height;
+ this->aspect_ratio_prio = 1;
+ lprintf("default aspect ratio: %f\n", this->aspect_ratio);
+ this->set_stream_info = 1;
}
avcodec_align_dimensions(context, &width, &height);
@@ -299,6 +303,12 @@ static int get_buffer(AVCodecContext *co
guarded_render = this->accel->guarded_render(this->accel_img);
#endif /* ENABLE_VAAPI */
+ /* The alignment rhapsody */
+ width += 2 * this->edge;
+ height += 2 * this->edge;
+ width = (width + 15) & ~15;
+ height = (height + 15) & ~15;
+
if ((this->full2mpeg || (this->context->pix_fmt != PIX_FMT_YUV420P &&
this->context->pix_fmt != PIX_FMT_YUVJ420P)) || guarded_render) {
if (!this->is_direct_rendering_disabled) {
@@ -316,8 +326,8 @@ static int get_buffer(AVCodecContext *co
if((width != this->bih.biWidth) || (height != this->bih.biHeight)) {
if(this->stream->video_out->get_capabilities(this->stream->video_out) & VO_CAP_CROP) {
- this->crop_right = width - this->bih.biWidth;
- this->crop_bottom = height - this->bih.biHeight;
+ crop_right = width - this->bih.biWidth - this->edge;
+ crop_bottom = height - this->bih.biHeight - this->edge;
} else {
if (!this->is_direct_rendering_disabled) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
@@ -343,6 +353,8 @@ static int get_buffer(AVCodecContext *co
av_frame->opaque = img;
+ av_frame->extended_data = av_frame->data;
+
av_frame->data[0]= img->base[0];
av_frame->data[1]= img->base[1];
av_frame->data[2]= img->base[2];
@@ -351,6 +363,16 @@ static int get_buffer(AVCodecContext *co
av_frame->linesize[1] = img->pitches[1];
av_frame->linesize[2] = img->pitches[2];
+ if (this->output_format == XINE_IMGFMT_YV12) {
+ av_frame->data[0] += (img->pitches[0] + 1) * this->edge;
+ av_frame->data[1] += (img->pitches[1] + 1) * this->edge / 2;
+ av_frame->data[2] += (img->pitches[2] + 1) * this->edge / 2;
+ img->crop_left = this->edge;
+ img->crop_top = this->edge;
+ img->crop_right = crop_right;
+ img->crop_bottom = crop_bottom;
+ }
+
/* We should really keep track of the ages of xine frames (see
* avcodec_default_get_buffer in libavcodec/utils.c)
* For the moment tell ffmpeg that every frame is new (age = bignumber) */
@@ -508,10 +530,20 @@ static void init_video_codec (ff_video_d
_x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_FOURCC);
- /* 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 */
+ this->stream->video_out->open (this->stream->video_out, this->stream);
+
+ this->edge = 0;
if(this->codec->capabilities & CODEC_CAP_DR1 && this->class->enable_dri) {
- this->context->flags |= CODEC_FLAG_EMU_EDGE;
+ if (this->stream->video_out->get_capabilities (this->stream->video_out) & VO_CAP_CROP) {
+ /* We can crop. Fine. Lets allow decoders to paint over the frame edges.
+ This will be slightly faster. And it is also a workaround for buggy
+ v54 who likes to ignore EMU_EDGE for wmv2 and xvid. */
+ this->edge = avcodec_get_edge_width ();
+ } else {
+ /* 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 */
+ this->context->flags |= CODEC_FLAG_EMU_EDGE;
+ }
}
/* TJ. without this, it wont work at all on my machine */
@@ -570,6 +602,7 @@ static void init_video_codec (ff_video_d
free(this->context);
this->context = NULL;
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+ this->stream->video_out->close (this->stream->video_out, this->stream);
return;
}
@@ -585,6 +618,7 @@ static void init_video_codec (ff_video_d
free(this->context);
this->context = NULL;
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0);
+ this->stream->video_out->close (this->stream->video_out, this->stream);
return;
}
}
@@ -615,8 +649,6 @@ static void init_video_codec (ff_video_d
set_stream_info(this);
}
- (this->stream->video_out->open) (this->stream->video_out, this->stream);
-
this->skipframes = 0;
/* flag for interlaced streams */
@@ -1439,9 +1477,6 @@ static void ff_handle_mpeg12_buffer (ff_
else
img->duration = this->video_step;
- img->crop_right = this->crop_right;
- img->crop_bottom = this->crop_bottom;
-
#ifdef ENABLE_VAAPI
if( this->context->pix_fmt == PIX_FMT_VAAPI_VLD) {
if(this->accel->guarded_render(this->accel_img)) {
@@ -1695,12 +1749,15 @@ static void ff_handle_buffer (ff_video_d
}
/* xine-lib expects the framesize to be a multiple of 16x16 (macroblock) */
+ /* TJ. says who? */
img = this->stream->video_out->get_frame (this->stream->video_out,
(this->bih.biWidth + 15) & ~15,
(this->bih.biHeight + 15) & ~15,
this->aspect_ratio,
this->output_format,
VO_BOTH_FIELDS|this->frame_flags);
+ img->crop_right = img->width - this->bih.biWidth;
+ img->crop_bottom = img->height - this->bih.biHeight;
free_img = 1;
} else {
/* DR1 */
@@ -1715,19 +1772,22 @@ static void ff_handle_buffer (ff_video_d
if(this->pp_available && this->pp_quality && this->context->pix_fmt != PIX_FMT_VAAPI_VLD) {
if(this->av_frame->opaque) {
- /* DR1 */
+ /* DR1: filter into a new frame. Same size to avoid reallcation, just move the
+ image to top left corner. */
img = this->stream->video_out->get_frame (this->stream->video_out,
- (img->width + 15) & ~15,
- (img->height + 15) & ~15,
+ img->width,
+ img->height,
this->aspect_ratio,
this->output_format,
VO_BOTH_FIELDS|this->frame_flags);
+ img->crop_right = img->width - this->bih.biWidth;
+ img->crop_bottom = img->height - this->bih.biHeight;
free_img = 1;
}
pp_postprocess((const uint8_t **)this->av_frame->data, this->av_frame->linesize,
img->base, img->pitches,
- img->width, img->height,
+ this->bih.biWidth, this->bih.biHeight,
this->av_frame->qscale_table, this->av_frame->qstride,
this->our_mode, this->our_context,
this->av_frame->pict_type);
@@ -1756,10 +1816,6 @@ static void ff_handle_buffer (ff_video_d
else
img->duration = video_step_to_use;
- /* additionally crop away the extra pixels due to adjusting frame size above */
- img->crop_right = img->width - this->bih.biWidth;
- img->crop_bottom = img->height - this->bih.biHeight;
-
/* transfer some more frame settings for deinterlacing */
img->progressive_frame = !this->av_frame->interlaced_frame;
img->top_field_first = this->av_frame->top_field_first;