Skip to content

VaSurface for RGBA with external Buffer #883

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions