2 * gstvaapidecoder_mpeg2.c - MPEG-2 decoder
4 * Copyright (C) 2011-2012 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 /* ------------------------------------------------------------------------- */
42 /* --- VLC Reader --- */
43 /* ------------------------------------------------------------------------- */
45 #define READ_UINT8(br, val, nbits) G_STMT_START { \
46 if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
47 GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
52 #define SKIP(reader, nbits) G_STMT_START { \
53 if (!gst_bit_reader_skip (reader, nbits)) { \
54 GST_WARNING ("failed to skip nbits: %d", nbits); \
59 /* VLC decoder from gst-plugins-bad */
60 typedef struct _VLCTable VLCTable;
68 decode_vlc(GstBitReader *br, gint *res, const VLCTable *table, guint length)
74 for (i = 0; i < length; i++) {
75 if (cbits != table[i].cbits) {
76 cbits = table[i].cbits;
77 if (!gst_bit_reader_peek_bits_uint32(br, &value, cbits)) {
82 if (value == table[i].cword) {
85 *res = table[i].value;
89 GST_DEBUG("failed to find VLC code");
92 GST_WARNING("failed to decode VLC, returning");
97 GST_MPEG_VIDEO_MACROBLOCK_ESCAPE = -1,
100 /* Table B-1: Variable length codes for macroblock_address_increment */
101 static const VLCTable mpeg2_mbaddr_vlc_table[] = {
135 { GST_MPEG_VIDEO_MACROBLOCK_ESCAPE, 0x08, 11 }
138 /* ------------------------------------------------------------------------- */
139 /* --- PTS Generator --- */
140 /* ------------------------------------------------------------------------- */
142 typedef struct _PTSGenerator PTSGenerator;
143 struct _PTSGenerator {
144 GstClockTime gop_pts; // Current GOP PTS
145 GstClockTime max_pts; // Max picture PTS
146 guint gop_tsn; // Absolute GOP TSN
147 guint max_tsn; // Max picture TSN, relative to last GOP TSN
148 guint ovl_tsn; // How many times TSN overflowed since GOP
149 guint lst_tsn; // Last picture TSN
155 pts_init(PTSGenerator *tsg)
157 tsg->gop_pts = GST_CLOCK_TIME_NONE;
158 tsg->max_pts = GST_CLOCK_TIME_NONE;
167 static inline GstClockTime
168 pts_get_duration(PTSGenerator *tsg, guint num_frames)
170 return gst_util_uint64_scale(num_frames,
171 GST_SECOND * tsg->fps_d, tsg->fps_n);
175 pts_get_poc(PTSGenerator *tsg)
177 return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
181 pts_set_framerate(PTSGenerator *tsg, guint fps_n, guint fps_d)
188 pts_sync(PTSGenerator *tsg, GstClockTime gop_pts)
192 if (!GST_CLOCK_TIME_IS_VALID(gop_pts) ||
193 (GST_CLOCK_TIME_IS_VALID(tsg->max_pts) && tsg->max_pts >= gop_pts)) {
194 /* Invalid GOP PTS, interpolate from the last known picture PTS */
195 if (GST_CLOCK_TIME_IS_VALID(tsg->max_pts)) {
196 gop_pts = tsg->max_pts + pts_get_duration(tsg, 1);
197 gop_tsn = tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->max_tsn + 1;
205 /* Interpolate GOP TSN from this valid PTS */
206 if (GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
207 gop_tsn = tsg->gop_tsn + gst_util_uint64_scale(
208 gop_pts - tsg->gop_pts + pts_get_duration(tsg, 1) - 1,
209 tsg->fps_n, GST_SECOND * tsg->fps_d);
214 tsg->gop_pts = gop_pts;
215 tsg->gop_tsn = gop_tsn;
222 pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
226 if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
229 pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
231 if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
234 if (tsg->max_tsn < pic_tsn)
235 tsg->max_tsn = pic_tsn;
236 else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
237 tsg->max_tsn = pic_tsn;
240 tsg->lst_tsn = pic_tsn;
244 /* ------------------------------------------------------------------------- */
245 /* --- MPEG-2 Parser Info --- */
246 /* ------------------------------------------------------------------------- */
248 typedef struct _GstMpegVideoSliceHdr GstMpegVideoSliceHdr;
249 struct _GstMpegVideoSliceHdr {
250 guint16 slice_horizontal_position;
251 guint16 slice_vertical_position;
252 guint8 quantiser_scale_code;
255 /* Size of the slice() header in bits */
259 typedef struct _GstVaapiParserInfoMpeg2 GstVaapiParserInfoMpeg2;
260 struct _GstVaapiParserInfoMpeg2 {
261 GstMpegVideoPacket packet;
262 guint8 extension_type; /* for Extension packets */
264 GstMpegVideoSequenceHdr seq_hdr;
265 GstMpegVideoSequenceExt seq_ext;
266 GstMpegVideoSequenceDisplayExt seq_display_ext;
268 GstMpegVideoQuantMatrixExt quant_matrix;
269 GstMpegVideoPictureHdr pic_hdr;
270 GstMpegVideoPictureExt pic_ext;
271 GstMpegVideoSliceHdr slice_hdr;
275 static inline const GstVaapiMiniObjectClass *
276 gst_vaapi_parser_info_mpeg2_class(void)
278 static const GstVaapiMiniObjectClass GstVaapiParserInfoMpeg2Class = {
279 sizeof(GstVaapiParserInfoMpeg2),
282 return &GstVaapiParserInfoMpeg2Class;
285 static inline GstVaapiParserInfoMpeg2 *
286 gst_vaapi_parser_info_mpeg2_new(void)
288 return (GstVaapiParserInfoMpeg2 *)
289 gst_vaapi_mini_object_new(gst_vaapi_parser_info_mpeg2_class());
292 static inline GstVaapiParserInfoMpeg2 *
293 gst_vaapi_parser_info_mpeg2_ensure(GstVaapiParserInfoMpeg2 **pi_ptr)
295 GstVaapiParserInfoMpeg2 *pi = *pi_ptr;
297 if (G_LIKELY(pi != NULL))
300 *pi_ptr = pi = gst_vaapi_parser_info_mpeg2_new();
304 #define gst_vaapi_parser_info_mpeg2_ref(pi) \
305 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
307 #define gst_vaapi_parser_info_mpeg2_unref(pi) \
308 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
310 #define gst_vaapi_parser_info_mpeg2_replace(old_pi_ptr, new_pi) \
311 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr), \
312 (GstVaapiMiniObject *)(new_pi))
314 /* ------------------------------------------------------------------------- */
315 /* --- MPEG-2 Decoder --- */
316 /* ------------------------------------------------------------------------- */
318 G_DEFINE_TYPE(GstVaapiDecoderMpeg2,
319 gst_vaapi_decoder_mpeg2,
320 GST_VAAPI_TYPE_DECODER)
322 #define GST_VAAPI_DECODER_MPEG2_CAST(decoder) \
323 ((GstVaapiDecoderMpeg2 *)(decoder))
325 #define GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(obj) \
326 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
327 GST_VAAPI_TYPE_DECODER_MPEG2, \
328 GstVaapiDecoderMpeg2Private))
330 struct _GstVaapiDecoderMpeg2Private {
331 GstVaapiProfile profile;
332 GstVaapiProfile hw_profile;
337 GstVaapiParserInfoMpeg2 *seq_hdr;
338 GstVaapiParserInfoMpeg2 *seq_ext;
339 GstVaapiParserInfoMpeg2 *seq_display_ext;
340 GstVaapiParserInfoMpeg2 *seq_scalable_ext;
341 GstVaapiParserInfoMpeg2 *gop;
342 GstVaapiParserInfoMpeg2 *pic_hdr;
343 GstVaapiParserInfoMpeg2 *pic_ext;
344 GstVaapiParserInfoMpeg2 *quant_matrix;
345 GstVaapiParserInfoMpeg2 *slice_hdr;
346 GstVaapiPicture *current_picture;
349 guint is_constructed : 1;
351 guint size_changed : 1;
352 guint profile_changed : 1;
353 guint quant_matrix_changed : 1;
354 guint progressive_sequence : 1;
355 guint closed_gop : 1;
356 guint broken_link : 1;
360 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
362 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
364 gst_vaapi_picture_replace(&priv->current_picture, NULL);
366 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_hdr, NULL);
367 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
368 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
369 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_scalable_ext, NULL);
370 gst_vaapi_parser_info_mpeg2_replace(&priv->gop, NULL);
371 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_hdr, NULL);
372 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
373 gst_vaapi_parser_info_mpeg2_replace(&priv->quant_matrix, NULL);
374 gst_vaapi_parser_info_mpeg2_replace(&priv->slice_hdr, NULL);
376 gst_vaapi_dpb_replace(&priv->dpb, NULL);
380 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
382 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
384 gst_vaapi_decoder_mpeg2_close(decoder);
386 priv->dpb = gst_vaapi_dpb_new(2);
390 pts_init(&priv->tsg);
395 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
397 gst_vaapi_decoder_mpeg2_close(decoder);
401 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
403 if (!GST_VAAPI_DECODER_CODEC(decoder))
409 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
411 memcpy(dst, src, 64);
415 get_profile_str(GstVaapiProfile profile)
420 case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
421 case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
422 case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
423 default: str = "<unknown>"; break;
428 static GstVaapiProfile
429 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
431 GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
432 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
433 GstVaapiProfile profile = priv->profile;
436 /* Return immediately if the exact same profile was found */
437 if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
440 /* Otherwise, try to map to a higher profile */
442 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
443 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
445 case GST_VAAPI_PROFILE_MPEG2_MAIN:
446 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
448 case GST_VAAPI_PROFILE_MPEG2_HIGH:
449 // Try to map to main profile if no high profile specific bits used
450 if (priv->profile == profile &&
451 !priv->seq_scalable_ext &&
453 priv->seq_ext->data.seq_ext.chroma_format == 1)) {
454 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
459 profile = GST_VAAPI_PROFILE_UNKNOWN;
462 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
464 if (profile != priv->profile)
465 GST_INFO("forced %s profile to %s profile",
466 get_profile_str(priv->profile), get_profile_str(profile));
470 static GstVaapiDecoderStatus
471 ensure_context(GstVaapiDecoderMpeg2 *decoder)
473 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
474 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
475 gboolean reset_context = FALSE;
477 if (priv->profile_changed) {
478 GST_DEBUG("profile changed");
479 priv->profile_changed = FALSE;
480 reset_context = TRUE;
482 priv->hw_profile = get_profile(decoder, entrypoint);
483 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
484 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
487 if (priv->size_changed) {
488 GST_DEBUG("size changed");
489 priv->size_changed = FALSE;
490 reset_context = TRUE;
494 GstVaapiContextInfo info;
496 info.profile = priv->hw_profile;
497 info.entrypoint = entrypoint;
498 info.width = priv->width;
499 info.height = priv->height;
501 reset_context = gst_vaapi_decoder_ensure_context(
502 GST_VAAPI_DECODER_CAST(decoder),
506 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
508 return GST_VAAPI_DECODER_STATUS_SUCCESS;
511 static GstVaapiDecoderStatus
512 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
514 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
515 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr->data.seq_hdr;
516 VAIQMatrixBufferMPEG2 *iq_matrix;
517 guint8 *intra_quant_matrix = NULL;
518 guint8 *non_intra_quant_matrix = NULL;
519 guint8 *chroma_intra_quant_matrix = NULL;
520 guint8 *chroma_non_intra_quant_matrix = NULL;
522 if (!priv->quant_matrix_changed)
523 return GST_VAAPI_DECODER_STATUS_SUCCESS;
525 priv->quant_matrix_changed = FALSE;
527 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
528 if (!picture->iq_matrix) {
529 GST_ERROR("failed to allocate IQ matrix");
530 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
532 iq_matrix = picture->iq_matrix->param;
534 intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
535 non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
537 if (priv->quant_matrix) {
538 GstMpegVideoQuantMatrixExt * const quant_matrix =
539 &priv->quant_matrix->data.quant_matrix;
540 if (quant_matrix->load_intra_quantiser_matrix)
541 intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
542 if (quant_matrix->load_non_intra_quantiser_matrix)
543 non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
544 if (quant_matrix->load_chroma_intra_quantiser_matrix)
545 chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
546 if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
547 chroma_non_intra_quant_matrix = quant_matrix->chroma_non_intra_quantiser_matrix;
550 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
551 if (intra_quant_matrix)
552 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
555 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
556 if (non_intra_quant_matrix)
557 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
558 non_intra_quant_matrix);
560 iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
561 if (chroma_intra_quant_matrix)
562 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
563 chroma_intra_quant_matrix);
565 iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
566 if (chroma_non_intra_quant_matrix)
567 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
568 chroma_non_intra_quant_matrix);
569 return GST_VAAPI_DECODER_STATUS_SUCCESS;
572 static GstVaapiDecoderStatus
573 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
575 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
576 GstVaapiPicture * const picture = priv->current_picture;
579 return GST_VAAPI_DECODER_STATUS_SUCCESS;
581 if (!gst_vaapi_picture_decode(picture))
583 if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
584 if (!gst_vaapi_dpb_add(priv->dpb, picture))
586 gst_vaapi_picture_replace(&priv->current_picture, NULL);
588 return GST_VAAPI_DECODER_STATUS_SUCCESS;
591 /* XXX: fix for cases where first field failed to be decoded */
592 gst_vaapi_picture_replace(&priv->current_picture, NULL);
593 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
596 static GstVaapiDecoderStatus
597 parse_sequence(GstVaapiDecoderMpeg2 *decoder,
598 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
600 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
601 GstMpegVideoSequenceHdr *seq_hdr;
603 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_hdr)) {
604 GST_ERROR("failed to allocate parser info for sequence header");
605 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
608 seq_hdr = &priv->seq_hdr->data.seq_hdr;
610 if (!gst_mpeg_video_parse_sequence_header(seq_hdr,
611 packet->data, packet->size, packet->offset)) {
612 GST_ERROR("failed to parse sequence header");
613 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
616 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_hdr, NULL);
617 return GST_VAAPI_DECODER_STATUS_SUCCESS;
620 static GstVaapiDecoderStatus
621 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
623 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
624 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
625 GstMpegVideoSequenceHdr * const seq_hdr = unit->parsed_info;
627 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
628 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
630 priv->fps_n = seq_hdr->fps_n;
631 priv->fps_d = seq_hdr->fps_d;
632 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
633 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
635 priv->width = seq_hdr->width;
636 priv->height = seq_hdr->height;
637 priv->size_changed = TRUE;
638 priv->quant_matrix_changed = TRUE;
639 priv->progressive_sequence = TRUE;
640 return GST_VAAPI_DECODER_STATUS_SUCCESS;
643 static GstVaapiDecoderStatus
644 parse_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
645 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
647 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
648 GstMpegVideoSequenceExt *seq_ext;
650 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_ext)) {
651 GST_ERROR("failed to allocate parser info for sequence extension");
652 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
655 seq_ext = &priv->seq_ext->data.seq_ext;
657 if (!gst_mpeg_video_parse_sequence_extension(seq_ext,
658 packet->data, packet->size, packet->offset)) {
659 GST_ERROR("failed to parse sequence-extension");
660 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
663 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_ext, NULL);
664 return GST_VAAPI_DECODER_STATUS_SUCCESS;
667 static GstVaapiDecoderStatus
668 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
670 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
671 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
672 GstMpegVideoSequenceExt * const seq_ext = unit->parsed_info;
673 GstVaapiProfile profile;
676 priv->progressive_sequence = seq_ext->progressive;
677 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
679 width = (priv->width & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
680 height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext << 12);
681 GST_DEBUG("video resolution %ux%u", width, height);
683 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
684 priv->fps_n *= seq_ext->fps_n_ext + 1;
685 priv->fps_d *= seq_ext->fps_d_ext + 1;
686 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
687 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
690 if (priv->width != width) {
692 priv->size_changed = TRUE;
695 if (priv->height != height) {
696 priv->height = height;
697 priv->size_changed = TRUE;
700 switch (seq_ext->profile) {
701 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
702 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
704 case GST_MPEG_VIDEO_PROFILE_MAIN:
705 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
707 case GST_MPEG_VIDEO_PROFILE_HIGH:
708 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
711 GST_ERROR("unsupported profile %d", seq_ext->profile);
712 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
714 if (priv->profile != profile) {
715 priv->profile = profile;
716 priv->profile_changed = TRUE;
718 return GST_VAAPI_DECODER_STATUS_SUCCESS;
721 static GstVaapiDecoderStatus
722 parse_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
723 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
725 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
726 GstMpegVideoSequenceDisplayExt *seq_display_ext;
728 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_display_ext)) {
729 GST_ERROR("failed to allocate parser info for sequence display extension");
730 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
733 seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
735 if (!gst_mpeg_video_parse_sequence_display_extension(seq_display_ext,
736 packet->data, packet->size, packet->offset)) {
737 GST_ERROR("failed to parse sequence-display-extension");
738 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
741 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_display_ext, NULL);
742 return GST_VAAPI_DECODER_STATUS_SUCCESS;
745 static GstVaapiDecoderStatus
746 decode_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
747 GstVaapiDecoderUnit *unit)
749 /* XXX: handle color primaries and cropping */
750 return GST_VAAPI_DECODER_STATUS_SUCCESS;
753 static GstVaapiDecoderStatus
754 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
756 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
757 GstVaapiDecoderStatus status;
759 status = decode_current_picture(decoder);
760 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
763 gst_vaapi_dpb_flush(priv->dpb);
764 return GST_VAAPI_DECODER_STATUS_SUCCESS;
767 static GstVaapiDecoderStatus
768 parse_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
769 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
771 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
772 GstMpegVideoQuantMatrixExt *quant_matrix;
774 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->quant_matrix)) {
775 GST_ERROR("failed to allocate parser info for quantization matrix");
776 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
779 quant_matrix = &priv->quant_matrix->data.quant_matrix;
781 if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix,
782 packet->data, packet->size, packet->offset)) {
783 GST_ERROR("failed to parse quant-matrix-extension");
784 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
787 gst_vaapi_decoder_unit_set_parsed_info(unit, quant_matrix, NULL);
788 return GST_VAAPI_DECODER_STATUS_SUCCESS;
791 static GstVaapiDecoderStatus
792 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
793 GstVaapiDecoderUnit *unit)
795 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
797 priv->quant_matrix_changed = TRUE;
798 return GST_VAAPI_DECODER_STATUS_SUCCESS;
801 static GstVaapiDecoderStatus
802 parse_gop(GstVaapiDecoderMpeg2 *decoder,
803 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
805 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
806 GstMpegVideoGop *gop;
808 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->gop)) {
809 GST_ERROR("failed to allocate parser info for GOP");
810 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
813 gop = &priv->gop->data.gop;
815 if (!gst_mpeg_video_parse_gop(gop,
816 packet->data, packet->size, packet->offset)) {
817 GST_ERROR("failed to parse GOP");
818 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
821 gst_vaapi_decoder_unit_set_parsed_info(unit, gop, NULL);
822 return GST_VAAPI_DECODER_STATUS_SUCCESS;
825 static GstVaapiDecoderStatus
826 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
828 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
829 GstMpegVideoGop * const gop = unit->parsed_info;
831 priv->closed_gop = gop->closed_gop;
832 priv->broken_link = gop->broken_link;
834 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
835 gop->hour, gop->minute, gop->second, gop->frame,
836 priv->closed_gop, priv->broken_link);
838 pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
839 return GST_VAAPI_DECODER_STATUS_SUCCESS;
842 static GstVaapiDecoderStatus
843 parse_picture(GstVaapiDecoderMpeg2 *decoder,
844 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
846 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
847 GstMpegVideoPictureHdr *pic_hdr;
849 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_hdr)) {
850 GST_ERROR("failed to allocate parser info for picture header");
851 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
854 pic_hdr = &priv->pic_hdr->data.pic_hdr;
856 if (!gst_mpeg_video_parse_picture_header(pic_hdr,
857 packet->data, packet->size, packet->offset)) {
858 GST_ERROR("failed to parse picture header");
859 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
862 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_hdr, NULL);
863 return GST_VAAPI_DECODER_STATUS_SUCCESS;
866 static GstVaapiDecoderStatus
867 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
869 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
871 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
872 return GST_VAAPI_DECODER_STATUS_SUCCESS;
875 static GstVaapiDecoderStatus
876 parse_picture_ext(GstVaapiDecoderMpeg2 *decoder,
877 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
879 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
880 GstMpegVideoPictureExt *pic_ext;
882 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_ext)) {
883 GST_ERROR("failed to allocate parser info for picture extension");
884 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
887 pic_ext = &priv->pic_ext->data.pic_ext;
889 if (!gst_mpeg_video_parse_picture_extension(pic_ext,
890 packet->data, packet->size, packet->offset)) {
891 GST_ERROR("failed to parse picture-extension");
892 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
895 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_ext, NULL);
896 return GST_VAAPI_DECODER_STATUS_SUCCESS;
899 static GstVaapiDecoderStatus
900 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
902 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
903 GstMpegVideoPictureExt * const pic_ext = unit->parsed_info;
905 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
906 GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
907 pic_ext->progressive_frame = 1;
910 if (pic_ext->picture_structure == 0 ||
911 (pic_ext->progressive_frame &&
912 pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
913 GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
914 pic_ext->picture_structure);
915 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
917 return GST_VAAPI_DECODER_STATUS_SUCCESS;
920 static inline guint32
921 pack_f_code(guint8 f_code[2][2])
923 return (((guint32)f_code[0][0] << 12) |
924 ((guint32)f_code[0][1] << 8) |
925 ((guint32)f_code[1][0] << 4) |
929 static GstVaapiDecoderStatus
930 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
932 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
933 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
934 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
936 switch (pic_hdr->pic_type) {
937 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
938 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
939 picture->type = GST_VAAPI_PICTURE_TYPE_I;
941 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
942 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
943 picture->type = GST_VAAPI_PICTURE_TYPE_P;
945 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
946 picture->type = GST_VAAPI_PICTURE_TYPE_B;
949 GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
950 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
953 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
954 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
955 if (pic_ext->top_field_first)
956 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
959 switch (pic_ext->picture_structure) {
960 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
961 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
963 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
964 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
966 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
967 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
971 /* Allocate dummy picture for first field based I-frame */
972 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
973 !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
974 gst_vaapi_dpb_size(priv->dpb) == 0) {
975 GstVaapiPicture *dummy_picture;
978 dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
979 if (!dummy_picture) {
980 GST_ERROR("failed to allocate dummy picture");
981 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
984 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
985 dummy_picture->pts = GST_CLOCK_TIME_NONE;
986 dummy_picture->poc = -1;
987 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
989 GST_VAAPI_PICTURE_FLAG_SET(
991 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
992 GST_VAAPI_PICTURE_FLAG_REFERENCE)
995 success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
996 gst_vaapi_picture_unref(dummy_picture);
998 GST_ERROR("failed to add dummy picture into DPB");
999 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1001 GST_INFO("allocated dummy picture for first field based I-frame");
1004 /* Update presentation time */
1005 picture->pts = pts_eval(&priv->tsg,
1006 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
1007 picture->poc = pts_get_poc(&priv->tsg);
1008 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1012 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
1014 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1015 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
1016 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1017 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
1018 GstVaapiPicture *prev_picture, *next_picture;
1020 /* Fill in VAPictureParameterBufferMPEG2 */
1021 pic_param->horizontal_size = priv->width;
1022 pic_param->vertical_size = priv->height;
1023 pic_param->forward_reference_picture = VA_INVALID_ID;
1024 pic_param->backward_reference_picture = VA_INVALID_ID;
1025 pic_param->picture_coding_type = pic_hdr->pic_type;
1026 pic_param->f_code = pack_f_code(pic_ext->f_code);
1028 #define COPY_FIELD(a, b, f) \
1029 pic_param->a.b.f = pic_ext->f
1030 pic_param->picture_coding_extension.value = 0;
1031 pic_param->picture_coding_extension.bits.is_first_field =
1032 GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
1033 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
1034 COPY_FIELD(picture_coding_extension, bits, picture_structure);
1035 COPY_FIELD(picture_coding_extension, bits, top_field_first);
1036 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
1037 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
1038 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
1039 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
1040 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
1041 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
1042 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
1044 gst_vaapi_dpb_get_neighbours(priv->dpb, picture,
1045 &prev_picture, &next_picture);
1047 switch (pic_hdr->pic_type) {
1048 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1050 pic_param->backward_reference_picture = next_picture->surface_id;
1052 pic_param->forward_reference_picture = prev_picture->surface_id;
1053 else if (!priv->closed_gop)
1054 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1056 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1058 pic_param->forward_reference_picture = prev_picture->surface_id;
1063 static GstVaapiDecoderStatus
1064 parse_slice(GstVaapiDecoderMpeg2 *decoder,
1065 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
1067 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1068 GstMpegVideoSliceHdr *slice_hdr;
1070 gint mb_x, mb_y, mb_inc;
1071 guint8 slice_vertical_position_extension;
1072 guint8 extra_bit_slice, junk8;
1074 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->slice_hdr)) {
1075 GST_ERROR("failed to allocate parser info for slice header");
1076 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1079 slice_hdr = &priv->slice_hdr->data.slice_hdr;
1081 gst_bit_reader_init(&br, packet->data + packet->offset, packet->size);
1082 if (priv->height > 2800)
1083 READ_UINT8(&br, slice_vertical_position_extension, 3);
1084 if (priv->seq_scalable_ext) {
1085 GST_ERROR("failed to parse slice with sequence_scalable_extension()");
1086 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1088 READ_UINT8(&br, slice_hdr->quantiser_scale_code, 5);
1089 READ_UINT8(&br, extra_bit_slice, 1);
1090 if (!extra_bit_slice)
1091 slice_hdr->intra_slice = 0;
1093 READ_UINT8(&br, slice_hdr->intra_slice, 1);
1094 READ_UINT8(&br, junk8, 7);
1095 READ_UINT8(&br, extra_bit_slice, 1);
1096 while (extra_bit_slice) {
1097 READ_UINT8(&br, junk8, 8);
1098 READ_UINT8(&br, extra_bit_slice, 1);
1101 slice_hdr->header_size = 32 + gst_bit_reader_get_pos(&br);
1103 mb_y = packet->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN;
1106 if (!decode_vlc(&br, &mb_inc, mpeg2_mbaddr_vlc_table,
1107 G_N_ELEMENTS(mpeg2_mbaddr_vlc_table))) {
1108 GST_WARNING("failed to decode first macroblock_address_increment");
1111 mb_x += mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
1112 } while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
1114 slice_hdr->slice_horizontal_position = mb_x;
1115 slice_hdr->slice_vertical_position = mb_y;
1117 gst_vaapi_decoder_unit_set_parsed_info(unit, slice_hdr, NULL);
1118 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1121 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1124 static GstVaapiDecoderStatus
1125 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
1127 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1128 GstVaapiPicture * const picture = priv->current_picture;
1129 GstVaapiSlice *slice;
1130 VASliceParameterBufferMPEG2 *slice_param;
1131 GstMpegVideoSliceHdr * const slice_hdr = unit->parsed_info;
1133 GST_DEBUG("slice %d (%u bytes)", slice_hdr->slice_vertical_position,
1136 slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1137 (GST_BUFFER_DATA(GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer) +
1138 unit->offset), unit->size);
1140 GST_ERROR("failed to allocate slice");
1141 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1143 gst_vaapi_picture_add_slice(picture, slice);
1145 /* Fill in VASliceParameterBufferMPEG2 */
1146 slice_param = slice->param;
1147 slice_param->macroblock_offset = slice_hdr->header_size;
1148 slice_param->slice_horizontal_position = slice_hdr->slice_horizontal_position;
1149 slice_param->slice_vertical_position = slice_hdr->slice_vertical_position;
1150 slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1151 slice_param->intra_slice_flag = slice_hdr->intra_slice;
1152 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1156 scan_for_start_code(const guchar *buf, guint buf_size,
1157 GstMpegVideoPacketTypeCode *type_ptr)
1161 while (i <= (buf_size - 4)) {
1164 else if (buf[i + 1])
1166 else if (buf[i] || buf[i + 2] != 1)
1172 if (i <= (buf_size - 4)) {
1174 *type_ptr = buf[i + 3];
1180 static GstVaapiDecoderStatus
1181 parse_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1182 GstMpegVideoPacket *packet)
1184 GstMpegVideoPacketTypeCode type;
1185 GstMpegVideoPacketExtensionCode ext_type;
1186 GstVaapiDecoderStatus status;
1188 type = packet->type;
1190 case GST_MPEG_VIDEO_PACKET_PICTURE:
1191 status = parse_picture(decoder, unit, packet);
1193 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1194 status = parse_sequence(decoder, unit, packet);
1196 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1197 ext_type = packet->data[4] >> 4;
1199 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1200 status = parse_sequence_ext(decoder, unit, packet);
1202 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1203 status = parse_sequence_display_ext(decoder, unit, packet);
1205 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1206 status = parse_quant_matrix_ext(decoder, unit, packet);
1208 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1209 status = parse_picture_ext(decoder, unit, packet);
1212 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1216 case GST_MPEG_VIDEO_PACKET_GOP:
1217 status = parse_gop(decoder, unit, packet);
1220 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1221 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1222 status = parse_slice(decoder, unit, packet);
1225 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1231 static GstVaapiDecoderStatus
1232 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1233 GstMpegVideoPacket *packet)
1235 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1236 GstMpegVideoPacketTypeCode type;
1237 GstMpegVideoPacketExtensionCode ext_type;
1238 GstVaapiDecoderStatus status;
1240 type = packet->type;
1242 case GST_MPEG_VIDEO_PACKET_PICTURE:
1243 if (!priv->width || !priv->height)
1244 goto unknown_picture_size;
1245 status = decode_picture(decoder, unit);
1247 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1248 status = decode_sequence(decoder, unit);
1250 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1251 ext_type = packet->data[4] >> 4;
1253 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1254 status = decode_sequence_ext(decoder, unit);
1256 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1257 status = decode_sequence_display_ext(decoder, unit);
1259 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1260 status = decode_quant_matrix_ext(decoder, unit);
1262 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1263 if (!priv->width || !priv->height)
1264 goto unknown_picture_size;
1265 status = decode_picture_ext(decoder, unit);
1268 // Ignore unknown start-code extensions
1269 GST_WARNING("unsupported packet extension type 0x%02x", ext_type);
1270 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1274 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1275 status = decode_sequence_end(decoder);
1277 case GST_MPEG_VIDEO_PACKET_GOP:
1278 status = decode_gop(decoder, unit);
1281 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1282 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1283 status = decode_slice(decoder, unit);
1286 GST_WARNING("unsupported packet type 0x%02x", type);
1287 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1292 unknown_picture_size:
1293 // Ignore packet while picture size is undefined
1294 // i.e. missing sequence headers, or not parsed correctly
1295 GST_WARNING("failed to parse picture of unknown size");
1296 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1299 static GstVaapiDecoderStatus
1300 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1302 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1304 g_return_val_if_fail(priv->is_constructed,
1305 GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
1307 if (!priv->is_opened) {
1308 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1309 if (!priv->is_opened)
1310 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1312 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1315 static GstVaapiDecoderStatus
1316 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1317 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
1319 GstVaapiDecoderMpeg2 * const decoder =
1320 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1321 GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
1322 GstVaapiDecoderStatus status;
1323 GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1325 guint buf_size, flags;
1326 gint ofs, ofs1, ofs2;
1328 status = ensure_decoder(decoder);
1329 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1332 buf_size = gst_adapter_available(adapter);
1334 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1336 buf = gst_adapter_peek(adapter, buf_size);
1338 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1340 ofs = scan_for_start_code(buf, buf_size, &type);
1342 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1345 ofs2 = ps->input_offset2 - 4;
1346 if (ofs2 < ofs1 + 4)
1349 ofs = G_UNLIKELY(buf_size < ofs2 + 4) ? -1 :
1350 scan_for_start_code(&buf[ofs2], buf_size - ofs2, &type2);
1352 // Assume the whole packet is present if end-of-stream
1354 ps->input_offset2 = buf_size;
1355 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1357 ofs = buf_size - ofs2;
1361 unit->size = ofs2 - ofs1;
1362 gst_adapter_flush(adapter, ofs1);
1363 ps->input_offset2 = 4;
1365 /* Check for start of new picture */
1368 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1369 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1370 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1372 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1373 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1375 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1376 case GST_MPEG_VIDEO_PACKET_GOP:
1377 case GST_MPEG_VIDEO_PACKET_PICTURE:
1378 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1380 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1381 if (G_UNLIKELY(unit->size < 5))
1382 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1385 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1386 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1387 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1389 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1390 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1391 case GST_MPEG_VIDEO_PACKET_GOP:
1392 case GST_MPEG_VIDEO_PACKET_PICTURE:
1393 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1400 // Ignore system start codes (PES headers)
1401 else if (type >= 0xb9 && type <= 0xff)
1402 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1405 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1406 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1409 static GstVaapiDecoderStatus
1410 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1411 GstVaapiDecoderUnit *unit)
1413 GstVaapiDecoderMpeg2 * const decoder =
1414 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1415 GstVaapiDecoderStatus status;
1416 GstMpegVideoPacket packet;
1418 status = ensure_decoder(decoder);
1419 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1423 (GST_BUFFER_DATA(GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer) +
1425 packet.size = unit->size;
1426 packet.type = packet.data[3];
1429 status = parse_unit(decoder, unit, &packet);
1430 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1432 return decode_unit(decoder, unit, &packet);
1435 static GstVaapiDecoderStatus
1436 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1437 GstVaapiDecoderUnit *base_unit)
1439 GstVaapiDecoderMpeg2 * const decoder =
1440 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1441 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1442 GstMpegVideoSequenceHdr *seq_hdr;
1443 GstMpegVideoSequenceExt *seq_ext;
1444 GstMpegVideoSequenceDisplayExt *seq_display_ext;
1445 GstVaapiPicture *picture;
1446 GstVaapiDecoderStatus status;
1448 if (!priv->width || !priv->height) {
1449 // Ignore packet while picture size is undefined
1450 // i.e. missing sequence headers, or not parsed correctly
1451 GST_WARNING("failed to decode picture of unknown size");
1452 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1455 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1456 seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1457 seq_display_ext = priv->seq_display_ext ?
1458 &priv->seq_display_ext->data.seq_display_ext : NULL;
1459 if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext,
1461 gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
1462 seq_hdr->par_w, seq_hdr->par_h);
1464 status = ensure_context(decoder);
1465 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1466 GST_ERROR("failed to reset context");
1470 if (priv->current_picture) {
1471 /* Re-use current picture where the first field was decoded */
1472 picture = gst_vaapi_picture_new_field(priv->current_picture);
1474 GST_ERROR("failed to allocate field picture");
1475 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1479 /* Create new picture */
1480 picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1482 GST_ERROR("failed to allocate picture");
1483 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1486 gst_vaapi_picture_replace(&priv->current_picture, picture);
1487 gst_vaapi_picture_unref(picture);
1489 status = ensure_quant_matrix(decoder, picture);
1490 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1491 GST_ERROR("failed to reset quantizer matrix");
1495 status = init_picture(decoder, picture);
1496 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1499 fill_picture(decoder, picture);
1500 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1503 static GstVaapiDecoderStatus
1504 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1506 GstVaapiDecoderMpeg2 * const decoder =
1507 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1509 return decode_current_picture(decoder);
1513 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
1515 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1517 gst_vaapi_decoder_mpeg2_destroy(decoder);
1519 G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
1523 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
1525 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1526 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1527 GObjectClass *parent_class;
1529 parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
1530 if (parent_class->constructed)
1531 parent_class->constructed(object);
1533 priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
1537 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1539 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
1540 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1542 g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
1544 object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
1545 object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
1547 decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1548 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1549 decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1550 decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1554 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
1556 GstVaapiDecoderMpeg2Private *priv;
1558 priv = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
1559 decoder->priv = priv;
1560 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
1561 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
1562 priv->profile_changed = TRUE; /* Allow fallbacks to work */
1566 * gst_vaapi_decoder_mpeg2_new:
1567 * @display: a #GstVaapiDisplay
1568 * @caps: a #GstCaps holding codec information
1570 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1571 * hold extra information like codec-data and pictured coded size.
1573 * Return value: the newly allocated #GstVaapiDecoder object
1576 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1578 GstVaapiDecoderMpeg2 *decoder;
1580 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
1581 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
1583 decoder = g_object_new(
1584 GST_VAAPI_TYPE_DECODER_MPEG2,
1589 if (!decoder->priv->is_constructed) {
1590 g_object_unref(decoder);
1593 return GST_VAAPI_DECODER_CAST(decoder);