Ejemplo n.º 1
0
VAStatus
vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats)
{
   struct pipe_screen *pscreen;
   enum pipe_format format;
   int i;

   STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS);

   if (!ctx)
      return VA_STATUS_ERROR_INVALID_CONTEXT;

   if (!(format_list && num_formats))
      return VA_STATUS_ERROR_INVALID_PARAMETER;

   *num_formats = 0;
   pscreen = VL_VA_PSCREEN(ctx);
   for (i = 0; i < ARRAY_SIZE(formats); ++i) {
      format = VaFourccToPipeFormat(formats[i].fourcc);
      if (pscreen->is_video_format_supported(pscreen, format,
          PIPE_VIDEO_PROFILE_UNKNOWN,
          PIPE_VIDEO_ENTRYPOINT_BITSTREAM))
         format_list[(*num_formats)++] = formats[i];
   }

   return VA_STATUS_SUCCESS;
}
Ejemplo n.º 2
0
VAStatus
vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
                    unsigned int width, unsigned int height,
                    VASurfaceID *surfaces, unsigned int num_surfaces,
                    VASurfaceAttrib *attrib_list, unsigned int num_attribs)
{
    vlVaDriver *drv;
    VASurfaceAttribExternalBuffers *memory_attibute;
    struct pipe_video_buffer templat;
    struct pipe_screen *pscreen;
    int i;
    int memory_type;
    int expected_fourcc;
    VAStatus vaStatus;

    if (!ctx)
       return VA_STATUS_ERROR_INVALID_CONTEXT;

    if (!(width && height))
       return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;

    drv = VL_VA_DRIVER(ctx);

    if (!drv)
        return VA_STATUS_ERROR_INVALID_CONTEXT;

    pscreen = VL_VA_PSCREEN(ctx);

    if (!pscreen)
        return VA_STATUS_ERROR_INVALID_CONTEXT;

    /* Default. */
    memory_attibute = NULL;
    memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
    expected_fourcc = 0;

    for (i = 0; i < num_attribs && attrib_list; i++) {
        if ((attrib_list[i].type == VASurfaceAttribPixelFormat) &&
            (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
            if (attrib_list[i].value.type != VAGenericValueTypeInteger)
                return VA_STATUS_ERROR_INVALID_PARAMETER;
            expected_fourcc = attrib_list[i].value.value.i;
        }

        if ((attrib_list[i].type == VASurfaceAttribMemoryType) &&
            (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {

            if (attrib_list[i].value.type != VAGenericValueTypeInteger)
                return VA_STATUS_ERROR_INVALID_PARAMETER;

            switch (attrib_list[i].value.value.i) {
                case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
                case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
                   memory_type = attrib_list[i].value.value.i;
                   break;
                default:
                   return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
            }
        }

        if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) &&
            (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) {
            if (attrib_list[i].value.type != VAGenericValueTypePointer)
                return VA_STATUS_ERROR_INVALID_PARAMETER;
            memory_attibute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
        }
    }

    if (VA_RT_FORMAT_YUV420 != format &&
        VA_RT_FORMAT_YUV422 != format &&
        VA_RT_FORMAT_YUV444 != format &&
        VA_RT_FORMAT_RGB32  != format) {
        return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
    }

    switch (memory_type) {
        case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
            break;
        case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
            if (!memory_attibute)
               return VA_STATUS_ERROR_INVALID_PARAMETER;

            expected_fourcc = memory_attibute->pixel_format;
            break;
        default:
            assert(0);
    }

    memset(&templat, 0, sizeof(templat));

    if (expected_fourcc) {
       templat.buffer_format = VaFourccToPipeFormat(expected_fourcc);
       templat.interlaced = 0;
    } else {
        templat.buffer_format = pscreen->get_video_param
        (
           pscreen,
           PIPE_VIDEO_PROFILE_UNKNOWN,
           PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
           PIPE_VIDEO_CAP_PREFERED_FORMAT
        );
        templat.interlaced = pscreen->get_video_param
        (
           pscreen,
           PIPE_VIDEO_PROFILE_UNKNOWN,
           PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
           PIPE_VIDEO_CAP_PREFERS_INTERLACED
        );
    }

    templat.chroma_format = ChromaToPipe(format);

    templat.width = width;
    templat.height = height;

    memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID));

    for (i = 0; i < num_surfaces; i++) {
        vlVaSurface *surf = CALLOC(1, sizeof(vlVaSurface));
        if (!surf)
            goto no_res;

        surf->templat = templat;

        switch (memory_type) {
            case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
                surf->buffer = drv->pipe->create_video_buffer(drv->pipe, &templat);
                if (!surf->buffer)
                    goto no_res;
                util_dynarray_init(&surf->subpics);
                surfaces[i] = handle_table_add(drv->htab, surf);
                break;
            case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
                vaStatus = suface_from_external_memory(ctx, surf, memory_attibute, i, surfaces, &templat);
                if (vaStatus != VA_STATUS_SUCCESS)
                  goto no_res;
                break;
            default:
                assert(0);
        }
    }

    return VA_STATUS_SUCCESS;

no_res:
   if (i)
      vlVaDestroySurfaces(ctx, surfaces, i);

   return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}