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 /* ------------------------------------------------------------------------- */
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);
377 gst_vaapi_dpb_unref(priv->dpb);
383 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
385 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
387 gst_vaapi_decoder_mpeg2_close(decoder);
389 priv->dpb = gst_vaapi_dpb2_new();
393 pts_init(&priv->tsg);
398 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
400 gst_vaapi_decoder_mpeg2_close(decoder);
404 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
406 if (!GST_VAAPI_DECODER_CODEC(decoder))
412 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
414 memcpy(dst, src, 64);
418 get_profile_str(GstVaapiProfile profile)
423 case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
424 case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
425 case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
426 default: str = "<unknown>"; break;
431 static GstVaapiProfile
432 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
434 GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
435 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
436 GstVaapiProfile profile = priv->profile;
439 /* Return immediately if the exact same profile was found */
440 if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
443 /* Otherwise, try to map to a higher profile */
445 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
446 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
448 case GST_VAAPI_PROFILE_MPEG2_MAIN:
449 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
451 case GST_VAAPI_PROFILE_MPEG2_HIGH:
452 // Try to map to main profile if no high profile specific bits used
453 if (priv->profile == profile &&
454 !priv->seq_scalable_ext &&
456 priv->seq_ext->data.seq_ext.chroma_format == 1)) {
457 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
462 profile = GST_VAAPI_PROFILE_UNKNOWN;
465 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
467 if (profile != priv->profile)
468 GST_INFO("forced %s profile to %s profile",
469 get_profile_str(priv->profile), get_profile_str(profile));
473 static GstVaapiDecoderStatus
474 ensure_context(GstVaapiDecoderMpeg2 *decoder)
476 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
477 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
478 gboolean reset_context = FALSE;
480 if (priv->profile_changed) {
481 GST_DEBUG("profile changed");
482 priv->profile_changed = FALSE;
483 reset_context = TRUE;
485 priv->hw_profile = get_profile(decoder, entrypoint);
486 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
487 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
490 if (priv->size_changed) {
491 GST_DEBUG("size changed");
492 priv->size_changed = FALSE;
493 reset_context = TRUE;
497 GstVaapiContextInfo info;
499 info.profile = priv->hw_profile;
500 info.entrypoint = entrypoint;
501 info.width = priv->width;
502 info.height = priv->height;
504 reset_context = gst_vaapi_decoder_ensure_context(
505 GST_VAAPI_DECODER_CAST(decoder),
509 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
511 return GST_VAAPI_DECODER_STATUS_SUCCESS;
514 static GstVaapiDecoderStatus
515 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
517 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
518 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr->data.seq_hdr;
519 VAIQMatrixBufferMPEG2 *iq_matrix;
520 guint8 *intra_quant_matrix = NULL;
521 guint8 *non_intra_quant_matrix = NULL;
522 guint8 *chroma_intra_quant_matrix = NULL;
523 guint8 *chroma_non_intra_quant_matrix = NULL;
525 if (!priv->quant_matrix_changed)
526 return GST_VAAPI_DECODER_STATUS_SUCCESS;
528 priv->quant_matrix_changed = FALSE;
530 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
531 if (!picture->iq_matrix) {
532 GST_ERROR("failed to allocate IQ matrix");
533 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
535 iq_matrix = picture->iq_matrix->param;
537 intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
538 non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
540 if (priv->quant_matrix) {
541 GstMpegVideoQuantMatrixExt * const quant_matrix =
542 &priv->quant_matrix->data.quant_matrix;
543 if (quant_matrix->load_intra_quantiser_matrix)
544 intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
545 if (quant_matrix->load_non_intra_quantiser_matrix)
546 non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
547 if (quant_matrix->load_chroma_intra_quantiser_matrix)
548 chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
549 if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
550 chroma_non_intra_quant_matrix = quant_matrix->chroma_non_intra_quantiser_matrix;
553 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
554 if (intra_quant_matrix)
555 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
558 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
559 if (non_intra_quant_matrix)
560 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
561 non_intra_quant_matrix);
563 iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
564 if (chroma_intra_quant_matrix)
565 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
566 chroma_intra_quant_matrix);
568 iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
569 if (chroma_non_intra_quant_matrix)
570 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
571 chroma_non_intra_quant_matrix);
572 return GST_VAAPI_DECODER_STATUS_SUCCESS;
575 static GstVaapiDecoderStatus
576 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
578 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
579 GstVaapiPicture * const picture = priv->current_picture;
582 return GST_VAAPI_DECODER_STATUS_SUCCESS;
584 if (!gst_vaapi_picture_decode(picture))
586 if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
587 if (!gst_vaapi_dpb_add(priv->dpb, picture))
589 gst_vaapi_picture_replace(&priv->current_picture, NULL);
591 return GST_VAAPI_DECODER_STATUS_SUCCESS;
594 /* XXX: fix for cases where first field failed to be decoded */
595 gst_vaapi_picture_replace(&priv->current_picture, NULL);
596 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
599 static GstVaapiDecoderStatus
600 parse_sequence(GstVaapiDecoderMpeg2 *decoder,
601 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
603 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
604 GstMpegVideoSequenceHdr *seq_hdr;
606 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_hdr)) {
607 GST_ERROR("failed to allocate parser info for sequence header");
608 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
611 seq_hdr = &priv->seq_hdr->data.seq_hdr;
613 if (!gst_mpeg_video_parse_sequence_header(seq_hdr,
614 packet->data, packet->size, packet->offset)) {
615 GST_ERROR("failed to parse sequence header");
616 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
619 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_hdr, NULL);
620 return GST_VAAPI_DECODER_STATUS_SUCCESS;
623 static GstVaapiDecoderStatus
624 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
626 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
627 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
628 GstMpegVideoSequenceHdr * const seq_hdr = unit->parsed_info;
630 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
631 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
633 priv->fps_n = seq_hdr->fps_n;
634 priv->fps_d = seq_hdr->fps_d;
635 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
636 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
638 priv->width = seq_hdr->width;
639 priv->height = seq_hdr->height;
640 priv->size_changed = TRUE;
641 priv->quant_matrix_changed = TRUE;
642 priv->progressive_sequence = TRUE;
643 return GST_VAAPI_DECODER_STATUS_SUCCESS;
646 static GstVaapiDecoderStatus
647 parse_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
648 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
650 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
651 GstMpegVideoSequenceExt *seq_ext;
653 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_ext)) {
654 GST_ERROR("failed to allocate parser info for sequence extension");
655 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
658 seq_ext = &priv->seq_ext->data.seq_ext;
660 if (!gst_mpeg_video_parse_sequence_extension(seq_ext,
661 packet->data, packet->size, packet->offset)) {
662 GST_ERROR("failed to parse sequence-extension");
663 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
666 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_ext, NULL);
667 return GST_VAAPI_DECODER_STATUS_SUCCESS;
670 static GstVaapiDecoderStatus
671 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
673 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
674 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
675 GstMpegVideoSequenceExt * const seq_ext = unit->parsed_info;
676 GstVaapiProfile profile;
679 priv->progressive_sequence = seq_ext->progressive;
680 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
682 width = (priv->width & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
683 height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext << 12);
684 GST_DEBUG("video resolution %ux%u", width, height);
686 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
687 priv->fps_n *= seq_ext->fps_n_ext + 1;
688 priv->fps_d *= seq_ext->fps_d_ext + 1;
689 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
690 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
693 if (priv->width != width) {
695 priv->size_changed = TRUE;
698 if (priv->height != height) {
699 priv->height = height;
700 priv->size_changed = TRUE;
703 switch (seq_ext->profile) {
704 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
705 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
707 case GST_MPEG_VIDEO_PROFILE_MAIN:
708 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
710 case GST_MPEG_VIDEO_PROFILE_HIGH:
711 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
714 GST_ERROR("unsupported profile %d", seq_ext->profile);
715 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
717 if (priv->profile != profile) {
718 priv->profile = profile;
719 priv->profile_changed = TRUE;
721 return GST_VAAPI_DECODER_STATUS_SUCCESS;
724 static GstVaapiDecoderStatus
725 parse_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
726 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
728 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
729 GstMpegVideoSequenceDisplayExt *seq_display_ext;
731 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_display_ext)) {
732 GST_ERROR("failed to allocate parser info for sequence display extension");
733 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
736 seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
738 if (!gst_mpeg_video_parse_sequence_display_extension(seq_display_ext,
739 packet->data, packet->size, packet->offset)) {
740 GST_ERROR("failed to parse sequence-display-extension");
741 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
744 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_display_ext, NULL);
745 return GST_VAAPI_DECODER_STATUS_SUCCESS;
748 static GstVaapiDecoderStatus
749 decode_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
750 GstVaapiDecoderUnit *unit)
752 /* XXX: handle color primaries and cropping */
753 return GST_VAAPI_DECODER_STATUS_SUCCESS;
756 static GstVaapiDecoderStatus
757 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
759 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
760 GstVaapiDecoderStatus status;
762 status = decode_current_picture(decoder);
763 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
766 gst_vaapi_dpb_flush(priv->dpb);
767 return GST_VAAPI_DECODER_STATUS_SUCCESS;
770 static GstVaapiDecoderStatus
771 parse_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
772 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
774 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
775 GstMpegVideoQuantMatrixExt *quant_matrix;
777 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->quant_matrix)) {
778 GST_ERROR("failed to allocate parser info for quantization matrix");
779 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
782 quant_matrix = &priv->quant_matrix->data.quant_matrix;
784 if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix,
785 packet->data, packet->size, packet->offset)) {
786 GST_ERROR("failed to parse quant-matrix-extension");
787 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
790 gst_vaapi_decoder_unit_set_parsed_info(unit, quant_matrix, NULL);
791 return GST_VAAPI_DECODER_STATUS_SUCCESS;
794 static GstVaapiDecoderStatus
795 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
796 GstVaapiDecoderUnit *unit)
798 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
800 priv->quant_matrix_changed = TRUE;
801 return GST_VAAPI_DECODER_STATUS_SUCCESS;
804 static GstVaapiDecoderStatus
805 parse_gop(GstVaapiDecoderMpeg2 *decoder,
806 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
808 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
809 GstMpegVideoGop *gop;
811 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->gop)) {
812 GST_ERROR("failed to allocate parser info for GOP");
813 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
816 gop = &priv->gop->data.gop;
818 if (!gst_mpeg_video_parse_gop(gop,
819 packet->data, packet->size, packet->offset)) {
820 GST_ERROR("failed to parse GOP");
821 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
824 gst_vaapi_decoder_unit_set_parsed_info(unit, gop, NULL);
825 return GST_VAAPI_DECODER_STATUS_SUCCESS;
828 static GstVaapiDecoderStatus
829 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
831 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
832 GstMpegVideoGop * const gop = unit->parsed_info;
834 priv->closed_gop = gop->closed_gop;
835 priv->broken_link = gop->broken_link;
837 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
838 gop->hour, gop->minute, gop->second, gop->frame,
839 priv->closed_gop, priv->broken_link);
841 pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
842 return GST_VAAPI_DECODER_STATUS_SUCCESS;
845 static GstVaapiDecoderStatus
846 parse_picture(GstVaapiDecoderMpeg2 *decoder,
847 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
849 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
850 GstMpegVideoPictureHdr *pic_hdr;
852 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_hdr)) {
853 GST_ERROR("failed to allocate parser info for picture header");
854 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
857 pic_hdr = &priv->pic_hdr->data.pic_hdr;
859 if (!gst_mpeg_video_parse_picture_header(pic_hdr,
860 packet->data, packet->size, packet->offset)) {
861 GST_ERROR("failed to parse picture header");
862 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
865 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_hdr, NULL);
866 return GST_VAAPI_DECODER_STATUS_SUCCESS;
869 static GstVaapiDecoderStatus
870 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
872 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
874 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
875 return GST_VAAPI_DECODER_STATUS_SUCCESS;
878 static GstVaapiDecoderStatus
879 parse_picture_ext(GstVaapiDecoderMpeg2 *decoder,
880 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
882 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
883 GstMpegVideoPictureExt *pic_ext;
885 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_ext)) {
886 GST_ERROR("failed to allocate parser info for picture extension");
887 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
890 pic_ext = &priv->pic_ext->data.pic_ext;
892 if (!gst_mpeg_video_parse_picture_extension(pic_ext,
893 packet->data, packet->size, packet->offset)) {
894 GST_ERROR("failed to parse picture-extension");
895 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
898 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_ext, NULL);
899 return GST_VAAPI_DECODER_STATUS_SUCCESS;
902 static GstVaapiDecoderStatus
903 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
905 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
906 GstMpegVideoPictureExt * const pic_ext = unit->parsed_info;
908 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
909 GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
910 pic_ext->progressive_frame = 1;
913 if (pic_ext->picture_structure == 0 ||
914 (pic_ext->progressive_frame &&
915 pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
916 GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
917 pic_ext->picture_structure);
918 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
920 return GST_VAAPI_DECODER_STATUS_SUCCESS;
923 static inline guint32
924 pack_f_code(guint8 f_code[2][2])
926 return (((guint32)f_code[0][0] << 12) |
927 ((guint32)f_code[0][1] << 8) |
928 ((guint32)f_code[1][0] << 4) |
932 static GstVaapiDecoderStatus
933 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
935 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
936 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
937 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
939 switch (pic_hdr->pic_type) {
940 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
941 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
942 picture->type = GST_VAAPI_PICTURE_TYPE_I;
944 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
945 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
946 picture->type = GST_VAAPI_PICTURE_TYPE_P;
948 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
949 picture->type = GST_VAAPI_PICTURE_TYPE_B;
952 GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
953 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
956 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
957 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
958 if (pic_ext->top_field_first)
959 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
962 switch (pic_ext->picture_structure) {
963 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
964 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
966 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
967 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
969 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
970 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
974 /* Allocate dummy picture for first field based I-frame */
975 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
976 !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
977 gst_vaapi_dpb_size(priv->dpb) == 0) {
978 GstVaapiPicture *dummy_picture;
981 dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
982 if (!dummy_picture) {
983 GST_ERROR("failed to allocate dummy picture");
984 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
987 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
988 dummy_picture->pts = GST_CLOCK_TIME_NONE;
989 dummy_picture->poc = -1;
990 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
992 GST_VAAPI_PICTURE_FLAG_SET(
994 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
995 GST_VAAPI_PICTURE_FLAG_REFERENCE)
998 success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
999 gst_vaapi_picture_unref(dummy_picture);
1001 GST_ERROR("failed to add dummy picture into DPB");
1002 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1004 GST_INFO("allocated dummy picture for first field based I-frame");
1007 /* Update presentation time */
1008 picture->pts = pts_eval(&priv->tsg,
1009 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
1010 picture->poc = pts_get_poc(&priv->tsg);
1011 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1015 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
1017 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1018 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
1019 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1020 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
1021 GstVaapiPicture *prev_picture, *next_picture;
1023 /* Fill in VAPictureParameterBufferMPEG2 */
1024 pic_param->horizontal_size = priv->width;
1025 pic_param->vertical_size = priv->height;
1026 pic_param->forward_reference_picture = VA_INVALID_ID;
1027 pic_param->backward_reference_picture = VA_INVALID_ID;
1028 pic_param->picture_coding_type = pic_hdr->pic_type;
1029 pic_param->f_code = pack_f_code(pic_ext->f_code);
1031 #define COPY_FIELD(a, b, f) \
1032 pic_param->a.b.f = pic_ext->f
1033 pic_param->picture_coding_extension.value = 0;
1034 pic_param->picture_coding_extension.bits.is_first_field =
1035 GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
1036 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
1037 COPY_FIELD(picture_coding_extension, bits, picture_structure);
1038 COPY_FIELD(picture_coding_extension, bits, top_field_first);
1039 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
1040 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
1041 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
1042 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
1043 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
1044 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
1045 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
1047 gst_vaapi_dpb2_get_references(priv->dpb, picture,
1048 &prev_picture, &next_picture);
1050 switch (pic_hdr->pic_type) {
1051 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1053 pic_param->backward_reference_picture = next_picture->surface_id;
1055 pic_param->forward_reference_picture = prev_picture->surface_id;
1056 else if (!priv->closed_gop)
1057 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1059 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1061 pic_param->forward_reference_picture = prev_picture->surface_id;
1066 static GstVaapiDecoderStatus
1067 parse_slice(GstVaapiDecoderMpeg2 *decoder,
1068 GstVaapiDecoderUnit *unit, GstMpegVideoPacket *packet)
1070 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1071 GstMpegVideoSliceHdr *slice_hdr;
1073 gint mb_x, mb_y, mb_inc;
1074 guint8 slice_vertical_position_extension;
1075 guint8 extra_bit_slice, junk8;
1077 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->slice_hdr)) {
1078 GST_ERROR("failed to allocate parser info for slice header");
1079 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1082 slice_hdr = &priv->slice_hdr->data.slice_hdr;
1084 gst_bit_reader_init(&br, packet->data + packet->offset, packet->size);
1085 if (priv->height > 2800)
1086 READ_UINT8(&br, slice_vertical_position_extension, 3);
1087 if (priv->seq_scalable_ext) {
1088 GST_ERROR("failed to parse slice with sequence_scalable_extension()");
1089 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1091 READ_UINT8(&br, slice_hdr->quantiser_scale_code, 5);
1092 READ_UINT8(&br, extra_bit_slice, 1);
1093 if (!extra_bit_slice)
1094 slice_hdr->intra_slice = 0;
1096 READ_UINT8(&br, slice_hdr->intra_slice, 1);
1097 READ_UINT8(&br, junk8, 7);
1098 READ_UINT8(&br, extra_bit_slice, 1);
1099 while (extra_bit_slice) {
1100 READ_UINT8(&br, junk8, 8);
1101 READ_UINT8(&br, extra_bit_slice, 1);
1104 slice_hdr->header_size = 32 + gst_bit_reader_get_pos(&br);
1106 mb_y = packet->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN;
1109 if (!decode_vlc(&br, &mb_inc, mpeg2_mbaddr_vlc_table,
1110 G_N_ELEMENTS(mpeg2_mbaddr_vlc_table))) {
1111 GST_WARNING("failed to decode first macroblock_address_increment");
1114 mb_x += mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
1115 } while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
1117 slice_hdr->slice_horizontal_position = mb_x;
1118 slice_hdr->slice_vertical_position = mb_y;
1120 gst_vaapi_decoder_unit_set_parsed_info(unit, slice_hdr, NULL);
1121 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1124 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1127 static GstVaapiDecoderStatus
1128 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
1130 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1131 GstVaapiPicture * const picture = priv->current_picture;
1132 GstVaapiSlice *slice;
1133 VASliceParameterBufferMPEG2 *slice_param;
1134 GstMpegVideoSliceHdr * const slice_hdr = unit->parsed_info;
1136 GST_DEBUG("slice %d (%u bytes)", slice_hdr->slice_vertical_position,
1139 slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1140 (GST_BUFFER_DATA(GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer) +
1141 unit->offset), unit->size);
1143 GST_ERROR("failed to allocate slice");
1144 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1146 gst_vaapi_picture_add_slice(picture, slice);
1148 /* Fill in VASliceParameterBufferMPEG2 */
1149 slice_param = slice->param;
1150 slice_param->macroblock_offset = slice_hdr->header_size;
1151 slice_param->slice_horizontal_position = slice_hdr->slice_horizontal_position;
1152 slice_param->slice_vertical_position = slice_hdr->slice_vertical_position;
1153 slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1154 slice_param->intra_slice_flag = slice_hdr->intra_slice;
1155 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1159 scan_for_start_code(const guchar *buf, guint buf_size,
1160 GstMpegVideoPacketTypeCode *type_ptr)
1164 while (i <= (buf_size - 4)) {
1167 else if (buf[i + 1])
1169 else if (buf[i] || buf[i + 2] != 1)
1175 if (i <= (buf_size - 4)) {
1177 *type_ptr = buf[i + 3];
1183 static GstVaapiDecoderStatus
1184 parse_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1185 GstMpegVideoPacket *packet)
1187 GstMpegVideoPacketTypeCode type;
1188 GstMpegVideoPacketExtensionCode ext_type;
1189 GstVaapiDecoderStatus status;
1191 type = packet->type;
1193 case GST_MPEG_VIDEO_PACKET_PICTURE:
1194 status = parse_picture(decoder, unit, packet);
1196 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1197 status = parse_sequence(decoder, unit, packet);
1199 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1200 ext_type = packet->data[4] >> 4;
1202 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1203 status = parse_sequence_ext(decoder, unit, packet);
1205 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1206 status = parse_sequence_display_ext(decoder, unit, packet);
1208 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1209 status = parse_quant_matrix_ext(decoder, unit, packet);
1211 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1212 status = parse_picture_ext(decoder, unit, packet);
1215 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1219 case GST_MPEG_VIDEO_PACKET_GOP:
1220 status = parse_gop(decoder, unit, packet);
1223 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1224 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1225 status = parse_slice(decoder, unit, packet);
1228 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1234 static GstVaapiDecoderStatus
1235 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1236 GstMpegVideoPacket *packet)
1238 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1239 GstMpegVideoPacketTypeCode type;
1240 GstMpegVideoPacketExtensionCode ext_type;
1241 GstVaapiDecoderStatus status;
1243 type = packet->type;
1245 case GST_MPEG_VIDEO_PACKET_PICTURE:
1246 if (!priv->width || !priv->height)
1247 goto unknown_picture_size;
1248 status = decode_picture(decoder, unit);
1250 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1251 status = decode_sequence(decoder, unit);
1253 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1254 ext_type = packet->data[4] >> 4;
1256 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1257 status = decode_sequence_ext(decoder, unit);
1259 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1260 status = decode_sequence_display_ext(decoder, unit);
1262 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1263 status = decode_quant_matrix_ext(decoder, unit);
1265 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1266 if (!priv->width || !priv->height)
1267 goto unknown_picture_size;
1268 status = decode_picture_ext(decoder, unit);
1271 // Ignore unknown start-code extensions
1272 GST_WARNING("unsupported packet extension type 0x%02x", ext_type);
1273 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1277 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1278 status = decode_sequence_end(decoder);
1280 case GST_MPEG_VIDEO_PACKET_GOP:
1281 status = decode_gop(decoder, unit);
1284 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1285 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1286 status = decode_slice(decoder, unit);
1289 GST_WARNING("unsupported packet type 0x%02x", type);
1290 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1295 unknown_picture_size:
1296 // Ignore packet while picture size is undefined
1297 // i.e. missing sequence headers, or not parsed correctly
1298 GST_WARNING("failed to parse picture of unknown size");
1299 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1302 static GstVaapiDecoderStatus
1303 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1305 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1307 g_return_val_if_fail(priv->is_constructed,
1308 GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
1310 if (!priv->is_opened) {
1311 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1312 if (!priv->is_opened)
1313 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1315 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1318 static GstVaapiDecoderStatus
1319 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1320 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
1322 GstVaapiDecoderMpeg2 * const decoder =
1323 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1324 GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
1325 GstVaapiDecoderStatus status;
1326 GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1328 guint buf_size, flags;
1329 gint ofs, ofs1, ofs2;
1331 status = ensure_decoder(decoder);
1332 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1335 buf_size = gst_adapter_available(adapter);
1337 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1339 buf = gst_adapter_peek(adapter, buf_size);
1341 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1343 ofs = scan_for_start_code(buf, buf_size, &type);
1345 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1348 ofs2 = ps->input_offset2 - 4;
1349 if (ofs2 < ofs1 + 4)
1352 ofs = G_UNLIKELY(buf_size < ofs2 + 4) ? -1 :
1353 scan_for_start_code(&buf[ofs2], buf_size - ofs2, &type2);
1355 // Assume the whole packet is present if end-of-stream
1357 ps->input_offset2 = buf_size;
1358 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1360 ofs = buf_size - ofs2;
1364 unit->size = ofs2 - ofs1;
1365 gst_adapter_flush(adapter, ofs1);
1366 ps->input_offset2 = 4;
1368 /* Check for start of new picture */
1371 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1372 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1373 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1375 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1376 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1378 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1379 case GST_MPEG_VIDEO_PACKET_GOP:
1380 case GST_MPEG_VIDEO_PACKET_PICTURE:
1381 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1383 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1384 if (G_UNLIKELY(unit->size < 5))
1385 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1388 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1389 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1390 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1392 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1393 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1394 case GST_MPEG_VIDEO_PACKET_GOP:
1395 case GST_MPEG_VIDEO_PACKET_PICTURE:
1396 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1403 // Ignore system start codes (PES headers)
1404 else if (type >= 0xb9 && type <= 0xff)
1405 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1408 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1409 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1412 static GstVaapiDecoderStatus
1413 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1414 GstVaapiDecoderUnit *unit)
1416 GstVaapiDecoderMpeg2 * const decoder =
1417 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1418 GstVaapiDecoderStatus status;
1419 GstMpegVideoPacket packet;
1421 status = ensure_decoder(decoder);
1422 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1426 (GST_BUFFER_DATA(GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer) +
1428 packet.size = unit->size;
1429 packet.type = packet.data[3];
1432 status = parse_unit(decoder, unit, &packet);
1433 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1435 return decode_unit(decoder, unit, &packet);
1438 static GstVaapiDecoderStatus
1439 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1440 GstVaapiDecoderUnit *base_unit)
1442 GstVaapiDecoderMpeg2 * const decoder =
1443 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1444 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1445 GstMpegVideoSequenceHdr *seq_hdr;
1446 GstMpegVideoSequenceExt *seq_ext;
1447 GstMpegVideoSequenceDisplayExt *seq_display_ext;
1448 GstVaapiPicture *picture;
1449 GstVaapiDecoderStatus status;
1451 if (!priv->width || !priv->height) {
1452 // Ignore packet while picture size is undefined
1453 // i.e. missing sequence headers, or not parsed correctly
1454 GST_WARNING("failed to decode picture of unknown size");
1455 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1458 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1459 seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1460 seq_display_ext = priv->seq_display_ext ?
1461 &priv->seq_display_ext->data.seq_display_ext : NULL;
1462 if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext,
1464 gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
1465 seq_hdr->par_w, seq_hdr->par_h);
1467 status = ensure_context(decoder);
1468 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1469 GST_ERROR("failed to reset context");
1473 if (priv->current_picture) {
1474 /* Re-use current picture where the first field was decoded */
1475 picture = gst_vaapi_picture_new_field(priv->current_picture);
1477 GST_ERROR("failed to allocate field picture");
1478 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1482 /* Create new picture */
1483 picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1485 GST_ERROR("failed to allocate picture");
1486 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1489 gst_vaapi_picture_replace(&priv->current_picture, picture);
1490 gst_vaapi_picture_unref(picture);
1492 status = ensure_quant_matrix(decoder, picture);
1493 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1494 GST_ERROR("failed to reset quantizer matrix");
1498 status = init_picture(decoder, picture);
1499 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1502 fill_picture(decoder, picture);
1503 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1506 static GstVaapiDecoderStatus
1507 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1509 GstVaapiDecoderMpeg2 * const decoder =
1510 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1512 return decode_current_picture(decoder);
1516 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
1518 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1520 gst_vaapi_decoder_mpeg2_destroy(decoder);
1522 G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
1526 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
1528 GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1529 GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1530 GObjectClass *parent_class;
1532 parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
1533 if (parent_class->constructed)
1534 parent_class->constructed(object);
1536 priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
1540 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1542 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
1543 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1545 g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
1547 object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
1548 object_class->constructed = gst_vaapi_decoder_mpeg2_constructed;
1550 decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1551 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1552 decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1553 decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1557 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
1559 GstVaapiDecoderMpeg2Private *priv;
1561 priv = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
1562 decoder->priv = priv;
1563 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
1564 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
1565 priv->profile_changed = TRUE; /* Allow fallbacks to work */
1569 * gst_vaapi_decoder_mpeg2_new:
1570 * @display: a #GstVaapiDisplay
1571 * @caps: a #GstCaps holding codec information
1573 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1574 * hold extra information like codec-data and pictured coded size.
1576 * Return value: the newly allocated #GstVaapiDecoder object
1579 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1581 GstVaapiDecoderMpeg2 *decoder;
1583 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
1584 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
1586 decoder = g_object_new(
1587 GST_VAAPI_TYPE_DECODER_MPEG2,
1592 if (!decoder->priv->is_constructed) {
1593 g_object_unref(decoder);
1596 return GST_VAAPI_DECODER_CAST(decoder);