2 * gstvaapidecoder_vp8.c - VP8 decoder
4 * Copyright (C) 2013-2014 Intel Corporation
5 * Author: Halley Zhao <halley.zhao@intel.com>
6 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1
11 * of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA
25 * SECTION:gstvaapidecoder_vp8
26 * @short_description: VP8 decoder
30 #include <gst/codecparsers/gstvp8parser.h>
31 #include "gstvaapidecoder_vp8.h"
32 #include "gstvaapidecoder_objects.h"
33 #include "gstvaapidecoder_priv.h"
34 #include "gstvaapidisplay_priv.h"
35 #include "gstvaapiobject_priv.h"
37 #include "gstvaapicompat.h"
38 #include <va/va_dec_vp8.h>
41 #include "gstvaapidebug.h"
43 #define GST_VAAPI_DECODER_VP8_CAST(decoder) \
44 ((GstVaapiDecoderVp8 *)(decoder))
46 typedef struct _GstVaapiDecoderVp8Private GstVaapiDecoderVp8Private;
47 typedef struct _GstVaapiDecoderVp8Class GstVaapiDecoderVp8Class;
49 struct _GstVaapiDecoderVp8Private
51 GstVaapiProfile profile;
55 GstVp8FrameHdr frame_hdr;
56 GstVaapiPicture *last_picture;
57 GstVaapiPicture *golden_ref_picture;
58 GstVaapiPicture *alt_ref_picture;
59 GstVaapiPicture *current_picture;
66 * A decoder based on Vp8.
68 struct _GstVaapiDecoderVp8
71 GstVaapiDecoder parent_instance;
73 GstVaapiDecoderVp8Private priv;
77 * GstVaapiDecoderVp8Class:
79 * A decoder class based on Vp8.
81 struct _GstVaapiDecoderVp8Class
84 GstVaapiDecoderClass parent_class;
87 static GstVaapiDecoderStatus
88 get_status (GstVp8ParserResult result)
90 GstVaapiDecoderStatus status;
93 case GST_VP8_PARSER_OK:
94 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
96 case GST_VP8_PARSER_ERROR:
97 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
100 status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
107 gst_vaapi_decoder_vp8_close (GstVaapiDecoderVp8 * decoder)
109 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
111 gst_vaapi_picture_replace (&priv->last_picture, NULL);
112 gst_vaapi_picture_replace (&priv->golden_ref_picture, NULL);
113 gst_vaapi_picture_replace (&priv->alt_ref_picture, NULL);
114 gst_vaapi_picture_replace (&priv->current_picture, NULL);
118 gst_vaapi_decoder_vp8_open (GstVaapiDecoderVp8 * decoder)
120 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
122 gst_vaapi_decoder_vp8_close (decoder);
123 gst_vp8_parser_init (&priv->parser);
128 gst_vaapi_decoder_vp8_destroy (GstVaapiDecoder * base_decoder)
130 GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
132 gst_vaapi_decoder_vp8_close (decoder);
136 gst_vaapi_decoder_vp8_create (GstVaapiDecoder * base_decoder)
138 GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
139 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
141 if (!gst_vaapi_decoder_vp8_open (decoder))
144 priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
148 static GstVaapiDecoderStatus
149 ensure_context (GstVaapiDecoderVp8 * decoder)
151 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
152 const GstVaapiProfile profile = GST_VAAPI_PROFILE_VP8;
153 const GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
154 gboolean reset_context = FALSE;
156 if (priv->profile != profile) {
157 if (!gst_vaapi_display_has_decoder (GST_VAAPI_DECODER_DISPLAY (decoder),
158 profile, entrypoint))
159 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
161 priv->profile = profile;
162 reset_context = TRUE;
165 if (priv->size_changed) {
166 GST_DEBUG ("size changed");
167 priv->size_changed = FALSE;
168 reset_context = TRUE;
172 GstVaapiContextInfo info;
174 info.profile = priv->profile;
175 info.entrypoint = entrypoint;
176 info.chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
177 info.width = priv->width;
178 info.height = priv->height;
181 gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info);
184 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
186 return GST_VAAPI_DECODER_STATUS_SUCCESS;
189 static GstVaapiDecoderStatus
190 ensure_quant_matrix (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
192 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
193 GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
194 GstVp8Segmentation *const seg = &priv->parser.segmentation;
195 VAIQMatrixBufferVP8 *iq_matrix;
196 const gint8 QI_MAX = 127;
200 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (VP8, decoder);
201 if (!picture->iq_matrix) {
202 GST_ERROR ("failed to allocate IQ matrix");
203 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
205 iq_matrix = picture->iq_matrix->param;
207 /* Fill in VAIQMatrixBufferVP8 */
208 for (i = 0; i < 4; i++) {
209 if (seg->segmentation_enabled) {
210 qi_base = seg->quantizer_update_value[i];
211 if (!seg->segment_feature_mode) // 0 means delta update
212 qi_base += frame_hdr->quant_indices.y_ac_qi;
214 qi_base = frame_hdr->quant_indices.y_ac_qi;
217 iq_matrix->quantization_index[i][0] = CLAMP (qi, 0, QI_MAX);
218 qi = qi_base + frame_hdr->quant_indices.y_dc_delta;
219 iq_matrix->quantization_index[i][1] = CLAMP (qi, 0, QI_MAX);
220 qi = qi_base + frame_hdr->quant_indices.y2_dc_delta;
221 iq_matrix->quantization_index[i][2] = CLAMP (qi, 0, QI_MAX);
222 qi = qi_base + frame_hdr->quant_indices.y2_ac_delta;
223 iq_matrix->quantization_index[i][3] = CLAMP (qi, 0, QI_MAX);
224 qi = qi_base + frame_hdr->quant_indices.uv_dc_delta;
225 iq_matrix->quantization_index[i][4] = CLAMP (qi, 0, QI_MAX);
226 qi = qi_base + frame_hdr->quant_indices.uv_ac_delta;
227 iq_matrix->quantization_index[i][5] = CLAMP (qi, 0, QI_MAX);
229 return GST_VAAPI_DECODER_STATUS_SUCCESS;
232 static GstVaapiDecoderStatus
233 ensure_probability_table (GstVaapiDecoderVp8 * decoder,
234 GstVaapiPicture * picture)
236 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
237 GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
238 VAProbabilityDataBufferVP8 *prob_table;
240 picture->prob_table = GST_VAAPI_PROBABILITY_TABLE_NEW (VP8, decoder);
241 if (!picture->prob_table) {
242 GST_ERROR ("failed to allocate probality table");
243 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
245 prob_table = picture->prob_table->param;
247 /* Fill in VAProbabilityDataBufferVP8 */
248 memcpy (prob_table->dct_coeff_probs, frame_hdr->token_probs.prob,
249 sizeof (frame_hdr->token_probs.prob));
251 return GST_VAAPI_DECODER_STATUS_SUCCESS;
255 init_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
257 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
258 GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
260 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
261 picture->type = frame_hdr->key_frame ? GST_VAAPI_PICTURE_TYPE_I :
262 GST_VAAPI_PICTURE_TYPE_P;
263 picture->pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;
265 if (!frame_hdr->show_frame)
266 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
270 fill_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
272 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
273 VAPictureParameterBufferVP8 *const pic_param = picture->param;
274 GstVp8Parser *const parser = &priv->parser;
275 GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
276 GstVp8Segmentation *const seg = &parser->segmentation;
279 /* Fill in VAPictureParameterBufferVP8 */
280 pic_param->frame_width = priv->width;
281 pic_param->frame_height = priv->height;
283 pic_param->last_ref_frame = VA_INVALID_SURFACE;
284 pic_param->golden_ref_frame = VA_INVALID_SURFACE;
285 pic_param->alt_ref_frame = VA_INVALID_SURFACE;
286 if (!frame_hdr->key_frame) {
287 if (priv->last_picture)
288 pic_param->last_ref_frame = priv->last_picture->surface_id;
289 if (priv->golden_ref_picture)
290 pic_param->golden_ref_frame = priv->golden_ref_picture->surface_id;
291 if (priv->alt_ref_picture)
292 pic_param->alt_ref_frame = priv->alt_ref_picture->surface_id;
294 pic_param->out_of_loop_frame = VA_INVALID_SURFACE; // not used currently
296 pic_param->pic_fields.value = 0;
297 pic_param->pic_fields.bits.key_frame = !frame_hdr->key_frame;
298 pic_param->pic_fields.bits.version = frame_hdr->version;
299 pic_param->pic_fields.bits.segmentation_enabled = seg->segmentation_enabled;
300 pic_param->pic_fields.bits.update_mb_segmentation_map =
301 seg->update_mb_segmentation_map;
302 pic_param->pic_fields.bits.update_segment_feature_data =
303 seg->update_segment_feature_data;
304 pic_param->pic_fields.bits.filter_type = frame_hdr->filter_type;
305 pic_param->pic_fields.bits.sharpness_level = frame_hdr->sharpness_level;
306 pic_param->pic_fields.bits.loop_filter_adj_enable =
307 parser->mb_lf_adjust.loop_filter_adj_enable;
308 pic_param->pic_fields.bits.mode_ref_lf_delta_update =
309 parser->mb_lf_adjust.mode_ref_lf_delta_update;
310 pic_param->pic_fields.bits.sign_bias_golden = frame_hdr->sign_bias_golden;
311 pic_param->pic_fields.bits.sign_bias_alternate =
312 frame_hdr->sign_bias_alternate;
313 pic_param->pic_fields.bits.mb_no_coeff_skip = frame_hdr->mb_no_skip_coeff;
315 for (i = 0; i < 3; i++)
316 pic_param->mb_segment_tree_probs[i] = seg->segment_prob[i];
318 for (i = 0; i < 4; i++) {
320 if (seg->segmentation_enabled) {
321 level = seg->lf_update_value[i];
322 if (!seg->segment_feature_mode) // 0 means delta update
323 level += frame_hdr->loop_filter_level;
325 level = frame_hdr->loop_filter_level;
326 pic_param->loop_filter_level[i] = CLAMP (level, 0, 63);
328 pic_param->loop_filter_deltas_ref_frame[i] =
329 parser->mb_lf_adjust.ref_frame_delta[i];
330 pic_param->loop_filter_deltas_mode[i] =
331 parser->mb_lf_adjust.mb_mode_delta[i];
334 /* In decoding, the only loop filter settings that matter are those
335 in the frame header (9.1) */
336 pic_param->pic_fields.bits.loop_filter_disable =
337 frame_hdr->loop_filter_level == 0;
339 pic_param->prob_skip_false = frame_hdr->prob_skip_false;
340 pic_param->prob_intra = frame_hdr->prob_intra;
341 pic_param->prob_last = frame_hdr->prob_last;
342 pic_param->prob_gf = frame_hdr->prob_gf;
344 memcpy (pic_param->y_mode_probs, frame_hdr->mode_probs.y_prob,
345 sizeof (frame_hdr->mode_probs.y_prob));
346 memcpy (pic_param->uv_mode_probs, frame_hdr->mode_probs.uv_prob,
347 sizeof (frame_hdr->mode_probs.uv_prob));
348 memcpy (pic_param->mv_probs, frame_hdr->mv_probs.prob,
349 sizeof (frame_hdr->mv_probs));
351 pic_param->bool_coder_ctx.range = frame_hdr->rd_range;
352 pic_param->bool_coder_ctx.value = frame_hdr->rd_value;
353 pic_param->bool_coder_ctx.count = frame_hdr->rd_count;
359 fill_slice (GstVaapiDecoderVp8 * decoder, GstVaapiSlice * slice)
361 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
362 VASliceParameterBufferVP8 *const slice_param = slice->param;
363 GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
366 /* Fill in VASliceParameterBufferVP8 */
367 slice_param->slice_data_offset = frame_hdr->data_chunk_size;
368 slice_param->macroblock_offset = frame_hdr->header_size;
369 slice_param->num_of_partitions =
370 (1 << frame_hdr->log2_nbr_of_dct_partitions) + 1;
372 slice_param->partition_size[0] =
373 frame_hdr->first_part_size - ((slice_param->macroblock_offset + 7) >> 3);
374 for (i = 1; i < slice_param->num_of_partitions; i++)
375 slice_param->partition_size[i] = frame_hdr->partition_size[i - 1];
376 for (; i < G_N_ELEMENTS (slice_param->partition_size); i++)
377 slice_param->partition_size[i] = 0;
382 static GstVaapiDecoderStatus
383 decode_slice (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture,
384 const guchar * buf, guint buf_size)
386 GstVaapiSlice *slice;
388 slice = GST_VAAPI_SLICE_NEW (VP8, decoder, buf, buf_size);
390 GST_ERROR ("failed to allocate slice");
391 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
394 if (!fill_slice (decoder, slice)) {
395 gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (slice));
396 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
399 gst_vaapi_picture_add_slice (GST_VAAPI_PICTURE_CAST (picture), slice);
400 return GST_VAAPI_DECODER_STATUS_SUCCESS;
403 static GstVaapiDecoderStatus
404 decode_picture (GstVaapiDecoderVp8 * decoder, const guchar * buf,
407 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
408 GstVaapiPicture *picture;
409 GstVaapiDecoderStatus status;
411 status = ensure_context (decoder);
412 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
415 /* Create new picture */
416 picture = GST_VAAPI_PICTURE_NEW (VP8, decoder);
418 GST_ERROR ("failed to allocate picture");
419 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
421 gst_vaapi_picture_replace (&priv->current_picture, picture);
422 gst_vaapi_picture_unref (picture);
424 status = ensure_quant_matrix (decoder, picture);
425 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
428 status = ensure_probability_table (decoder, picture);
429 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
432 init_picture (decoder, picture);
433 if (!fill_picture (decoder, picture))
434 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
436 return decode_slice (decoder, picture, buf, buf_size);
440 update_ref_frames (GstVaapiDecoderVp8 * decoder)
442 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
443 GstVaapiPicture *picture = priv->current_picture;
444 GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
446 // update picture reference
447 if (frame_hdr->key_frame) {
448 gst_vaapi_picture_replace (&priv->golden_ref_picture, picture);
449 gst_vaapi_picture_replace (&priv->alt_ref_picture, picture);
451 // process refresh_alternate_frame/copy_buffer_to_alternate first
452 if (frame_hdr->refresh_alternate_frame) {
453 gst_vaapi_picture_replace (&priv->alt_ref_picture, picture);
455 switch (frame_hdr->copy_buffer_to_alternate) {
460 gst_vaapi_picture_replace (&priv->alt_ref_picture,
464 gst_vaapi_picture_replace (&priv->alt_ref_picture,
465 priv->golden_ref_picture);
469 ("WARNING: VP8 decoder: unrecognized copy_buffer_to_alternate");
473 if (frame_hdr->refresh_golden_frame) {
474 gst_vaapi_picture_replace (&priv->golden_ref_picture, picture);
476 switch (frame_hdr->copy_buffer_to_golden) {
481 gst_vaapi_picture_replace (&priv->golden_ref_picture,
485 gst_vaapi_picture_replace (&priv->golden_ref_picture,
486 priv->alt_ref_picture);
490 ("WARNING: VP8 decoder: unrecognized copy_buffer_to_golden");
494 if (frame_hdr->key_frame || frame_hdr->refresh_last)
495 gst_vaapi_picture_replace (&priv->last_picture, picture);
498 static GstVaapiDecoderStatus
499 decode_current_picture (GstVaapiDecoderVp8 * decoder)
501 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
502 GstVaapiPicture *const picture = priv->current_picture;
505 return GST_VAAPI_DECODER_STATUS_SUCCESS;
507 update_ref_frames (decoder);
508 if (!gst_vaapi_picture_decode (picture))
510 if (!gst_vaapi_picture_output (picture))
512 gst_vaapi_picture_replace (&priv->current_picture, NULL);
513 return GST_VAAPI_DECODER_STATUS_SUCCESS;
516 /* XXX: fix for cases where first field failed to be decoded */
517 gst_vaapi_picture_replace (&priv->current_picture, NULL);
518 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
521 static GstVaapiDecoderStatus
522 parse_frame_header (GstVaapiDecoderVp8 * decoder, const guchar * buf,
523 guint buf_size, GstVp8FrameHdr * frame_hdr)
525 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
526 GstVp8ParserResult result;
528 memset (frame_hdr, 0, sizeof (*frame_hdr));
529 result = gst_vp8_parser_parse_frame_header (&priv->parser, frame_hdr,
531 if (result != GST_VP8_PARSER_OK)
532 return get_status (result);
534 if (frame_hdr->key_frame &&
535 (frame_hdr->width != priv->width || frame_hdr->height != priv->height)) {
536 priv->width = frame_hdr->width;
537 priv->height = frame_hdr->height;
538 priv->size_changed = TRUE;
540 return GST_VAAPI_DECODER_STATUS_SUCCESS;
543 static GstVaapiDecoderStatus
544 gst_vaapi_decoder_vp8_parse (GstVaapiDecoder * base_decoder,
545 GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
549 unit->size = gst_adapter_available (adapter);
551 /* The whole frame is available */
552 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
553 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
554 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
555 GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
556 return GST_VAAPI_DECODER_STATUS_SUCCESS;
560 static GstVaapiDecoderStatus
561 decode_buffer (GstVaapiDecoderVp8 * decoder, const guchar * buf, guint buf_size)
563 GstVaapiDecoderVp8Private *const priv = &decoder->priv;
564 GstVaapiDecoderStatus status;
566 status = parse_frame_header (decoder, buf, buf_size, &priv->frame_hdr);
567 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
570 return decode_picture (decoder, buf, buf_size);
573 GstVaapiDecoderStatus
574 gst_vaapi_decoder_vp8_decode (GstVaapiDecoder * base_decoder,
575 GstVaapiDecoderUnit * unit)
577 GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
578 GstVaapiDecoderStatus status;
579 GstBuffer *const buffer =
580 GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
583 if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
584 GST_ERROR ("failed to map buffer");
585 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
588 status = decode_buffer (decoder, map_info.data + unit->offset, unit->size);
589 gst_buffer_unmap (buffer, &map_info);
590 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
592 return GST_VAAPI_DECODER_STATUS_SUCCESS;
595 static GstVaapiDecoderStatus
596 gst_vaapi_decoder_vp8_start_frame (GstVaapiDecoder * base_decoder,
597 GstVaapiDecoderUnit * base_unit)
599 return GST_VAAPI_DECODER_STATUS_SUCCESS;
602 static GstVaapiDecoderStatus
603 gst_vaapi_decoder_vp8_end_frame (GstVaapiDecoder * base_decoder)
605 GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
607 return decode_current_picture (decoder);
610 static GstVaapiDecoderStatus
611 gst_vaapi_decoder_vp8_flush (GstVaapiDecoder * base_decoder)
613 return GST_VAAPI_DECODER_STATUS_SUCCESS;
617 gst_vaapi_decoder_vp8_class_init (GstVaapiDecoderVp8Class * klass)
619 GstVaapiMiniObjectClass *const object_class =
620 GST_VAAPI_MINI_OBJECT_CLASS (klass);
621 GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
623 object_class->size = sizeof (GstVaapiDecoderVp8);
624 object_class->finalize = (GDestroyNotify) gst_vaapi_decoder_finalize;
626 decoder_class->create = gst_vaapi_decoder_vp8_create;
627 decoder_class->destroy = gst_vaapi_decoder_vp8_destroy;
628 decoder_class->parse = gst_vaapi_decoder_vp8_parse;
629 decoder_class->decode = gst_vaapi_decoder_vp8_decode;
630 decoder_class->start_frame = gst_vaapi_decoder_vp8_start_frame;
631 decoder_class->end_frame = gst_vaapi_decoder_vp8_end_frame;
632 decoder_class->flush = gst_vaapi_decoder_vp8_flush;
635 static inline const GstVaapiDecoderClass *
636 gst_vaapi_decoder_vp8_class (void)
638 static GstVaapiDecoderVp8Class g_class;
639 static gsize g_class_init = FALSE;
641 if (g_once_init_enter (&g_class_init)) {
642 gst_vaapi_decoder_vp8_class_init (&g_class);
643 g_once_init_leave (&g_class_init, TRUE);
645 return GST_VAAPI_DECODER_CLASS (&g_class);
649 * gst_vaapi_decoder_vp8_new:
650 * @display: a #GstVaapiDisplay
651 * @caps: a #GstCaps holding codec information
653 * Creates a new #GstVaapiDecoder for VP8 decoding. The @caps can
654 * hold extra information like codec-data and pictured coded size.
656 * Return value: the newly allocated #GstVaapiDecoder object
659 gst_vaapi_decoder_vp8_new (GstVaapiDisplay * display, GstCaps * caps)
661 return gst_vaapi_decoder_new (gst_vaapi_decoder_vp8_class (), display, caps);