Example #1
0
static int is_vaapi_rgb_format(const VAImageFormat *image_format)
{
    switch (image_format->fourcc) {
    case VA_FOURCC('A','R','G','B'):
    case VA_FOURCC('A','B','G','R'):
    case VA_FOURCC('B','G','R','A'):
    case VA_FOURCC('R','G','B','A'):
        return 1;
    }
    return 0;
}
Example #2
0
static gboolean
vaapi_image_is_linear(const VAImage *va_image)
{
    guint i, width, height, width2, height2, data_size;

    for (i = 1; i < va_image->num_planes; i++)
        if (va_image->offsets[i] < va_image->offsets[i - 1])
            return FALSE;

    width   = va_image->width;
    height  = va_image->height;
    width2  = (width  + 1) / 2;
    height2 = (height + 1) / 2;

    switch (va_image->format.fourcc) {
    case VA_FOURCC('N','V','1','2'):
    case VA_FOURCC('Y','V','1','2'):
    case VA_FOURCC('I','4','2','0'):
        data_size = width * height + 2 * width2 * height2;
        break;
    case VA_FOURCC('A','Y','U','V'):
    case VA_FOURCC('A','R','G','B'):
    case VA_FOURCC('R','G','B','A'):
    case VA_FOURCC('A','B','G','R'):
    case VA_FOURCC('B','G','R','A'):
        data_size = 4 * width * height;
        break;
    default:
        g_error("FIXME: incomplete formats");
        break;
    }
    return va_image->data_size == data_size;
}
Example #3
0
bool V4l2Encoder::acceptInputBuffer(struct v4l2_buffer *qbuf)
{
    int i;
    VideoEncRawBuffer *inputBuffer = &(m_inputFrames[qbuf->index]);
    // XXX todo: add multiple planes support for yami
    inputBuffer->data = reinterpret_cast<uint8_t*>(qbuf->m.planes[0].m.userptr);
    inputBuffer->size = 0;
    for (i=0; i<qbuf->length; i++) {
       inputBuffer->size += qbuf->m.planes[i].bytesused;
    }
    inputBuffer->bufAvailable = false;
    DEBUG("qbuf->index: %d, inputBuffer: %p, bufAvailable: %d", qbuf->index, inputBuffer, inputBuffer->bufAvailable);
    inputBuffer->timeStamp = qbuf->timestamp.tv_sec * 1000000 + qbuf->timestamp.tv_usec; // XXX
    if (m_forceKeyFrame) {
        inputBuffer->forceKeyFrame = true;
        m_forceKeyFrame = false;
    }
    switch(m_pixelFormat[INPUT]) {
    case V4L2_PIX_FMT_YUV420M:
        inputBuffer->fourcc = VA_FOURCC('I', '4', '2', '0');
        break;
    case V4L2_PIX_FMT_YUYV:
        inputBuffer->fourcc = VA_FOURCC_YUY2;
        break;
    default:
        ASSERT(0);
        break;
    }

    return true;
}
static VAStatus
media_surface_native_memory (VADriverContextP ctx,
			     struct object_surface *obj_surface,
			     INT format, INT expected_fourcc)
{
  MEDIA_DRV_CONTEXT *drv_ctx = (MEDIA_DRV_CONTEXT *) ctx->pDriverData;
  MEDIA_DRV_ASSERT (ctx);
  MEDIA_DRV_ASSERT (drv_ctx);
  INT tiling = HAS_TILED_SURFACE (drv_ctx);
  if (!expected_fourcc)
    return VA_STATUS_SUCCESS;

  // todo, should we disable tiling for 422 format?
  if (expected_fourcc == VA_FOURCC ('I', '4', '2', '0') ||
      expected_fourcc == VA_FOURCC ('I', 'Y', 'U', 'V') ||
      expected_fourcc == VA_FOURCC ('Y', 'V', '1', '2')
      || expected_fourcc == VA_FOURCC ('P', '2', '0', '8'))
    tiling = 0;

  media_alloc_surface_bo (ctx, obj_surface, tiling, expected_fourcc,
			  media_get_sampling_from_fourcc (expected_fourcc));

  return VA_STATUS_SUCCESS;
}
Example #5
0
static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
                           int i_width, int i_height )
{
    assert( i_width > 0 && i_height > 0 );

    /* */
    p_va->p_surface = calloc( p_va->i_surface_count, sizeof(*p_va->p_surface) );
    if( !p_va->p_surface )
        return VLC_EGENERIC;
    p_va->image.image_id = VA_INVALID_ID;
    p_va->i_context_id   = VA_INVALID_ID;

    /* Create surfaces */
    VASurfaceID pi_surface_id[p_va->i_surface_count];
    if( vaCreateSurfaces( p_va->p_display, i_width, i_height, VA_RT_FORMAT_YUV420,
                          p_va->i_surface_count, pi_surface_id ) )
    {
        for( int i = 0; i < p_va->i_surface_count; i++ )
            p_va->p_surface[i].i_id = VA_INVALID_SURFACE;
        goto error;
    }

    for( int i = 0; i < p_va->i_surface_count; i++ )
    {
        vlc_va_surface_t *p_surface = &p_va->p_surface[i];

        p_surface->i_id = pi_surface_id[i];
        p_surface->i_refcount = 0;
        p_surface->i_order = 0;
    }

    /* Create a context */
    if( vaCreateContext( p_va->p_display, p_va->i_config_id,
                         i_width, i_height, VA_PROGRESSIVE,
                         pi_surface_id, p_va->i_surface_count, &p_va->i_context_id ) )
    {
        p_va->i_context_id = VA_INVALID_ID;
        goto error;
    }

    /* Find and create a supported image chroma */
    int i_fmt_count = vaMaxNumImageFormats( p_va->p_display );
    VAImageFormat *p_fmt = calloc( i_fmt_count, sizeof(*p_fmt) );
    if( !p_fmt )
        goto error;

    if( vaQueryImageFormats( p_va->p_display, p_fmt, &i_fmt_count ) )
    {
        free( p_fmt );
        goto error;
    }

    VAImage testImage;
    if(vaDeriveImage(p_va->p_display, pi_surface_id[0], &testImage) == VA_STATUS_SUCCESS)
    {
        p_va->b_supports_derive = true;
        vaDestroyImage(p_va->p_display, testImage.image_id);
    }

    vlc_fourcc_t  i_chroma = 0;
    VAImageFormat fmt;
    for( int i = 0; i < i_fmt_count; i++ )
    {
        if( p_fmt[i].fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
            p_fmt[i].fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ||
            p_fmt[i].fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) )
        {
            if( vaCreateImage(  p_va->p_display, &p_fmt[i], i_width, i_height, &p_va->image ) )
            {
                p_va->image.image_id = VA_INVALID_ID;
                continue;
            }
            /* Validate that vaGetImage works with this format */
            if( vaGetImage( p_va->p_display, pi_surface_id[0],
                            0, 0, i_width, i_height,
                            p_va->image.image_id) )
            {
                vaDestroyImage( p_va->p_display, p_va->image.image_id );
                p_va->image.image_id = VA_INVALID_ID;
                continue;
            }

            i_chroma = VLC_CODEC_YV12;
            fmt = p_fmt[i];
            break;
        }
    }
    free( p_fmt );
    if( !i_chroma )
        goto error;
    *pi_chroma = i_chroma;

    if(p_va->b_supports_derive)
    {
        vaDestroyImage( p_va->p_display, p_va->image.image_id );
        p_va->image.image_id = VA_INVALID_ID;
    }

    if( unlikely(CopyInitCache( &p_va->image_cache, i_width )) )
        goto error;

    /* Setup the ffmpeg hardware context */
    *pp_hw_ctx = &p_va->hw_ctx;

    memset( &p_va->hw_ctx, 0, sizeof(p_va->hw_ctx) );
    p_va->hw_ctx.display    = p_va->p_display;
    p_va->hw_ctx.config_id  = p_va->i_config_id;
    p_va->hw_ctx.context_id = p_va->i_context_id;

    /* */
    p_va->i_surface_chroma = i_chroma;
    p_va->i_surface_width = i_width;
    p_va->i_surface_height = i_height;
    return VLC_SUCCESS;

