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); \
64 /* ------------------------------------------------------------------------- */
65 /* --- PTS Generator --- */
66 /* ------------------------------------------------------------------------- */
68 typedef struct _PTSGenerator PTSGenerator;
69 struct _PTSGenerator {
70 GstClockTime gop_pts; // Current GOP PTS
71 GstClockTime max_pts; // Max picture PTS
72 guint gop_tsn; // Absolute GOP TSN
73 guint max_tsn; // Max picture TSN, relative to last GOP TSN
74 guint ovl_tsn; // How many times TSN overflowed since GOP
75 guint lst_tsn; // Last picture TSN
81 pts_init(PTSGenerator *tsg)
83 tsg->gop_pts = GST_CLOCK_TIME_NONE;
84 tsg->max_pts = GST_CLOCK_TIME_NONE;
93 static inline GstClockTime
94 pts_get_duration(PTSGenerator *tsg, guint num_frames)
96 return gst_util_uint64_scale(num_frames,
97 GST_SECOND * tsg->fps_d, tsg->fps_n);
101 pts_get_poc(PTSGenerator *tsg)
103 return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
107 pts_set_framerate(PTSGenerator *tsg, guint fps_n, guint fps_d)
114 pts_sync(PTSGenerator *tsg, GstClockTime gop_pts)
118 if (!GST_CLOCK_TIME_IS_VALID(gop_pts) ||
119 (GST_CLOCK_TIME_IS_VALID(tsg->max_pts) && tsg->max_pts >= gop_pts)) {
120 /* Invalid GOP PTS, interpolate from the last known picture PTS */
121 if (GST_CLOCK_TIME_IS_VALID(tsg->max_pts)) {
122 gop_pts = tsg->max_pts + pts_get_duration(tsg, 1);
123 gop_tsn = tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->max_tsn + 1;
131 /* Interpolate GOP TSN from this valid PTS */
132 if (GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
133 gop_tsn = tsg->gop_tsn + gst_util_uint64_scale(
134 gop_pts - tsg->gop_pts + pts_get_duration(tsg, 1) - 1,
135 tsg->fps_n, GST_SECOND * tsg->fps_d);
140 tsg->gop_pts = gop_pts;
141 tsg->gop_tsn = gop_tsn;
148 pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
152 if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
155 pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
157 if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
160 if (tsg->max_tsn < pic_tsn)
161 tsg->max_tsn = pic_tsn;
162 else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
163 tsg->max_tsn = pic_tsn;
166 tsg->lst_tsn = pic_tsn;
170 /* ------------------------------------------------------------------------- */
171 /* --- MPEG-2 Decoder Units --- */
172 /* ------------------------------------------------------------------------- */
174 typedef struct _GstMpegVideoSliceHdr GstMpegVideoSliceHdr;
175 struct _GstMpegVideoSliceHdr {
176 guint16 slice_horizontal_position;
177 guint16 slice_vertical_position;
178 guint8 quantiser_scale_code;
181 /* Size of the slice() header in bits */
185 typedef struct _GstVaapiDecoderUnitMpeg2 GstVaapiDecoderUnitMpeg2;
186 struct _GstVaapiDecoderUnitMpeg2 {
187 GstVaapiDecoderUnit base;
188 GstMpegVideoPacket packet;
189 guint8 extension_type; /* for Extension packets */
191 GstMpegVideoSequenceHdr seq_hdr;
192 GstMpegVideoSequenceExt seq_ext;
194 GstMpegVideoQuantMatrixExt quant_matrix;
195 GstMpegVideoPictureHdr pic_hdr;
196 GstMpegVideoPictureExt pic_ext;
197 GstMpegVideoSliceHdr slice_hdr;
201 static GstVaapiDecoderUnitMpeg2 *
202 gst_vaapi_decoder_unit_mpeg2_new(guint size)
204 GstVaapiDecoderUnitMpeg2 *unit;
206 static const GstVaapiMiniObjectClass GstVaapiDecoderUnitMpeg2Class = {
207 sizeof(GstVaapiDecoderUnitMpeg2),
208 (GDestroyNotify)gst_vaapi_decoder_unit_finalize
211 unit = (GstVaapiDecoderUnitMpeg2 *)
212 gst_vaapi_mini_object_new(&GstVaapiDecoderUnitMpeg2Class);
216 gst_vaapi_decoder_unit_init(&unit->base, size);
220 /* ------------------------------------------------------------------------- */
221 /* --- MPEG-2 Decoder --- */
222 /* ------------------------------------------------------------------------- */
224 struct _GstVaapiDecoderMpeg2Private {
225 GstVaapiProfile profile;
226 GstVaapiProfile hw_profile;
231 GstVaapiDecoderUnitMpeg2 *seq_hdr_unit;
232 GstVaapiDecoderUnitMpeg2 *seq_ext_unit;
233 GstVaapiDecoderUnitMpeg2 *seq_scalable_ext_unit;
234 GstVaapiDecoderUnitMpeg2 *pic_hdr_unit;
235 GstVaapiDecoderUnitMpeg2 *pic_ext_unit;
236 GstVaapiDecoderUnitMpeg2 *quant_matrix_unit;
237 GstVaapiPicture *current_picture;
240 guint is_constructed : 1;
242 guint size_changed : 1;
243 guint profile_changed : 1;
244 guint quant_matrix_changed : 1;
245 guint progressive_sequence : 1;
246 guint closed_gop : 1;
247 guint broken_link : 1;
250 /* VLC decoder from gst-plugins-bad */
251 typedef struct _VLCTable VLCTable;
259 decode_vlc(GstBitReader *br, gint *res, const VLCTable *table, guint length)
265 for (i = 0; i < length; i++) {
266 if (cbits != table[i].cbits) {
267 cbits = table[i].cbits;
268 if (!gst_bit_reader_peek_bits_uint32(br, &value, cbits)) {
273 if (value == table[i].cword) {
276 *res = table[i].value;
280 GST_DEBUG("failed to find VLC code");
283 GST_WARNING("failed to decode VLC, returning");
288 GST_MPEG_VIDEO_MACROBLOCK_ESCAPE = -1,
291 /* Table B-1: Variable length codes for macroblock_address_increment */
292 static const VLCTable mpeg2_mbaddr_vlc_table[] = {
326 { GST_MPEG_VIDEO_MACROBLOCK_ESCAPE, 0x08, 11 }
330 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
332 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
334 gst_vaapi_picture_replace(&priv->current_picture, NULL);
336 gst_vaapi_decoder_unit_replace(&priv->seq_hdr_unit, NULL);
337 gst_vaapi_decoder_unit_replace(&priv->seq_ext_unit, NULL);
338 gst_vaapi_decoder_unit_replace(&priv->seq_scalable_ext_unit, NULL);
339 gst_vaapi_decoder_unit_replace(&priv->pic_hdr_unit, NULL);
340 gst_vaapi_decoder_unit_replace(&priv->pic_ext_unit, NULL);
341 gst_vaapi_decoder_unit_replace(&priv->quant_matrix_unit, NULL);
344 gst_vaapi_dpb_unref(priv->dpb);
350 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
352 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
354 gst_vaapi_decoder_mpeg2_close(decoder);
356 priv->dpb = gst_vaapi_dpb_mpeg2_new();
360 pts_init(&priv->tsg);
365 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
367 gst_vaapi_decoder_mpeg2_close(decoder);
371 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
373 if (!GST_VAAPI_DECODER_CODEC(decoder))
379 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
381 memcpy(dst, src, 64);
385 get_profile_str(GstVaapiProfile profile)
390 case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
391 case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
392 case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
393 default: str = "<unknown>"; break;
398 static GstVaapiProfile
399 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
401 GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
402 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
403 GstVaapiProfile profile = priv->profile;
406 /* Return immediately if the exact same profile was found */
407 if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
410 /* Otherwise, try to map to a higher profile */
412 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
413 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
415 case GST_VAAPI_PROFILE_MPEG2_MAIN:
416 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
418 case GST_VAAPI_PROFILE_MPEG2_HIGH:
419 // Try to map to main profile if no high profile specific bits used
420 if (priv->profile == profile &&
421 !priv->seq_scalable_ext_unit &&
422 (priv->seq_ext_unit &&
423 priv->seq_ext_unit->data.seq_ext.chroma_format == 1)) {
424 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
429 profile = GST_VAAPI_PROFILE_UNKNOWN;
432 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
434 if (profile != priv->profile)
435 GST_INFO("forced %s profile to %s profile",
436 get_profile_str(priv->profile), get_profile_str(profile));
440 static GstVaapiDecoderStatus
441 ensure_context(GstVaapiDecoderMpeg2 *decoder)
443 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
444 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
445 gboolean reset_context = FALSE;
447 if (priv->profile_changed) {
448 GST_DEBUG("profile changed");
449 priv->profile_changed = FALSE;
450 reset_context = TRUE;
452 priv->hw_profile = get_profile(decoder, entrypoint);
453 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
454 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
457 if (priv->size_changed) {
458 GST_DEBUG("size changed");
459 priv->size_changed = FALSE;
460 reset_context = TRUE;
464 GstVaapiContextInfo info;
466 info.profile = priv->hw_profile;
467 info.entrypoint = entrypoint;
468 info.width = priv->width;
469 info.height = priv->height;
471 reset_context = gst_vaapi_decoder_ensure_context(
472 GST_VAAPI_DECODER(decoder),
476 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
478 return GST_VAAPI_DECODER_STATUS_SUCCESS;
481 static GstVaapiDecoderStatus
482 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
484 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
485 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr_unit->data.seq_hdr;
486 VAIQMatrixBufferMPEG2 *iq_matrix;
487 guint8 *intra_quant_matrix = NULL;
488 guint8 *non_intra_quant_matrix = NULL;
489 guint8 *chroma_intra_quant_matrix = NULL;
490 guint8 *chroma_non_intra_quant_matrix = NULL;
492 if (!priv->quant_matrix_changed)
493 return GST_VAAPI_DECODER_STATUS_SUCCESS;
495 priv->quant_matrix_changed = FALSE;
497 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
498 if (!picture->iq_matrix) {
499 GST_ERROR("failed to allocate IQ matrix");
500 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
502 iq_matrix = picture->iq_matrix->param;
504 intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
505 non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
507 if (priv->quant_matrix_unit) {
508 GstMpegVideoQuantMatrixExt * const quant_matrix =
509 &priv->quant_matrix_unit->data.quant_matrix;
510 if (quant_matrix->load_intra_quantiser_matrix)
511 intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
512 if (quant_matrix->load_non_intra_quantiser_matrix)
513 non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
514 if (quant_matrix->load_chroma_intra_quantiser_matrix)
515 chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
516 if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
517 chroma_non_intra_quant_matrix = quant_matrix->chroma_non_intra_quantiser_matrix;
520 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
521 if (intra_quant_matrix)
522 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
525 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
526 if (non_intra_quant_matrix)
527 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
528 non_intra_quant_matrix);
530 iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
531 if (chroma_intra_quant_matrix)
532 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
533 chroma_intra_quant_matrix);
535 iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
536 if (chroma_non_intra_quant_matrix)
537 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
538 chroma_non_intra_quant_matrix);
539 return GST_VAAPI_DECODER_STATUS_SUCCESS;
542 static GstVaapiDecoderStatus
543 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
545 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
546 GstVaapiPicture * const picture = priv->current_picture;
549 return GST_VAAPI_DECODER_STATUS_SUCCESS;
551 if (!gst_vaapi_picture_decode(picture))
553 if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
554 if (!gst_vaapi_dpb_add(priv->dpb, picture))
556 gst_vaapi_picture_replace(&priv->current_picture, NULL);
558 return GST_VAAPI_DECODER_STATUS_SUCCESS;
561 /* XXX: fix for cases where first field failed to be decoded */
562 gst_vaapi_picture_replace(&priv->current_picture, NULL);
563 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
566 static GstVaapiDecoderStatus
567 parse_sequence(GstVaapiDecoderUnitMpeg2 *unit)
569 GstMpegVideoPacket * const packet = &unit->packet;
571 if (!gst_mpeg_video_parse_sequence_header(&unit->data.seq_hdr,
572 packet->data, packet->size, packet->offset)) {
573 GST_ERROR("failed to parse sequence header");
574 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
576 return GST_VAAPI_DECODER_STATUS_SUCCESS;
579 static GstVaapiDecoderStatus
580 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
582 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
583 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
584 GstMpegVideoSequenceHdr *seq_hdr;
586 gst_vaapi_decoder_unit_replace(&priv->seq_hdr_unit, unit);
587 seq_hdr = &priv->seq_hdr_unit->data.seq_hdr;
588 gst_vaapi_decoder_unit_replace(&priv->seq_ext_unit, NULL);
590 priv->fps_n = seq_hdr->fps_n;
591 priv->fps_d = seq_hdr->fps_d;
592 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
593 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
595 if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, NULL, NULL))
596 gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
597 seq_hdr->par_w, seq_hdr->par_h);
599 priv->width = seq_hdr->width;
600 priv->height = seq_hdr->height;
601 priv->size_changed = TRUE;
602 priv->quant_matrix_changed = TRUE;
603 priv->progressive_sequence = TRUE;
604 return GST_VAAPI_DECODER_STATUS_SUCCESS;
607 static GstVaapiDecoderStatus
608 parse_sequence_ext(GstVaapiDecoderUnitMpeg2 *unit)
610 GstMpegVideoPacket * const packet = &unit->packet;
612 if (!gst_mpeg_video_parse_sequence_extension(&unit->data.seq_ext,
613 packet->data, packet->size, packet->offset)) {
614 GST_ERROR("failed to parse sequence-extension");
615 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
617 return GST_VAAPI_DECODER_STATUS_SUCCESS;
620 static GstVaapiDecoderStatus
621 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
622 GstVaapiDecoderUnitMpeg2 *unit)
624 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
625 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
626 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr_unit->data.seq_hdr;
627 GstMpegVideoSequenceExt *seq_ext;
628 GstVaapiProfile profile;
631 gst_vaapi_decoder_unit_replace(&priv->seq_ext_unit, unit);
632 seq_ext = &priv->seq_ext_unit->data.seq_ext;
634 priv->progressive_sequence = seq_ext->progressive;
635 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
637 width = (priv->width & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
638 height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext << 12);
639 GST_DEBUG("video resolution %ux%u", width, height);
641 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
642 priv->fps_n *= seq_ext->fps_n_ext + 1;
643 priv->fps_d *= seq_ext->fps_d_ext + 1;
644 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
645 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
648 if (priv->width != width) {
650 priv->size_changed = TRUE;
653 if (priv->height != height) {
654 priv->height = height;
655 priv->size_changed = TRUE;
658 switch (seq_ext->profile) {
659 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
660 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
662 case GST_MPEG_VIDEO_PROFILE_MAIN:
663 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
665 case GST_MPEG_VIDEO_PROFILE_HIGH:
666 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
669 GST_ERROR("unsupported profile %d", seq_ext->profile);
670 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
672 if (priv->profile != profile) {
673 priv->profile = profile;
674 priv->profile_changed = TRUE;
677 if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext, NULL))
678 gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
679 seq_hdr->par_w, seq_hdr->par_h);
681 return GST_VAAPI_DECODER_STATUS_SUCCESS;
684 static GstVaapiDecoderStatus
685 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
687 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
688 GstVaapiDecoderStatus status;
690 status = decode_current_picture(decoder);
691 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
694 gst_vaapi_dpb_flush(priv->dpb);
695 return GST_VAAPI_DECODER_STATUS_SUCCESS;
698 static GstVaapiDecoderStatus
699 parse_quant_matrix_ext(GstVaapiDecoderUnitMpeg2 *unit)
701 GstMpegVideoPacket * const packet = &unit->packet;
703 if (!gst_mpeg_video_parse_quant_matrix_extension(&unit->data.quant_matrix,
704 packet->data, packet->size, packet->offset)) {
705 GST_ERROR("failed to parse quant-matrix-extension");
706 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
708 return GST_VAAPI_DECODER_STATUS_SUCCESS;
711 static GstVaapiDecoderStatus
712 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
713 GstVaapiDecoderUnitMpeg2 *unit)
715 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
717 gst_vaapi_decoder_unit_replace(&priv->quant_matrix_unit, unit);
718 priv->quant_matrix_changed = TRUE;
719 return GST_VAAPI_DECODER_STATUS_SUCCESS;
722 static GstVaapiDecoderStatus
723 parse_gop(GstVaapiDecoderUnitMpeg2 *unit)
725 GstMpegVideoPacket * const packet = &unit->packet;
727 if (!gst_mpeg_video_parse_gop(&unit->data.gop,
728 packet->data, packet->size, packet->offset)) {
729 GST_ERROR("failed to parse GOP");
730 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
732 return GST_VAAPI_DECODER_STATUS_SUCCESS;
735 static GstVaapiDecoderStatus
736 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
738 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
739 GstMpegVideoGop * const gop = &unit->data.gop;
741 priv->closed_gop = gop->closed_gop;
742 priv->broken_link = gop->broken_link;
744 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
745 gop->hour, gop->minute, gop->second, gop->frame,
746 priv->closed_gop, priv->broken_link);
748 pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
749 return GST_VAAPI_DECODER_STATUS_SUCCESS;
752 static GstVaapiDecoderStatus
753 parse_picture(GstVaapiDecoderUnitMpeg2 *unit)
755 GstMpegVideoPacket * const packet = &unit->packet;
757 if (!gst_mpeg_video_parse_picture_header(&unit->data.pic_hdr,
758 packet->data, packet->size, packet->offset)) {
759 GST_ERROR("failed to parse picture header");
760 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
762 return GST_VAAPI_DECODER_STATUS_SUCCESS;
765 static GstVaapiDecoderStatus
766 parse_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
768 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
769 GstMpegVideoSliceHdr * const slice_hdr = &unit->data.slice_hdr;
770 GstMpegVideoPacket * const packet = &unit->packet;
772 gint mb_x, mb_y, mb_inc;
773 guint8 slice_vertical_position_extension;
774 guint8 extra_bit_slice, junk8;
776 gst_bit_reader_init(&br, packet->data + packet->offset, packet->size);
777 if (priv->height > 2800)
778 READ_UINT8(&br, slice_vertical_position_extension, 3);
779 if (priv->seq_scalable_ext_unit) {
780 GST_ERROR("failed to parse slice with sequence_scalable_extension()");
781 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
783 READ_UINT8(&br, slice_hdr->quantiser_scale_code, 5);
784 READ_UINT8(&br, extra_bit_slice, 1);
785 if (!extra_bit_slice)
786 slice_hdr->intra_slice = 0;
788 READ_UINT8(&br, slice_hdr->intra_slice, 1);
789 READ_UINT8(&br, junk8, 7);
790 READ_UINT8(&br, extra_bit_slice, 1);
791 while (extra_bit_slice) {
792 READ_UINT8(&br, junk8, 8);
793 READ_UINT8(&br, extra_bit_slice, 1);
796 slice_hdr->header_size = 32 + gst_bit_reader_get_pos(&br);
798 mb_y = packet->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN;
801 if (!decode_vlc(&br, &mb_inc, mpeg2_mbaddr_vlc_table,
802 G_N_ELEMENTS(mpeg2_mbaddr_vlc_table))) {
803 GST_WARNING("failed to decode first macroblock_address_increment");
806 mb_x += mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
807 } while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
809 slice_hdr->slice_horizontal_position = mb_x;
810 slice_hdr->slice_vertical_position = mb_y;
811 return GST_VAAPI_DECODER_STATUS_SUCCESS;
814 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
817 static GstVaapiDecoderStatus
818 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
820 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
822 gst_vaapi_decoder_unit_replace(&priv->pic_hdr_unit, unit);
823 gst_vaapi_decoder_unit_replace(&priv->pic_ext_unit, NULL);
824 return GST_VAAPI_DECODER_STATUS_SUCCESS;
827 static GstVaapiDecoderStatus
828 parse_picture_ext(GstVaapiDecoderUnitMpeg2 *unit)
830 GstMpegVideoPacket * const packet = &unit->packet;
832 if (!gst_mpeg_video_parse_picture_extension(&unit->data.pic_ext,
833 packet->data, packet->size, packet->offset)) {
834 GST_ERROR("failed to parse picture-extension");
835 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
837 return GST_VAAPI_DECODER_STATUS_SUCCESS;
840 static GstVaapiDecoderStatus
841 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder,
842 GstVaapiDecoderUnitMpeg2 *unit)
844 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
845 GstMpegVideoPictureExt *pic_ext;
847 gst_vaapi_decoder_unit_replace(&priv->pic_ext_unit, unit);
848 pic_ext = &priv->pic_ext_unit->data.pic_ext;
850 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
851 GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
852 pic_ext->progressive_frame = 1;
855 if (pic_ext->picture_structure == 0 ||
856 (pic_ext->progressive_frame &&
857 pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
858 GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
859 pic_ext->picture_structure);
860 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
862 return GST_VAAPI_DECODER_STATUS_SUCCESS;
865 static inline guint32
866 pack_f_code(guint8 f_code[2][2])
868 return (((guint32)f_code[0][0] << 12) |
869 ((guint32)f_code[0][1] << 8) |
870 ((guint32)f_code[1][0] << 4) |
874 static GstVaapiDecoderStatus
875 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
877 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
878 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr_unit->data.pic_hdr;
879 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext_unit->data.pic_ext;
881 switch (pic_hdr->pic_type) {
882 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
883 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
884 picture->type = GST_VAAPI_PICTURE_TYPE_I;
886 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
887 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
888 picture->type = GST_VAAPI_PICTURE_TYPE_P;
890 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
891 picture->type = GST_VAAPI_PICTURE_TYPE_B;
894 GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
895 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
898 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
899 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
900 if (pic_ext->top_field_first)
901 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
904 switch (pic_ext->picture_structure) {
905 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
906 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
908 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
909 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
911 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
912 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
916 /* Allocate dummy picture for first field based I-frame */
917 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
918 !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
919 gst_vaapi_dpb_size(priv->dpb) == 0) {
920 GstVaapiPicture *dummy_picture;
923 dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
924 if (!dummy_picture) {
925 GST_ERROR("failed to allocate dummy picture");
926 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
929 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
930 dummy_picture->pts = GST_CLOCK_TIME_NONE;
931 dummy_picture->poc = -1;
932 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
934 GST_VAAPI_PICTURE_FLAG_SET(
936 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
937 GST_VAAPI_PICTURE_FLAG_REFERENCE)
940 success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
941 gst_vaapi_picture_unref(dummy_picture);
943 GST_ERROR("failed to add dummy picture into DPB");
944 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
946 GST_INFO("allocated dummy picture for first field based I-frame");
949 /* Update presentation time */
950 picture->pts = pts_eval(&priv->tsg,
951 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
952 picture->poc = pts_get_poc(&priv->tsg);
953 return GST_VAAPI_DECODER_STATUS_SUCCESS;
957 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
959 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
960 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
961 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr_unit->data.pic_hdr;
962 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext_unit->data.pic_ext;
963 GstVaapiPicture *prev_picture, *next_picture;
965 /* Fill in VAPictureParameterBufferMPEG2 */
966 pic_param->horizontal_size = priv->width;
967 pic_param->vertical_size = priv->height;
968 pic_param->forward_reference_picture = VA_INVALID_ID;
969 pic_param->backward_reference_picture = VA_INVALID_ID;
970 pic_param->picture_coding_type = pic_hdr->pic_type;
971 pic_param->f_code = pack_f_code(pic_ext->f_code);
973 #define COPY_FIELD(a, b, f) \
974 pic_param->a.b.f = pic_ext->f
975 pic_param->picture_coding_extension.value = 0;
976 pic_param->picture_coding_extension.bits.is_first_field =
977 GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
978 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
979 COPY_FIELD(picture_coding_extension, bits, picture_structure);
980 COPY_FIELD(picture_coding_extension, bits, top_field_first);
981 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
982 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
983 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
984 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
985 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
986 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
987 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
989 gst_vaapi_dpb_mpeg2_get_references(priv->dpb, picture,
990 &prev_picture, &next_picture);
992 switch (pic_hdr->pic_type) {
993 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
995 pic_param->backward_reference_picture = next_picture->surface_id;
997 pic_param->forward_reference_picture = prev_picture->surface_id;
998 else if (!priv->closed_gop)
999 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1001 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1003 pic_param->forward_reference_picture = prev_picture->surface_id;
1008 static GstVaapiDecoderStatus
1009 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
1011 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1012 GstVaapiPicture * const picture = priv->current_picture;
1013 GstVaapiSlice *slice;
1014 VASliceParameterBufferMPEG2 *slice_param;
1015 GstMpegVideoPacket * const packet = &unit->packet;
1016 GstMpegVideoSliceHdr * const slice_hdr = &unit->data.slice_hdr;
1018 GST_DEBUG("slice %d (%u bytes)", slice_hdr->slice_vertical_position,
1021 unit->base.buffer = gst_buffer_create_sub(
1022 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer,
1023 unit->base.offset, unit->base.size);
1024 if (!unit->base.buffer) {
1025 GST_ERROR("failed to allocate slice data");
1026 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1029 slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1030 GST_BUFFER_DATA(unit->base.buffer), packet->size);
1032 GST_ERROR("failed to allocate slice");
1033 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1035 gst_vaapi_picture_add_slice(picture, slice);
1037 /* Fill in VASliceParameterBufferMPEG2 */
1038 slice_param = slice->param;
1039 slice_param->macroblock_offset = slice_hdr->header_size;
1040 slice_param->slice_horizontal_position = slice_hdr->slice_horizontal_position;
1041 slice_param->slice_vertical_position = slice_hdr->slice_vertical_position;
1042 slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1043 slice_param->intra_slice_flag = slice_hdr->intra_slice;
1044 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1048 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
1050 return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
1051 0xffffff00, 0x00000100,
1056 static GstVaapiDecoderStatus
1057 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
1059 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1060 const GstMpegVideoPacketTypeCode type = unit->packet.type;
1061 GstVaapiDecoderStatus status;
1064 case GST_MPEG_VIDEO_PACKET_PICTURE:
1065 if (!priv->width || !priv->height)
1066 goto unknown_picture_size;
1067 status = decode_picture(decoder, unit);
1069 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1070 status = decode_sequence(decoder, unit);
1072 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1073 switch (unit->extension_type) {
1074 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1075 status = decode_sequence_ext(decoder, unit);
1077 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1078 status = decode_quant_matrix_ext(decoder, unit);
1080 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1081 if (!priv->width || !priv->height)
1082 goto unknown_picture_size;
1083 status = decode_picture_ext(decoder, unit);
1086 // Ignore unknown start-code extensions
1087 GST_WARNING("unsupported packet extension type 0x%02x",
1088 unit->extension_type);
1089 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1093 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1094 status = decode_sequence_end(decoder);
1096 case GST_MPEG_VIDEO_PACKET_GOP:
1097 status = decode_gop(decoder, unit);
1100 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1101 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1102 status = decode_slice(decoder, unit);
1105 GST_WARNING("unsupported packet type 0x%02x", type);
1106 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1111 unknown_picture_size:
1112 // Ignore packet while picture size is undefined
1113 // i.e. missing sequence headers, or not parsed correctly
1114 GST_WARNING("failed to parse picture of unknown size");
1115 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1118 static GstVaapiDecoderStatus
1119 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1121 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1123 g_return_val_if_fail(priv->is_constructed,
1124 GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
1126 if (!priv->is_opened) {
1127 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1128 if (!priv->is_opened)
1129 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1131 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1134 static GstVaapiDecoderStatus
1135 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1136 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit **unit_ptr)
1138 GstVaapiDecoderMpeg2 * const decoder =
1139 GST_VAAPI_DECODER_MPEG2(base_decoder);
1140 GstVaapiDecoderUnitMpeg2 *unit;
1141 GstVaapiDecoderStatus status;
1142 GstMpegVideoPacket *packet;
1145 guint size, buf_size, flags;
1148 status = ensure_decoder(decoder);
1149 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1152 size = gst_adapter_available(adapter);
1154 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1156 ofs = scan_for_start_code(adapter, 0, size, &start_code);
1158 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1159 gst_adapter_flush(adapter, ofs);
1162 ofs = G_UNLIKELY(size < 8) ? -1 :
1163 scan_for_start_code(adapter, 4, size - 4, NULL);
1165 // Assume the whole packet is present if end-of-stream
1167 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1172 buf = gst_adapter_peek(adapter, buf_size);
1174 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1176 unit = gst_vaapi_decoder_unit_mpeg2_new(buf_size);
1178 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1180 packet = &unit->packet;
1182 packet->size = buf_size;
1184 packet->type = start_code & 0xff;
1187 switch (packet->type) {
1188 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1189 status = parse_sequence(unit);
1191 case GST_MPEG_VIDEO_PACKET_GOP:
1192 status = parse_gop(unit);
1194 case GST_MPEG_VIDEO_PACKET_PICTURE:
1195 status = parse_picture(unit);
1197 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1198 if (G_UNLIKELY(buf_size < 5)) {
1199 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1202 unit->extension_type = buf[4] >> 4;
1203 switch (unit->extension_type) {
1204 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1205 status = parse_sequence_ext(unit);
1207 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1208 status = parse_quant_matrix_ext(unit);
1210 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1211 status = parse_picture_ext(unit);
1214 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1219 if (packet->type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1220 packet->type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1221 status = parse_slice(decoder, unit);
1225 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1228 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1231 /* Check for start of new picture */
1233 switch (packet->type) {
1234 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1235 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1236 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1238 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1239 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1241 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1242 case GST_MPEG_VIDEO_PACKET_GOP:
1243 case GST_MPEG_VIDEO_PACKET_PICTURE:
1244 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1247 if (packet->type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1248 packet->type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX)
1249 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1251 // Ignore system start codes (PES headers)
1252 else if (packet->type >= 0xb9 && packet->type <= 0xff)
1253 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1256 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1258 unit->packet.data = NULL;
1259 *unit_ptr = &unit->base;
1260 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1263 static GstVaapiDecoderStatus
1264 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1265 GstVaapiDecoderUnit *unit)
1267 GstVaapiDecoderMpeg2 * const decoder =
1268 GST_VAAPI_DECODER_MPEG2(base_decoder);
1269 GstVaapiDecoderStatus status;
1271 status = ensure_decoder(decoder);
1272 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1274 return decode_unit(decoder, (GstVaapiDecoderUnitMpeg2 *)unit);
1277 static GstVaapiDecoderStatus
1278 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1279 GstVaapiDecoderUnit *base_unit)
1281 GstVaapiDecoderMpeg2 * const decoder =
1282 GST_VAAPI_DECODER_MPEG2(base_decoder);
1283 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1284 GstVaapiPicture *picture;
1285 GstVaapiDecoderStatus status;
1287 if (!priv->width || !priv->height) {
1288 // Ignore packet while picture size is undefined
1289 // i.e. missing sequence headers, or not parsed correctly
1290 GST_WARNING("failed to decode picture of unknown size");
1291 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1294 status = ensure_context(decoder);
1295 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1296 GST_ERROR("failed to reset context");
1300 if (priv->current_picture) {
1301 /* Re-use current picture where the first field was decoded */
1302 picture = gst_vaapi_picture_new_field(priv->current_picture);
1304 GST_ERROR("failed to allocate field picture");
1305 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1309 /* Create new picture */
1310 picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1312 GST_ERROR("failed to allocate picture");
1313 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1316 gst_vaapi_picture_replace(&priv->current_picture, picture);
1317 gst_vaapi_picture_unref(picture);
1319 status = ensure_quant_matrix(decoder, picture);
1320 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1321 GST_ERROR("failed to reset quantizer matrix");
1325 status = init_picture(decoder, picture);
1326 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1329 fill_picture(decoder, picture);
1330 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1333 static GstVaapiDecoderStatus
1334 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1336 GstVaapiDecoderMpeg2 * const decoder =
1337 GST_VAAPI_DECODER_MPEG2(base_decoder);
1339 return decode_current_picture(decoder);
1343 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
1345 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
1347 gst_vaapi_decoder_mpeg2_destroy(decoder);
1349 G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
1353 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
1355 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
1356 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1357 GObjectClass *parent_class;
1359 parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
1360 if (parent_class->constructed)
1361 parent_class->constructed(object);
1363 priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
1367 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1369 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
1370 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1372 g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
1374 object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
1375 object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
1377 decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1378 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1379 decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1380 decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1384 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
1386 GstVaapiDecoderMpeg2Private *priv;
1388 priv = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
1389 decoder->priv = priv;
1394 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
1395 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
1396 priv->current_picture = NULL;
1397 priv->is_constructed = FALSE;
1398 priv->is_opened = FALSE;
1399 priv->size_changed = FALSE;
1400 priv->profile_changed = TRUE; /* Allow fallbacks to work */
1401 priv->quant_matrix_changed = FALSE;
1402 priv->progressive_sequence = FALSE;
1403 priv->closed_gop = FALSE;
1404 priv->broken_link = FALSE;
1408 * gst_vaapi_decoder_mpeg2_new:
1409 * @display: a #GstVaapiDisplay
1410 * @caps: a #GstCaps holding codec information
1412 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1413 * hold extra information like codec-data and pictured coded size.
1415 * Return value: the newly allocated #GstVaapiDecoder object
1418 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1420 GstVaapiDecoderMpeg2 *decoder;
1422 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
1423 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
1425 decoder = g_object_new(
1426 GST_VAAPI_TYPE_DECODER_MPEG2,
1431 if (!decoder->priv->is_constructed) {
1432 g_object_unref(decoder);
1435 return GST_VAAPI_DECODER_CAST(decoder);