static struct vl_mpeg12_buffer *
vl_mpeg12_get_decode_buffer(struct vl_mpeg12_decoder *dec, struct pipe_video_buffer *target)
{
   struct vl_mpeg12_buffer *buffer;

   assert(dec);

   buffer = vl_video_buffer_get_associated_data(target, &dec->base);
   if (buffer)
      return buffer;

   buffer = dec->dec_buffers[dec->current_buffer];
   if (buffer)
      return buffer;

   buffer = CALLOC_STRUCT(vl_mpeg12_buffer);
   if (buffer == NULL)
      return NULL;

   if (!vl_vb_init(&buffer->vertex_stream, dec->base.context,
                   dec->base.width / VL_MACROBLOCK_WIDTH,
                   dec->base.height / VL_MACROBLOCK_HEIGHT))
      goto error_vertex_buffer;

   if (!init_mc_buffer(dec, buffer))
      goto error_mc;

   if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
      if (!init_idct_buffer(dec, buffer))
         goto error_idct;

   if (!init_zscan_buffer(dec, buffer))
      goto error_zscan;

   if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
      vl_mpg12_bs_init(&buffer->bs, &dec->base);

   if (dec->expect_chunked_decode)
      vl_video_buffer_set_associated_data(target, &dec->base,
                                          buffer, vl_mpeg12_destroy_buffer);
   else
      dec->dec_buffers[dec->current_buffer] = buffer;

   return buffer;

error_zscan:
   cleanup_idct_buffer(buffer);

error_idct:
   cleanup_mc_buffer(buffer);

error_mc:
   vl_vb_cleanup(&buffer->vertex_stream);

error_vertex_buffer:
   FREE(buffer);
   return NULL;
}
static void
vl_video_buffer_destroy(struct pipe_video_buffer *buffer)
{
   struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
   unsigned i;

   assert(buf);

   for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
      pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
      pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
      pipe_resource_reference(&buf->resources[i], NULL);
   }

   for (i = 0; i < VL_NUM_COMPONENTS * 2; ++i)
      pipe_surface_reference(&buf->surfaces[i], NULL);

   vl_video_buffer_set_associated_data(buffer, NULL, NULL, NULL);

   FREE(buffer);
}