Skip to content

VaSurface for RGBA with external Buffer #883

@sivarub

Description

@sivarub

I am trying to create a VaSurface with an external buffer attached for RGBA format. I am using follwing code to create surfaces and dumping into file. When I looked dumped rgba data , it is purely black ( used ffplay to verify this)

please look following code and provide feedback to resolve this issue.

Thanks for your help..

static VAStatus va_encoder_setup_external_rgba(va_enc_t *venc)
{
VAStatus vas = VA_STATUS_ERROR_UNKNOWN;
int surface_type = VA_RT_FORMAT_RGB32;
int fourcc_buffer_format = venc->fourcc_buffer_format;

int num_formats = vaMaxNumImageFormats(venc->display);
VAImageFormat *format_list = malloc(num_formats * sizeof(VAImageFormat));

vas = vaQueryImageFormats(venc->display, format_list, &num_formats);
if ( vas  != VA_STATUS_SUCCESS) {
    LOGE("Failed vaQueryImageFormats");
    return vas;
}

for (int i = 0; i < num_formats; i++) {
    if (format_list[i].fourcc == fourcc_buffer_format) {
        LOGE("Found format");
        venc->rgba_format = format_list[i];
        break;
    }
}

if( (venc->va_external_sid = calloc(1, sizeof(VASurfaceID) * venc->ibufs.nbuffers)) == NULL ) {
    LOGE("Couldn't allocate %zubytes", sizeof(VASurfaceID) * venc->ibufs.nbuffers);
} else {
    VADRMPRIMESurfaceDescriptor    ext_surface = { 0 };
    VASurfaceAttrib                attrs[2] = { 0 };
    int                            width  =  venc->ibufs.width;
    int                            height =  venc->ibufs.height;

    int                            frame_width_mbaligned   = width;
    int                            frame_height_mbaligned  = height;

    venc->config.frame_bitrate = (long long int) width * height * 12 * g_frame_rate / 50;

    attrs[0].type = VASurfaceAttribMemoryType;
    attrs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
    attrs[0].value.type = VAGenericValueTypeInteger;
    attrs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2;
   
    attrs[1].type = VASurfaceAttribExternalBufferDescriptor;
    attrs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
    attrs[1].value.type = VAGenericValueTypePointer;
    attrs[1].value.value.p = &ext_surface;

    ext_surface.fourcc = fourcc_buffer_format;
    ext_surface.width  = frame_width_mbaligned;
    ext_surface.height = frame_height_mbaligned;
    
    ext_surface.num_objects = 1;
    ext_surface.objects[0].size = venc->ibufs.bsize;
    ext_surface.objects[0].drm_format_modifier = 0;
   
    ext_surface.num_layers = 1;
    ext_surface.layers[0].drm_format = fourcc_buffer_format;
    ext_surface.layers[0].num_planes = 1;
    ext_surface.layers[0].object_index[0] = 0;
    ext_surface.layers[0].offset[0] = venc->screen_buffer_planar_offset[0];
    ext_surface.layers[0].pitch[0] = venc->screen_buffer_stride;

    LOGE("marker bsize %d  pitch0 %d offset %d",venc->ibufs.bsize, venc->screen_buffer_stride,venc->screen_buffer_planar_offset[0]);

    /* create source surfaces */
    for( int i = 0; i < venc->ibufs.nbuffers; i++ ) {
        int fd =  qnx_screen_get_dmabuf_fd(venc->ibufs.buffer_info[i].buf_handle); 
        LOGI("fd %d egle %d",fd,(int)venc->ibufs.buffer_info[i].buf_handle);
        ext_surface.objects[0].fd = fd;
        vas = vaCreateSurfaces(venc->display, surface_type, frame_width_mbaligned, frame_height_mbaligned, &(venc->va_external_sid[i]), 1, attrs, 2);
        if ( vas != VA_STATUS_SUCCESS) {
            LOGE("vaError: %s",vaErrorStr(vas));
            if ( i > 0 ) {
             vaDestroySurfaces(venc->display, venc->va_external_sid, i );
            }
            free(venc->va_external_sid);
            venc->va_external_sid = NULL;
            return vas;
        }
        LOGE("marker sid %d",venc->va_external_sid[i]);
    }
}
return vas;

}

VAStatus va_encoder_dump_rgba_from_surface(va_enc_t *venc, VASurfaceID src_sid){
VAStatus vas = VA_STATUS_ERROR_UNKNOWN;
VAImage img;
VAImageFormat rgba_fmt;
unsigned char *map = NULL;

if ( venc->fprgba == NULL ) {
    char name[256];
    sprintf(name,"/tmp/va_enc.rgba");
    venc->fprgba = fopen(name, "w");
    if ( venc->fprgba == NULL ){
        LOGE("Failed to open (%s)",name);
        return vas;
    }
}
VAStatus st = vaDeriveImage(venc->display, src_sid, &img);
if (st != VA_STATUS_SUCCESS) {
    memset(&rgba_fmt, 0, sizeof(rgba_fmt));
    rgba_fmt.fourcc         = venc->fourcc_buffer_format;
    rgba_fmt.byte_order     = VA_LSB_FIRST;
    rgba_fmt.bits_per_pixel = 32;
    rgba_fmt.depth          = 32;
    rgba_fmt.red_mask       = 0x000000FF;
    rgba_fmt.green_mask     = 0x0000FF00;
    rgba_fmt.blue_mask      = 0x00FF0000;
    rgba_fmt.alpha_mask     = 0xFF000000;
    if (vaCreateImage(venc->display, &rgba_fmt, venc->width, venc->height, &img) != VA_STATUS_SUCCESS) {
     return vas;
    }
    if (vaGetImage(venc->display, src_sid, 0, 0, venc->width, venc->height, img.image_id) != VA_STATUS_SUCCESS) {
     vaDestroyImage(venc->display, img.image_id);
     return vas;
    }
}

if (vaMapBuffer(venc->display, img.buf, (void **)&map) != VA_STATUS_SUCCESS) {
    vaDestroyImage(venc->display, img.image_id);
    return vas;
}

uint8_t *rgba = (uint8_t *)map + img.offsets[0];
uint32_t stride    = img.pitches[0];

if ((uint8_t *)map != rgba  ) {
    LOGE("offset %d",img.offsets[0]);
}
LOGE("Image: src_sid %d %ux%u, stride=%u, format=0x%08X", src_sid, img.width, img.height, stride , img.format.fourcc);

fwrite(rgba, 1, venc->width * venc->height * 4, venc->fprgba);

vaUnmapBuffer(venc->display, img.buf);
vaDestroyImage(venc->display, img.image_id);
return VA_STATUS_SUCCESS;

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions