2 * gstvaapidecoder_mpeg2.c - MPEG-2 decoder
4 * Copyright (C) 2011 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
23 * SECTION:gstvaapidecoder_mpeg2
24 * @short_description: MPEG-2 decoder
29 #include <gst/base/gstbitreader.h>
30 #include <gst/codecparsers/gstmpegvideoparser.h>
31 #include "gstvaapidecoder_mpeg2.h"
32 #include "gstvaapidecoder_priv.h"
33 #include "gstvaapidisplay_priv.h"
34 #include "gstvaapiobject_priv.h"
37 #include "gstvaapidebug.h"
39 G_DEFINE_TYPE(GstVaapiDecoderMpeg2,
40 gst_vaapi_decoder_mpeg2,
41 GST_VAAPI_TYPE_DECODER);
43 #define GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(obj) \
44 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
45 GST_VAAPI_TYPE_DECODER_MPEG2, \
46 GstVaapiDecoderMpeg2Private))
48 #define READ_UINT8(br, val, nbits) G_STMT_START { \
49 if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
50 GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
55 struct _GstVaapiDecoderMpeg2Private {
56 GstVaapiProfile profile;
61 GstMpegVideoSequenceHdr seq_hdr;
62 GstMpegVideoSequenceExt seq_ext;
63 GstMpegVideoPictureHdr pic_hdr;
64 GstMpegVideoPictureExt pic_ext;
65 GstMpegVideoQuantMatrixExt quant_matrix_ext;
66 GstVaapiPicture *current_picture;
67 GstVaapiPicture *next_picture;
68 GstVaapiPicture *prev_picture;
70 GstBuffer *sub_buffer;
75 GstClockTime pts_diff;
76 guint is_constructed : 1;
78 guint is_first_field : 1;
79 guint has_seq_ext : 1;
80 guint has_seq_scalable_ext : 1;
81 guint has_pic_ext : 1;
82 guint has_quant_matrix_ext : 1;
83 guint size_changed : 1;
84 guint profile_changed : 1;
85 guint quant_matrix_changed : 1;
86 guint progressive_sequence : 1;
88 guint broken_link : 1;
92 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
94 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
95 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
97 if (priv->current_picture) {
98 gst_vaapi_decoder_free_picture(base_decoder, priv->current_picture);
99 priv->current_picture = NULL;
102 if (priv->next_picture) {
103 gst_vaapi_decoder_free_picture(base_decoder, priv->next_picture);
104 priv->next_picture = NULL;
107 if (priv->prev_picture) {
108 gst_vaapi_decoder_free_picture(base_decoder, priv->prev_picture);
109 priv->prev_picture = NULL;
112 if (priv->sub_buffer) {
113 gst_buffer_unref(priv->sub_buffer);
114 priv->sub_buffer = NULL;
118 gst_adapter_clear(priv->adapter);
119 g_object_unref(priv->adapter);
120 priv->adapter = NULL;
125 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
127 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
129 gst_vaapi_decoder_mpeg2_close(decoder);
131 priv->adapter = gst_adapter_new();
138 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
140 gst_vaapi_decoder_mpeg2_close(decoder);
144 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
146 if (!GST_VAAPI_DECODER_CODEC(decoder))
152 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
154 memcpy(dst, src, 64);
157 static GstVaapiDecoderStatus
158 ensure_context(GstVaapiDecoderMpeg2 *decoder)
160 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
161 GstVaapiProfile profiles[2];
162 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
163 guint i, n_profiles = 0;
164 gboolean reset_context = FALSE;
166 if (priv->profile_changed) {
167 GST_DEBUG("profile changed");
168 priv->profile_changed = FALSE;
169 reset_context = TRUE;
171 profiles[n_profiles++] = priv->profile;
172 if (priv->profile == GST_VAAPI_PROFILE_MPEG2_SIMPLE)
173 profiles[n_profiles++] = GST_VAAPI_PROFILE_MPEG2_MAIN;
175 for (i = 0; i < n_profiles; i++) {
176 if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
177 profiles[i], entrypoint))
181 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
182 priv->profile = profiles[i];
185 if (priv->size_changed) {
186 GST_DEBUG("size changed");
187 priv->size_changed = FALSE;
188 reset_context = TRUE;
190 if (priv->progressive_sequence)
191 priv->mb_height = (priv->height + 15) / 16;
193 priv->mb_height = (priv->height + 31) / 32 * 2;
197 reset_context = gst_vaapi_decoder_ensure_context(
198 GST_VAAPI_DECODER(decoder),
201 priv->width, priv->height
204 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
206 return GST_VAAPI_DECODER_STATUS_SUCCESS;
209 static GstVaapiDecoderStatus
210 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
212 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
213 VAIQMatrixBufferMPEG2 *iq_matrix;
214 guint8 *intra_quant_matrix = NULL;
215 guint8 *non_intra_quant_matrix = NULL;
216 guint8 *chroma_intra_quant_matrix = NULL;
217 guint8 *chroma_non_intra_quant_matrix = NULL;
219 if (!priv->quant_matrix_changed)
220 return GST_VAAPI_DECODER_STATUS_SUCCESS;
222 priv->quant_matrix_changed = FALSE;
224 picture->iq_matrix = gst_vaapi_decoder_new_iq_matrix(GST_VAAPI_DECODER(decoder));
225 if (!picture->iq_matrix) {
226 GST_DEBUG("failed to allocate IQ matrix");
227 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
229 iq_matrix = picture->iq_matrix->param;
231 intra_quant_matrix = priv->seq_hdr.intra_quantizer_matrix;
232 non_intra_quant_matrix = priv->seq_hdr.non_intra_quantizer_matrix;
233 if (priv->has_quant_matrix_ext) {
234 if (priv->quant_matrix_ext.load_intra_quantiser_matrix)
235 intra_quant_matrix = priv->quant_matrix_ext.intra_quantiser_matrix;
236 if (priv->quant_matrix_ext.load_non_intra_quantiser_matrix)
237 non_intra_quant_matrix = priv->quant_matrix_ext.non_intra_quantiser_matrix;
238 if (priv->quant_matrix_ext.load_chroma_intra_quantiser_matrix)
239 chroma_intra_quant_matrix = priv->quant_matrix_ext.chroma_intra_quantiser_matrix;
240 if (priv->quant_matrix_ext.load_chroma_non_intra_quantiser_matrix)
241 chroma_non_intra_quant_matrix = priv->quant_matrix_ext.chroma_non_intra_quantiser_matrix;
244 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
245 if (intra_quant_matrix) {
246 iq_matrix->load_intra_quantiser_matrix = 1;
247 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
251 iq_matrix->load_intra_quantiser_matrix = 1;
252 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
253 priv->seq_hdr.intra_quantizer_matrix);
255 iq_matrix->load_non_intra_quantiser_matrix = 1;
256 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
257 priv->seq_hdr.non_intra_quantizer_matrix);
259 iq_matrix->load_chroma_intra_quantiser_matrix = 0;
260 iq_matrix->load_chroma_non_intra_quantiser_matrix = 0;
261 if (priv->has_quant_matrix_ext) {
262 if (priv->quant_matrix_ext.load_intra_quantiser_matrix)
263 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
264 priv->quant_matrix_ext.intra_quantiser_matrix);
266 if (priv->quant_matrix_ext.load_non_intra_quantiser_matrix)
267 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
268 priv->quant_matrix_ext.non_intra_quantiser_matrix);
270 if (priv->quant_matrix_ext.load_chroma_intra_quantiser_matrix) {
271 iq_matrix->load_chroma_intra_quantiser_matrix = 1;
272 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
273 priv->quant_matrix_ext.chroma_intra_quantiser_matrix);
276 if (priv->quant_matrix_ext.load_chroma_non_intra_quantiser_matrix) {
277 iq_matrix->load_chroma_non_intra_quantiser_matrix = 1;
278 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
279 priv->quant_matrix_ext.chroma_non_intra_quantiser_matrix);
282 return GST_VAAPI_DECODER_STATUS_SUCCESS;
285 static inline GstVaapiDecoderStatus
286 render_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
288 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
290 if (!gst_vaapi_decoder_push_surface(base_decoder,
293 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
294 return GST_VAAPI_DECODER_STATUS_SUCCESS;
297 static GstVaapiDecoderStatus
298 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
300 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
301 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
302 GstVaapiPicture * const picture = priv->current_picture;
303 GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
306 if (!gst_vaapi_decoder_decode_picture(base_decoder, picture))
307 status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
308 if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
309 if ((priv->prev_picture && priv->next_picture) ||
310 (priv->closed_gop && priv->next_picture))
311 status = render_picture(decoder, picture);
312 gst_vaapi_decoder_free_picture(base_decoder, picture);
314 priv->current_picture = NULL;
319 static GstVaapiDecoderStatus
320 decode_sequence(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
322 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
323 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
324 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr;
326 if (!gst_mpeg_video_parse_sequence_header(seq_hdr, buf, buf_size, 0)) {
327 GST_DEBUG("failed to parse sequence header");
328 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
331 priv->fps_n = seq_hdr->fps_n;
332 priv->fps_d = seq_hdr->fps_d;
333 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
335 priv->seq_pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
337 priv->width = seq_hdr->width;
338 priv->height = seq_hdr->height;
339 priv->has_seq_ext = FALSE;
340 priv->size_changed = TRUE;
341 priv->quant_matrix_changed = TRUE;
342 priv->progressive_sequence = TRUE;
343 return GST_VAAPI_DECODER_STATUS_SUCCESS;
346 static GstVaapiDecoderStatus
347 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
349 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
350 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
351 GstMpegVideoSequenceExt * const seq_ext = &priv->seq_ext;
352 GstVaapiProfile profile;
355 if (!gst_mpeg_video_parse_sequence_extension(seq_ext, buf, buf_size, 0)) {
356 GST_DEBUG("failed to parse sequence-extension");
357 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
359 priv->has_seq_ext = TRUE;
360 priv->progressive_sequence = seq_ext->progressive;
362 width = (priv->width & 0xffff) | ((guint32)seq_ext->horiz_size_ext << 16);
363 height = (priv->height & 0xffff) | ((guint32)seq_ext->vert_size_ext << 16);
364 GST_DEBUG("video resolution %ux%u", width, height);
366 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
367 priv->fps_n *= seq_ext->fps_n_ext + 1;
368 priv->fps_d *= seq_ext->fps_d_ext + 1;
369 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
372 if (priv->width != width) {
374 priv->size_changed = TRUE;
377 if (priv->height != height) {
378 priv->height = height;
379 priv->size_changed = TRUE;
382 switch (seq_ext->profile) {
383 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
384 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
386 case GST_MPEG_VIDEO_PROFILE_MAIN:
387 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
390 GST_DEBUG("unsupported profile %d", seq_ext->profile);
391 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
393 if (priv->profile != profile) {
394 priv->profile = profile;
395 priv->profile_changed = TRUE;
397 return GST_VAAPI_DECODER_STATUS_SUCCESS;
400 static GstVaapiDecoderStatus
401 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
403 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
404 GstVaapiDecoderStatus status;
406 if (priv->current_picture) {
407 status = decode_current_picture(decoder);
408 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
410 status = render_picture(decoder, priv->current_picture);
411 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
415 if (priv->next_picture) {
416 status = render_picture(decoder, priv->next_picture);
417 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
420 return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
423 static GstVaapiDecoderStatus
424 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
426 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
427 GstMpegVideoQuantMatrixExt * const quant_matrix_ext = &priv->quant_matrix_ext;
429 if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix_ext, buf, buf_size, 0)) {
430 GST_DEBUG("failed to parse quant-matrix-extension");
431 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
433 priv->has_quant_matrix_ext = TRUE;
434 priv->quant_matrix_changed = TRUE;
435 return GST_VAAPI_DECODER_STATUS_SUCCESS;
438 static GstVaapiDecoderStatus
439 decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
441 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
445 if (!gst_mpeg_video_parse_gop(&gop, buf, buf_size, 0)) {
446 GST_DEBUG("failed to parse GOP");
447 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
450 priv->closed_gop = gop.closed_gop;
451 priv->broken_link = gop.broken_link;
453 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
454 gop.hour, gop.minute, gop.second, gop.frame,
455 priv->closed_gop, priv->broken_link);
457 pts = GST_SECOND * (gop.hour * 3600 + gop.minute * 60 + gop.second);
458 pts += gst_util_uint64_scale(gop.frame, GST_SECOND * priv->fps_d, priv->fps_n);
461 priv->pts_diff = priv->seq_pts - priv->gop_pts;
462 return GST_VAAPI_DECODER_STATUS_SUCCESS;
465 static GstVaapiDecoderStatus
466 decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
468 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
469 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
470 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
471 GstVaapiPicture *picture;
472 GstVaapiDecoderStatus status;
475 status = ensure_context(decoder);
476 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
477 GST_DEBUG("failed to reset context");
481 if (priv->current_picture) {
482 status = decode_current_picture(decoder);
483 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
487 priv->current_picture = gst_vaapi_decoder_new_picture(base_decoder);
488 if (!priv->current_picture) {
489 GST_DEBUG("failed to allocate picture");
490 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
492 picture = priv->current_picture;
494 status = ensure_quant_matrix(decoder, picture);
495 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
496 GST_DEBUG("failed to reset quantizer matrix");
500 if (!gst_mpeg_video_parse_picture_header(pic_hdr, buf, buf_size, 0)) {
501 GST_DEBUG("failed to parse picture header");
502 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
504 priv->has_pic_ext = FALSE;
506 switch (pic_hdr->pic_type) {
507 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
508 picture->type = GST_VAAPI_PICTURE_TYPE_I;
510 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
511 picture->type = GST_VAAPI_PICTURE_TYPE_P;
513 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
514 picture->type = GST_VAAPI_PICTURE_TYPE_B;
517 GST_DEBUG("unsupported picture type %d", pic_hdr->pic_type);
518 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
522 if (pic_hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_I)
523 priv->is_first_field = TRUE;
525 priv->is_first_field ^= 1;
527 /* Update presentation time */
529 pts += gst_util_uint64_scale(pic_hdr->tsn, GST_SECOND * priv->fps_d, priv->fps_n);
530 picture->pts = pts + priv->pts_diff;
532 /* Update reference pictures */
533 if (pic_hdr->pic_type != GST_MPEG_VIDEO_PICTURE_TYPE_B) {
534 picture->flags |= GST_VAAPI_PICTURE_REFERENCE;
535 if (priv->prev_picture) {
536 gst_vaapi_decoder_free_picture(base_decoder, priv->prev_picture);
537 priv->prev_picture = NULL;
539 if (priv->next_picture) {
540 priv->prev_picture = priv->next_picture;
541 priv->next_picture = NULL;
542 status = render_picture(decoder, priv->prev_picture);
544 priv->next_picture = picture;
549 static GstVaapiDecoderStatus
550 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
552 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
553 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
555 if (!gst_mpeg_video_parse_picture_extension(pic_ext, buf, buf_size, 0)) {
556 GST_DEBUG("failed to parse picture-extension");
557 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
559 priv->has_pic_ext = TRUE;
560 return GST_VAAPI_DECODER_STATUS_SUCCESS;
563 static inline guint32
564 pack_f_code(guint8 f_code[2][2])
566 return (((guint32)f_code[0][0] << 12) |
567 ((guint32)f_code[0][1] << 8) |
568 ((guint32)f_code[1][0] << 4) |
573 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
575 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
576 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
577 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
578 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
580 if (!priv->has_pic_ext)
583 /* Fill in VAPictureParameterBufferMPEG2 */
584 pic_param->horizontal_size = priv->width;
585 pic_param->vertical_size = priv->height;
586 pic_param->forward_reference_picture = VA_INVALID_ID;
587 pic_param->backward_reference_picture = VA_INVALID_ID;
588 pic_param->picture_coding_type = pic_hdr->pic_type;
589 pic_param->f_code = pack_f_code(pic_ext->f_code);
591 #define COPY_FIELD(a, b, f) \
592 pic_param->a.b.f = pic_ext->f
593 pic_param->picture_coding_extension.value = 0;
594 pic_param->picture_coding_extension.bits.is_first_field = priv->is_first_field;
595 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
596 COPY_FIELD(picture_coding_extension, bits, picture_structure);
597 COPY_FIELD(picture_coding_extension, bits, top_field_first);
598 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
599 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
600 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
601 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
602 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
603 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
604 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
606 switch (pic_hdr->pic_type) {
607 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
608 if (priv->next_picture)
609 pic_param->backward_reference_picture = priv->next_picture->surface_id;
611 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
612 if (priv->prev_picture)
613 pic_param->forward_reference_picture = priv->prev_picture->surface_id;
619 static GstVaapiDecoderStatus
621 GstVaapiDecoderMpeg2 *decoder,
627 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
628 GstVaapiPicture * const picture = priv->current_picture;
629 GstVaapiSlice *slice;
630 VASliceParameterBufferMPEG2 *slice_param;
631 GstVaapiDecoderStatus status;
633 guint8 slice_vertical_position_extension;
634 guint8 quantiser_scale_code;
635 guint8 intra_slice_flag, intra_slice = 0;
636 guint8 extra_bit_slice, junk8;
638 GST_DEBUG("slice %d @ %p, %u bytes)", slice_no, buf, buf_size);
640 if (picture->slices->len == 0 && !fill_picture(decoder, picture))
641 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
643 priv->mb_y = slice_no;
645 slice = gst_vaapi_decoder_new_slice(
646 GST_VAAPI_DECODER(decoder),
651 GST_DEBUG("failed to allocate slice");
652 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
656 gst_bit_reader_init(&br, buf, buf_size);
657 if (priv->height > 2800)
658 READ_UINT8(&br, slice_vertical_position_extension, 3);
659 if (priv->has_seq_scalable_ext) {
660 GST_DEBUG("failed to parse slice %d. Unsupported sequence_scalable_extension()", slice_no);
661 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
663 READ_UINT8(&br, quantiser_scale_code, 5);
664 READ_UINT8(&br, extra_bit_slice, 1);
665 if (extra_bit_slice == 1) {
666 READ_UINT8(&br, intra_slice_flag, 1);
667 if (intra_slice_flag) {
668 READ_UINT8(&br, intra_slice, 1);
669 READ_UINT8(&br, junk8, 7);
671 READ_UINT8(&br, extra_bit_slice, 1);
672 while (extra_bit_slice == 1) {
673 READ_UINT8(&br, junk8, 8);
674 READ_UINT8(&br, extra_bit_slice, 1);
678 /* Fill in VASliceParameterBufferMPEG2 */
679 slice_param = slice->param;
680 slice_param->macroblock_offset = gst_bit_reader_get_pos(&br);
681 slice_param->slice_horizontal_position = 0;
682 slice_param->slice_vertical_position = priv->mb_y;
683 slice_param->quantiser_scale_code = quantiser_scale_code;
684 slice_param->intra_slice_flag = intra_slice;
686 /* Commit picture for decoding if we reached the last slice */
687 if (++priv->mb_y >= priv->mb_height) {
688 status = decode_current_picture(decoder);
689 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
693 return GST_VAAPI_DECODER_STATUS_SUCCESS;
696 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
699 static GstVaapiDecoderStatus
700 decode_chunks(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer, GList *chunks)
702 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
703 GstMpegVideoTypeOffsetSize *tos;
704 GstVaapiDecoderStatus status;
705 guchar * const buf = GST_BUFFER_DATA(buffer);
706 const guint buf_size = GST_BUFFER_SIZE(buffer);
708 guint data_size, ofs, pos = 0;
711 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
712 for (l = chunks; l; l = g_list_next(l)) {
714 data = buf + tos->offset;
715 data_size = tos->size;
719 ofs = tos->offset - pos + tos->size;
720 if (gst_adapter_available(priv->adapter) >= ofs)
721 gst_adapter_flush(priv->adapter, ofs);
725 case GST_MPEG_VIDEO_PACKET_PICTURE:
726 status = decode_picture(decoder, data, data_size);
728 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
729 status = decode_sequence(decoder, data, data_size);
731 case GST_MPEG_VIDEO_PACKET_EXTENSION: {
732 const guchar id = data[0] >> 4;
734 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
735 status = decode_sequence_ext(decoder, data, data_size);
737 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
738 status = decode_quant_matrix_ext(decoder, data, data_size);
740 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
741 status = decode_picture_ext(decoder, data, data_size);
744 // Ignore unknown extensions
745 GST_DEBUG("unsupported start-code extension (0x%02x)", id);
750 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
751 status = decode_sequence_end(decoder);
753 case GST_MPEG_VIDEO_PACKET_GOP:
754 status = decode_gop(decoder, data, data_size);
756 case GST_MPEG_VIDEO_PACKET_USER_DATA:
757 // Ignore user-data packets
758 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
761 if (tos->type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
762 tos->type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
763 status = decode_slice(
765 tos->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN,
770 else if (tos->type >= 0xb9 && tos->type <= 0xff) {
771 // Ignore system start codes (PES headers)
772 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
775 GST_DEBUG("unsupported start code (0x%02x)", tos->type);
776 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
779 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
783 if (status == GST_VAAPI_DECODER_STATUS_SUCCESS && pos < buf_size)
784 priv->sub_buffer = gst_buffer_create_sub(buffer, pos, buf_size - pos);
788 static GstVaapiDecoderStatus
789 decode_buffer(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
791 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
792 GstVaapiDecoderStatus status;
797 buf = GST_BUFFER_DATA(buffer);
798 buf_size = GST_BUFFER_SIZE(buffer);
799 if (!buf && buf_size == 0)
800 return decode_sequence_end(decoder);
802 gst_buffer_ref(buffer);
803 gst_adapter_push(priv->adapter, buffer);
804 if (priv->sub_buffer) {
805 buffer = gst_buffer_merge(priv->sub_buffer, buffer);
807 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
808 gst_buffer_unref(priv->sub_buffer);
809 priv->sub_buffer = NULL;
812 buf = GST_BUFFER_DATA(buffer);
813 buf_size = GST_BUFFER_SIZE(buffer);
814 chunks = gst_mpeg_video_parse(buf, buf_size, 0);
816 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
818 status = decode_chunks(decoder, buffer, chunks);
819 g_list_free_full(chunks, (GDestroyNotify)g_free);
823 GstVaapiDecoderStatus
824 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base, GstBuffer *buffer)
826 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(base);
827 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
829 g_return_val_if_fail(priv->is_constructed,
830 GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
832 if (!priv->is_opened) {
833 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder, buffer);
834 if (!priv->is_opened)
835 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
837 return decode_buffer(decoder, buffer);
841 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
843 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
845 gst_vaapi_decoder_mpeg2_destroy(decoder);
847 G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
851 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
853 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
854 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
855 GObjectClass *parent_class;
857 parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
858 if (parent_class->constructed)
859 parent_class->constructed(object);
861 priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
865 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
867 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
868 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
870 g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
872 object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
873 object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
875 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
879 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
881 GstVaapiDecoderMpeg2Private *priv;
883 priv = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
884 decoder->priv = priv;
889 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
890 priv->current_picture = NULL;
891 priv->next_picture = NULL;
892 priv->prev_picture = NULL;
893 priv->adapter = NULL;
894 priv->sub_buffer = NULL;
897 priv->seq_pts = GST_CLOCK_TIME_NONE;
898 priv->gop_pts = GST_CLOCK_TIME_NONE;
900 priv->is_constructed = FALSE;
901 priv->is_opened = FALSE;
902 priv->is_first_field = FALSE;
903 priv->has_seq_ext = FALSE;
904 priv->has_seq_scalable_ext = FALSE;
905 priv->has_pic_ext = FALSE;
906 priv->has_quant_matrix_ext = FALSE;
907 priv->size_changed = FALSE;
908 priv->profile_changed = FALSE;
909 priv->quant_matrix_changed = FALSE;
910 priv->progressive_sequence = FALSE;
911 priv->closed_gop = FALSE;
912 priv->broken_link = FALSE;
916 * gst_vaapi_decoder_mpeg2_new:
917 * @display: a #GstVaapiDisplay
918 * @caps: a #GstCaps holding codec information
920 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
921 * hold extra information like codec-data and pictured coded size.
923 * Return value: the newly allocated #GstVaapiDecoder object
926 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
928 GstVaapiDecoderMpeg2 *decoder;
930 static const GstVaapiCodecInfo codec_info = {
931 .pic_size = sizeof(GstVaapiPicture),
932 .slice_size = sizeof(GstVaapiSlice),
933 .pic_param_size = sizeof(VAPictureParameterBufferMPEG2),
934 .slice_param_size = sizeof(VASliceParameterBufferMPEG2),
935 .iq_matrix_size = sizeof(VAIQMatrixBufferMPEG2),
938 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
939 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
941 decoder = g_object_new(
942 GST_VAAPI_TYPE_DECODER_MPEG2,
945 "codec-info", &codec_info,
948 if (!decoder->priv->is_constructed) {
949 g_object_unref(decoder);
952 return GST_VAAPI_DECODER_CAST(decoder);