error:
    DestroySurfaces( p_va );
    return VLC_EGENERIC;
}
Example #6
0
VAStatus
vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image)
{
   VAStatus status;
   vlVaDriver *drv;
   VAImage *img;
   int w, h;

   if (!ctx)
      return VA_STATUS_ERROR_INVALID_CONTEXT;

   if (!(format && image && width && height))
      return VA_STATUS_ERROR_INVALID_PARAMETER;

   drv = VL_VA_DRIVER(ctx);

   img = CALLOC(1, sizeof(VAImage));
   if (!img)
      return VA_STATUS_ERROR_ALLOCATION_FAILED;
   pipe_mutex_lock(drv->mutex);
   img->image_id = handle_table_add(drv->htab, img);
   pipe_mutex_unlock(drv->mutex);

   img->format = *format;
   img->width = width;
   img->height = height;
   w = align(width, 2);
   h = align(height, 2);

   switch (format->fourcc) {
   case VA_FOURCC('N','V','1','2'):
      img->num_planes = 2;
      img->pitches[0] = w;
      img->offsets[0] = 0;
      img->pitches[1] = w;
      img->offsets[1] = w * h;
      img->data_size  = w * h * 3 / 2;
      break;

   case VA_FOURCC('I','4','2','0'):
   case VA_FOURCC('Y','V','1','2'):
      img->num_planes = 3;
      img->pitches[0] = w;
      img->offsets[0] = 0;
      img->pitches[1] = w / 2;
      img->offsets[1] = w * h;
      img->pitches[2] = w / 2;
      img->offsets[2] = w * h * 5 / 4;
      img->data_size  = w * h * 3 / 2;
      break;

   case VA_FOURCC('U','Y','V','Y'):
   case VA_FOURCC('Y','U','Y','V'):
      img->num_planes = 1;
      img->pitches[0] = w * 2;
      img->offsets[0] = 0;
      img->data_size  = w * h * 2;
      break;

   case VA_FOURCC('B','G','R','A'):
   case VA_FOURCC('R','G','B','A'):
   case VA_FOURCC('B','G','R','X'):
   case VA_FOURCC('R','G','B','X'):
      img->num_planes = 1;
      img->pitches[0] = w * 4;
      img->offsets[0] = 0;
      img->data_size  = w * h * 4;
      break;

   default:
      return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
   }

   status =  vlVaCreateBuffer(ctx, 0, VAImageBufferType,
                           align(img->data_size, 16),
                           1, NULL, &img->buf);
   if (status != VA_STATUS_SUCCESS)
      return status;
   *image = *img;

   return status;
}
Example #7
0
VAStatus
vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
             int src_x, int src_y, unsigned int src_width, unsigned int src_height,
             int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height)
{
   vlVaDriver *drv;
   vlVaSurface *surf;
   vlVaBuffer *img_buf;
   VAImage *vaimage;
   struct pipe_sampler_view **views;
   enum pipe_format format;
   void *data[3];
   unsigned pitches[3], i, j;

   if (!ctx)
      return VA_STATUS_ERROR_INVALID_CONTEXT;

   drv = VL_VA_DRIVER(ctx);
   pipe_mutex_lock(drv->mutex);

   surf = handle_table_get(drv->htab, surface);
   if (!surf || !surf->buffer) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_SURFACE;
   }

   vaimage = handle_table_get(drv->htab, image);
   if (!vaimage) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_IMAGE;
   }

   img_buf = handle_table_get(drv->htab, vaimage->buf);
   if (!img_buf) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_BUFFER;
   }

   if (img_buf->derived_surface.resource) {
      /* Attempting to transfer derived image to surface */
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_UNIMPLEMENTED;
   }

   format = VaFourccToPipeFormat(vaimage->format.fourcc);

   if (format == PIPE_FORMAT_NONE) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_OPERATION_FAILED;
   }

   if (format != surf->buffer->buffer_format) {
      struct pipe_video_buffer *tmp_buf;
      enum pipe_format old_surf_format = surf->templat.buffer_format;

      surf->templat.buffer_format = format;
      tmp_buf = drv->pipe->create_video_buffer(drv->pipe, &surf->templat);

      if (!tmp_buf) {
         surf->templat.buffer_format = old_surf_format;
         pipe_mutex_unlock(drv->mutex);
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
      }

      surf->buffer->destroy(surf->buffer);
      surf->buffer = tmp_buf;
   }

   views = surf->buffer->get_sampler_view_planes(surf->buffer);
   if (!views) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_OPERATION_FAILED;
   }

   for (i = 0; i < vaimage->num_planes; i++) {
      data[i] = img_buf->data + vaimage->offsets[i];
      pitches[i] = vaimage->pitches[i];
   }
   if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) {
      void *tmp_d;
      unsigned tmp_p;
      tmp_d  = data[1];
      data[1] = data[2];
      data[2] = tmp_d;
      tmp_p = pitches[1];
      pitches[1] = pitches[2];
      pitches[2] = tmp_p;
   }

   for (i = 0; i < vaimage->num_planes; ++i) {
      unsigned width, height;
      if (!views[i]) continue;
      vlVaVideoSurfaceSize(surf, i, &width, &height);
      for (j = 0; j < views[i]->texture->array_size; ++j) {
         struct pipe_box dst_box = {0, 0, j, width, height, 1};
         drv->pipe->transfer_inline_write(drv->pipe, views[i]->texture, 0,
            PIPE_TRANSFER_WRITE, &dst_box,
            data[i] + pitches[i] * j,
            pitches[i] * views[i]->texture->array_size, 0);
      }
   }
   pipe_mutex_unlock(drv->mutex);

   return VA_STATUS_SUCCESS;
}
Example #8
0
VAStatus
vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
             unsigned int width, unsigned int height, VAImageID image)
{
   vlVaDriver *drv;
   vlVaSurface *surf;
   vlVaBuffer *img_buf;
   VAImage *vaimage;
   struct pipe_sampler_view **views;
   enum pipe_format format;
   bool convert = false;
   void *data[3];
   unsigned pitches[3], i, j;

   if (!ctx)
      return VA_STATUS_ERROR_INVALID_CONTEXT;

   drv = VL_VA_DRIVER(ctx);

   pipe_mutex_lock(drv->mutex);
   surf = handle_table_get(drv->htab, surface);
   if (!surf || !surf->buffer) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_SURFACE;
   }

   vaimage = handle_table_get(drv->htab, image);
   if (!vaimage) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_IMAGE;
   }

   img_buf = handle_table_get(drv->htab, vaimage->buf);
   if (!img_buf) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_INVALID_BUFFER;
   }

   format = VaFourccToPipeFormat(vaimage->format.fourcc);
   if (format == PIPE_FORMAT_NONE) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_OPERATION_FAILED;
   }

   if (format != surf->buffer->buffer_format) {
      /* support NV12 to YV12 and IYUV conversion now only */
      if ((format == PIPE_FORMAT_YV12 &&
          surf->buffer->buffer_format == PIPE_FORMAT_NV12) ||
          (format == PIPE_FORMAT_IYUV &&
          surf->buffer->buffer_format == PIPE_FORMAT_NV12))
         convert = true;
      else {
         pipe_mutex_unlock(drv->mutex);
         return VA_STATUS_ERROR_OPERATION_FAILED;
      }
   }

   views = surf->buffer->get_sampler_view_planes(surf->buffer);
   if (!views) {
      pipe_mutex_unlock(drv->mutex);
      return VA_STATUS_ERROR_OPERATION_FAILED;
   }

   for (i = 0; i < vaimage->num_planes; i++) {
      data[i] = img_buf->data + vaimage->offsets[i];
      pitches[i] = vaimage->pitches[i];
   }
   if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) {
      void *tmp_d;
      unsigned tmp_p;
      tmp_d  = data[1];
      data[1] = data[2];
      data[2] = tmp_d;
      tmp_p = pitches[1];
      pitches[1] = pitches[2];
      pitches[2] = tmp_p;
   }

   for (i = 0; i < vaimage->num_planes; i++) {
      unsigned width, height;
      if (!views[i]) continue;
      vlVaVideoSurfaceSize(surf, i, &width, &height);
      for (j = 0; j < views[i]->texture->array_size; ++j) {
         struct pipe_box box = {0, 0, j, width, height, 1};
         struct pipe_transfer *transfer;
         uint8_t *map;
         map = drv->pipe->transfer_map(drv->pipe, views[i]->texture, 0,
                  PIPE_TRANSFER_READ, &box, &transfer);
         if (!map) {
            pipe_mutex_unlock(drv->mutex);
            return VA_STATUS_ERROR_OPERATION_FAILED;
         }

         if (i == 1 && convert) {
            u_copy_nv12_to_yv12(data, pitches, i, j,
               transfer->stride, views[i]->texture->array_size,
               map, box.width, box.height);
         } else {
            util_copy_rect(data[i] + pitches[i] * j,
               views[i]->texture->format,
               pitches[i] * views[i]->texture->array_size, 0, 0,
               box.width, box.height, map, transfer->stride, 0, 0);
         }
         pipe_transfer_unmap(drv->pipe, transfer);
      }
   }
   pipe_mutex_unlock(drv->mutex);

   return VA_STATUS_SUCCESS;
}
Example #9
0
VAStatus
vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
{
   vlVaDriver *drv;
   vlVaSurface *surf;
   vlVaBuffer *img_buf;
   VAImage *img;
   struct pipe_surface **surfaces;
   int w;
   int h;
   int i;

   if (!ctx)
      return VA_STATUS_ERROR_INVALID_CONTEXT;

   drv = VL_VA_DRIVER(ctx);

   if (!drv)
      return VA_STATUS_ERROR_INVALID_CONTEXT;

   surf = handle_table_get(drv->htab, surface);

   if (!surf || !surf->buffer || surf->buffer->interlaced)
      return VA_STATUS_ERROR_INVALID_SURFACE;

   surfaces = surf->buffer->get_surfaces(surf->buffer);
   if (!surfaces || !surfaces[0]->texture)
      return VA_STATUS_ERROR_ALLOCATION_FAILED;

   img = CALLOC(1, sizeof(VAImage));
   if (!img)
      return VA_STATUS_ERROR_ALLOCATION_FAILED;

   img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format);
   img->buf = VA_INVALID_ID;
   img->width = surf->buffer->width;
   img->height = surf->buffer->height;
   img->num_palette_entries = 0;
   img->entry_bytes = 0;
   w = align(surf->buffer->width, 2);
   h = align(surf->buffer->height, 2);

   for (i = 0; i < ARRAY_SIZE(formats); ++i) {
      if (img->format.fourcc == formats[i].fourcc) {
         img->format = formats[i];
         break;
      }
   }

   switch (img->format.fourcc) {
   case VA_FOURCC('U','Y','V','Y'):
   case VA_FOURCC('Y','U','Y','V'):
      img->num_planes = 1;
      img->pitches[0] = w * 2;
      img->offsets[0] = 0;
      img->data_size  = w * h * 2;
      break;

   case VA_FOURCC('B','G','R','A'):
   case VA_FOURCC('R','G','B','A'):
   case VA_FOURCC('B','G','R','X'):
   case VA_FOURCC('R','G','B','X'):
      img->num_planes = 1;
      img->pitches[0] = w * 4;
      img->offsets[0] = 0;
      img->data_size  = w * h * 4;
      break;

   default:
      /* VaDeriveImage is designed for contiguous planes. */
      FREE(img);
      return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
   }

   img_buf = CALLOC(1, sizeof(vlVaBuffer));
   if (!img_buf) {
      FREE(img);
      return VA_STATUS_ERROR_ALLOCATION_FAILED;
   }

   pipe_mutex_lock(drv->mutex);
   img->image_id = handle_table_add(drv->htab, img);

   img_buf->type = VAImageBufferType;
   img_buf->size = img->data_size;
   img_buf->num_elements = 1;

   pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture);

   img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf);
   pipe_mutex_unlock(drv->mutex);

   *image = *img;

   return VA_STATUS_SUCCESS;
}
Example #10
0
#include "pipe/p_screen.h"

