2 * gstvaapidecoder_mpeg2.c - MPEG-2 decoder
4 * Copyright (C) 2011-2013 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))
331 GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR = 1 << 0,
332 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT = 1 << 1,
333 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR = 1 << 2,
334 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT = 1 << 3,
335 GST_MPEG_VIDEO_STATE_GOT_SLICE = 1 << 4,
337 GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS = (
338 GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
339 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT),
340 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS = (
341 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR|
342 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT),
343 GST_MPEG_VIDEO_STATE_VALID_PICTURE = (
344 GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS|
345 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS|
346 GST_MPEG_VIDEO_STATE_GOT_SLICE)
349 struct _GstVaapiDecoderMpeg2Private {
350 GstVaapiProfile profile;
351 GstVaapiProfile hw_profile;
357 GstVaapiParserInfoMpeg2 *seq_hdr;
358 GstVaapiParserInfoMpeg2 *seq_ext;
359 GstVaapiParserInfoMpeg2 *seq_display_ext;
360 GstVaapiParserInfoMpeg2 *seq_scalable_ext;
361 GstVaapiParserInfoMpeg2 *gop;
362 GstVaapiParserInfoMpeg2 *pic_hdr;
363 GstVaapiParserInfoMpeg2 *pic_ext;
364 GstVaapiParserInfoMpeg2 *quant_matrix;
365 GstVaapiParserInfoMpeg2 *slice_hdr;
366 GstVaapiPicture *current_picture;
369 guint is_constructed : 1;
371 guint size_changed : 1;
372 guint profile_changed : 1;
373 guint quant_matrix_changed : 1;
374 guint progressive_sequence : 1;
375 guint closed_gop : 1;
376 guint broken_link : 1;
380 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
382 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
384 gst_vaapi_picture_replace(&priv->current_picture, NULL);
386 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_hdr, NULL);
387 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
388 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
389 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_scalable_ext, NULL);
390 gst_vaapi_parser_info_mpeg2_replace(&priv->gop, NULL);
391 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_hdr, NULL);
392 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
393 gst_vaapi_parser_info_mpeg2_replace(&priv->quant_matrix, NULL);
394 gst_vaapi_parser_info_mpeg2_replace(&priv->slice_hdr, NULL);
396 gst_vaapi_dpb_replace(&priv->dpb, NULL);
400 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
402 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
404 gst_vaapi_decoder_mpeg2_close(decoder);
406 priv->dpb = gst_vaapi_dpb_new(2);
410 pts_init(&priv->tsg);
415 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
417 gst_vaapi_decoder_mpeg2_close(decoder);
421 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
423 if (!GST_VAAPI_DECODER_CODEC(decoder))
429 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
431 memcpy(dst, src, 64);
435 get_profile_str(GstVaapiProfile profile)
440 case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
441 case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
442 case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
443 default: str = "<unknown>"; break;
448 static GstVaapiProfile
449 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
451 GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
452 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
453 GstVaapiProfile profile = priv->profile;
456 /* Return immediately if the exact same profile was found */
457 if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
460 /* Otherwise, try to map to a higher profile */
462 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
463 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
465 case GST_VAAPI_PROFILE_MPEG2_MAIN:
466 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
468 case GST_VAAPI_PROFILE_MPEG2_HIGH:
469 // Try to map to main profile if no high profile specific bits used
470 if (priv->profile == profile &&
471 !priv->seq_scalable_ext &&
473 priv->seq_ext->data.seq_ext.chroma_format == 1)) {
474 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
479 profile = GST_VAAPI_PROFILE_UNKNOWN;
482 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
484 if (profile != priv->profile)
485 GST_INFO("forced %s profile to %s profile",
486 get_profile_str(priv->profile), get_profile_str(profile));
490 static GstVaapiDecoderStatus
491 ensure_context(GstVaapiDecoderMpeg2 *decoder)
493 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
494 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
495 gboolean reset_context = FALSE;
497 if (priv->profile_changed) {
498 GST_DEBUG("profile changed");
499 priv->profile_changed = FALSE;
500 reset_context = TRUE;
502 priv->hw_profile = get_profile(decoder, entrypoint);
503 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
504 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
507 if (priv->size_changed) {
508 GST_DEBUG("size changed");
509 priv->size_changed = FALSE;
510 reset_context = TRUE;
514 GstVaapiContextInfo info;
516 info.profile = priv->hw_profile;
517 info.entrypoint = entrypoint;
518 info.width = priv->width;
519 info.height = priv->height;
521 reset_context = gst_vaapi_decoder_ensure_context(
522 GST_VAAPI_DECODER_CAST(decoder),
526 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
528 return GST_VAAPI_DECODER_STATUS_SUCCESS;
531 static GstVaapiDecoderStatus
532 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
534 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
535 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr->data.seq_hdr;
536 VAIQMatrixBufferMPEG2 *iq_matrix;
537 guint8 *intra_quant_matrix = NULL;
538 guint8 *non_intra_quant_matrix = NULL;
539 guint8 *chroma_intra_quant_matrix = NULL;
540 guint8 *chroma_non_intra_quant_matrix = NULL;
542 if (!priv->quant_matrix_changed)
543 return GST_VAAPI_DECODER_STATUS_SUCCESS;
545 priv->quant_matrix_changed = FALSE;
547 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
548 if (!picture->iq_matrix) {
549 GST_ERROR("failed to allocate IQ matrix");
550 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
552 iq_matrix = picture->iq_matrix->param;
554 intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
555 non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
557 if (priv->quant_matrix) {
558 GstMpegVideoQuantMatrixExt * const quant_matrix =
559 &priv->quant_matrix->data.quant_matrix;
560 if (quant_matrix->load_intra_quantiser_matrix)
561 intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
562 if (quant_matrix->load_non_intra_quantiser_matrix)
563 non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
564 if (quant_matrix->load_chroma_intra_quantiser_matrix)
565 chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
566 if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
567 chroma_non_intra_quant_matrix = quant_matrix->chroma_non_intra_quantiser_matrix;
570 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
571 if (intra_quant_matrix)
572 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
575 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
576 if (non_intra_quant_matrix)
577 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
578 non_intra_quant_matrix);
580 iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
581 if (chroma_intra_quant_matrix)
582 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
583 chroma_intra_quant_matrix);
585 iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
586 if (chroma_non_intra_quant_matrix)
587 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
588 chroma_non_intra_quant_matrix);
589 return GST_VAAPI_DECODER_STATUS_SUCCESS;
592 static inline gboolean
593 is_valid_state(GstVaapiDecoderMpeg2 *decoder, guint state)
595 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
597 return (priv->state & state) == state;
600 static GstVaapiDecoderStatus
601 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
603 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
604 GstVaapiPicture * const picture = priv->current_picture;
606 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PICTURE))
608 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
611 return GST_VAAPI_DECODER_STATUS_SUCCESS;
613 if (!gst_vaapi_picture_decode(picture))
615 if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
616 if (!gst_vaapi_dpb_add(priv->dpb, picture))
618 gst_vaapi_picture_replace(&priv->current_picture, NULL);
620 return GST_VAAPI_DECODER_STATUS_SUCCESS;
623 /* XXX: fix for cases where first field failed to be decoded */
624 gst_vaapi_picture_replace(&priv->current_picture, NULL);
625 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
628 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
629 return GST_VAAPI_DECODER_STATUS_DROP_FRAME;
632 static GstVaapiDecoderStatus
633 parse_sequence(GstVaapiDecoderMpeg2 *decoder,
634 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
636 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
637 GstMpegVideoSequenceHdr *seq_hdr;
641 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_hdr)) {
642 GST_ERROR("failed to allocate parser info for sequence header");
643 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
646 seq_hdr = &priv->seq_hdr->data.seq_hdr;
648 if (!gst_mpeg_video_parse_sequence_header(seq_hdr,
649 packet->data, packet->size, packet->offset)) {
650 GST_ERROR("failed to parse sequence header");
651 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
654 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_hdr, NULL);
655 return GST_VAAPI_DECODER_STATUS_SUCCESS;
658 static GstVaapiDecoderStatus
659 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
661 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
662 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
663 GstMpegVideoSequenceHdr * const seq_hdr = unit->parsed_info;
665 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
666 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
668 priv->fps_n = seq_hdr->fps_n;
669 priv->fps_d = seq_hdr->fps_d;
670 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
671 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
673 priv->width = seq_hdr->width;
674 priv->height = seq_hdr->height;
675 priv->size_changed = TRUE;
676 priv->quant_matrix_changed = TRUE;
677 priv->progressive_sequence = TRUE;
679 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
680 return GST_VAAPI_DECODER_STATUS_SUCCESS;
683 static GstVaapiDecoderStatus
684 parse_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
685 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
687 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
688 GstMpegVideoSequenceExt *seq_ext;
690 priv->state &= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
692 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_ext)) {
693 GST_ERROR("failed to allocate parser info for sequence extension");
694 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
697 seq_ext = &priv->seq_ext->data.seq_ext;
699 if (!gst_mpeg_video_parse_sequence_extension(seq_ext,
700 packet->data, packet->size, packet->offset)) {
701 GST_ERROR("failed to parse sequence-extension");
702 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
705 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_ext, NULL);
706 return GST_VAAPI_DECODER_STATUS_SUCCESS;
709 static GstVaapiDecoderStatus
710 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
712 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
713 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
714 GstMpegVideoSequenceExt * const seq_ext = unit->parsed_info;
715 GstVaapiProfile profile;
718 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR))
719 return GST_VAAPI_DECODER_STATUS_SUCCESS;
721 priv->progressive_sequence = seq_ext->progressive;
722 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
724 width = (priv->width & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
725 height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext << 12);
726 GST_DEBUG("video resolution %ux%u", width, height);
728 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
729 priv->fps_n *= seq_ext->fps_n_ext + 1;
730 priv->fps_d *= seq_ext->fps_d_ext + 1;
731 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
732 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
735 if (priv->width != width) {
737 priv->size_changed = TRUE;
740 if (priv->height != height) {
741 priv->height = height;
742 priv->size_changed = TRUE;
745 switch (seq_ext->profile) {
746 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
747 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
749 case GST_MPEG_VIDEO_PROFILE_MAIN:
750 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
752 case GST_MPEG_VIDEO_PROFILE_HIGH:
753 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
756 GST_ERROR("unsupported profile %d", seq_ext->profile);
757 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
759 if (priv->profile != profile) {
760 priv->profile = profile;
761 priv->profile_changed = TRUE;
764 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT;
765 return GST_VAAPI_DECODER_STATUS_SUCCESS;
768 static GstVaapiDecoderStatus
769 parse_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
770 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
772 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
773 GstMpegVideoSequenceDisplayExt *seq_display_ext;
775 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_display_ext)) {
776 GST_ERROR("failed to allocate parser info for sequence display extension");
777 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
780 seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
782 if (!gst_mpeg_video_parse_sequence_display_extension(seq_display_ext,
783 packet->data, packet->size, packet->offset)) {
784 GST_ERROR("failed to parse sequence-display-extension");
785 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
788 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_display_ext, NULL);
789 return GST_VAAPI_DECODER_STATUS_SUCCESS;
792 static GstVaapiDecoderStatus
793 decode_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
794 GstVaapiDecoderUnit *unit)
796 /* XXX: handle color primaries and cropping */
797 return GST_VAAPI_DECODER_STATUS_SUCCESS;
800 static GstVaapiDecoderStatus
801 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
803 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
805 gst_vaapi_dpb_flush(priv->dpb);
806 return GST_VAAPI_DECODER_STATUS_SUCCESS;
809 static GstVaapiDecoderStatus
810 parse_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
811 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
813 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
814 GstMpegVideoQuantMatrixExt *quant_matrix;
816 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->quant_matrix)) {
817 GST_ERROR("failed to allocate parser info for quantization matrix");
818 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
821 quant_matrix = &priv->quant_matrix->data.quant_matrix;
823 if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix,
824 packet->data, packet->size, packet->offset)) {
825 GST_ERROR("failed to parse quant-matrix-extension");
826 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
829 gst_vaapi_decoder_unit_set_parsed_info(unit, quant_matrix, NULL);
830 return GST_VAAPI_DECODER_STATUS_SUCCESS;
833 static GstVaapiDecoderStatus
834 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
835 GstVaapiDecoderUnit *unit)
837 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
839 priv->quant_matrix_changed = TRUE;
840 return GST_VAAPI_DECODER_STATUS_SUCCESS;
843 static GstVaapiDecoderStatus
844 parse_gop(GstVaapiDecoderMpeg2 *decoder,
845 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
847 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
848 GstMpegVideoGop *gop;
850 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->gop)) {
851 GST_ERROR("failed to allocate parser info for GOP");
852 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
855 gop = &priv->gop->data.gop;
857 if (!gst_mpeg_video_parse_gop(gop,
858 packet->data, packet->size, packet->offset)) {
859 GST_ERROR("failed to parse GOP");
860 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
863 gst_vaapi_decoder_unit_set_parsed_info(unit, gop, NULL);
864 return GST_VAAPI_DECODER_STATUS_SUCCESS;
867 static GstVaapiDecoderStatus
868 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
870 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
871 GstMpegVideoGop * const gop = unit->parsed_info;
873 priv->closed_gop = gop->closed_gop;
874 priv->broken_link = gop->broken_link;
876 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
877 gop->hour, gop->minute, gop->second, gop->frame,
878 priv->closed_gop, priv->broken_link);
880 pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
881 return GST_VAAPI_DECODER_STATUS_SUCCESS;
884 static GstVaapiDecoderStatus
885 parse_picture(GstVaapiDecoderMpeg2 *decoder,
886 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
888 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
889 GstMpegVideoPictureHdr *pic_hdr;
891 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
892 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT);
894 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_hdr)) {
895 GST_ERROR("failed to allocate parser info for picture header");
896 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
899 pic_hdr = &priv->pic_hdr->data.pic_hdr;
901 if (!gst_mpeg_video_parse_picture_header(pic_hdr,
902 packet->data, packet->size, packet->offset)) {
903 GST_ERROR("failed to parse picture header");
904 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
907 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_hdr, NULL);
908 return GST_VAAPI_DECODER_STATUS_SUCCESS;
911 static GstVaapiDecoderStatus
912 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
914 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
916 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS))
917 return GST_VAAPI_DECODER_STATUS_SUCCESS;
919 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
921 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_HDR;
922 return GST_VAAPI_DECODER_STATUS_SUCCESS;
925 static GstVaapiDecoderStatus
926 parse_picture_ext(GstVaapiDecoderMpeg2 *decoder,
927 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
929 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
930 GstMpegVideoPictureExt *pic_ext;
932 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
933 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT|
934 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR);
936 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_ext)) {
937 GST_ERROR("failed to allocate parser info for picture extension");
938 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
941 pic_ext = &priv->pic_ext->data.pic_ext;
943 if (!gst_mpeg_video_parse_picture_extension(pic_ext,
944 packet->data, packet->size, packet->offset)) {
945 GST_ERROR("failed to parse picture-extension");
946 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
949 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_ext, NULL);
950 return GST_VAAPI_DECODER_STATUS_SUCCESS;
953 static GstVaapiDecoderStatus
954 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
956 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
957 GstMpegVideoPictureExt * const pic_ext = unit->parsed_info;
959 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_PIC_HDR))
960 return GST_VAAPI_DECODER_STATUS_SUCCESS;
962 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
963 GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
964 pic_ext->progressive_frame = 1;
967 if (pic_ext->picture_structure == 0 ||
968 (pic_ext->progressive_frame &&
969 pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
970 GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
971 pic_ext->picture_structure);
972 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
975 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_EXT;
976 return GST_VAAPI_DECODER_STATUS_SUCCESS;
979 static inline guint32
980 pack_f_code(guint8 f_code[2][2])
982 return (((guint32)f_code[0][0] << 12) |
983 ((guint32)f_code[0][1] << 8) |
984 ((guint32)f_code[1][0] << 4) |
988 static GstVaapiDecoderStatus
989 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
991 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
992 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
993 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
995 switch (pic_hdr->pic_type) {
996 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
997 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
998 picture->type = GST_VAAPI_PICTURE_TYPE_I;
1000 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1001 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
1002 picture->type = GST_VAAPI_PICTURE_TYPE_P;
1004 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1005 picture->type = GST_VAAPI_PICTURE_TYPE_B;
1008 GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
1009 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1012 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
1013 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
1014 if (pic_ext->top_field_first)
1015 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
1018 switch (pic_ext->picture_structure) {
1019 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
1020 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
1022 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
1023 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
1025 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
1026 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1030 /* Allocate dummy picture for first field based I-frame */
1031 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
1032 !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
1033 gst_vaapi_dpb_size(priv->dpb) == 0) {
1034 GstVaapiPicture *dummy_picture;
1037 dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1038 if (!dummy_picture) {
1039 GST_ERROR("failed to allocate dummy picture");
1040 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1043 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
1044 dummy_picture->pts = GST_CLOCK_TIME_NONE;
1045 dummy_picture->poc = -1;
1046 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1048 GST_VAAPI_PICTURE_FLAG_SET(
1050 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
1051 GST_VAAPI_PICTURE_FLAG_REFERENCE)
1054 success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
1055 gst_vaapi_picture_unref(dummy_picture);
1057 GST_ERROR("failed to add dummy picture into DPB");
1058 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1060 GST_INFO("allocated dummy picture for first field based I-frame");
1063 /* Update presentation time */
1064 picture->pts = pts_eval(&priv->tsg,
1065 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
1066 picture->poc = pts_get_poc(&priv->tsg);
1067 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1071 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
1073 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1074 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
1075 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1076 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
1077 GstVaapiPicture *prev_picture, *next_picture;
1079 /* Fill in VAPictureParameterBufferMPEG2 */
1080 pic_param->horizontal_size = priv->width;
1081 pic_param->vertical_size = priv->height;
1082 pic_param->forward_reference_picture = VA_INVALID_ID;
1083 pic_param->backward_reference_picture = VA_INVALID_ID;
1084 pic_param->picture_coding_type = pic_hdr->pic_type;
1085 pic_param->f_code = pack_f_code(pic_ext->f_code);
1087 #define COPY_FIELD(a, b, f) \
1088 pic_param->a.b.f = pic_ext->f
1089 pic_param->picture_coding_extension.value = 0;
1090 pic_param->picture_coding_extension.bits.is_first_field =
1091 GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
1092 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
1093 COPY_FIELD(picture_coding_extension, bits, picture_structure);
1094 COPY_FIELD(picture_coding_extension, bits, top_field_first);
1095 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
1096 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
1097 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
1098 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
1099 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
1100 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
1101 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
1103 gst_vaapi_dpb_get_neighbours(priv->dpb, picture,
1104 &prev_picture, &next_picture);
1106 switch (pic_hdr->pic_type) {
1107 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1109 pic_param->backward_reference_picture = next_picture->surface_id;
1111 pic_param->forward_reference_picture = prev_picture->surface_id;
1112 else if (!priv->closed_gop)
1113 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1115 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1117 pic_param->forward_reference_picture = prev_picture->surface_id;
1122 static GstVaapiDecoderStatus
1123 parse_slice(GstVaapiDecoderMpeg2 *decoder,
1124 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
1126 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1127 GstMpegVideoSliceHdr *slice_hdr;
1129 gint mb_x, mb_y, mb_inc;
1130 guint8 slice_vertical_position_extension = 0;
1131 guint8 extra_bit_slice, junk8;
1133 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
1134 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT|
1135 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR|
1136 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT);
1138 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->slice_hdr)) {
1139 GST_ERROR("failed to allocate parser info for slice header");
1140 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1143 slice_hdr = &priv->slice_hdr->data.slice_hdr;
1145 gst_bit_reader_init(&br, packet->data + packet->offset, packet->size);
1146 if (priv->height > 2800)
1147 READ_UINT8(&br, slice_vertical_position_extension, 3);
1148 if (priv->seq_scalable_ext) {
1149 GST_ERROR("failed to parse slice with sequence_scalable_extension()");
1150 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1152 READ_UINT8(&br, slice_hdr->quantiser_scale_code, 5);
1153 READ_UINT8(&br, extra_bit_slice, 1);
1154 if (!extra_bit_slice)
1155 slice_hdr->intra_slice = 0;
1157 READ_UINT8(&br, slice_hdr->intra_slice, 1);
1158 READ_UINT8(&br, junk8, 7);
1159 READ_UINT8(&br, extra_bit_slice, 1);
1160 while (extra_bit_slice) {
1161 READ_UINT8(&br, junk8, 8);
1162 READ_UINT8(&br, extra_bit_slice, 1);
1165 slice_hdr->header_size = 32 + gst_bit_reader_get_pos(&br);
1167 mb_y = ((guint)slice_vertical_position_extension << 7) +
1168 packet->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN;
1171 if (!decode_vlc(&br, &mb_inc, mpeg2_mbaddr_vlc_table,
1172 G_N_ELEMENTS(mpeg2_mbaddr_vlc_table))) {
1173 GST_WARNING("failed to decode first macroblock_address_increment");
1176 mb_x += mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
1177 } while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
1179 slice_hdr->slice_horizontal_position = mb_x;
1180 slice_hdr->slice_vertical_position = mb_y;
1182 gst_vaapi_decoder_unit_set_parsed_info(unit, slice_hdr, NULL);
1183 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1186 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1189 static GstVaapiDecoderStatus
1190 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
1192 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1193 GstVaapiPicture * const picture = priv->current_picture;
1194 GstVaapiSlice *slice;
1195 VASliceParameterBufferMPEG2 *slice_param;
1196 GstMpegVideoSliceHdr * const slice_hdr = unit->parsed_info;
1197 GstBuffer * const buffer =
1198 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1199 GstMapInfo map_info;
1201 GST_DEBUG("slice %d (%u bytes)", slice_hdr->slice_vertical_position,
1204 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1205 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1207 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1208 GST_ERROR("failed to map buffer");
1209 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1212 slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1213 (map_info.data + unit->offset), unit->size);
1215 GST_ERROR("failed to allocate slice");
1216 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1218 gst_vaapi_picture_add_slice(picture, slice);
1220 /* Fill in VASliceParameterBufferMPEG2 */
1221 slice_param = slice->param;
1222 slice_param->macroblock_offset = slice_hdr->header_size;
1223 slice_param->slice_horizontal_position = slice_hdr->slice_horizontal_position;
1224 slice_param->slice_vertical_position = slice_hdr->slice_vertical_position;
1225 slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1226 slice_param->intra_slice_flag = slice_hdr->intra_slice;
1228 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SLICE;
1229 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1233 scan_for_start_code(const guchar *buf, guint buf_size,
1234 GstMpegVideoPacketTypeCode *type_ptr)
1238 while (i <= (buf_size - 4)) {
1241 else if (buf[i + 1])
1243 else if (buf[i] || buf[i + 2] != 1)
1249 if (i <= (buf_size - 4)) {
1251 *type_ptr = buf[i + 3];
1257 static GstVaapiDecoderStatus
1258 parse_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1259 GstMpegVideoPacket *packet)
1261 GstMpegVideoPacketTypeCode type;
1262 GstMpegVideoPacketExtensionCode ext_type;
1263 GstVaapiDecoderStatus status;
1265 type = packet->type;
1267 case GST_MPEG_VIDEO_PACKET_PICTURE:
1268 status = parse_picture(decoder, unit, packet);
1270 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1271 status = parse_sequence(decoder, unit, packet);
1273 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1274 ext_type = packet->data[4] >> 4;
1276 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1277 status = parse_sequence_ext(decoder, unit, packet);
1279 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1280 status = parse_sequence_display_ext(decoder, unit, packet);
1282 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1283 status = parse_quant_matrix_ext(decoder, unit, packet);
1285 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1286 status = parse_picture_ext(decoder, unit, packet);
1289 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1293 case GST_MPEG_VIDEO_PACKET_GOP:
1294 status = parse_gop(decoder, unit, packet);
1297 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1298 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1299 status = parse_slice(decoder, unit, packet);
1302 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1308 static GstVaapiDecoderStatus
1309 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1310 GstMpegVideoPacket *packet)
1312 GstMpegVideoPacketTypeCode type;
1313 GstMpegVideoPacketExtensionCode ext_type;
1314 GstVaapiDecoderStatus status;
1316 type = packet->type;
1318 case GST_MPEG_VIDEO_PACKET_PICTURE:
1319 status = decode_picture(decoder, unit);
1321 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1322 status = decode_sequence(decoder, unit);
1324 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1325 ext_type = packet->data[4] >> 4;
1327 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1328 status = decode_sequence_ext(decoder, unit);
1330 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1331 status = decode_sequence_display_ext(decoder, unit);
1333 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1334 status = decode_quant_matrix_ext(decoder, unit);
1336 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1337 status = decode_picture_ext(decoder, unit);
1340 // Ignore unknown start-code extensions
1341 GST_WARNING("unsupported packet extension type 0x%02x", ext_type);
1342 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1346 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1347 status = decode_sequence_end(decoder);
1349 case GST_MPEG_VIDEO_PACKET_GOP:
1350 status = decode_gop(decoder, unit);
1353 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1354 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1355 status = decode_slice(decoder, unit);
1358 GST_WARNING("unsupported packet type 0x%02x", type);
1359 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1365 static GstVaapiDecoderStatus
1366 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1368 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1370 g_return_val_if_fail(priv->is_constructed,
1371 GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
1373 if (!priv->is_opened) {
1374 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1375 if (!priv->is_opened)
1376 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1378 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1381 static GstVaapiDecoderStatus
1382 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1383 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
1385 GstVaapiDecoderMpeg2 * const decoder =
1386 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1387 GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
1388 GstVaapiDecoderStatus status;
1389 GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1391 guint buf_size, flags;
1392 gint ofs, ofs1, ofs2;
1394 status = ensure_decoder(decoder);
1395 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1398 buf_size = gst_adapter_available(adapter);
1400 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1402 buf = gst_adapter_map(adapter, buf_size);
1404 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1406 ofs = scan_for_start_code(buf, buf_size, &type);
1408 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1411 ofs2 = ps->input_offset2 - 4;
1412 if (ofs2 < ofs1 + 4)
1415 ofs = G_UNLIKELY(buf_size < ofs2 + 4) ? -1 :
1416 scan_for_start_code(&buf[ofs2], buf_size - ofs2, &type2);
1418 // Assume the whole packet is present if end-of-stream
1420 ps->input_offset2 = buf_size;
1421 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1423 ofs = buf_size - ofs2;
1427 unit->size = ofs2 - ofs1;
1428 gst_adapter_flush(adapter, ofs1);
1429 ps->input_offset2 = 4;
1431 /* Check for start of new picture */
1434 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1435 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1436 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1438 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1439 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1441 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1442 case GST_MPEG_VIDEO_PACKET_GOP:
1443 case GST_MPEG_VIDEO_PACKET_PICTURE:
1444 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1446 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1447 if (G_UNLIKELY(unit->size < 5))
1448 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1451 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1452 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1453 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1455 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1456 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1457 case GST_MPEG_VIDEO_PACKET_GOP:
1458 case GST_MPEG_VIDEO_PACKET_PICTURE:
1459 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1466 // Ignore system start codes (PES headers)
1467 else if (type >= 0xb9 && type <= 0xff)
1468 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1471 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1472 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1475 static GstVaapiDecoderStatus
1476 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1477 GstVaapiDecoderUnit *unit)
1479 GstVaapiDecoderMpeg2 * const decoder =
1480 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1481 GstVaapiDecoderStatus status;
1482 GstMpegVideoPacket packet;
1483 GstBuffer * const buffer =
1484 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1485 GstMapInfo map_info;
1487 status = ensure_decoder(decoder);
1488 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1491 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1492 GST_ERROR("failed to map buffer");
1493 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1496 packet.data = map_info.data + unit->offset;
1497 packet.size = unit->size;
1498 packet.type = packet.data[3];
1501 status = parse_unit(decoder, unit, &packet);
1502 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1504 return decode_unit(decoder, unit, &packet);
1507 static GstVaapiDecoderStatus
1508 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1509 GstVaapiDecoderUnit *base_unit)
1511 GstVaapiDecoderMpeg2 * const decoder =
1512 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1513 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1514 GstMpegVideoSequenceHdr *seq_hdr;
1515 GstMpegVideoSequenceExt *seq_ext;
1516 GstMpegVideoSequenceDisplayExt *seq_display_ext;
1517 GstVaapiPicture *picture;
1518 GstVaapiDecoderStatus status;
1520 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1521 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1522 priv->state &= ~GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1524 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1525 seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1526 seq_display_ext = priv->seq_display_ext ?
1527 &priv->seq_display_ext->data.seq_display_ext : NULL;
1528 if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext,
1530 gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
1531 seq_hdr->par_w, seq_hdr->par_h);
1533 status = ensure_context(decoder);
1534 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1535 GST_ERROR("failed to reset context");
1539 if (priv->current_picture) {
1540 /* Re-use current picture where the first field was decoded */
1541 picture = gst_vaapi_picture_new_field(priv->current_picture);
1543 GST_ERROR("failed to allocate field picture");
1544 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1548 /* Create new picture */
1549 picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1551 GST_ERROR("failed to allocate picture");
1552 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1555 gst_vaapi_picture_replace(&priv->current_picture, picture);
1556 gst_vaapi_picture_unref(picture);
1558 status = ensure_quant_matrix(decoder, picture);
1559 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1560 GST_ERROR("failed to reset quantizer matrix");
1564 status = init_picture(decoder, picture);
1565 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1568 fill_picture(decoder, picture);
1570 priv->state |= GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1571 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1574 static GstVaapiDecoderStatus
1575 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1577 GstVaapiDecoderMpeg2 * const decoder =
1578 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1580 return decode_current_picture(decoder);
1583 static GstVaapiDecoderStatus
1584 gst_vaapi_decoder_mpeg2_flush(GstVaapiDecoder *base_decoder)
1586 GstVaapiDecoderMpeg2 * const decoder =
1587 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1588 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1590 gst_vaapi_dpb_flush(priv->dpb);
1591 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1595 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
1597 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1599 gst_vaapi_decoder_mpeg2_destroy(decoder);
1601 G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
1605 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
1607 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1608 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1609 GObjectClass *parent_class;
1611 parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
1612 if (parent_class->constructed)
1613 parent_class->constructed(object);
1615 priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
1619 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1621 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
1622 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1624 g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
1626 object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
1627 object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
1629 decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1630 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1631 decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1632 decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1633 decoder_class->flush = gst_vaapi_decoder_mpeg2_flush;
1637 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
1639 GstVaapiDecoderMpeg2Private *priv;
1641 priv = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
1642 decoder->priv = priv;
1643 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
1644 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
1645 priv->profile_changed = TRUE; /* Allow fallbacks to work */
1649 * gst_vaapi_decoder_mpeg2_new:
1650 * @display: a #GstVaapiDisplay
1651 * @caps: a #GstCaps holding codec information
1653 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1654 * hold extra information like codec-data and pictured coded size.
1656 * Return value: the newly allocated #GstVaapiDecoder object
1659 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1661 GstVaapiDecoderMpeg2 *decoder;
1663 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
1664 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
1666 decoder = g_object_new(
1667 GST_VAAPI_TYPE_DECODER_MPEG2,
1672 if (!decoder->priv->is_constructed) {
1673 g_object_unref(decoder);
1676 return GST_VAAPI_DECODER_CAST(decoder);