[vlc-commits] vdpau: fix importing surface from main memory
Rémi Denis-Courmont
git at videolan.org
Wed Apr 29 20:23:41 CEST 2015
vlc/vlc-2.2 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Apr 28 23:42:23 2015 +0300| [1798c312d838fe89febcf4e1adba26eea8038528] | committer: Rémi Denis-Courmont
vdpau: fix importing surface from main memory
On the one hand, when decoding in hardware, the video surface
dimensions will match the coded dimensions, rather than the visible
ones. Otherwise the hardware decoder would not have enough space for
its output. In this the libavcodec plugin does not add padding (since
libavcodec SIMD optimizations are not involved).
On the other hand, when decoding in software, the video surface height
must not include the padding added by libavcodec SIMD optimizations. So
then the visible height needs to be used to avoid bleeding green lines.
(cherry picked from commit 3b3bd7e49d52875024c6f1b0ef4eac124a637c2d)
Conflicts:
modules/hw/vdpau/chroma.c
> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=1798c312d838fe89febcf4e1adba26eea8038528
---
modules/hw/vdpau/chroma.c | 42 +++++++++++++++++++++++++++++++++---------
1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/modules/hw/vdpau/chroma.c b/modules/hw/vdpau/chroma.c
index 1fe511c..00f5ad7 100644
--- a/modules/hw/vdpau/chroma.c
+++ b/modules/hw/vdpau/chroma.c
@@ -65,7 +65,8 @@ static VdpStatus MixerSetupColors(filter_t *filter, const VdpProcamp *procamp,
{
filter_sys_t *sys = filter->p_sys;
VdpStatus err;
- VdpColorStandard std = (filter->fmt_in.video.i_height > 576)
+ /* XXX: add some margin for padding... */
+ VdpColorStandard std = (filter->fmt_in.video.i_height > 576 + 16)
? VDP_COLOR_STANDARD_ITUR_BT_709
: VDP_COLOR_STANDARD_ITUR_BT_601;
@@ -95,7 +96,7 @@ static VdpStatus MixerSetupColors(filter_t *filter, const VdpProcamp *procamp,
}
/** Create VDPAU video mixer */
-static VdpVideoMixer MixerCreate(filter_t *filter)
+static VdpVideoMixer MixerCreate(filter_t *filter, bool import)
{
filter_sys_t *sys = filter->p_sys;
VdpVideoMixer mixer;
@@ -187,7 +188,8 @@ static VdpVideoMixer MixerCreate(filter_t *filter)
VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE,
};
uint32_t width = filter->fmt_in.video.i_width;
- uint32_t height = filter->fmt_in.video.i_height;
+ uint32_t height = import ? filter->fmt_in.video.i_visible_height
+ : filter->fmt_in.video.i_height;
const void *values[3] = { &width, &height, &sys->chroma, };
err = vdp_video_mixer_create(sys->vdp, sys->device, featc, featv,
@@ -279,6 +281,8 @@ static void Flush(filter_t *filter)
}
}
+static picture_t *YCbCrRender(filter_t *filter, picture_t *src);
+
/** Get a VLC picture for a VDPAU output surface */
static picture_t *OutputAllocate(filter_t *filter)
{
@@ -300,7 +304,7 @@ static picture_t *OutputAllocate(filter_t *filter)
/* First picture: get the context and allocate the mixer */
sys->vdp = vdp_hold_x11(psys->vdp, NULL);
sys->device = psys->device;
- sys->mixer = MixerCreate(filter);
+ sys->mixer = MixerCreate(filter, filter->pf_video_filter == YCbCrRender);
if (sys->mixer != VDP_INVALID_HANDLE)
return pic;
@@ -362,7 +366,8 @@ static picture_t *VideoImport(filter_t *filter, picture_t *src)
/* Create surface (TODO: reuse?) */
err = vdp_video_surface_create(sys->vdp, sys->device, sys->chroma,
filter->fmt_in.video.i_width,
- filter->fmt_in.video.i_height, &surface);
+ filter->fmt_in.video.i_visible_height,
+ &surface);
if (err != VDP_STATUS_OK)
{
msg_Err(filter, "video %s %s failure: %s", "surface", "creation",
@@ -375,7 +380,8 @@ static picture_t *VideoImport(filter_t *filter, picture_t *src)
uint32_t pitches[3];
for (int i = 0; i < src->i_planes; i++)
{
- planes[i] = src->p[i].p_pixels;
+ planes[i] = src->p[i].p_pixels
+ + filter->fmt_in.video.i_y_offset * src->p[i].i_pitch;
pitches[i] = src->p[i].i_pitch;
}
if (src->format.i_chroma == VLC_CODEC_I420)
@@ -385,6 +391,15 @@ static picture_t *VideoImport(filter_t *filter, picture_t *src)
pitches[1] = src->p[2].i_pitch;
pitches[2] = src->p[1].i_pitch;
}
+ if (src->format.i_chroma == VLC_CODEC_I420
+ || src->format.i_chroma == VLC_CODEC_YV12
+ || src->format.i_chroma == VLC_CODEC_NV12)
+ {
+ for (int i = 1; i < src->i_planes; i++)
+ planes[i] = ((const uint8_t *)planes[i])
+ + (filter->fmt_in.video.i_y_offset / 2) * src->p[i].i_pitch;
+ }
+
err = vdp_video_surface_put_bits_y_cb_cr(sys->vdp, surface, sys->format,
planes, pitches);
if (err != VDP_STATUS_OK)
@@ -399,6 +414,7 @@ static picture_t *VideoImport(filter_t *filter, picture_t *src)
fmt.i_chroma = (sys->chroma == VDP_CHROMA_TYPE_420)
? VLC_CODEC_VDPAU_VIDEO_420 : VLC_CODEC_VDPAU_VIDEO_422;
+
picture_t *dst = picture_NewFromFormat(&fmt);
if (unlikely(dst == NULL))
goto error;
@@ -425,7 +441,7 @@ static inline VdpVideoSurface picture_GetVideoSurface(const picture_t *pic)
return field->frame->surface;
}
-static picture_t *VideoRender(filter_t *filter, picture_t *src)
+static picture_t *Render(filter_t *filter, picture_t *src, bool import)
{
filter_sys_t *sys = filter->p_sys;
VdpStatus err;
@@ -608,9 +624,11 @@ static picture_t *VideoRender(filter_t *filter, picture_t *src)
VdpVideoSurface future[MAX_FUTURE];
VdpRect src_rect = {
filter->fmt_in.video.i_x_offset, filter->fmt_in.video.i_y_offset,
- filter->fmt_in.video.i_x_offset, filter->fmt_in.video.i_y_offset
+ filter->fmt_in.video.i_x_offset, filter->fmt_in.video.i_y_offset,
};
+ if (import)
+ src_rect.y0 = src_rect.y1 = 0;
if (hflip)
src_rect.x0 += filter->fmt_in.video.i_visible_width;
else
@@ -678,6 +696,12 @@ error:
goto skip;
}
+static picture_t *VideoRender(filter_t *filter, picture_t *src)
+{
+ return Render(filter, src, false);
+}
+
+
static picture_t *YCbCrRender(filter_t *filter, picture_t *src)
{
/* FIXME: Define a way to initialize the mixer in Open() instead. */
@@ -689,7 +713,7 @@ static picture_t *YCbCrRender(filter_t *filter, picture_t *src)
}
src = VideoImport(filter, src);
- return (src != NULL) ? VideoRender(filter, src) : NULL;
+ return (src != NULL) ? Render(filter, src, true) : NULL;
}
static int OutputOpen(vlc_object_t *obj)
More information about the vlc-commits
mailing list