#include "util/u_memory.h"
#include "util/u_handle_table.h"
#include "util/u_surface.h"
#include "util/u_video.h"

#include "vl/vl_winsys.h"
#include "vl/vl_video_buffer.h"

#include "va_private.h"

static const VAImageFormat formats[] =
{
   {VA_FOURCC('N','V','1','2')},
   {VA_FOURCC('I','4','2','0')},
   {VA_FOURCC('Y','V','1','2')},
   {VA_FOURCC('Y','U','Y','V')},
   {VA_FOURCC('U','Y','V','Y')},
   {.fourcc = VA_FOURCC('B','G','R','A'), .byte_order = VA_LSB_FIRST, 32, 32,
    0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000},
   {.fourcc = VA_FOURCC('R','G','B','A'), .byte_order = VA_LSB_FIRST, 32, 32,
    0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000},
   {.fourcc = VA_FOURCC('B','G','R','X'), .byte_order = VA_LSB_FIRST, 32, 24,
    0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
   {.fourcc = VA_FOURCC('R','G','B','X'), .byte_order = VA_LSB_FIRST, 32, 24,
    0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}
};

static void
static VAStatus
media_suface_external_memory (VADriverContextP ctx,
			      struct object_surface *obj_surface,
			      INT external_memory_type,
			      VASurfaceAttribExternalBuffers *
			      memory_attibute, INT index)
{
  MEDIA_DRV_CONTEXT *drv_ctx = (MEDIA_DRV_CONTEXT *) ctx->pDriverData;
  MEDIA_DRV_ASSERT (ctx);
  MEDIA_DRV_ASSERT (drv_ctx);


  if (!memory_attibute ||
      !memory_attibute->buffers || index > memory_attibute->num_buffers)
    return VA_STATUS_ERROR_INVALID_PARAMETER;

  MEDIA_DRV_ASSERT (obj_surface->orig_width == memory_attibute->width);
  MEDIA_DRV_ASSERT (obj_surface->orig_height == memory_attibute->height);
  MEDIA_DRV_ASSERT (memory_attibute->num_planes >= 1);

  obj_surface->fourcc = memory_attibute->pixel_format;
  obj_surface->width = memory_attibute->pitches[0];
  obj_surface->size = memory_attibute->data_size;

  if (memory_attibute->num_planes == 1)
    obj_surface->height = memory_attibute->data_size / obj_surface->width;
  else
    obj_surface->height = memory_attibute->offsets[1] / obj_surface->width;

  obj_surface->x_cb_offset = 0;	/* X offset is always 0 */
  obj_surface->x_cr_offset = 0;

  switch (obj_surface->fourcc)
    {
    case VA_FOURCC ('N', 'V', '1', '2'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 2);
      MEDIA_DRV_ASSERT (memory_attibute->pitches[0] ==
			memory_attibute->pitches[1]);

      obj_surface->subsampling = SUBSAMPLE_YUV420;
      obj_surface->y_cb_offset = obj_surface->height;
      obj_surface->y_cr_offset = obj_surface->height;
      obj_surface->cb_cr_width = obj_surface->orig_width / 2;
      obj_surface->cb_cr_height = obj_surface->orig_height / 2;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[1];

      break;

    case VA_FOURCC ('Y', 'V', '1', '2'):
    case VA_FOURCC ('I', 'M', 'C', '1'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 3);
      MEDIA_DRV_ASSERT (memory_attibute->pitches[1] ==
			memory_attibute->pitches[2]);

      obj_surface->subsampling = SUBSAMPLE_YUV420;
      obj_surface->y_cr_offset = obj_surface->height;
      obj_surface->y_cb_offset =
	memory_attibute->offsets[2] / obj_surface->width;
      obj_surface->cb_cr_width = obj_surface->orig_width / 2;
      obj_surface->cb_cr_height = obj_surface->orig_height / 2;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[1];

      break;

    case VA_FOURCC ('I', '4', '2', '0'):
    case VA_FOURCC ('I', 'Y', 'U', 'V'):
    case VA_FOURCC ('I', 'M', 'C', '3'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 3);
      MEDIA_DRV_ASSERT (memory_attibute->pitches[1] ==
			memory_attibute->pitches[2]);

      obj_surface->subsampling = SUBSAMPLE_YUV420;
      obj_surface->y_cb_offset = obj_surface->height;
      obj_surface->y_cr_offset =
	memory_attibute->offsets[2] / obj_surface->width;
      obj_surface->cb_cr_width = obj_surface->orig_width / 2;
      obj_surface->cb_cr_height = obj_surface->orig_height / 2;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[1];

      break;

    case VA_FOURCC ('Y', 'U', 'Y', '2'):
    case VA_FOURCC ('U', 'Y', 'V', 'Y'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 1);

      obj_surface->subsampling = SUBSAMPLE_YUV422H;
      obj_surface->y_cb_offset = 0;
      obj_surface->y_cr_offset = 0;
      obj_surface->cb_cr_width = obj_surface->orig_width / 2;
      obj_surface->cb_cr_height = obj_surface->orig_height;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[0];

      break;

    case VA_FOURCC ('R', 'G', 'B', 'A'):
    case VA_FOURCC ('R', 'G', 'B', 'X'):
    case VA_FOURCC ('B', 'G', 'R', 'A'):
    case VA_FOURCC ('B', 'G', 'R', 'X'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 1);

      obj_surface->subsampling = SUBSAMPLE_RGBX;
      obj_surface->y_cb_offset = 0;
      obj_surface->y_cr_offset = 0;
      obj_surface->cb_cr_width = 0;
      obj_surface->cb_cr_height = 0;
      obj_surface->cb_cr_pitch = 0;

      break;

    case VA_FOURCC ('Y', '8', '0', '0'):	/* monochrome surface */
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 1);

      obj_surface->subsampling = SUBSAMPLE_YUV400;
      obj_surface->y_cb_offset = 0;
      obj_surface->y_cr_offset = 0;
      obj_surface->cb_cr_width = 0;
      obj_surface->cb_cr_height = 0;
      obj_surface->cb_cr_pitch = 0;

      break;

    case VA_FOURCC ('4', '1', '1', 'P'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 3);
      MEDIA_DRV_ASSERT (memory_attibute->pitches[1] ==
			memory_attibute->pitches[2]);

      obj_surface->subsampling = SUBSAMPLE_YUV411;
      obj_surface->y_cb_offset = 0;
      obj_surface->y_cr_offset = 0;
      obj_surface->cb_cr_width = obj_surface->orig_width / 4;
      obj_surface->cb_cr_height = obj_surface->orig_height;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[1];

      break;

    case VA_FOURCC ('4', '2', '2', 'H'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 3);
      MEDIA_DRV_ASSERT (memory_attibute->pitches[1] ==
			memory_attibute->pitches[2]);

      obj_surface->subsampling = SUBSAMPLE_YUV422H;
      obj_surface->y_cb_offset = obj_surface->height;
      obj_surface->y_cr_offset =
	memory_attibute->offsets[2] / obj_surface->width;
      obj_surface->cb_cr_width = obj_surface->orig_width / 2;
      obj_surface->cb_cr_height = obj_surface->orig_height;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[1];

      break;

    case VA_FOURCC ('4', '2', '2', 'V'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 3);
      MEDIA_DRV_ASSERT (memory_attibute->pitches[1] ==
			memory_attibute->pitches[2]);

      obj_surface->subsampling = SUBSAMPLE_YUV422H;
      obj_surface->y_cb_offset = obj_surface->height;
      obj_surface->y_cr_offset =
	memory_attibute->offsets[2] / obj_surface->width;
      obj_surface->cb_cr_width = obj_surface->orig_width;
      obj_surface->cb_cr_height = obj_surface->orig_height / 2;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[1];

      break;

    case VA_FOURCC ('4', '4', '4', 'P'):
      MEDIA_DRV_ASSERT (memory_attibute->num_planes == 3);
      MEDIA_DRV_ASSERT (memory_attibute->pitches[1] ==
			memory_attibute->pitches[2]);

      obj_surface->subsampling = SUBSAMPLE_YUV444;
      obj_surface->y_cb_offset = obj_surface->height;
      obj_surface->y_cr_offset =
	memory_attibute->offsets[2] / obj_surface->width;
      obj_surface->cb_cr_width = obj_surface->orig_width;
      obj_surface->cb_cr_height = obj_surface->orig_height;
      obj_surface->cb_cr_pitch = memory_attibute->pitches[1];

      break;

    default:

      return VA_STATUS_ERROR_INVALID_PARAMETER;
    }

  if (external_memory_type == I965_SURFACE_MEM_GEM_FLINK)
    obj_surface->bo =
      drm_intel_bo_gem_create_from_name (drv_ctx->drv_data.bufmgr,
					 "gem flinked vaapi surface",
					 memory_attibute->buffers[index]);
  else if (external_memory_type == I965_SURFACE_MEM_DRM_PRIME)
    obj_surface->bo =
      drm_intel_bo_gem_create_from_prime (drv_ctx->drv_data.bufmgr,
					  memory_attibute->buffers[index],
					  obj_surface->size);

  if (!obj_surface->bo)
    return VA_STATUS_ERROR_INVALID_PARAMETER;

  return VA_STATUS_SUCCESS;
}
Example #12
0
        context_id = vaapi->context_id;
        surface_id = vaapi->surface_id;
    }

    vaapi->config_id      = config_id;
    vaapi->context_id     = context_id;
    vaapi->surface_id     = surface_id;
    vaapi->profile        = profile;
    vaapi->entrypoint     = entrypoint;
    vaapi->picture_width  = picture_width;
    vaapi->picture_height = picture_height;
    return 0;
}

