st/va: Fix up YV12 to NV12 putImage conversion

Use the utility u_copy_nv12_from_yv12 to implement this similarly to
how it's been done in the VPAU state tracker. The old code mixed up
planes and fields and didn't correctly handle video surfaces in
interlaced format.

Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
This commit is contained in:
Thomas Hellstrom 2017-02-22 13:07:47 +01:00
parent 3a418322ec
commit 7b82efe4ee
2 changed files with 29 additions and 58 deletions

View File

@ -172,43 +172,6 @@ u_copy_yv12_to_nv12(void *const *destination_data,
}
}
static inline void
u_copy_yv12_img_to_nv12_surf(ubyte *const *src,
ubyte *dst,
unsigned width,
unsigned height,
unsigned src_stride,
unsigned dst_stride,
int field)
{
if (field == 0) {
ubyte *src_0 = src[field];
for (int i = 0; i < height ; i++) {
memcpy(dst, src_0, width);
dst += dst_stride;
src_0 += src_stride;
}
} else if (field == 1) {
const ubyte *src_1 = src[field];
const ubyte *src_2 = src[field+1];
bool odd = true;
for (unsigned i = 0; i < height ; i++) {
for (unsigned j = 0; j < width*2 ; j++) {
if (odd == false) {
dst[j] = src_1[j/2];
odd = true;
} else {
dst[j] = src_2[j/2];
odd = false;
}
}
dst += dst_stride;
src_1 += src_stride;
src_2 += src_stride;
}
}
}
static inline void
u_copy_swap422_packed(void *const *destination_data,
uint32_t const *destination_pitches,

View File

@ -513,28 +513,36 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
for (i = 0; i < vaimage->num_planes; ++i) {
unsigned width, height;
if (!views[i]) continue;
vlVaVideoSurfaceSize(surf, i, &width, &height);
if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV)) &&
(surf->buffer->buffer_format == PIPE_FORMAT_NV12)) {
struct pipe_transfer *transfer = NULL;
uint8_t *map = NULL;
struct pipe_box dst_box_1 = {0, 0, 0, width, height, 1};
map = drv->pipe->transfer_map(drv->pipe,
views[i]->texture,
0,
PIPE_TRANSFER_DISCARD_RANGE,
&dst_box_1, &transfer);
if (map == NULL)
return VA_STATUS_ERROR_OPERATION_FAILED;
struct pipe_resource *tex;
u_copy_yv12_img_to_nv12_surf ((ubyte * const*)data, map, width, height,
pitches[i], transfer->stride, i);
pipe_transfer_unmap(drv->pipe, transfer);
} else {
for (j = 0; j < views[i]->texture->array_size; ++j) {
struct pipe_box dst_box = {0, 0, j, width, height, 1};
drv->pipe->texture_subdata(drv->pipe, views[i]->texture, 0,
if (!views[i]) continue;
tex = views[i]->texture;
vlVaVideoSurfaceSize(surf, i, &width, &height);
for (j = 0; j < tex->array_size; ++j) {
struct pipe_box dst_box = {0, 0, j, width, height, 1};
if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV))
&& (surf->buffer->buffer_format == PIPE_FORMAT_NV12)
&& i == 1) {
struct pipe_transfer *transfer = NULL;
uint8_t *map = NULL;
map = drv->pipe->transfer_map(drv->pipe,
tex,
0,
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_DISCARD_RANGE,
&dst_box, &transfer);
if (map == NULL)
return VA_STATUS_ERROR_OPERATION_FAILED;
u_copy_nv12_from_yv12((const void * const*) data, pitches, i, j,
transfer->stride, tex->array_size,
map, dst_box.width, dst_box.height);
pipe_transfer_unmap(drv->pipe, transfer);
} else {
drv->pipe->texture_subdata(drv->pipe, tex, 0,
PIPE_TRANSFER_WRITE, &dst_box,
data[i] + pitches[i] * j,
pitches[i] * views[i]->texture->array_size, 0);