Example #1
0
static int release_image(VAImage *va_image)
{
    VAAPIContext * const vaapi = vaapi_get_context();
    VAStatus status;

    status = vaUnmapBuffer(vaapi->display, va_image->buf);
    if (!vaapi_check_status(status, "vaUnmapBuffer()"))
        return -1;
    return 0;
}
Example #2
0
static int bind_image(VAImage *va_image, Image *image)
{
    VAAPIContext * const vaapi = vaapi_get_context();
    VAImageFormat * const va_format = &va_image->format;
    VAStatus status;
    void *va_image_data;
    unsigned int i;

    if (va_image->num_planes > MAX_IMAGE_PLANES)
        return -1;

    status = vaMapBuffer(vaapi->display, va_image->buf, &va_image_data);
    if (!vaapi_check_status(status, "vaMapBuffer()"))
        return -1;

    memset(image, 0, sizeof(*image));
    image->format = va_format->fourcc;
    if (is_vaapi_rgb_format(va_format)) {
        image->format = image_rgba_format(
            va_format->bits_per_pixel,
            va_format->byte_order == VA_MSB_FIRST,
            va_format->red_mask,
            va_format->green_mask,
            va_format->blue_mask,
            va_format->alpha_mask
        );
        if (!image->format)
            return -1;
    }

    image->width      = va_image->width;
    image->height     = va_image->height;
    image->num_planes = va_image->num_planes;
    for (i = 0; i < va_image->num_planes; i++) {
        image->pixels[i]  = (uint8_t *)va_image_data + va_image->offsets[i];
        image->pitches[i] = va_image->pitches[i];
    }
    return 0;
}
Example #3
0
int decode(void)
{
    VAAPIContext * const vaapi = vaapi_get_context();
    VAPictureParameterBufferMPEG4 *pic_param;
    VASliceParameterBufferMPEG4 *slice_param;
    VAIQMatrixBufferMPEG4 *iq_matrix;
    int i, slice_count;

    MPEG4PictureInfo mpeg4_pic_info;
    MPEG4SliceInfo mpeg4_slice_info;
    MPEG4IQMatrix mpeg4_iq_matrix;
    const uint8_t *mpeg4_slice_data;
    unsigned int mpeg4_slice_data_size;

    if (!vaapi)
        return -1;

    mpeg4_get_picture_info(&mpeg4_pic_info);

    if (vaapi_init_decoder(VAProfileMPEG4AdvancedSimple, VAEntrypointVLD,
                           mpeg4_pic_info.width, mpeg4_pic_info.height) < 0)
        return -1;

    if ((pic_param = vaapi_alloc_picture(sizeof(*pic_param))) == NULL)
        return -1;

#define COPY(field) \
    pic_param->field = mpeg4_pic_info.field
#define COPY_BFM(a,b,c) \
    pic_param->BFM(a,b,c) = mpeg4_pic_info.a.b.c
    pic_param->vop_width = mpeg4_pic_info.width;
    pic_param->vop_height = mpeg4_pic_info.height;
    pic_param->forward_reference_picture = 0xffffffff;
    pic_param->backward_reference_picture = 0xffffffff;
    pic_param->BFV(vol_fields, value) = 0; /* reset all bits */
    COPY_BFM(vol_fields, bits, short_video_header);
    COPY_BFM(vol_fields, bits, chroma_format);
    COPY_BFM(vol_fields, bits, interlaced);
    COPY_BFM(vol_fields, bits, obmc_disable);
    COPY_BFM(vol_fields, bits, sprite_enable);
    COPY_BFM(vol_fields, bits, sprite_warping_accuracy);
    COPY_BFM(vol_fields, bits, quant_type);
    COPY_BFM(vol_fields, bits, quarter_sample);
    COPY_BFM(vol_fields, bits, data_partitioned);
    COPY_BFM(vol_fields, bits, reversible_vlc);
    COPY(no_of_sprite_warping_points);
    for (i = 0; i < 3; i++) {
        COPY(sprite_trajectory_du[i]);
        COPY(sprite_trajectory_dv[i]);
    }
    COPY(quant_precision);
    pic_param->BFV(vop_fields, value) = 0; /* reset all bits */
    COPY_BFM(vop_fields, bits, vop_coding_type);
    COPY_BFM(vop_fields, bits, backward_reference_vop_coding_type);
    COPY_BFM(vop_fields, bits, vop_rounding_type);
    COPY_BFM(vop_fields, bits, intra_dc_vlc_thr);
    COPY_BFM(vop_fields, bits, top_field_first);
    COPY_BFM(vop_fields, bits, alternate_vertical_scan_flag);
    COPY(vop_fcode_forward);
    COPY(vop_fcode_backward);
    COPY(num_gobs_in_vop);
    COPY(num_macroblocks_in_gob);
    COPY(TRB);
    COPY(TRD);
#if (VA_CHECK_VERSION(0,31,1) /* XXX: update when changes are merged */ || \
     (VA_CHECK_VERSION(0,31,0) && VA_SDS_VERSION >= 4))
    COPY(vop_time_increment_resolution);
    COPY_BFM(vol_fields, bits, resync_marker_disable);