static const uint32_t image_formats[] = {
    VA_FOURCC('Y','V','1','2'),
    VA_FOURCC('N','V','1','2'),
    VA_FOURCC('U','Y','V','Y'),
    VA_FOURCC('Y','U','Y','V'),
    VA_FOURCC('A','R','G','B'),
    VA_FOURCC('A','B','G','R'),
    VA_FOURCC('B','G','R','A'),
    VA_FOURCC('R','G','B','A'),
    0
};

static int
get_image_format(
    VAAPIContext   *vaapi,
    uint32_t        fourcc,
    VAImageFormat **image_format
Example #13
0
int main(int argc, char** argv)
{
    int32_t fd = -1;
    uint32_t i = 0;
    int32_t ioctlRet = -1;

    // parse command line parameters
    if (!process_cmdline(argc, argv))
        return -1;

#if ANDROID
    if (!inputFileName) {
        inputMemoryType = (enum v4l2_memory)V4L2_MEMORY_ANDROID_BUFFER_HANDLE;
        inputFourcc = VA_FOURCC_NV12;
    }
#endif
    streamInput = EncodeInput::create(inputFileName, inputFourcc, videoWidth, videoHeight);
    ASSERT(streamInput);

    // open device
    fd = YamiV4L2_Open("encoder", 0);
    ASSERT(fd!=-1);

    // query hw capability
    struct v4l2_capability caps;
    memset(&caps, 0, sizeof(caps));
    caps.capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_QUERYCAP, &caps);
    ASSERT(ioctlRet != -1);

    // set input/output data format
    struct v4l2_format format;
    memset(&format, 0, sizeof(format));
    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_S_FMT, &format);
    ASSERT(ioctlRet != -1);

    memset(&format, 0, sizeof(format));
    format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    DEBUG_FOURCC("inputFourcc", inputFourcc);
    switch (inputFourcc) {
    case VA_FOURCC_YV12:
    case VA_FOURCC('I', '4', '2', '0'):
        format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
        inputFramePlaneCount = 3;
        inputFrameSize = videoWidth*videoHeight*3/2;
        break;
    case VA_FOURCC_NV12:
        format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
        inputFramePlaneCount = 2;
        inputFrameSize = videoWidth*videoHeight*3/2;
        break;
    case VA_FOURCC_YUY2:
        format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUYV;
        inputFramePlaneCount = 1;
        inputFrameSize = videoWidth*videoHeight*2;
        break;
    default:
        ASSERT(0);
        break;
    }
    format.fmt.pix_mp.width = videoWidth;
    format.fmt.pix_mp.height = videoHeight;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_S_FMT, &format);
    ASSERT(ioctlRet != -1);

    // set input buffer type
    {
    VideoDataMemoryType memoryType = VIDEO_DATA_MEMORY_TYPE_RAW_POINTER;
#if ANDROID
    if (inputMemoryType == V4L2_MEMORY_ANDROID_BUFFER_HANDLE)
        memoryType = VIDEO_DATA_MEMORY_TYPE_ANDROID_BUFFER_HANDLE;
#endif
    YamiV4L2_FrameMemoryType(fd, memoryType);
    }

    // set framerate
    struct v4l2_streamparm parms;
    memset(&parms, 0, sizeof(parms));
    parms.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    parms.parm.output.timeperframe.denominator = 1;
    parms.parm.output.timeperframe.numerator = fps;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_S_PARM, &parms);
    ASSERT(ioctlRet != -1);

    // set bitrate
    struct v4l2_ext_control ctrls[1];
    struct v4l2_ext_controls control;
    memset(&ctrls, 0, sizeof(ctrls));
    memset(&control, 0, sizeof(control));
    ctrls[0].id = V4L2_CID_MPEG_VIDEO_BITRATE;
    ctrls[0].value = bitRate;
    control.ctrl_class = V4L2_CTRL_CLASS_MPEG;
    control.count = 1;
    control.controls = ctrls;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_S_EXT_CTRLS, &control);
    ASSERT(ioctlRet != -1);

    // other controls
    memset(&ctrls, 0, sizeof(ctrls));
    memset(&control, 0, sizeof(control));
    // No B-frames, for lowest decoding latency.
    ctrls[0].id = V4L2_CID_MPEG_VIDEO_B_FRAMES;
    ctrls[0].value = 0;
    control.ctrl_class = V4L2_CTRL_CLASS_MPEG;
    control.count = 1;
    control.controls = ctrls;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_S_EXT_CTRLS, &control);
    ASSERT(ioctlRet != -1);

    // start
    __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_STREAMON, &type);
    ASSERT(ioctlRet != -1);
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_STREAMON, &type);
    ASSERT(ioctlRet != -1);

    // setup input buffers
    struct v4l2_requestbuffers reqbufs;
    memset(&reqbufs, 0, sizeof(reqbufs));
    reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    reqbufs.memory = inputMemoryType;
    reqbufs.count = 2;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
    ASSERT(ioctlRet != -1);
    ASSERT(reqbufs.count>0 && reqbufs.count <= kMaxFrameQueueLength);
    inputQueueCapacity = reqbufs.count;

    if (inputMemoryType == V4L2_MEMORY_USERPTR)
    {
        for (i = 0; i < inputQueueCapacity; i++) {
            inputFrames[i].handle = reinterpret_cast<intptr_t>(malloc(inputFrameSize));
        }
        for (i = inputQueueCapacity; i < kMaxFrameQueueLength; i++)
            inputFrames[i].handle = 0;
    }

    // setup output buffers
    memset(&reqbufs, 0, sizeof(reqbufs));
    reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    reqbufs.memory = outputMemoryType;
    reqbufs.count = 2;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
    ASSERT(ioctlRet != -1);
    ASSERT(reqbufs.count>0 && reqbufs.count <= kMaxFrameQueueLength);
    outputQueueCapacity = reqbufs.count;

    for (i=0; i<outputQueueCapacity; i++) {
        struct v4l2_plane planes[1];
        struct v4l2_buffer buffer;
        memset(&buffer, 0, sizeof(buffer));
        memset(planes, 0, sizeof(planes));
        buffer.index = i;
        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
        buffer.memory = outputMemoryType;
        buffer.m.planes = planes;
        buffer.length = 1;
        ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_QUERYBUF, &buffer);
        ASSERT(ioctlRet != -1);
        void* address = YamiV4L2_Mmap(NULL,
                                      buffer.m.planes[0].length,
                                      PROT_READ | PROT_WRITE,
                                      MAP_SHARED, fd,
                                      buffer.m.planes[0].m.mem_offset);
        ASSERT(address);
        outputFrames[i] = static_cast<uint8_t*>(address);
        // ignore lenght here
    }
    for (i=outputQueueCapacity; i<kMaxFrameQueueLength; i++) {
        outputFrames[i] = NULL;
    }

    // feed input/output frames first
    for (i=0; i<inputQueueCapacity; i++) {
        if (!feedOneInputFrame(fd, i)) {
            ASSERT(0);
        }
    }

    for (i=0; i<outputQueueCapacity; i++) {
        if (!takeOneOutputFrame(fd, i)) {
            ASSERT(0);
        }
    }

    bool event_pending=true;
    do {
        takeOneOutputFrame(fd);
        feedOneInputFrame(fd);
        if (isReadEOS)
            break;
    } while (YamiV4L2_Poll(fd, true, &event_pending) == 0);

    // drain input buffer
    ASSERT(isReadEOS);
    while (!isEncodeEOS) {
        takeOneOutputFrame(fd);
        feedOneInputFrame(fd);
        usleep(10000);
    }

    // drain output buffer
    // stop input port to indicate EOS
    type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_STREAMOFF, &type);
    ASSERT(ioctlRet != -1);
    ASSERT(isEncodeEOS);
    while (!isOutputEOS) {
        usleep(10000);
        takeOneOutputFrame(fd);
    }

    ASSERT(isOutputEOS);
    // YamiV4L2_Munmap(void* addr, size_t length)

    // release queued input/output buffer
    memset(&reqbufs, 0, sizeof(reqbufs));
    reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
    reqbufs.memory = inputMemoryType;
    reqbufs.count = 0;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
    ASSERT(ioctlRet != -1);

    memset(&reqbufs, 0, sizeof(reqbufs));
    reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    reqbufs.memory = outputMemoryType;
    reqbufs.count = 0;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
    ASSERT(ioctlRet != -1);

    // stop output prot
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    ioctlRet = YamiV4L2_Ioctl(fd, VIDIOC_STREAMOFF, &type);
    ASSERT(ioctlRet != -1);

    // close device
    ioctlRet = YamiV4L2_Close(fd);
    ASSERT(ioctlRet != -1);

    fprintf(stderr, "encode done\n");
}
VdpStatus
vdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, VdpYCbCrFormat destination_ycbcr_format,
                            void *const *destination_data, uint32_t const *destination_pitches)
{
    VdpStatus err_code;
    if (!destination_data || !destination_pitches)
        return VDP_STATUS_INVALID_POINTER;
    VdpVideoSurfaceData *srcSurfData = handle_acquire(surface, HANDLETYPE_VIDEO_SURFACE);
    if (NULL == srcSurfData)
        return VDP_STATUS_INVALID_HANDLE;
    VdpDeviceData *deviceData = srcSurfData->deviceData;
    VADisplay va_dpy = deviceData->va_dpy;

    if (deviceData->va_available) {
        VAImage q;
        vaDeriveImage(va_dpy, srcSurfData->va_surf, &q);
        if (VA_FOURCC('N', 'V', '1', '2') == q.format.fourcc &&
            VDP_YCBCR_FORMAT_NV12 == destination_ycbcr_format)
        {
            uint8_t *img_data;
            vaMapBuffer(va_dpy, q.buf, (void **)&img_data);
            if (destination_pitches[0] == q.pitches[0] &&
                destination_pitches[1] == q.pitches[1])
            {
                const uint32_t sz = (uint32_t)q.width * (uint32_t)q.height;
                memcpy(destination_data[0], img_data + q.offsets[0], sz);
                memcpy(destination_data[1], img_data + q.offsets[1], sz / 2);
            } else {
                uint8_t *src = img_data + q.offsets[0];
                uint8_t *dst = destination_data[0];
                for (unsigned int y = 0; y < q.height; y ++) {  // Y plane
                    memcpy (dst, src, q.width);
                    src += q.pitches[0];
                    dst += destination_pitches[0];
                }
                src = img_data + q.offsets[1];
                dst = destination_data[1];
                for (unsigned int y = 0; y < q.height / 2; y ++) {  // UV plane
                    memcpy(dst, src, q.width);  // q.width/2 samples of U and V each, hence q.width
                    src += q.pitches[1];
                    dst += destination_pitches[1];
                }
            }
            vaUnmapBuffer(va_dpy, q.buf);
        } else if (VA_FOURCC('N', 'V', '1', '2') == q.format.fourcc &&
                   VDP_YCBCR_FORMAT_YV12 == destination_ycbcr_format)
        {
            uint8_t *img_data;
            vaMapBuffer(va_dpy, q.buf, (void **)&img_data);

            // Y plane
            if (destination_pitches[0] == q.pitches[0]) {
                const uint32_t sz = (uint32_t)q.width * (uint32_t)q.height;
                memcpy(destination_data[0], img_data + q.offsets[0], sz);
            } else {
                uint8_t *src = img_data + q.offsets[0];
                uint8_t *dst = destination_data[0];
                for (unsigned int y = 0; y < q.height; y ++) {
                    memcpy (dst, src, q.width);
                    src += q.pitches[0];
                    dst += destination_pitches[0];
                }
            }

            // unpack mixed UV to separate planes
            for (unsigned int y = 0; y < q.height/2; y ++) {
                uint8_t *src = img_data + q.offsets[1] + y * q.pitches[1];
                uint8_t *dst_u = destination_data[1] + y * destination_pitches[1];
                uint8_t *dst_v = destination_data[2] + y * destination_pitches[2];

                for (unsigned int x = 0; x < q.width/2; x++) {
                    *dst_v++ = *src++;
                    *dst_u++ = *src++;
                }
            }

            vaUnmapBuffer(va_dpy, q.buf);
        } else {
            const char *c = (const char *)&q.format.fourcc;
            traceError("error (%s): not implemented conversion VA FOURCC %c%c%c%c -> %s\n",
                       __func__, *c, *(c+1), *(c+2), *(c+3),
                       reverse_ycbcr_format(destination_ycbcr_format));
            vaDestroyImage(va_dpy, q.image_id);
            err_code = VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
            goto quit;
        }
        vaDestroyImage(va_dpy, q.image_id);
    } else {
        // software fallback
        traceError("error (%s): not implemented software fallback\n", __func__);
        err_code = VDP_STATUS_ERROR;
        goto quit;
    }

    GLenum gl_error = glGetError();
    if (GL_NO_ERROR != gl_error) {
        traceError("error (%s): gl error %d\n", __func__, gl_error);
        err_code = VDP_STATUS_ERROR;
        goto quit;
    }

    err_code = VDP_STATUS_OK;
quit:
    handle_release(surface);
    return err_code;
}
Example #15
0
static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
{
    vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);

    VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3];

