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_objects.h"
33 #include "gstvaapidecoder_dpb.h"
34 #include "gstvaapidecoder_priv.h"
35 #include "gstvaapidisplay_priv.h"
36 #include "gstvaapiobject_priv.h"
39 #include "gstvaapidebug.h"
41 G_DEFINE_TYPE(GstVaapiDecoderMpeg2,
42 gst_vaapi_decoder_mpeg2,
43 GST_VAAPI_TYPE_DECODER);
45 #define GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(obj) \
46 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
47 GST_VAAPI_TYPE_DECODER_MPEG2, \
48 GstVaapiDecoderMpeg2Private))
50 #define READ_UINT8(br, val, nbits) G_STMT_START { \
51 if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
52 GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
57 #define SKIP(reader, nbits) G_STMT_START { \
58 if (!gst_bit_reader_skip (reader, nbits)) { \
59 GST_WARNING ("failed to skip nbits: %d", nbits); \
65 typedef struct _PTSGenerator PTSGenerator;
66 struct _PTSGenerator {
67 GstClockTime gop_pts; // Current GOP PTS
68 GstClockTime max_pts; // Max picture PTS
69 guint gop_tsn; // Absolute GOP TSN
70 guint max_tsn; // Max picture TSN, relative to last GOP TSN
71 guint ovl_tsn; // How many times TSN overflowed since GOP
72 guint lst_tsn; // Last picture TSN
78 pts_init(PTSGenerator *tsg)
80 tsg->gop_pts = GST_CLOCK_TIME_NONE;
81 tsg->max_pts = GST_CLOCK_TIME_NONE;
90 static inline GstClockTime
91 pts_get_duration(PTSGenerator *tsg, guint num_frames)
93 return gst_util_uint64_scale(num_frames,
94 GST_SECOND * tsg->fps_d, tsg->fps_n);
98 pts_get_poc(PTSGenerator *tsg)
100 return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
104 pts_set_framerate(PTSGenerator *tsg, guint fps_n, guint fps_d)
111 pts_sync(PTSGenerator *tsg, GstClockTime gop_pts)
115 if (!GST_CLOCK_TIME_IS_VALID(gop_pts) ||
116 (GST_CLOCK_TIME_IS_VALID(tsg->max_pts) && tsg->max_pts >= gop_pts)) {
117 /* Invalid GOP PTS, interpolate from the last known picture PTS */
118 if (GST_CLOCK_TIME_IS_VALID(tsg->max_pts)) {
119 gop_pts = tsg->max_pts + pts_get_duration(tsg, 1);
120 gop_tsn = tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->max_tsn + 1;
128 /* Interpolate GOP TSN from this valid PTS */
129 if (GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
130 gop_tsn = tsg->gop_tsn + gst_util_uint64_scale(
131 gop_pts - tsg->gop_pts + pts_get_duration(tsg, 1) - 1,
132 tsg->fps_n, GST_SECOND * tsg->fps_d);
137 tsg->gop_pts = gop_pts;
138 tsg->gop_tsn = gop_tsn;
145 pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
149 if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
152 pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
154 if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
157 if (tsg->max_tsn < pic_tsn)
158 tsg->max_tsn = pic_tsn;
159 else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
160 tsg->max_tsn = pic_tsn;
163 tsg->lst_tsn = pic_tsn;
167 struct _GstVaapiDecoderMpeg2Private {
168 GstVaapiProfile profile;
169 GstVaapiProfile hw_profile;
174 GstMpegVideoSequenceHdr seq_hdr;
175 GstMpegVideoSequenceExt seq_ext;
176 GstMpegVideoPictureHdr pic_hdr;
177 GstMpegVideoPictureExt pic_ext;
178 GstMpegVideoQuantMatrixExt quant_matrix_ext;
179 GstVaapiPicture *current_picture;
183 guint is_constructed : 1;
185 guint has_seq_ext : 1;
186 guint has_seq_scalable_ext : 1;
187 guint has_pic_ext : 1;
188 guint has_quant_matrix_ext : 1;
189 guint size_changed : 1;
190 guint profile_changed : 1;
191 guint quant_matrix_changed : 1;
192 guint progressive_sequence : 1;
193 guint closed_gop : 1;
194 guint broken_link : 1;
197 /* VLC decoder from gst-plugins-bad */
198 typedef struct _VLCTable VLCTable;
206 decode_vlc(GstBitReader *br, gint *res, const VLCTable *table, guint length)
212 for (i = 0; i < length; i++) {
213 if (cbits != table[i].cbits) {
214 cbits = table[i].cbits;
215 if (!gst_bit_reader_peek_bits_uint32(br, &value, cbits)) {
220 if (value == table[i].cword) {
223 *res = table[i].value;
227 GST_DEBUG("failed to find VLC code");
230 GST_WARNING("failed to decode VLC, returning");
235 GST_MPEG_VIDEO_MACROBLOCK_ESCAPE = -1,
238 /* Table B-1: Variable length codes for macroblock_address_increment */
239 static const VLCTable mpeg2_mbaddr_vlc_table[] = {
273 { GST_MPEG_VIDEO_MACROBLOCK_ESCAPE, 0x08, 11 }
277 gst_vaapi_decoder_mpeg2_clear_buffer(GstVaapiDecoder *base)
279 GstVaapiDecoderMpeg2* const decoder = GST_VAAPI_DECODER_MPEG2(base);
280 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
282 priv->closed_gop = FALSE;
283 priv->broken_link = FALSE;
285 gst_vaapi_picture_replace(&priv->current_picture, NULL);
287 pts_init(&priv->tsg);
288 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
291 gst_vaapi_dpb_flush(priv->dpb);
295 gst_adapter_clear(priv->adapter);
300 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
302 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
304 gst_vaapi_picture_replace(&priv->current_picture, NULL);
307 gst_vaapi_dpb_unref(priv->dpb);
312 gst_adapter_clear(priv->adapter);
313 g_object_unref(priv->adapter);
314 priv->adapter = NULL;
319 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
321 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
323 gst_vaapi_decoder_mpeg2_close(decoder);
325 priv->adapter = gst_adapter_new();
329 priv->dpb = gst_vaapi_dpb_mpeg2_new();
333 pts_init(&priv->tsg);
338 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
340 gst_vaapi_decoder_mpeg2_close(decoder);
344 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
346 if (!GST_VAAPI_DECODER_CODEC(decoder))
352 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
354 memcpy(dst, src, 64);
358 get_profile_str(GstVaapiProfile profile)
363 case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
364 case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
365 case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
366 default: str = "<unknown>"; break;
371 static GstVaapiProfile
372 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
374 GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
375 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
376 GstVaapiProfile profile = priv->profile;
379 /* Return immediately if the exact same profile was found */
380 if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
383 /* Otherwise, try to map to a higher profile */
385 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
386 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
388 case GST_VAAPI_PROFILE_MPEG2_MAIN:
389 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
391 case GST_VAAPI_PROFILE_MPEG2_HIGH:
392 // Try to map to main profile if no high profile specific bits used
393 if (priv->profile == profile &&
394 !priv->has_seq_scalable_ext &&
395 (priv->has_seq_ext && priv->seq_ext.chroma_format == 1)) {
396 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
401 profile = GST_VAAPI_PROFILE_UNKNOWN;
404 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
406 if (profile != priv->profile)
407 GST_INFO("forced %s profile to %s profile",
408 get_profile_str(priv->profile), get_profile_str(profile));
412 static GstVaapiDecoderStatus
413 ensure_context(GstVaapiDecoderMpeg2 *decoder)
415 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
416 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
417 gboolean reset_context = FALSE;
419 if (priv->profile_changed) {
420 GST_DEBUG("profile changed");
421 priv->profile_changed = FALSE;
422 reset_context = TRUE;
424 priv->hw_profile = get_profile(decoder, entrypoint);
425 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
426 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
429 if (priv->size_changed) {
430 GST_DEBUG("size changed");
431 priv->size_changed = FALSE;
432 reset_context = TRUE;
436 reset_context = gst_vaapi_decoder_ensure_context(
437 GST_VAAPI_DECODER(decoder),
442 GST_DECODER_DEFAULT_SURFACES_COUNT
445 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
447 return GST_VAAPI_DECODER_STATUS_SUCCESS;
450 static GstVaapiDecoderStatus
451 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
453 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
454 VAIQMatrixBufferMPEG2 *iq_matrix;
455 guint8 *intra_quant_matrix = NULL;
456 guint8 *non_intra_quant_matrix = NULL;
457 guint8 *chroma_intra_quant_matrix = NULL;
458 guint8 *chroma_non_intra_quant_matrix = NULL;
460 if (!priv->quant_matrix_changed)
461 return GST_VAAPI_DECODER_STATUS_SUCCESS;
463 priv->quant_matrix_changed = FALSE;
465 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
466 if (!picture->iq_matrix) {
467 GST_ERROR("failed to allocate IQ matrix");
468 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
470 iq_matrix = picture->iq_matrix->param;
472 intra_quant_matrix = priv->seq_hdr.intra_quantizer_matrix;
473 non_intra_quant_matrix = priv->seq_hdr.non_intra_quantizer_matrix;
474 if (priv->has_quant_matrix_ext) {
475 if (priv->quant_matrix_ext.load_intra_quantiser_matrix)
476 intra_quant_matrix = priv->quant_matrix_ext.intra_quantiser_matrix;
477 if (priv->quant_matrix_ext.load_non_intra_quantiser_matrix)
478 non_intra_quant_matrix = priv->quant_matrix_ext.non_intra_quantiser_matrix;
479 if (priv->quant_matrix_ext.load_chroma_intra_quantiser_matrix)
480 chroma_intra_quant_matrix = priv->quant_matrix_ext.chroma_intra_quantiser_matrix;
481 if (priv->quant_matrix_ext.load_chroma_non_intra_quantiser_matrix)
482 chroma_non_intra_quant_matrix = priv->quant_matrix_ext.chroma_non_intra_quantiser_matrix;
485 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
486 if (intra_quant_matrix)
487 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
490 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
491 if (non_intra_quant_matrix)
492 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
493 non_intra_quant_matrix);
495 iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
496 if (chroma_intra_quant_matrix)
497 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
498 chroma_intra_quant_matrix);
500 iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
501 if (chroma_non_intra_quant_matrix)
502 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
503 chroma_non_intra_quant_matrix);
504 return GST_VAAPI_DECODER_STATUS_SUCCESS;
508 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
510 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
511 GstVaapiPicture * const picture = priv->current_picture;
514 if (!gst_vaapi_picture_decode(picture))
516 if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
517 if (!gst_vaapi_dpb_add(priv->dpb, picture))
519 gst_vaapi_picture_replace(&priv->current_picture, NULL);
525 static GstVaapiDecoderStatus
526 decode_sequence(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
528 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
529 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
530 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr;
532 if (!gst_mpeg_video_parse_sequence_header(seq_hdr, buf, buf_size, 4)) {
533 GST_ERROR("failed to parse sequence header");
534 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
537 priv->fps_n = seq_hdr->fps_n;
538 priv->fps_d = seq_hdr->fps_d;
539 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
540 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
542 priv->width = seq_hdr->width;
543 priv->height = seq_hdr->height;
544 priv->has_seq_ext = FALSE;
545 priv->size_changed = TRUE;
546 priv->quant_matrix_changed = TRUE;
547 priv->progressive_sequence = TRUE;
548 return GST_VAAPI_DECODER_STATUS_SUCCESS;
551 static GstVaapiDecoderStatus
552 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
554 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
555 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
556 GstMpegVideoSequenceExt * const seq_ext = &priv->seq_ext;
557 GstVaapiProfile profile;
560 if (!gst_mpeg_video_parse_sequence_extension(seq_ext, buf, buf_size, 4)) {
561 GST_ERROR("failed to parse sequence-extension");
562 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
564 priv->has_seq_ext = TRUE;
565 priv->progressive_sequence = seq_ext->progressive;
566 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
568 width = (priv->width & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
569 height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext << 12);
570 GST_DEBUG("video resolution %ux%u", width, height);
572 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
573 priv->fps_n *= seq_ext->fps_n_ext + 1;
574 priv->fps_d *= seq_ext->fps_d_ext + 1;
575 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
576 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
579 if (priv->width != width) {
581 priv->size_changed = TRUE;
584 if (priv->height != height) {
585 priv->height = height;
586 priv->size_changed = TRUE;
589 switch (seq_ext->profile) {
590 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
591 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
593 case GST_MPEG_VIDEO_PROFILE_MAIN:
594 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
596 case GST_MPEG_VIDEO_PROFILE_HIGH:
597 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
600 GST_ERROR("unsupported profile %d", seq_ext->profile);
601 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
603 if (priv->profile != profile) {
604 priv->profile = profile;
605 priv->profile_changed = TRUE;
607 return GST_VAAPI_DECODER_STATUS_SUCCESS;
610 static GstVaapiDecoderStatus
611 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
613 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
615 if (priv->current_picture && !decode_current_picture(decoder))
616 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
618 gst_vaapi_dpb_flush(priv->dpb);
619 return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
622 static GstVaapiDecoderStatus
623 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
625 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
626 GstMpegVideoQuantMatrixExt * const quant_matrix_ext = &priv->quant_matrix_ext;
628 if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix_ext, buf, buf_size, 4)) {
629 GST_ERROR("failed to parse quant-matrix-extension");
630 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
632 priv->has_quant_matrix_ext = TRUE;
633 priv->quant_matrix_changed = TRUE;
634 return GST_VAAPI_DECODER_STATUS_SUCCESS;
637 static GstVaapiDecoderStatus
638 decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
640 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
644 if (!gst_mpeg_video_parse_gop(&gop, buf, buf_size, 4)) {
645 GST_ERROR("failed to parse GOP");
646 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
649 priv->closed_gop = gop.closed_gop;
650 priv->broken_link = gop.broken_link;
652 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
653 gop.hour, gop.minute, gop.second, gop.frame,
654 priv->closed_gop, priv->broken_link);
656 pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
657 pts_sync(&priv->tsg, pts);
658 return GST_VAAPI_DECODER_STATUS_SUCCESS;
661 static GstVaapiDecoderStatus
662 decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
664 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
665 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
666 GstVaapiPicture *picture;
667 GstVaapiDecoderStatus status;
670 status = ensure_context(decoder);
671 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
672 GST_ERROR("failed to reset context");
676 if (priv->current_picture && !decode_current_picture(decoder))
677 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
679 if (priv->current_picture) {
680 /* Re-use current picture where the first field was decoded */
681 picture = gst_vaapi_picture_new_field(priv->current_picture);
683 GST_ERROR("failed to allocate field picture");
684 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
688 /* Create new picture */
689 picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
691 GST_ERROR("failed to allocate picture");
692 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
695 gst_vaapi_picture_replace(&priv->current_picture, picture);
696 gst_vaapi_picture_unref(picture);
698 status = ensure_quant_matrix(decoder, picture);
699 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
700 GST_ERROR("failed to reset quantizer matrix");
704 if (!gst_mpeg_video_parse_picture_header(pic_hdr, buf, buf_size, 4)) {
705 GST_ERROR("failed to parse picture header");
706 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
708 priv->has_pic_ext = FALSE;
710 switch (pic_hdr->pic_type) {
711 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
712 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
713 picture->type = GST_VAAPI_PICTURE_TYPE_I;
715 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
716 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
717 picture->type = GST_VAAPI_PICTURE_TYPE_P;
719 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
720 picture->type = GST_VAAPI_PICTURE_TYPE_B;
723 GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
724 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
727 /* Update presentation time */
728 pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
729 picture->pts = pts_eval(&priv->tsg, pts, pic_hdr->tsn);
730 picture->poc = pts_get_poc(&priv->tsg);
734 static GstVaapiDecoderStatus
735 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
737 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
738 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
739 GstVaapiPicture * const picture = priv->current_picture;
741 if (!gst_mpeg_video_parse_picture_extension(pic_ext, buf, buf_size, 4)) {
742 GST_ERROR("failed to parse picture-extension");
743 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
745 priv->has_pic_ext = TRUE;
747 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
748 GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
749 pic_ext->progressive_frame = 1;
752 if (pic_ext->picture_structure == 0 ||
753 (pic_ext->progressive_frame &&
754 pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
755 GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
756 pic_ext->picture_structure);
757 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
760 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
761 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
762 if (pic_ext->top_field_first)
763 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
766 switch (pic_ext->picture_structure) {
767 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
768 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
770 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
771 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
773 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
774 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
778 /* Allocate dummy picture for first field based I-frame */
779 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
780 !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
781 gst_vaapi_dpb_size(priv->dpb) == 0) {
782 GstVaapiPicture *dummy_picture;
785 dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
786 if (!dummy_picture) {
787 GST_ERROR("failed to allocate dummy picture");
788 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
791 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
792 dummy_picture->pts = GST_CLOCK_TIME_NONE;
793 dummy_picture->poc = -1;
794 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
796 GST_VAAPI_PICTURE_FLAG_SET(
798 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
799 GST_VAAPI_PICTURE_FLAG_REFERENCE)
802 success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
803 gst_vaapi_picture_unref(dummy_picture);
805 GST_ERROR("failed to add dummy picture into DPB");
806 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
808 GST_INFO("allocated dummy picture for first field based I-frame");
810 return GST_VAAPI_DECODER_STATUS_SUCCESS;
813 static inline guint32
814 pack_f_code(guint8 f_code[2][2])
816 return (((guint32)f_code[0][0] << 12) |
817 ((guint32)f_code[0][1] << 8) |
818 ((guint32)f_code[1][0] << 4) |
823 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
825 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
826 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
827 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
828 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
829 GstVaapiPicture *prev_picture, *next_picture;
831 if (!priv->has_pic_ext)
834 /* Fill in VAPictureParameterBufferMPEG2 */
835 pic_param->horizontal_size = priv->width;
836 pic_param->vertical_size = priv->height;
837 pic_param->forward_reference_picture = VA_INVALID_ID;
838 pic_param->backward_reference_picture = VA_INVALID_ID;
839 pic_param->picture_coding_type = pic_hdr->pic_type;
840 pic_param->f_code = pack_f_code(pic_ext->f_code);
842 #define COPY_FIELD(a, b, f) \
843 pic_param->a.b.f = pic_ext->f
844 pic_param->picture_coding_extension.value = 0;
845 pic_param->picture_coding_extension.bits.is_first_field = GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
846 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
847 COPY_FIELD(picture_coding_extension, bits, picture_structure);
848 COPY_FIELD(picture_coding_extension, bits, top_field_first);
849 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
850 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
851 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
852 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
853 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
854 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
855 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
857 gst_vaapi_dpb_mpeg2_get_references(
864 switch (pic_hdr->pic_type) {
865 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
867 pic_param->backward_reference_picture = next_picture->surface_id;
869 pic_param->forward_reference_picture = prev_picture->surface_id;
870 else if (!priv->closed_gop)
871 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
873 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
875 pic_param->forward_reference_picture = prev_picture->surface_id;
881 static GstVaapiDecoderStatus
883 GstVaapiDecoderMpeg2 *decoder,
889 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
890 GstVaapiPicture * const picture = priv->current_picture;
891 GstVaapiSlice *slice;
892 VASliceParameterBufferMPEG2 *slice_param;
894 gint mb_x, mb_y, mb_inc;
895 guint macroblock_offset;
896 guint8 slice_vertical_position_extension;
897 guint8 quantiser_scale_code;
898 guint8 intra_slice = 0;
899 guint8 extra_bit_slice, junk8;
901 GST_DEBUG("slice %d @ %p, %u bytes)", slice_no, buf, buf_size);
903 if (picture->slices->len == 0 && !fill_picture(decoder, picture))
904 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
906 slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder, buf, buf_size);
908 GST_ERROR("failed to allocate slice");
909 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
911 gst_vaapi_picture_add_slice(picture, slice);
914 gst_bit_reader_init(&br, buf, buf_size);
915 SKIP(&br, 32); /* slice_start_code */
916 if (priv->height > 2800)
917 READ_UINT8(&br, slice_vertical_position_extension, 3);
918 if (priv->has_seq_scalable_ext) {
919 GST_ERROR("failed to parse slice %d. Unsupported sequence_scalable_extension()", slice_no);
920 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
922 READ_UINT8(&br, quantiser_scale_code, 5);
923 READ_UINT8(&br, extra_bit_slice, 1);
924 if (extra_bit_slice == 1) {
925 READ_UINT8(&br, intra_slice, 1);
926 READ_UINT8(&br, junk8, 7);
927 READ_UINT8(&br, extra_bit_slice, 1);
928 while (extra_bit_slice == 1) {
929 READ_UINT8(&br, junk8, 8);
930 READ_UINT8(&br, extra_bit_slice, 1);
933 macroblock_offset = gst_bit_reader_get_pos(&br);
938 if (!decode_vlc(&br, &mb_inc, mpeg2_mbaddr_vlc_table,
939 G_N_ELEMENTS(mpeg2_mbaddr_vlc_table))) {
940 GST_WARNING("failed to decode first macroblock_address_increment");
943 mb_x += mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
944 } while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
946 /* Fill in VASliceParameterBufferMPEG2 */
947 slice_param = slice->param;
948 slice_param->macroblock_offset = macroblock_offset;
949 slice_param->slice_horizontal_position = mb_x;
950 slice_param->slice_vertical_position = mb_y;
951 slice_param->quantiser_scale_code = quantiser_scale_code;
952 slice_param->intra_slice_flag = intra_slice;
953 return GST_VAAPI_DECODER_STATUS_SUCCESS;
956 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
960 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
962 return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
963 0xffffff00, 0x00000100,
968 static GstVaapiDecoderStatus
969 decode_buffer(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
971 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
972 GstVaapiDecoderStatus status;
974 guint buf_size, size;
979 buf = GST_BUFFER_DATA(buffer);
980 buf_size = GST_BUFFER_SIZE(buffer);
981 if (!buf && buf_size == 0)
982 return decode_sequence_end(decoder);
984 gst_adapter_push(priv->adapter, gst_buffer_ref(buffer));
986 size = gst_adapter_available(priv->adapter);
987 status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
991 ofs = scan_for_start_code(priv->adapter, 0, size, &start_code);
994 gst_adapter_flush(priv->adapter, ofs);
997 status = gst_vaapi_decoder_check_status(GST_VAAPI_DECODER(decoder));
998 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1003 ofs = scan_for_start_code(priv->adapter, 4, size - 4, NULL);
1006 buffer = gst_adapter_take_buffer(priv->adapter, ofs);
1010 // Ignore empty user-data packets
1011 if ((start_code & 0xff) == GST_MPEG_VIDEO_PACKET_USER_DATA)
1013 GST_ERROR("failed to get a valid packet (SC: 0x%08x)", start_code);
1014 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1018 buf = GST_BUFFER_DATA(buffer);
1019 buf_size = GST_BUFFER_SIZE(buffer);
1021 type = start_code & 0xff;
1023 case GST_MPEG_VIDEO_PACKET_PICTURE:
1024 if (!priv->width || !priv->height)
1026 status = decode_picture(decoder, buf, buf_size);
1028 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1029 status = decode_sequence(decoder, buf, buf_size);
1031 case GST_MPEG_VIDEO_PACKET_EXTENSION: {
1032 const guchar id = buf[4] >> 4;
1034 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1035 status = decode_sequence_ext(decoder, buf, buf_size);
1037 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1038 status = decode_quant_matrix_ext(decoder, buf, buf_size);
1040 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1041 if (!priv->width || !priv->height)
1043 status = decode_picture_ext(decoder, buf, buf_size);
1046 // Ignore unknown extensions
1047 GST_WARNING("unsupported start-code extension (0x%02x)", id);
1052 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1053 status = decode_sequence_end(decoder);
1055 case GST_MPEG_VIDEO_PACKET_GOP:
1056 status = decode_gop(decoder, buf, buf_size);
1058 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1059 // Ignore user-data packets
1060 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1063 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1064 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1065 if (!priv->current_picture)
1067 status = decode_slice(
1069 type - GST_MPEG_VIDEO_PACKET_SLICE_MIN,
1074 else if (type >= 0xb9 && type <= 0xff) {
1075 // Ignore system start codes (PES headers)
1076 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1079 GST_WARNING("unsupported start code (0x%02x)", type);
1080 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1083 gst_buffer_unref(buffer);
1084 } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
1088 GstVaapiDecoderStatus
1089 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base, GstBuffer *buffer)
1091 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(base);
1092 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1094 g_return_val_if_fail(priv->is_constructed,
1095 GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
1097 if (!priv->is_opened) {
1098 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder, buffer);
1099 if (!priv->is_opened)
1100 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1102 return decode_buffer(decoder, buffer);
1106 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
1108 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
1110 gst_vaapi_decoder_mpeg2_destroy(decoder);
1112 G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
1116 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
1118 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
1119 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1120 GObjectClass *parent_class;
1122 parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
1123 if (parent_class->constructed)
1124 parent_class->constructed(object);
1126 priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
1130 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1132 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
1133 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1135 g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
1137 object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
1138 object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
1140 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1141 decoder_class->clear_buffer = gst_vaapi_decoder_mpeg2_clear_buffer;
1145 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
1147 GstVaapiDecoderMpeg2Private *priv;
1149 priv = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
1150 decoder->priv = priv;
1155 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
1156 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
1157 priv->current_picture = NULL;
1158 priv->adapter = NULL;
1159 priv->is_constructed = FALSE;
1160 priv->is_opened = FALSE;
1161 priv->has_seq_ext = FALSE;
1162 priv->has_seq_scalable_ext = FALSE;
1163 priv->has_pic_ext = FALSE;
1164 priv->has_quant_matrix_ext = FALSE;
1165 priv->size_changed = FALSE;
1166 priv->profile_changed = TRUE; /* Allow fallbacks to work */
1167 priv->quant_matrix_changed = FALSE;
1168 priv->progressive_sequence = FALSE;
1169 priv->closed_gop = FALSE;
1170 priv->broken_link = FALSE;
1174 * gst_vaapi_decoder_mpeg2_new:
1175 * @display: a #GstVaapiDisplay
1176 * @caps: a #GstCaps holding codec information
1178 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1179 * hold extra information like codec-data and pictured coded size.
1181 * Return value: the newly allocated #GstVaapiDecoder object
1184 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1186 GstVaapiDecoderMpeg2 *decoder;
1188 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
1189 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
1191 decoder = g_object_new(
1192 GST_VAAPI_TYPE_DECODER_MPEG2,
1197 if (!decoder->priv->is_constructed) {
1198 g_object_unref(decoder);
1201 return GST_VAAPI_DECODER_CAST(decoder);