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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
#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; }
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
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; }
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); }