#if VA_CHECK_VERSION(0,31,0)
    if( vaSyncSurface( p_va->p_display, i_surface_id ) )
#else
    if( vaSyncSurface( p_va->p_display, p_va->i_context_id, i_surface_id ) )
#endif
        return VLC_EGENERIC;

    if(p_va->b_supports_derive)
    {
        if(vaDeriveImage(p_va->p_display, i_surface_id, &(p_va->image)) != VA_STATUS_SUCCESS)
            return VLC_EGENERIC;
    }
    else
    {
        if( vaGetImage( p_va->p_display, i_surface_id,
                        0, 0, p_va->i_surface_width, p_va->i_surface_height,
                        p_va->image.image_id) )
            return VLC_EGENERIC;
    }

    void *p_base;
    if( vaMapBuffer( p_va->p_display, p_va->image.buf, &p_base ) )
        return VLC_EGENERIC;

    const uint32_t i_fourcc = p_va->image.format.fourcc;
    if( i_fourcc == VA_FOURCC('Y','V','1','2') ||
        i_fourcc == VA_FOURCC('I','4','2','0') )
    {
        bool b_swap_uv = i_fourcc == VA_FOURCC('I','4','2','0');
        uint8_t *pp_plane[3];
        size_t  pi_pitch[3];

        for( int i = 0; i < 3; i++ )
        {
            const int i_src_plane = (b_swap_uv && i != 0) ?  (3 - i) : i;
            pp_plane[i] = (uint8_t*)p_base + p_va->image.offsets[i_src_plane];
            pi_pitch[i] = p_va->image.pitches[i_src_plane];
        }
        CopyFromYv12( p_picture, pp_plane, pi_pitch,
                      p_va->i_surface_width,
                      p_va->i_surface_height,
                      &p_va->image_cache );
    }
    else
    {
        assert( i_fourcc == VA_FOURCC('N','V','1','2') );
        uint8_t *pp_plane[2];
        size_t  pi_pitch[2];

        for( int i = 0; i < 2; i++ )
        {
            pp_plane[i] = (uint8_t*)p_base + p_va->image.offsets[i];
            pi_pitch[i] = p_va->image.pitches[i];
        }
        CopyFromNv12( p_picture, pp_plane, pi_pitch,
                      p_va->i_surface_width,
                      p_va->i_surface_height,
                      &p_va->image_cache );
    }

    if( vaUnmapBuffer( p_va->p_display, p_va->image.buf ) )
        return VLC_EGENERIC;

    if(p_va->b_supports_derive)
    {
        vaDestroyImage( p_va->p_display, p_va->image.image_id );
        p_va->image.image_id = VA_INVALID_ID;
    }

    return VLC_SUCCESS;
}
void hsw_veb_iecp_csc_table(VADriverContextP ctx, struct intel_vebox_context *proc_ctx)
{
    unsigned int *p_table = (unsigned int*)(proc_ctx->iecp_state_table.ptr + 220);
    float tran_coef[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
    float v_coef[3]    = {0.0, 0.0, 0.0};
    float u_coef[3]    = {0.0, 0.0, 0.0};
    int   is_transform_enabled = 0;

    if(!(proc_ctx->filters_mask & VPP_IECP_CSC)){
        memset(p_table, 0, 8 * 4);
        return;
    }
    /*
    VAProcColorStandardType   in_color_std  = proc_ctx->pipeline_param->surface_color_standard;
    VAProcColorStandardType   out_color_std = proc_ctx->pipeline_param->output_color_standard;
    assert(in_color_std == out_color_std);  
    */
    if(proc_ctx->fourcc_input == VA_FOURCC('R','G','B','A') &&
       (proc_ctx->fourcc_output == VA_FOURCC('N','V','1','2') ||
        proc_ctx->fourcc_output == VA_FOURCC('Y','V','1','2') ||
        proc_ctx->fourcc_output == VA_FOURCC('Y','V','Y','2') ||
        proc_ctx->fourcc_output == VA_FOURCC('A','Y','U','V'))) {

         tran_coef[0] = 0.257;
         tran_coef[1] = 0.504;
         tran_coef[2] = 0.098;
         tran_coef[3] = -0.148;
         tran_coef[4] = -0.291;
         tran_coef[5] = 0.439;
         tran_coef[6] = 0.439;
         tran_coef[7] = -0.368;
         tran_coef[8] = -0.071; 

         u_coef[0] = 16 * 4;
         u_coef[1] = 128 * 4;
         u_coef[2] = 128 * 4;
 
         is_transform_enabled = 1; 
    }else if((proc_ctx->fourcc_input  == VA_FOURCC('N','V','1','2') || 
              proc_ctx->fourcc_input  == VA_FOURCC('Y','V','1','2') || 
              proc_ctx->fourcc_input  == VA_FOURCC('Y','U','Y','2') ||
              proc_ctx->fourcc_input  == VA_FOURCC('A','Y','U','V'))&&
              proc_ctx->fourcc_output == VA_FOURCC('R','G','B','A')) {

         tran_coef[0] = 1.164;
         tran_coef[1] = 0.000;
         tran_coef[2] = 1.569;
         tran_coef[3] = 1.164;
         tran_coef[4] = -0.813;
         tran_coef[5] = -0.392;
         tran_coef[6] = 1.164;
         tran_coef[7] = 2.017;
         tran_coef[8] = 0.000; 

         v_coef[0] = -16 * 4;
         v_coef[1] = -128 * 4;
         v_coef[2] = -128 * 4;

        is_transform_enabled = 1; 
    }else if(proc_ctx->fourcc_input != proc_ctx->fourcc_output){
         //enable when input and output format are different.
         is_transform_enabled = 1;
    }

    if(is_transform_enabled == 0){
        memset(p_table, 0, 8 * 4);
    }else{
        *p_table ++ = ( 0 << 29 | //reserved
                        format_convert(tran_coef[1], 2, 10, 1) << 16 | //c1, s2.10 format
                        format_convert(tran_coef[0], 2, 10, 1) << 3 |  //c0, s2.10 format
                        0 << 2 | //reserved
                        0 << 1 | // yuv_channel swap
                        is_transform_enabled);                

        *p_table ++ = ( 0 << 26 | //reserved
                        format_convert(tran_coef[3], 2, 10, 1) << 13 | 
                        format_convert(tran_coef[2], 2, 10, 1));
    
        *p_table ++ = ( 0 << 26 | //reserved
                        format_convert(tran_coef[5], 2, 10, 1) << 13 | 
                        format_convert(tran_coef[4], 2, 10, 1));

        *p_table ++ = ( 0 << 26 | //reserved
                        format_convert(tran_coef[7], 2, 10, 1) << 13 | 
                        format_convert(tran_coef[6], 2, 10, 1));

        *p_table ++ = ( 0 << 13 | //reserved
                        format_convert(tran_coef[8], 2, 10, 1));

        *p_table ++ = ( 0 << 22 | //reserved
                        format_convert(u_coef[0], 10, 0, 1) << 11 | 
                        format_convert(v_coef[0], 10, 0, 1));

        *p_table ++ = ( 0 << 22 | //reserved
                        format_convert(u_coef[1], 10, 0, 1) << 11 | 
                        format_convert(v_coef[1], 10, 0, 1));

        *p_table ++ = ( 0 << 22 | //reserved
                        format_convert(u_coef[2], 10, 0, 1) << 11 | 
                        format_convert(v_coef[2], 10, 0, 1));
    }
}
VOID
media_alloc_surface_bo (VADriverContextP ctx,
			struct object_surface * obj_surface,
			INT tiled, UINT fourcc, UINT subsampling)
{
  INT region_width, region_height;
  MEDIA_DRV_CONTEXT *drv_ctx = (MEDIA_DRV_CONTEXT *) ctx->pDriverData;
  MEDIA_DRV_ASSERT (ctx);
  MEDIA_DRV_ASSERT (drv_ctx);
  if (obj_surface->bo)
    {
      MEDIA_DRV_ASSERT (obj_surface->fourcc);
      MEDIA_DRV_ASSERT (obj_surface->fourcc == fourcc);
      MEDIA_DRV_ASSERT (obj_surface->subsampling == subsampling);
      return;
    }
  obj_surface->x_cb_offset = 0;	/* X offset is always 0 */
  obj_surface->x_cr_offset = 0;
  if (tiled)
    {
      MEDIA_DRV_ASSERT (fourcc != VA_FOURCC ('I', '4', '2', '0') &&
			fourcc != VA_FOURCC ('I', 'Y', 'U', 'V') &&
			fourcc != VA_FOURCC ('Y', 'V', '1', '2'));

      obj_surface->width = ALIGN (obj_surface->orig_width, 128);
      obj_surface->height = ALIGN (obj_surface->orig_height, 32);
      region_height = obj_surface->height;
      switch (fourcc)
	{
	case VA_FOURCC ('N', 'V', '1', '2'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV420);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height / 2;
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset = obj_surface->height;
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32);

	  break;

	case VA_FOURCC ('I', 'M', 'C', '1'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV420);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height / 2;
	  obj_surface->y_cr_offset = obj_surface->height;
	  obj_surface->y_cb_offset =
	    obj_surface->y_cr_offset + ALIGN (obj_surface->cb_cr_height, 32);
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32) * 2;

	  break;

	case VA_FOURCC ('I', 'M', 'C', '3'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV420);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height / 2;
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset =
	    obj_surface->y_cb_offset + ALIGN (obj_surface->cb_cr_height, 32);
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32) * 2;

	  break;

	case VA_FOURCC ('4', '2', '2', 'H'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV422H);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height;
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset =
	    obj_surface->y_cb_offset + ALIGN (obj_surface->cb_cr_height, 32);
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32) * 2;

	  break;

	case VA_FOURCC ('4', '2', '2', 'V'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV422V);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = obj_surface->orig_width;
	  obj_surface->cb_cr_height = obj_surface->orig_height / 2;
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset =
	    obj_surface->y_cb_offset + ALIGN (obj_surface->cb_cr_height, 32);
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32) * 2;

	  break;

	case VA_FOURCC ('4', '1', '1', 'P'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV411);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 4;
	  obj_surface->cb_cr_height = obj_surface->orig_height;
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset =
	    obj_surface->y_cb_offset + ALIGN (obj_surface->cb_cr_height, 32);
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32) * 2;

	  break;

	case VA_FOURCC ('4', '4', '4', 'P'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV444);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = obj_surface->orig_width;
	  obj_surface->cb_cr_height = obj_surface->orig_height;
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset =
	    obj_surface->y_cb_offset + ALIGN (obj_surface->cb_cr_height, 32);
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32) * 2;

	  break;

	case VA_FOURCC ('Y', '8', '0', '0'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV400);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->cb_cr_width = 0;
	  obj_surface->cb_cr_height = 0;
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset =
	    obj_surface->y_cb_offset + ALIGN (obj_surface->cb_cr_height, 32);
	  region_width = obj_surface->width;
	  region_height =
	    obj_surface->height + ALIGN (obj_surface->cb_cr_height, 32) * 2;

	  break;

	case VA_FOURCC ('Y', 'U', 'Y', '2'):
	case VA_FOURCC ('U', 'Y', 'V', 'Y'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV422H);
	  obj_surface->width = ALIGN (obj_surface->orig_width * 2, 128);
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  obj_surface->y_cb_offset = 0;
	  obj_surface->y_cr_offset = 0;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height / 2;
	  region_width = obj_surface->width;
	  region_height = obj_surface->height;

	  break;

	case VA_FOURCC ('R', 'G', 'B', 'A'):
	case VA_FOURCC ('R', 'G', 'B', 'X'):
	case VA_FOURCC ('B', 'G', 'R', 'A'):
	case VA_FOURCC ('B', 'G', 'R', 'X'):
	  MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_RGBX);

	  obj_surface->width = ALIGN (obj_surface->orig_width * 4, 128);
	  region_width = obj_surface->width;
	  region_height = obj_surface->height;
	  break;

	default:
	  /* Never get here */
	  MEDIA_DRV_ASSERT (0);
	  break;
	}
    }
  else
    {
      MEDIA_DRV_ASSERT (subsampling == SUBSAMPLE_YUV420 ||
			subsampling == SUBSAMPLE_YUV422H ||
			subsampling == SUBSAMPLE_YUV422V ||
			subsampling == SUBSAMPLE_RGBX
			|| subsampling == SUBSAMPLE_P208);

      region_width = obj_surface->width;
      region_height = obj_surface->height;

      switch (fourcc)
	{
	case VA_FOURCC ('N', 'V', '1', '2'):
	  obj_surface->y_cb_offset = obj_surface->height;
	  obj_surface->y_cr_offset = obj_surface->height;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height / 2;
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  region_height = obj_surface->height + obj_surface->height / 2;
	  break;

	case VA_FOURCC ('Y', 'V', '1', '2'):
	case VA_FOURCC ('I', '4', '2', '0'):
	  if (fourcc == VA_FOURCC ('Y', 'V', '1', '2'))
	    {
	      obj_surface->y_cr_offset = obj_surface->height;
	      obj_surface->y_cb_offset =
		obj_surface->height + obj_surface->height / 4;
	    }
	  else
	    {
	      obj_surface->y_cb_offset = obj_surface->height;
	      obj_surface->y_cr_offset =
		obj_surface->height + obj_surface->height / 4;
	    }

	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height / 2;
	  obj_surface->cb_cr_pitch = obj_surface->width / 2;
	  region_height = obj_surface->height + obj_surface->height / 2;
	  break;

	case VA_FOURCC ('Y', 'U', 'Y', '2'):
	case VA_FOURCC ('U', 'Y', 'V', 'Y'):
	  obj_surface->width = ALIGN (obj_surface->orig_width * 2, 16);
	  obj_surface->y_cb_offset = 0;
	  obj_surface->y_cr_offset = 0;
	  obj_surface->cb_cr_width = obj_surface->orig_width / 2;
	  obj_surface->cb_cr_height = obj_surface->orig_height;
	  obj_surface->cb_cr_pitch = obj_surface->width;
	  region_width = obj_surface->width;
	  region_height = obj_surface->height;
	  break;
	case VA_FOURCC ('R', 'G', 'B', 'A'):
	case VA_FOURCC ('R', 'G', 'B', 'X'):
	case VA_FOURCC ('B', 'G', 'R', 'A'):
	case VA_FOURCC ('B', 'G', 'R', 'X'):
	  obj_surface->width = ALIGN (obj_surface->orig_width * 4, 16);
	  region_width = obj_surface->width;
	  region_height = obj_surface->height;
	  break;
	case VA_FOURCC ('P', '2', '0', '8'):
	  obj_surface->width = ALIGN (obj_surface->orig_width, 32);
	  region_width = obj_surface->width;
	  region_height = obj_surface->height;
	  break;

	default:
	  /* Never get here */
	  MEDIA_DRV_ASSERT (0);
	  break;
	}
    }

  obj_surface->size = ALIGN (region_width * region_height, 0x1000);

  if (tiled)
    {
      UINT tiling_mode = I915_TILING_Y;	/* always uses Y-tiled format */
      ULONG pitch;

      obj_surface->bo = drm_intel_bo_alloc_tiled (drv_ctx->drv_data.bufmgr,
						  "vaapi surface",
						  region_width,
						  region_height,
						  1, &tiling_mode, &pitch, 0);
      MEDIA_DRV_ASSERT (tiling_mode == I915_TILING_Y);
      MEDIA_DRV_ASSERT (pitch == obj_surface->width);
    }
  else
    {
      obj_surface->bo = dri_bo_alloc (drv_ctx->drv_data.bufmgr,
				      "vaapi surface",
				      obj_surface->size, 0x1000);
    }

  obj_surface->fourcc = fourcc;
  obj_surface->subsampling = subsampling;
  MEDIA_DRV_ASSERT (obj_surface->bo);
}