Home | History | Annotate | Download | only in vdpau
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 Thomas Balling Srensen.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 #include "util/u_memory.h"
     29 #include "util/u_math.h"
     30 #include "util/u_debug.h"
     31 #include "util/u_video.h"
     32 
     33 #include "vl/vl_vlc.h"
     34 
     35 #include "vdpau_private.h"
     36 
     37 /**
     38  * Create a VdpDecoder.
     39  */
     40 VdpStatus
     41 vlVdpDecoderCreate(VdpDevice device,
     42                    VdpDecoderProfile profile,
     43                    uint32_t width, uint32_t height,
     44                    uint32_t max_references,
     45                    VdpDecoder *decoder)
     46 {
     47    enum pipe_video_profile p_profile;
     48    struct pipe_context *pipe;
     49    struct pipe_screen *screen;
     50    vlVdpDevice *dev;
     51    vlVdpDecoder *vldecoder;
     52    VdpStatus ret;
     53    bool supported;
     54 
     55    if (!decoder)
     56       return VDP_STATUS_INVALID_POINTER;
     57    *decoder = 0;
     58 
     59    if (!(width && height))
     60       return VDP_STATUS_INVALID_VALUE;
     61 
     62    p_profile = ProfileToPipe(profile);
     63    if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN)
     64       return VDP_STATUS_INVALID_DECODER_PROFILE;
     65 
     66    dev = vlGetDataHTAB(device);
     67    if (!dev)
     68       return VDP_STATUS_INVALID_HANDLE;
     69 
     70    pipe = dev->context;
     71    screen = dev->vscreen->pscreen;
     72 
     73    pipe_mutex_lock(dev->mutex);
     74 
     75    supported = screen->get_video_param
     76    (
     77       screen,
     78       p_profile,
     79       PIPE_VIDEO_CAP_SUPPORTED
     80    );
     81    if (!supported) {
     82       pipe_mutex_unlock(dev->mutex);
     83       return VDP_STATUS_INVALID_DECODER_PROFILE;
     84    }
     85 
     86    vldecoder = CALLOC(1,sizeof(vlVdpDecoder));
     87    if (!vldecoder) {
     88       pipe_mutex_unlock(dev->mutex);
     89       return VDP_STATUS_RESOURCES;
     90    }
     91 
     92    vldecoder->device = dev;
     93 
     94    vldecoder->decoder = pipe->create_video_decoder
     95    (
     96       pipe, p_profile,
     97       PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
     98       PIPE_VIDEO_CHROMA_FORMAT_420,
     99       width, height, max_references,
    100       false
    101    );
    102 
    103    if (!vldecoder->decoder) {
    104       ret = VDP_STATUS_ERROR;
    105       goto error_decoder;
    106    }
    107 
    108    *decoder = vlAddDataHTAB(vldecoder);
    109    if (*decoder == 0) {
    110       ret = VDP_STATUS_ERROR;
    111       goto error_handle;
    112    }
    113    pipe_mutex_unlock(dev->mutex);
    114 
    115    return VDP_STATUS_OK;
    116 
    117 error_handle:
    118    vldecoder->decoder->destroy(vldecoder->decoder);
    119 
    120 error_decoder:
    121    pipe_mutex_unlock(dev->mutex);
    122    FREE(vldecoder);
    123    return ret;
    124 }
    125 
    126 /**
    127  * Destroy a VdpDecoder.
    128  */
    129 VdpStatus
    130 vlVdpDecoderDestroy(VdpDecoder decoder)
    131 {
    132    vlVdpDecoder *vldecoder;
    133 
    134    vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
    135    if (!vldecoder)
    136       return VDP_STATUS_INVALID_HANDLE;
    137 
    138    pipe_mutex_lock(vldecoder->device->mutex);
    139    vldecoder->decoder->destroy(vldecoder->decoder);
    140    pipe_mutex_unlock(vldecoder->device->mutex);
    141 
    142    FREE(vldecoder);
    143 
    144    return VDP_STATUS_OK;
    145 }
    146 
    147 /**
    148  * Retrieve the parameters used to create a VdpBitmapSurface.
    149  */
    150 VdpStatus
    151 vlVdpDecoderGetParameters(VdpDecoder decoder,
    152                           VdpDecoderProfile *profile,
    153                           uint32_t *width,
    154                           uint32_t *height)
    155 {
    156    vlVdpDecoder *vldecoder;
    157 
    158    vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
    159    if (!vldecoder)
    160       return VDP_STATUS_INVALID_HANDLE;
    161 
    162    *profile = PipeToProfile(vldecoder->decoder->profile);
    163    *width = vldecoder->decoder->width;
    164    *height = vldecoder->decoder->height;
    165 
    166    return VDP_STATUS_OK;
    167 }
    168 
    169 static VdpStatus
    170 vlVdpGetReferenceFrame(VdpVideoSurface handle, struct pipe_video_buffer **ref_frame)
    171 {
    172    vlVdpSurface *surface;
    173 
    174    /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */
    175    if (handle ==  VDP_INVALID_HANDLE) {
    176       *ref_frame = NULL;
    177       return VDP_STATUS_OK;
    178    }
    179 
    180    surface = vlGetDataHTAB(handle);
    181    if (!surface)
    182       return VDP_STATUS_INVALID_HANDLE;
    183 
    184    *ref_frame = surface->video_buffer;
    185    if (!*ref_frame)
    186          return VDP_STATUS_INVALID_HANDLE;
    187 
    188    return VDP_STATUS_OK;
    189 }
    190 
    191 /**
    192  * Decode a mpeg 1/2 video.
    193  */
    194 static VdpStatus
    195 vlVdpDecoderRenderMpeg12(struct pipe_mpeg12_picture_desc *picture,
    196                          VdpPictureInfoMPEG1Or2 *picture_info)
    197 {
    198    VdpStatus r;
    199 
    200    VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG12\n");
    201 
    202    r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]);
    203    if (r != VDP_STATUS_OK)
    204       return r;
    205 
    206    r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]);
    207    if (r != VDP_STATUS_OK)
    208       return r;
    209 
    210    picture->picture_coding_type = picture_info->picture_coding_type;
    211    picture->picture_structure = picture_info->picture_structure;
    212    picture->frame_pred_frame_dct = picture_info->frame_pred_frame_dct;
    213    picture->q_scale_type = picture_info->q_scale_type;
    214    picture->alternate_scan = picture_info->alternate_scan;
    215    picture->intra_vlc_format = picture_info->intra_vlc_format;
    216    picture->concealment_motion_vectors = picture_info->concealment_motion_vectors;
    217    picture->intra_dc_precision = picture_info->intra_dc_precision;
    218    picture->f_code[0][0] = picture_info->f_code[0][0] - 1;
    219    picture->f_code[0][1] = picture_info->f_code[0][1] - 1;
    220    picture->f_code[1][0] = picture_info->f_code[1][0] - 1;
    221    picture->f_code[1][1] = picture_info->f_code[1][1] - 1;
    222    picture->num_slices = picture_info->slice_count;
    223    picture->top_field_first = picture_info->top_field_first;
    224    picture->full_pel_forward_vector = picture_info->full_pel_forward_vector;
    225    picture->full_pel_backward_vector = picture_info->full_pel_backward_vector;
    226    picture->intra_matrix = picture_info->intra_quantizer_matrix;
    227    picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix;
    228 
    229    return VDP_STATUS_OK;
    230 }
    231 
    232 /**
    233  * Decode a mpeg 4 video.
    234  */
    235 static VdpStatus
    236 vlVdpDecoderRenderMpeg4(struct pipe_mpeg4_picture_desc *picture,
    237                         VdpPictureInfoMPEG4Part2 *picture_info)
    238 {
    239    VdpStatus r;
    240    unsigned i;
    241 
    242    VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG4\n");
    243 
    244    r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]);
    245    if (r != VDP_STATUS_OK)
    246       return r;
    247 
    248    r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]);
    249    if (r != VDP_STATUS_OK)
    250       return r;
    251 
    252    for (i = 0; i < 2; ++i) {
    253       picture->trd[i] = picture_info->trd[i];
    254       picture->trb[i] = picture_info->trb[i];
    255    }
    256    picture->vop_time_increment_resolution = picture_info->vop_time_increment_resolution;
    257    picture->vop_coding_type = picture_info->vop_coding_type;
    258    picture->vop_fcode_forward = picture_info->vop_fcode_forward;
    259    picture->vop_fcode_backward = picture_info->vop_fcode_backward;
    260    picture->resync_marker_disable = picture_info->resync_marker_disable;
    261    picture->interlaced = picture_info->interlaced;
    262    picture->quant_type = picture_info->quant_type;
    263    picture->quarter_sample = picture_info->quarter_sample;
    264    picture->short_video_header = picture_info->short_video_header;
    265    picture->rounding_control = picture_info->rounding_control;
    266    picture->alternate_vertical_scan_flag = picture_info->alternate_vertical_scan_flag;
    267    picture->top_field_first = picture_info->top_field_first;
    268    picture->intra_matrix = picture_info->intra_quantizer_matrix;
    269    picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix;
    270 
    271    return VDP_STATUS_OK;
    272 }
    273 
    274 static VdpStatus
    275 vlVdpDecoderRenderVC1(struct pipe_vc1_picture_desc *picture,
    276                       VdpPictureInfoVC1 *picture_info)
    277 {
    278    VdpStatus r;
    279 
    280    VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding VC-1\n");
    281 
    282    r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]);
    283    if (r != VDP_STATUS_OK)
    284       return r;
    285 
    286    r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]);
    287    if (r != VDP_STATUS_OK)
    288       return r;
    289 
    290    picture->slice_count = picture_info->slice_count;
    291    picture->picture_type = picture_info->picture_type;
    292    picture->frame_coding_mode = picture_info->frame_coding_mode;
    293    picture->postprocflag = picture_info->postprocflag;
    294    picture->pulldown = picture_info->pulldown;
    295    picture->interlace = picture_info->interlace;
    296    picture->tfcntrflag = picture_info->tfcntrflag;
    297    picture->finterpflag = picture_info->finterpflag;
    298    picture->psf = picture_info->psf;
    299    picture->dquant = picture_info->dquant;
    300    picture->panscan_flag = picture_info->panscan_flag;
    301    picture->refdist_flag = picture_info->refdist_flag;
    302    picture->quantizer = picture_info->quantizer;
    303    picture->extended_mv = picture_info->extended_mv;
    304    picture->extended_dmv = picture_info->extended_dmv;
    305    picture->overlap = picture_info->overlap;
    306    picture->vstransform = picture_info->vstransform;
    307    picture->loopfilter = picture_info->loopfilter;
    308    picture->fastuvmc = picture_info->fastuvmc;
    309    picture->range_mapy_flag = picture_info->range_mapy_flag;
    310    picture->range_mapy = picture_info->range_mapy;
    311    picture->range_mapuv_flag = picture_info->range_mapuv_flag;
    312    picture->range_mapuv = picture_info->range_mapuv;
    313    picture->multires = picture_info->multires;
    314    picture->syncmarker = picture_info->syncmarker;
    315    picture->rangered = picture_info->rangered;
    316    picture->maxbframes = picture_info->maxbframes;
    317    picture->deblockEnable = picture_info->deblockEnable;
    318    picture->pquant = picture_info->pquant;
    319 
    320    return VDP_STATUS_OK;
    321 }
    322 
    323 static VdpStatus
    324 vlVdpDecoderRenderH264(struct pipe_h264_picture_desc *picture,
    325                        VdpPictureInfoH264 *picture_info)
    326 {
    327    unsigned i;
    328 
    329    VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding H264\n");
    330 
    331    picture->slice_count = picture_info->slice_count;
    332    picture->field_order_cnt[0] = picture_info->field_order_cnt[0];
    333    picture->field_order_cnt[1] = picture_info->field_order_cnt[1];
    334    picture->is_reference = picture_info->is_reference;
    335    picture->frame_num = picture_info->frame_num;
    336    picture->field_pic_flag = picture_info->field_pic_flag;
    337    picture->bottom_field_flag = picture_info->bottom_field_flag;
    338    picture->num_ref_frames = picture_info->num_ref_frames;
    339    picture->mb_adaptive_frame_field_flag = picture_info->mb_adaptive_frame_field_flag;
    340    picture->constrained_intra_pred_flag = picture_info->constrained_intra_pred_flag;
    341    picture->weighted_pred_flag = picture_info->weighted_pred_flag;
    342    picture->weighted_bipred_idc = picture_info->weighted_bipred_idc;
    343    picture->frame_mbs_only_flag = picture_info->frame_mbs_only_flag;
    344    picture->transform_8x8_mode_flag = picture_info->transform_8x8_mode_flag;
    345    picture->chroma_qp_index_offset = picture_info->chroma_qp_index_offset;
    346    picture->second_chroma_qp_index_offset = picture_info->second_chroma_qp_index_offset;
    347    picture->pic_init_qp_minus26 = picture_info->pic_init_qp_minus26;
    348    picture->num_ref_idx_l0_active_minus1 = picture_info->num_ref_idx_l0_active_minus1;
    349    picture->num_ref_idx_l1_active_minus1 = picture_info->num_ref_idx_l1_active_minus1;
    350    picture->log2_max_frame_num_minus4 = picture_info->log2_max_frame_num_minus4;
    351    picture->pic_order_cnt_type = picture_info->pic_order_cnt_type;
    352    picture->log2_max_pic_order_cnt_lsb_minus4 = picture_info->log2_max_pic_order_cnt_lsb_minus4;
    353    picture->delta_pic_order_always_zero_flag = picture_info->delta_pic_order_always_zero_flag;
    354    picture->direct_8x8_inference_flag = picture_info->direct_8x8_inference_flag;
    355    picture->entropy_coding_mode_flag = picture_info->entropy_coding_mode_flag;
    356    picture->pic_order_present_flag = picture_info->pic_order_present_flag;
    357    picture->deblocking_filter_control_present_flag = picture_info->deblocking_filter_control_present_flag;
    358    picture->redundant_pic_cnt_present_flag = picture_info->redundant_pic_cnt_present_flag;
    359 
    360    memcpy(picture->scaling_lists_4x4, picture_info->scaling_lists_4x4, 6*16);
    361    memcpy(picture->scaling_lists_8x8, picture_info->scaling_lists_8x8, 2*64);
    362 
    363    for (i = 0; i < 16; ++i) {
    364       VdpStatus ret = vlVdpGetReferenceFrame
    365       (
    366          picture_info->referenceFrames[i].surface,
    367          &picture->ref[i]
    368       );
    369       if (ret != VDP_STATUS_OK)
    370          return ret;
    371 
    372       picture->is_long_term[i] = picture_info->referenceFrames[i].is_long_term;
    373       picture->top_is_reference[i] = picture_info->referenceFrames[i].top_is_reference;
    374       picture->bottom_is_reference[i] = picture_info->referenceFrames[i].bottom_is_reference;
    375       picture->field_order_cnt_list[i][0] = picture_info->referenceFrames[i].field_order_cnt[0];
    376       picture->field_order_cnt_list[i][1] = picture_info->referenceFrames[i].field_order_cnt[1];
    377       picture->frame_num_list[i] = picture_info->referenceFrames[i].frame_idx;
    378    }
    379 
    380    return VDP_STATUS_OK;
    381 }
    382 
    383 static void
    384 vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers, const void *buffers[], unsigned sizes[])
    385 {
    386    static const uint8_t vc1_startcode[] = { 0x00, 0x00, 0x01, 0x0D };
    387    struct vl_vlc vlc;
    388    unsigned i;
    389 
    390    /* search the first 64 bytes for a startcode */
    391    vl_vlc_init(&vlc, *num_buffers, buffers, sizes);
    392    for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= 32; ++i) {
    393       uint32_t value = vl_vlc_peekbits(&vlc, 32);
    394       if (value == 0x0000010D ||
    395           value == 0x0000010C ||
    396           value == 0x0000010B)
    397          return;
    398       vl_vlc_eatbits(&vlc, 8);
    399       vl_vlc_fillbits(&vlc);
    400    }
    401 
    402    /* none found, ok add one manually */
    403    VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Manually adding VC-1 startcode\n");
    404    for (i = *num_buffers; i > 0; --i) {
    405       buffers[i] = buffers[i - 1];
    406       sizes[i] = sizes[i - 1];
    407    }
    408    ++(*num_buffers);
    409    buffers[0] = vc1_startcode;
    410    sizes[0] = 4;
    411 }
    412 
    413 /**
    414  * Decode a compressed field/frame and render the result into a VdpVideoSurface.
    415  */
    416 VdpStatus
    417 vlVdpDecoderRender(VdpDecoder decoder,
    418                    VdpVideoSurface target,
    419                    VdpPictureInfo const *picture_info,
    420                    uint32_t bitstream_buffer_count,
    421                    VdpBitstreamBuffer const *bitstream_buffers)
    422 {
    423    const void * buffers[bitstream_buffer_count + 1];
    424    unsigned sizes[bitstream_buffer_count + 1];
    425    vlVdpDecoder *vldecoder;
    426    vlVdpSurface *vlsurf;
    427    VdpStatus ret;
    428    struct pipe_screen *screen;
    429    struct pipe_video_decoder *dec;
    430    bool buffer_support[2];
    431    unsigned i;
    432    union {
    433       struct pipe_picture_desc base;
    434       struct pipe_mpeg12_picture_desc mpeg12;
    435       struct pipe_mpeg4_picture_desc mpeg4;
    436       struct pipe_vc1_picture_desc vc1;
    437       struct pipe_h264_picture_desc h264;
    438    } desc;
    439 
    440    if (!(picture_info && bitstream_buffers))
    441       return VDP_STATUS_INVALID_POINTER;
    442 
    443    vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
    444    if (!vldecoder)
    445       return VDP_STATUS_INVALID_HANDLE;
    446    dec = vldecoder->decoder;
    447    screen = dec->context->screen;
    448 
    449    vlsurf = (vlVdpSurface *)vlGetDataHTAB(target);
    450    if (!vlsurf)
    451       return VDP_STATUS_INVALID_HANDLE;
    452 
    453    if (vlsurf->device != vldecoder->device)
    454       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
    455 
    456    if (vlsurf->video_buffer != NULL && vlsurf->video_buffer->chroma_format != dec->chroma_format)
    457       // TODO: Recreate decoder with correct chroma
    458       return VDP_STATUS_INVALID_CHROMA_TYPE;
    459 
    460    pipe_mutex_lock(vlsurf->device->mutex);
    461 
    462    buffer_support[0] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE);
    463    buffer_support[1] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_SUPPORTS_INTERLACED);
    464 
    465    if (vlsurf->video_buffer == NULL ||
    466        !screen->is_video_format_supported(screen, vlsurf->video_buffer->buffer_format, dec->profile) ||
    467        !buffer_support[vlsurf->video_buffer->interlaced]) {
    468 
    469       /* destroy the old one */
    470       if (vlsurf->video_buffer)
    471          vlsurf->video_buffer->destroy(vlsurf->video_buffer);
    472 
    473       /* set the buffer format to the prefered one */
    474       vlsurf->templat.buffer_format = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_PREFERED_FORMAT);
    475 
    476       /* also set interlacing to decoders preferences */
    477       vlsurf->templat.interlaced = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_PREFERS_INTERLACED);
    478 
    479       /* and recreate the video buffer */
    480       vlsurf->video_buffer = dec->context->create_video_buffer(dec->context, &vlsurf->templat);
    481 
    482       /* still no luck? get me out of here... */
    483       if (!vlsurf->video_buffer) {
    484          pipe_mutex_unlock(vlsurf->device->mutex);
    485          return VDP_STATUS_NO_IMPLEMENTATION;
    486       }
    487       vlVdpVideoSurfaceClear(vlsurf);
    488    }
    489 
    490    for (i = 0; i < bitstream_buffer_count; ++i) {
    491       buffers[i] = bitstream_buffers[i].bitstream;
    492       sizes[i] = bitstream_buffers[i].bitstream_bytes;
    493    }
    494 
    495    memset(&desc, 0, sizeof(desc));
    496    desc.base.profile = dec->profile;
    497    switch (u_reduce_video_profile(dec->profile)) {
    498    case PIPE_VIDEO_CODEC_MPEG12:
    499       ret = vlVdpDecoderRenderMpeg12(&desc.mpeg12, (VdpPictureInfoMPEG1Or2 *)picture_info);
    500       break;
    501    case PIPE_VIDEO_CODEC_MPEG4:
    502       ret = vlVdpDecoderRenderMpeg4(&desc.mpeg4, (VdpPictureInfoMPEG4Part2 *)picture_info);
    503       break;
    504    case PIPE_VIDEO_CODEC_VC1:
    505       if (dec->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED)
    506          vlVdpDecoderFixVC1Startcode(&bitstream_buffer_count, buffers, sizes);
    507       ret = vlVdpDecoderRenderVC1(&desc.vc1, (VdpPictureInfoVC1 *)picture_info);
    508       break;
    509    case PIPE_VIDEO_CODEC_MPEG4_AVC:
    510       ret = vlVdpDecoderRenderH264(&desc.h264, (VdpPictureInfoH264 *)picture_info);
    511       break;
    512    default:
    513       pipe_mutex_unlock(vlsurf->device->mutex);
    514       return VDP_STATUS_INVALID_DECODER_PROFILE;
    515    }
    516 
    517    if (ret != VDP_STATUS_OK) {
    518       pipe_mutex_unlock(vlsurf->device->mutex);
    519       return ret;
    520    }
    521 
    522    dec->begin_frame(dec, vlsurf->video_buffer, &desc.base);
    523    dec->decode_bitstream(dec, vlsurf->video_buffer, &desc.base, bitstream_buffer_count, buffers, sizes);
    524    dec->end_frame(dec, vlsurf->video_buffer, &desc.base);
    525    pipe_mutex_unlock(vlsurf->device->mutex);
    526    return ret;
    527 }
    528