#endif
#undef COPY_BFM
#undef COPY

    if (mpeg4_iq_matrix.load_intra_quant_mat ||
        mpeg4_iq_matrix.load_non_intra_quant_mat) {
        if ((iq_matrix = vaapi_alloc_iq_matrix(sizeof(*iq_matrix))) == NULL)
            return -1;
        mpeg4_get_iq_matrix(&mpeg4_iq_matrix);

#define COPY(field) iq_matrix->field = mpeg4_iq_matrix.field
        COPY(load_intra_quant_mat);
        COPY(load_non_intra_quant_mat);
        for (i = 0; i < 64; i++) {
            COPY(intra_quant_mat[i]);
            COPY(non_intra_quant_mat[i]);
        }
#undef COPY
    }

    slice_count = mpeg4_get_slice_count();
    for (i = 0; i < slice_count; i++) {
        if (mpeg4_get_slice_info(i, &mpeg4_slice_info) < 0)
            return -1;
        if (mpeg4_get_slice_data(i, &mpeg4_slice_data, &mpeg4_slice_data_size) < 0)
            return -1;
        if (mpeg4_slice_data_size != mpeg4_slice_info.slice_data_size)
            return -1;
        if ((slice_param = vaapi_alloc_slice(sizeof(*slice_param),
                                             mpeg4_slice_data,
                                             mpeg4_slice_data_size)) == NULL)
            return -1;

#define COPY(field) slice_param->field = mpeg4_slice_info.field
        COPY(macroblock_offset);
        COPY(macroblock_number);
        COPY(quant_scale);
#undef COPY
    }

    return vaapi_decode();
}
Example #4
0
int get_image(VASurfaceID surface, Image *dst_img)
{
    VAAPIContext * const vaapi = vaapi_get_context();
    VAImage image;
    VAImageFormat *image_format = NULL;
    VAStatus status;
    Image bound_image;
    int i, is_bound_image = 0, is_derived_image = 0, error = -1;

    image.image_id = VA_INVALID_ID;
    image.buf      = VA_INVALID_ID;

    if (!image_format) {
        status = vaDeriveImage(vaapi->display, surface, &image);
        if (vaapi_check_status(status, "vaDeriveImage()")) {
            if (image.image_id != VA_INVALID_ID && image.buf != VA_INVALID_ID) {
                D(bug("using vaDeriveImage()\n"));
                is_derived_image = 1;
                image_format = &image.format;
            }
            else {
                D(bug("vaDeriveImage() returned success but VA image is invalid. Trying vaGetImage()\n"));
            }
        }
    }

    if (!image_format) {
        for (i = 0; image_formats[i] != 0; i++) {
            if (get_image_format(vaapi, image_formats[i], &image_format))
                break;
        }
    }

    if (!image_format)
        goto end;
    D(bug("selected %s image format for getimage\n",
          string_of_VAImageFormat(image_format)));

    if (!is_derived_image) {
        status = vaCreateImage(vaapi->display, image_format,
                               vaapi->picture_width, vaapi->picture_height,
                               &image);
        if (!vaapi_check_status(status, "vaCreateImage()"))
            goto end;
        D(bug("created image with id 0x%08x and buffer id 0x%08x\n",
              image.image_id, image.buf));

        VARectangle src_rect;

        src_rect.x      = 0;
        src_rect.y      = 0;
        src_rect.width  = vaapi->picture_width;
        src_rect.height = vaapi->picture_height;

        D(bug("src rect (%d,%d):%ux%u\n",
              src_rect.x, src_rect.y, src_rect.width, src_rect.height));

        status = vaGetImage(
            vaapi->display, vaapi->surface_id,
            src_rect.x, src_rect.y, src_rect.width, src_rect.height,
            image.image_id
        );
        if (!vaapi_check_status(status, "vaGetImage()")) {
            vaDestroyImage(vaapi->display, image.image_id);
            goto end;
        }
    }

    if (bind_image(&image, &bound_image) < 0)
        goto end;
    is_bound_image = 1;

    if (image_convert(dst_img, &bound_image) < 0)
        goto end;

    error = 0;
end:
    if (is_bound_image) {
        if (release_image(&image) < 0)
            error = -1;
    }

    if (image.image_id != VA_INVALID_ID) {
        status = vaDestroyImage(vaapi->display, image.image_id);
        if (!vaapi_check_status(status, "vaDestroyImage()"))
            error = -1;
    }
    return error;
}
Example #5
0
int vaapi_init_decoder(VAProfile    profile,
                       VAEntrypoint entrypoint,
                       unsigned int picture_width,
                       unsigned int picture_height)
{
    VAAPIContext * const vaapi = vaapi_get_context();
    VAConfigAttrib attrib;
    VAConfigID config_id = 0;
    VAContextID context_id = 0;
    VASurfaceID surface_id = 0;
    VAStatus status;

    if (!vaapi)
        return -1;
#if 0
    if (common_init_decoder(picture_width, picture_height) < 0)
        return -1;
#endif

    if (!has_profile(vaapi, profile))
        return -1;
    if (!has_entrypoint(vaapi, profile, entrypoint))
        return -1;

    if (vaapi->profile != profile || vaapi->entrypoint != entrypoint) {
        if (vaapi->config_id)
            vaDestroyConfig(vaapi->display, vaapi->config_id);

        attrib.type = VAConfigAttribRTFormat;
        status = vaGetConfigAttributes(vaapi->display, profile, entrypoint,
                                       &attrib, 1);
        if (!vaapi_check_status(status, "vaGetConfigAttributes()"))
            return -1;
        if ((attrib.value & VA_RT_FORMAT_YUV420) == 0)
            return -1;

        status = vaCreateConfig(vaapi->display, profile, entrypoint,
                                &attrib, 1, &config_id);
        if (!vaapi_check_status(status, "vaCreateConfig()"))
            return -1;
    }
    else
        config_id = vaapi->config_id;

    if (vaapi->picture_width != picture_width || vaapi->picture_height != picture_height) {
        if (vaapi->surface_id)
            vaDestroySurfaces(vaapi->display, &vaapi->surface_id, 1);

        status = vaCreateSurfaces(vaapi->display, picture_width, picture_height,
                                  VA_RT_FORMAT_YUV420, 1, &surface_id);
        if (!vaapi_check_status(status, "vaCreateSurfaces()"))
            return -1;

        if (vaapi->context_id)
            vaDestroyContext(vaapi->display, vaapi->context_id);

        status = vaCreateContext(vaapi->display, config_id,
                                 picture_width, picture_height,
                                 VA_PROGRESSIVE,
                                 &surface_id, 1,
                                 &context_id);
        if (!vaapi_check_status(status, "vaCreateContext()"))
            return -1;
    }
    else {
        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;
}
Example #6
0
int vaapi_exit(void)
{
    VAAPIContext * const vaapi = vaapi_get_context();
    unsigned int i;

    if (!vaapi)
        return 0;

#if USE_GLX
    if (display_type() == DISPLAY_GLX)
        vaapi_glx_destroy_surface();
#endif

    destroy_buffers(vaapi->display, &vaapi->pic_param_buf_id, 1);
    destroy_buffers(vaapi->display, &vaapi->iq_matrix_buf_id, 1);
    destroy_buffers(vaapi->display, &vaapi->bitplane_buf_id, 1);
    destroy_buffers(vaapi->display, vaapi->slice_buf_ids, vaapi->n_slice_buf_ids);

    if (vaapi->subpic_flags) {
        free(vaapi->subpic_flags);
        vaapi->subpic_flags = NULL;
    }

    if (vaapi->subpic_formats) {
        free(vaapi->subpic_formats);
        vaapi->subpic_formats = NULL;
        vaapi->n_subpic_formats = 0;
    }

    if (vaapi->image_formats) {
        free(vaapi->image_formats);
        vaapi->image_formats = NULL;
        vaapi->n_image_formats = 0;
    }

    if (vaapi->entrypoints) {
        free(vaapi->entrypoints);
        vaapi->entrypoints = NULL;
        vaapi->n_entrypoints = 0;
    }

    if (vaapi->profiles) {
        free(vaapi->profiles);
        vaapi->profiles = NULL;
        vaapi->n_profiles = 0;
    }

    if (vaapi->slice_params) {
        free(vaapi->slice_params);
        vaapi->slice_params = NULL;
        vaapi->slice_params_alloc = 0;
        vaapi->n_slice_params = 0;
    }

    if (vaapi->slice_buf_ids) {
        free(vaapi->slice_buf_ids);
        vaapi->slice_buf_ids = NULL;
        vaapi->n_slice_buf_ids = 0;
    }

    if (vaapi->subpic_image.image_id != VA_INVALID_ID) {
        vaDestroyImage(vaapi->display, vaapi->subpic_image.image_id);
        vaapi->subpic_image.image_id = VA_INVALID_ID;
    }

    for (i = 0; i < ARRAY_ELEMS(vaapi->subpic_ids); i++) {
        if (vaapi->subpic_ids[i] != VA_INVALID_ID) {
            vaDestroySubpicture(vaapi->display, vaapi->subpic_ids[i]);
            vaapi->subpic_ids[i] = VA_INVALID_ID;
        }
    }

    if (vaapi->surface_id) {
        vaDestroySurfaces(vaapi->display, &vaapi->surface_id, 1);
        vaapi->surface_id = 0;
    }

    if (vaapi->context_id) {
        vaDestroyContext(vaapi->display, vaapi->context_id);
        vaapi->context_id = 0;
    }

    if (vaapi->config_id) {
        vaDestroyConfig(vaapi->display, vaapi->config_id);
        vaapi->config_id = 0;
    }

    if (vaapi->display) {
        vaTerminate(vaapi->display);
        vaapi->display = NULL;
    }

    free(vaapi_context);
    return 0;
}