2 * gstvaapidecoder_mpeg2.c - MPEG-2 decoder
4 * Copyright (C) 2011-2013 Intel Corporation
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
24 * SECTION:gstvaapidecoder_mpeg2
25 * @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"
38 #include "gstvaapidebug.h"
40 /* ------------------------------------------------------------------------- */
41 /* --- PTS Generator --- */
42 /* ------------------------------------------------------------------------- */
44 typedef struct _PTSGenerator PTSGenerator;
47 GstClockTime gop_pts; // Current GOP PTS
48 GstClockTime max_pts; // Max picture PTS
49 guint gop_tsn; // Absolute GOP TSN
50 guint max_tsn; // Max picture TSN, relative to last GOP TSN
51 guint ovl_tsn; // How many times TSN overflowed since GOP
52 guint lst_tsn; // Last picture TSN
58 pts_init (PTSGenerator * tsg)
60 tsg->gop_pts = GST_CLOCK_TIME_NONE;
61 tsg->max_pts = GST_CLOCK_TIME_NONE;
70 static inline GstClockTime
71 pts_get_duration (PTSGenerator * tsg, guint num_frames)
73 return gst_util_uint64_scale (num_frames,
74 GST_SECOND * tsg->fps_d, tsg->fps_n);
78 pts_get_poc (PTSGenerator * tsg)
80 return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
84 pts_set_framerate (PTSGenerator * tsg, guint fps_n, guint fps_d)
91 pts_sync (PTSGenerator * tsg, GstClockTime gop_pts)
95 if (!GST_CLOCK_TIME_IS_VALID (gop_pts) ||
96 (GST_CLOCK_TIME_IS_VALID (tsg->max_pts) && tsg->max_pts >= gop_pts)) {
97 /* Invalid GOP PTS, interpolate from the last known picture PTS */
98 if (GST_CLOCK_TIME_IS_VALID (tsg->max_pts)) {
99 gop_pts = tsg->max_pts + pts_get_duration (tsg, 1);
100 gop_tsn = tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->max_tsn + 1;
106 /* Interpolate GOP TSN from this valid PTS */
107 if (GST_CLOCK_TIME_IS_VALID (tsg->gop_pts))
109 tsg->gop_tsn + gst_util_uint64_scale (gop_pts - tsg->gop_pts +
110 pts_get_duration (tsg, 1) - 1, tsg->fps_n, GST_SECOND * tsg->fps_d);
115 tsg->gop_pts = gop_pts;
116 tsg->gop_tsn = gop_tsn;
123 pts_eval (PTSGenerator * tsg, GstClockTime pic_pts, guint pic_tsn)
127 if (!GST_CLOCK_TIME_IS_VALID (tsg->gop_pts))
128 tsg->gop_pts = pts_get_duration (tsg, pic_tsn);
131 if (!GST_CLOCK_TIME_IS_VALID (pts))
132 pts = tsg->gop_pts + pts_get_duration (tsg, tsg->ovl_tsn * 1024 + pic_tsn);
133 else if (pts == tsg->gop_pts) {
134 /* The picture following the GOP header shall be an I-frame.
135 So we can compensate for the GOP start time from here */
136 tsg->gop_pts -= pts_get_duration (tsg, pic_tsn);
139 if (!GST_CLOCK_TIME_IS_VALID (tsg->max_pts) || tsg->max_pts < pts)
142 if (tsg->max_tsn < pic_tsn)
143 tsg->max_tsn = pic_tsn;
144 else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
145 tsg->max_tsn = pic_tsn;
148 tsg->lst_tsn = pic_tsn;
153 /* ------------------------------------------------------------------------- */
154 /* --- MPEG-2 Parser Info --- */
155 /* ------------------------------------------------------------------------- */
157 typedef struct _GstVaapiParserInfoMpeg2 GstVaapiParserInfoMpeg2;
158 struct _GstVaapiParserInfoMpeg2
160 GstVaapiMiniObject parent_instance;
161 GstMpegVideoPacket packet;
162 guint8 extension_type; /* for Extension packets */
165 GstMpegVideoSequenceHdr seq_hdr;
166 GstMpegVideoSequenceExt seq_ext;
167 GstMpegVideoSequenceDisplayExt seq_display_ext;
168 GstMpegVideoSequenceScalableExt seq_scalable_ext;
170 GstMpegVideoQuantMatrixExt quant_matrix;
171 GstMpegVideoPictureHdr pic_hdr;
172 GstMpegVideoPictureExt pic_ext;
173 GstMpegVideoSliceHdr slice_hdr;
177 static inline const GstVaapiMiniObjectClass *
178 gst_vaapi_parser_info_mpeg2_class (void)
180 static const GstVaapiMiniObjectClass GstVaapiParserInfoMpeg2Class = {
181 sizeof (GstVaapiParserInfoMpeg2),
184 return &GstVaapiParserInfoMpeg2Class;
187 static inline GstVaapiParserInfoMpeg2 *
188 gst_vaapi_parser_info_mpeg2_new (void)
190 return (GstVaapiParserInfoMpeg2 *)
191 gst_vaapi_mini_object_new (gst_vaapi_parser_info_mpeg2_class ());
194 static inline GstVaapiParserInfoMpeg2 *
195 gst_vaapi_parser_info_mpeg2_ensure (GstVaapiParserInfoMpeg2 ** pi_ptr)
197 GstVaapiParserInfoMpeg2 *pi = *pi_ptr;
199 if (G_LIKELY (pi != NULL))
202 *pi_ptr = pi = gst_vaapi_parser_info_mpeg2_new ();
206 #define gst_vaapi_parser_info_mpeg2_ref(pi) \
207 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
209 #define gst_vaapi_parser_info_mpeg2_unref(pi) \
210 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
212 #define gst_vaapi_parser_info_mpeg2_replace(old_pi_ptr, new_pi) \
213 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr), \
214 (GstVaapiMiniObject *)(new_pi))
216 /* ------------------------------------------------------------------------- */
217 /* --- MPEG-2 Decoder --- */
218 /* ------------------------------------------------------------------------- */
220 #define GST_VAAPI_DECODER_MPEG2_CAST(decoder) \
221 ((GstVaapiDecoderMpeg2 *)(decoder))
223 typedef struct _GstVaapiDecoderMpeg2Private GstVaapiDecoderMpeg2Private;
224 typedef struct _GstVaapiDecoderMpeg2Class GstVaapiDecoderMpeg2Class;
228 GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR = 1 << 0,
229 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT = 1 << 1,
230 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR = 1 << 2,
231 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT = 1 << 3,
232 GST_MPEG_VIDEO_STATE_GOT_SLICE = 1 << 4,
234 GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS = (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
235 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT),
236 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS = (GST_MPEG_VIDEO_STATE_GOT_PIC_HDR |
237 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT),
238 GST_MPEG_VIDEO_STATE_VALID_PICTURE = (GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS |
239 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS | GST_MPEG_VIDEO_STATE_GOT_SLICE)
242 struct _GstVaapiDecoderMpeg2Private
244 GstVaapiProfile profile;
245 GstVaapiProfile hw_profile;
251 GstVaapiRectangle crop_rect;
252 GstVaapiParserInfoMpeg2 *seq_hdr;
253 GstVaapiParserInfoMpeg2 *seq_ext;
254 GstVaapiParserInfoMpeg2 *seq_display_ext;
255 GstVaapiParserInfoMpeg2 *seq_scalable_ext;
256 GstVaapiParserInfoMpeg2 *gop;
257 GstVaapiParserInfoMpeg2 *pic_hdr;
258 GstVaapiParserInfoMpeg2 *pic_ext;
259 GstVaapiParserInfoMpeg2 *pic_display_ext;
260 GstVaapiParserInfoMpeg2 *quant_matrix;
261 GstVaapiParserInfoMpeg2 *slice_hdr;
262 GstVaapiPicture *current_picture;
266 guint size_changed:1;
267 guint profile_changed:1;
268 guint quant_matrix_changed:1;
269 guint progressive_sequence:1;
275 * GstVaapiDecoderMpeg2:
277 * A decoder based on Mpeg2.
279 struct _GstVaapiDecoderMpeg2
282 GstVaapiDecoder parent_instance;
283 GstVaapiDecoderMpeg2Private priv;
287 * GstVaapiDecoderMpeg2Class:
289 * A decoder class based on Mpeg2.
291 struct _GstVaapiDecoderMpeg2Class
294 GstVaapiDecoderClass parent_class;
297 G_DEFINE_TYPE (GstVaapiDecoderMpeg2, gst_vaapi_decoder_mpeg2,
298 GST_TYPE_VAAPI_DECODER);
301 gst_vaapi_decoder_mpeg2_close (GstVaapiDecoderMpeg2 * decoder)
303 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
305 gst_vaapi_picture_replace (&priv->current_picture, NULL);
307 gst_vaapi_parser_info_mpeg2_replace (&priv->seq_hdr, NULL);
308 gst_vaapi_parser_info_mpeg2_replace (&priv->seq_ext, NULL);
309 gst_vaapi_parser_info_mpeg2_replace (&priv->seq_display_ext, NULL);
310 gst_vaapi_parser_info_mpeg2_replace (&priv->seq_scalable_ext, NULL);
311 gst_vaapi_parser_info_mpeg2_replace (&priv->gop, NULL);
312 gst_vaapi_parser_info_mpeg2_replace (&priv->pic_hdr, NULL);
313 gst_vaapi_parser_info_mpeg2_replace (&priv->pic_ext, NULL);
314 gst_vaapi_parser_info_mpeg2_replace (&priv->pic_display_ext, NULL);
315 gst_vaapi_parser_info_mpeg2_replace (&priv->quant_matrix, NULL);
316 gst_vaapi_parser_info_mpeg2_replace (&priv->slice_hdr, NULL);
320 gst_vaapi_dpb_replace (&priv->dpb, NULL);
322 priv->is_opened = FALSE;
326 gst_vaapi_decoder_mpeg2_open (GstVaapiDecoderMpeg2 * decoder)
328 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
330 gst_vaapi_decoder_mpeg2_close (decoder);
332 priv->dpb = gst_vaapi_dpb_new (2);
336 pts_init (&priv->tsg);
341 gst_vaapi_decoder_mpeg2_destroy (GstVaapiDecoder * base_decoder)
343 GstVaapiDecoderMpeg2 *const decoder =
344 GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
346 gst_vaapi_decoder_mpeg2_close (decoder);
350 gst_vaapi_decoder_mpeg2_create (GstVaapiDecoder * base_decoder)
352 GstVaapiDecoderMpeg2 *const decoder =
353 GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
354 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
356 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
357 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
358 priv->profile_changed = TRUE; /* Allow fallbacks to work */
362 static GstVaapiDecoderStatus
363 gst_vaapi_decoder_mpeg2_reset (GstVaapiDecoder * base_decoder)
365 gst_vaapi_decoder_mpeg2_destroy (base_decoder);
366 gst_vaapi_decoder_mpeg2_create (base_decoder);
367 return GST_VAAPI_DECODER_STATUS_SUCCESS;
371 copy_quant_matrix (guint8 dst[64], const guint8 src[64])
373 memcpy (dst, src, 64);
377 get_profile_str (GstVaapiProfile profile)
382 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
385 case GST_VAAPI_PROFILE_MPEG2_MAIN:
388 case GST_VAAPI_PROFILE_MPEG2_HIGH:
398 static GstVaapiProfile
399 get_profile (GstVaapiDecoderMpeg2 * decoder, GstVaapiEntrypoint entrypoint)
401 GstVaapiDisplay *const va_display = GST_VAAPI_DECODER_DISPLAY (decoder);
402 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
403 GstVaapiProfile profile = priv->profile;
406 /* Return immediately if the exact same profile was found */
407 if (gst_vaapi_display_has_decoder (va_display, profile, entrypoint))
410 /* Otherwise, try to map to a higher profile */
412 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
413 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
415 case GST_VAAPI_PROFILE_MPEG2_MAIN:
416 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
418 case GST_VAAPI_PROFILE_MPEG2_HIGH:
419 // Try to map to main profile if no high profile specific bits used
420 if (priv->profile == profile &&
421 !priv->seq_scalable_ext &&
422 (priv->seq_ext && priv->seq_ext->data.seq_ext.chroma_format == 1)) {
423 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
428 profile = GST_VAAPI_PROFILE_UNKNOWN;
431 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
433 if (profile != priv->profile)
434 GST_INFO ("forced %s profile to %s profile",
435 get_profile_str (priv->profile), get_profile_str (profile));
439 static GstVaapiDecoderStatus
440 ensure_context (GstVaapiDecoderMpeg2 * decoder)
442 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
443 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
444 gboolean reset_context = FALSE;
446 if (priv->profile_changed) {
447 GST_DEBUG ("profile changed");
448 priv->profile_changed = FALSE;
449 reset_context = TRUE;
451 priv->hw_profile = get_profile (decoder, entrypoint);
452 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
453 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
456 if (priv->size_changed) {
457 GST_DEBUG ("size changed");
458 priv->size_changed = FALSE;
459 reset_context = TRUE;
463 GstVaapiContextInfo info;
465 info.profile = priv->hw_profile;
466 info.entrypoint = entrypoint;
467 info.chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
468 info.width = priv->width;
469 info.height = priv->height;
472 gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER_CAST (decoder),
475 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
477 return GST_VAAPI_DECODER_STATUS_SUCCESS;
480 static GstVaapiDecoderStatus
481 ensure_quant_matrix (GstVaapiDecoderMpeg2 * decoder, GstVaapiPicture * picture)
483 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
484 GstMpegVideoSequenceHdr *const seq_hdr = &priv->seq_hdr->data.seq_hdr;
485 VAIQMatrixBufferMPEG2 *iq_matrix;
486 guint8 *intra_quant_matrix = NULL;
487 guint8 *non_intra_quant_matrix = NULL;
488 guint8 *chroma_intra_quant_matrix = NULL;
489 guint8 *chroma_non_intra_quant_matrix = NULL;
491 if (!priv->quant_matrix_changed)
492 return GST_VAAPI_DECODER_STATUS_SUCCESS;
494 priv->quant_matrix_changed = FALSE;
496 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (MPEG2, decoder);
497 if (!picture->iq_matrix) {
498 GST_ERROR ("failed to allocate IQ matrix");
499 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
501 iq_matrix = picture->iq_matrix->param;
503 intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
504 non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
506 if (priv->quant_matrix) {
507 GstMpegVideoQuantMatrixExt *const quant_matrix =
508 &priv->quant_matrix->data.quant_matrix;
509 if (quant_matrix->load_intra_quantiser_matrix)
510 intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
511 if (quant_matrix->load_non_intra_quantiser_matrix)
512 non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
513 if (quant_matrix->load_chroma_intra_quantiser_matrix)
514 chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
515 if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
516 chroma_non_intra_quant_matrix =
517 quant_matrix->chroma_non_intra_quantiser_matrix;
520 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
521 if (intra_quant_matrix)
522 copy_quant_matrix (iq_matrix->intra_quantiser_matrix, intra_quant_matrix);
524 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
525 if (non_intra_quant_matrix)
526 copy_quant_matrix (iq_matrix->non_intra_quantiser_matrix,
527 non_intra_quant_matrix);
529 iq_matrix->load_chroma_intra_quantiser_matrix =
530 chroma_intra_quant_matrix != NULL;
531 if (chroma_intra_quant_matrix)
532 copy_quant_matrix (iq_matrix->chroma_intra_quantiser_matrix,
533 chroma_intra_quant_matrix);
535 iq_matrix->load_chroma_non_intra_quantiser_matrix =
536 chroma_non_intra_quant_matrix != NULL;
537 if (chroma_non_intra_quant_matrix)
538 copy_quant_matrix (iq_matrix->chroma_non_intra_quantiser_matrix,
539 chroma_non_intra_quant_matrix);
540 return GST_VAAPI_DECODER_STATUS_SUCCESS;
543 static inline gboolean
544 is_valid_state (GstVaapiDecoderMpeg2 * decoder, guint state)
546 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
548 return (priv->state & state) == state;
551 static GstVaapiDecoderStatus
552 decode_current_picture (GstVaapiDecoderMpeg2 * decoder)
554 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
555 GstVaapiPicture *const picture = priv->current_picture;
557 if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PICTURE))
559 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
562 return GST_VAAPI_DECODER_STATUS_SUCCESS;
564 if (!gst_vaapi_picture_decode (picture))
566 if (GST_VAAPI_PICTURE_IS_COMPLETE (picture)) {
567 if (!gst_vaapi_dpb_add (priv->dpb, picture))
569 gst_vaapi_picture_replace (&priv->current_picture, NULL);
571 return GST_VAAPI_DECODER_STATUS_SUCCESS;
576 /* XXX: fix for cases where first field failed to be decoded */
577 gst_vaapi_picture_replace (&priv->current_picture, NULL);
578 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
583 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
584 return (GstVaapiDecoderStatus) GST_VAAPI_DECODER_STATUS_DROP_FRAME;
588 static GstVaapiDecoderStatus
589 parse_sequence (GstVaapiDecoderMpeg2 * decoder,
590 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
592 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
593 GstMpegVideoSequenceHdr *seq_hdr;
597 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_hdr)) {
598 GST_ERROR ("failed to allocate parser info for sequence header");
599 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
602 seq_hdr = &priv->seq_hdr->data.seq_hdr;
604 if (!gst_mpeg_video_packet_parse_sequence_header (packet, seq_hdr)) {
605 GST_ERROR ("failed to parse sequence header");
606 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
609 gst_vaapi_decoder_unit_set_parsed_info (unit, seq_hdr, NULL);
610 return GST_VAAPI_DECODER_STATUS_SUCCESS;
613 static GstVaapiDecoderStatus
614 decode_sequence (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
616 GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER_CAST (decoder);
617 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
618 GstMpegVideoSequenceHdr *const seq_hdr = unit->parsed_info;
620 gst_vaapi_parser_info_mpeg2_replace (&priv->seq_ext, NULL);
621 gst_vaapi_parser_info_mpeg2_replace (&priv->seq_display_ext, NULL);
622 gst_vaapi_parser_info_mpeg2_replace (&priv->seq_scalable_ext, NULL);
623 gst_vaapi_parser_info_mpeg2_replace (&priv->quant_matrix, NULL);
624 gst_vaapi_parser_info_mpeg2_replace (&priv->pic_display_ext, NULL);
626 priv->fps_n = seq_hdr->fps_n;
627 priv->fps_d = seq_hdr->fps_d;
628 pts_set_framerate (&priv->tsg, priv->fps_n, priv->fps_d);
629 gst_vaapi_decoder_set_framerate (base_decoder, priv->fps_n, priv->fps_d);
631 priv->width = seq_hdr->width;
632 priv->height = seq_hdr->height;
633 priv->size_changed = TRUE;
634 priv->quant_matrix_changed = TRUE;
635 priv->progressive_sequence = TRUE;
637 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
638 return GST_VAAPI_DECODER_STATUS_SUCCESS;
641 static GstVaapiDecoderStatus
642 parse_sequence_ext (GstVaapiDecoderMpeg2 * decoder,
643 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
645 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
646 GstMpegVideoSequenceExt *seq_ext;
648 priv->state &= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
650 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_ext)) {
651 GST_ERROR ("failed to allocate parser info for sequence extension");
652 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
655 seq_ext = &priv->seq_ext->data.seq_ext;
657 if (!gst_mpeg_video_packet_parse_sequence_extension (packet, seq_ext)) {
658 GST_ERROR ("failed to parse sequence-extension");
659 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
662 gst_vaapi_decoder_unit_set_parsed_info (unit, seq_ext, NULL);
663 return GST_VAAPI_DECODER_STATUS_SUCCESS;
666 static GstVaapiDecoderStatus
667 decode_sequence_ext (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
669 GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER_CAST (decoder);
670 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
671 GstMpegVideoSequenceExt *const seq_ext = unit->parsed_info;
672 GstVaapiProfile profile;
675 if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR))
676 return GST_VAAPI_DECODER_STATUS_SUCCESS;
678 priv->progressive_sequence = seq_ext->progressive;
679 gst_vaapi_decoder_set_interlaced (base_decoder, !priv->progressive_sequence);
681 width = (priv->width & 0x0fff) | ((guint32) seq_ext->horiz_size_ext << 12);
682 height = (priv->height & 0x0fff) | ((guint32) seq_ext->vert_size_ext << 12);
683 GST_DEBUG ("video resolution %ux%u", width, height);
685 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
686 priv->fps_n *= seq_ext->fps_n_ext + 1;
687 priv->fps_d *= seq_ext->fps_d_ext + 1;
688 pts_set_framerate (&priv->tsg, priv->fps_n, priv->fps_d);
689 gst_vaapi_decoder_set_framerate (base_decoder, priv->fps_n, priv->fps_d);
692 if (priv->width != width) {
694 priv->size_changed = TRUE;
697 if (priv->height != height) {
698 priv->height = height;
699 priv->size_changed = TRUE;
702 switch (seq_ext->profile) {
703 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
704 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
706 case GST_MPEG_VIDEO_PROFILE_MAIN:
707 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
709 case GST_MPEG_VIDEO_PROFILE_HIGH:
710 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
713 GST_ERROR ("unsupported profile %d", seq_ext->profile);
714 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
716 if (priv->profile != profile) {
717 priv->profile = profile;
718 priv->profile_changed = TRUE;
721 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT;
722 return GST_VAAPI_DECODER_STATUS_SUCCESS;
725 static GstVaapiDecoderStatus
726 parse_sequence_display_ext (GstVaapiDecoderMpeg2 * decoder,
727 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
729 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
730 GstMpegVideoSequenceDisplayExt *seq_display_ext;
732 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_display_ext)) {
733 GST_ERROR ("failed to allocate parser info for sequence display extension");
734 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
737 seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
739 if (!gst_mpeg_video_packet_parse_sequence_display_extension (packet,
741 GST_ERROR ("failed to parse sequence-display-extension");
742 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
745 gst_vaapi_decoder_unit_set_parsed_info (unit, seq_display_ext, NULL);
746 return GST_VAAPI_DECODER_STATUS_SUCCESS;
749 static GstVaapiDecoderStatus
750 decode_sequence_display_ext (GstVaapiDecoderMpeg2 * decoder,
751 GstVaapiDecoderUnit * unit)
753 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
754 GstMpegVideoSequenceDisplayExt *seq_display_ext;
756 seq_display_ext = priv->seq_display_ext ?
757 &priv->seq_display_ext->data.seq_display_ext : NULL;
759 /* Update cropping rectangle */
760 if (seq_display_ext) {
761 GstVaapiRectangle *const crop_rect = &priv->crop_rect;
764 crop_rect->width = seq_display_ext->display_horizontal_size;
765 crop_rect->height = seq_display_ext->display_vertical_size;
768 /* XXX: handle color primaries */
769 return GST_VAAPI_DECODER_STATUS_SUCCESS;
772 static GstVaapiDecoderStatus
773 parse_sequence_scalable_ext (GstVaapiDecoderMpeg2 * decoder,
774 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
776 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
777 GstMpegVideoSequenceScalableExt *seq_scalable_ext;
779 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_scalable_ext)) {
781 ("failed to allocate parser info for sequence scalable extension");
782 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
785 seq_scalable_ext = &priv->seq_scalable_ext->data.seq_scalable_ext;
787 if (!gst_mpeg_video_packet_parse_sequence_scalable_extension (packet,
789 GST_ERROR ("failed to parse sequence-scalable-extension");
790 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
793 gst_vaapi_decoder_unit_set_parsed_info (unit, seq_scalable_ext, NULL);
794 return GST_VAAPI_DECODER_STATUS_SUCCESS;
797 static GstVaapiDecoderStatus
798 decode_sequence_scalable_ext (GstVaapiDecoderMpeg2 * decoder,
799 GstVaapiDecoderUnit * unit)
801 /* XXX: unsupported header -- ignore */
802 return GST_VAAPI_DECODER_STATUS_SUCCESS;
805 static GstVaapiDecoderStatus
806 decode_sequence_end (GstVaapiDecoderMpeg2 * decoder)
808 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
811 gst_vaapi_dpb_flush (priv->dpb);
812 return GST_VAAPI_DECODER_STATUS_SUCCESS;
815 static GstVaapiDecoderStatus
816 parse_quant_matrix_ext (GstVaapiDecoderMpeg2 * decoder,
817 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
819 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
820 GstMpegVideoQuantMatrixExt *quant_matrix;
822 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->quant_matrix)) {
823 GST_ERROR ("failed to allocate parser info for quantization matrix");
824 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
827 quant_matrix = &priv->quant_matrix->data.quant_matrix;
829 if (!gst_mpeg_video_packet_parse_quant_matrix_extension (packet,
831 GST_ERROR ("failed to parse quant-matrix-extension");
832 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
835 gst_vaapi_decoder_unit_set_parsed_info (unit, quant_matrix, NULL);
836 return GST_VAAPI_DECODER_STATUS_SUCCESS;
839 static GstVaapiDecoderStatus
840 decode_quant_matrix_ext (GstVaapiDecoderMpeg2 * decoder,
841 GstVaapiDecoderUnit * unit)
843 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
845 priv->quant_matrix_changed = TRUE;
846 return GST_VAAPI_DECODER_STATUS_SUCCESS;
849 static GstVaapiDecoderStatus
850 parse_gop (GstVaapiDecoderMpeg2 * decoder,
851 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
853 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
854 GstMpegVideoGop *gop;
856 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->gop)) {
857 GST_ERROR ("failed to allocate parser info for GOP");
858 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
861 gop = &priv->gop->data.gop;
863 if (!gst_mpeg_video_packet_parse_gop (packet, gop)) {
864 GST_ERROR ("failed to parse GOP");
865 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
868 gst_vaapi_decoder_unit_set_parsed_info (unit, gop, NULL);
869 return GST_VAAPI_DECODER_STATUS_SUCCESS;
872 static GstVaapiDecoderStatus
873 decode_gop (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
875 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
876 GstMpegVideoGop *const gop = unit->parsed_info;
878 priv->closed_gop = gop->closed_gop;
879 priv->broken_link = gop->broken_link;
881 GST_DEBUG ("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
882 gop->hour, gop->minute, gop->second, gop->frame,
883 priv->closed_gop, priv->broken_link);
885 pts_sync (&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts);
886 return GST_VAAPI_DECODER_STATUS_SUCCESS;
889 static GstVaapiDecoderStatus
890 parse_picture (GstVaapiDecoderMpeg2 * decoder,
891 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
893 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
894 GstMpegVideoPictureHdr *pic_hdr;
896 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
897 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT);
899 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->pic_hdr)) {
900 GST_ERROR ("failed to allocate parser info for picture header");
901 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
904 pic_hdr = &priv->pic_hdr->data.pic_hdr;
906 if (!gst_mpeg_video_packet_parse_picture_header (packet, pic_hdr)) {
907 GST_ERROR ("failed to parse picture header");
908 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
911 gst_vaapi_decoder_unit_set_parsed_info (unit, pic_hdr, NULL);
912 return GST_VAAPI_DECODER_STATUS_SUCCESS;
915 static GstVaapiDecoderStatus
916 decode_picture (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
918 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
920 if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS))
921 return GST_VAAPI_DECODER_STATUS_SUCCESS;
923 gst_vaapi_parser_info_mpeg2_replace (&priv->pic_ext, NULL);
925 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_HDR;
926 return GST_VAAPI_DECODER_STATUS_SUCCESS;
929 static GstVaapiDecoderStatus
930 parse_picture_ext (GstVaapiDecoderMpeg2 * decoder,
931 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
933 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
934 GstMpegVideoPictureExt *pic_ext;
936 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
937 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT | GST_MPEG_VIDEO_STATE_GOT_PIC_HDR);
939 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->pic_ext)) {
940 GST_ERROR ("failed to allocate parser info for picture extension");
941 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
944 pic_ext = &priv->pic_ext->data.pic_ext;
946 if (!gst_mpeg_video_packet_parse_picture_extension (packet, pic_ext)) {
947 GST_ERROR ("failed to parse picture-extension");
948 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
951 gst_vaapi_decoder_unit_set_parsed_info (unit, pic_ext, NULL);
952 return GST_VAAPI_DECODER_STATUS_SUCCESS;
955 static GstVaapiDecoderStatus
956 decode_picture_ext (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
958 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
959 GstMpegVideoPictureExt *const pic_ext = unit->parsed_info;
961 if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_GOT_PIC_HDR))
962 return GST_VAAPI_DECODER_STATUS_SUCCESS;
964 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
965 GST_WARNING ("invalid interlaced frame in progressive sequence, fixing");
966 pic_ext->progressive_frame = 1;
969 if (pic_ext->picture_structure == 0 ||
970 (pic_ext->progressive_frame &&
971 pic_ext->picture_structure !=
972 GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
973 GST_WARNING ("invalid picture_structure %d, replacing with \"frame\"",
974 pic_ext->picture_structure);
975 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
978 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_EXT;
979 return GST_VAAPI_DECODER_STATUS_SUCCESS;
982 static inline guint32
983 pack_f_code (guint8 f_code[2][2])
985 return (((guint32) f_code[0][0] << 12) |
986 ((guint32) f_code[0][1] << 8) |
987 ((guint32) f_code[1][0] << 4) | (f_code[1][1]));
990 static GstVaapiDecoderStatus
991 init_picture (GstVaapiDecoderMpeg2 * decoder, GstVaapiPicture * picture)
993 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
994 GstMpegVideoPictureHdr *const pic_hdr = &priv->pic_hdr->data.pic_hdr;
995 GstMpegVideoPictureExt *const pic_ext = &priv->pic_ext->data.pic_ext;
997 switch (pic_hdr->pic_type) {
998 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
999 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
1000 picture->type = GST_VAAPI_PICTURE_TYPE_I;
1002 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1003 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
1004 picture->type = GST_VAAPI_PICTURE_TYPE_P;
1006 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1007 picture->type = GST_VAAPI_PICTURE_TYPE_B;
1010 GST_ERROR ("unsupported picture type %d", pic_hdr->pic_type);
1011 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1014 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
1015 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
1016 if (pic_ext->top_field_first)
1017 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_TFF);
1020 switch (pic_ext->picture_structure) {
1021 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
1022 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
1024 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
1025 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
1027 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
1028 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1032 /* Allocate dummy picture for first field based I-frame */
1033 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
1034 !GST_VAAPI_PICTURE_IS_FRAME (picture) &&
1035 gst_vaapi_dpb_size (priv->dpb) == 0) {
1036 GstVaapiPicture *dummy_picture;
1039 dummy_picture = GST_VAAPI_PICTURE_NEW (MPEG2, decoder);
1040 if (!dummy_picture) {
1041 GST_ERROR ("failed to allocate dummy picture");
1042 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1045 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
1046 dummy_picture->pts = GST_CLOCK_TIME_NONE;
1047 dummy_picture->poc = -1;
1048 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1050 GST_VAAPI_PICTURE_FLAG_SET (dummy_picture,
1051 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
1052 GST_VAAPI_PICTURE_FLAG_OUTPUT | GST_VAAPI_PICTURE_FLAG_REFERENCE)
1055 success = gst_vaapi_dpb_add (priv->dpb, dummy_picture);
1056 gst_vaapi_picture_unref (dummy_picture);
1058 GST_ERROR ("failed to add dummy picture into DPB");
1059 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1061 GST_INFO ("allocated dummy picture for first field based I-frame");
1064 /* Update presentation time */
1065 picture->pts = pts_eval (&priv->tsg,
1066 GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts, pic_hdr->tsn);
1067 picture->poc = pts_get_poc (&priv->tsg);
1068 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1072 fill_picture (GstVaapiDecoderMpeg2 * decoder, GstVaapiPicture * picture)
1074 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1075 VAPictureParameterBufferMPEG2 *const pic_param = picture->param;
1076 GstMpegVideoPictureHdr *const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1077 GstMpegVideoPictureExt *const pic_ext = &priv->pic_ext->data.pic_ext;
1078 GstVaapiPicture *prev_picture, *next_picture;
1080 /* Fill in VAPictureParameterBufferMPEG2 */
1081 pic_param->horizontal_size = priv->width;
1082 pic_param->vertical_size = priv->height;
1083 pic_param->forward_reference_picture = VA_INVALID_ID;
1084 pic_param->backward_reference_picture = VA_INVALID_ID;
1085 pic_param->picture_coding_type = pic_hdr->pic_type;
1086 pic_param->f_code = pack_f_code (pic_ext->f_code);
1088 #define COPY_FIELD(a, b, f) \
1089 pic_param->a.b.f = pic_ext->f
1090 pic_param->picture_coding_extension.value = 0;
1091 pic_param->picture_coding_extension.bits.is_first_field =
1092 GST_VAAPI_PICTURE_IS_FIRST_FIELD (picture);
1093 COPY_FIELD (picture_coding_extension, bits, intra_dc_precision);
1094 COPY_FIELD (picture_coding_extension, bits, picture_structure);
1095 COPY_FIELD (picture_coding_extension, bits, top_field_first);
1096 COPY_FIELD (picture_coding_extension, bits, frame_pred_frame_dct);
1097 COPY_FIELD (picture_coding_extension, bits, concealment_motion_vectors);
1098 COPY_FIELD (picture_coding_extension, bits, q_scale_type);
1099 COPY_FIELD (picture_coding_extension, bits, intra_vlc_format);
1100 COPY_FIELD (picture_coding_extension, bits, alternate_scan);
1101 COPY_FIELD (picture_coding_extension, bits, repeat_first_field);
1102 COPY_FIELD (picture_coding_extension, bits, progressive_frame);
1104 gst_vaapi_dpb_get_neighbours (priv->dpb, picture,
1105 &prev_picture, &next_picture);
1107 switch (pic_hdr->pic_type) {
1108 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1110 pic_param->backward_reference_picture = next_picture->surface_id;
1112 pic_param->forward_reference_picture = prev_picture->surface_id;
1113 else if (!priv->closed_gop)
1114 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1116 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1118 pic_param->forward_reference_picture = prev_picture->surface_id;
1123 static GstVaapiDecoderStatus
1124 parse_slice (GstVaapiDecoderMpeg2 * decoder,
1125 GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
1127 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1128 GstMpegVideoSliceHdr *slice_hdr;
1129 GstMpegVideoSequenceHdr *seq_hdr;
1130 GstMpegVideoSequenceScalableExt *seq_scalable_ext;
1132 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
1133 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT |
1134 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR | GST_MPEG_VIDEO_STATE_GOT_PIC_EXT);
1136 if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1137 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1139 if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->slice_hdr)) {
1140 GST_ERROR ("failed to allocate parser info for slice header");
1141 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1144 slice_hdr = &priv->slice_hdr->data.slice_hdr;
1145 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1146 seq_scalable_ext = priv->seq_scalable_ext ?
1147 &priv->seq_scalable_ext->data.seq_scalable_ext : NULL;
1149 if (!gst_mpeg_video_packet_parse_slice_header (packet, slice_hdr,
1150 seq_hdr, seq_scalable_ext)) {
1151 GST_ERROR ("failed to parse slice header");
1152 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1155 gst_vaapi_decoder_unit_set_parsed_info (unit, slice_hdr, NULL);
1156 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1159 static GstVaapiDecoderStatus
1160 decode_slice (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
1162 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1163 GstVaapiPicture *const picture = priv->current_picture;
1164 GstVaapiSlice *slice;
1165 VASliceParameterBufferMPEG2 *slice_param;
1166 GstMpegVideoSliceHdr *const slice_hdr = unit->parsed_info;
1167 GstBuffer *const buffer =
1168 GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
1169 GstMapInfo map_info;
1171 if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1172 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1174 if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
1175 GST_ERROR ("failed to map buffer");
1176 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1179 GST_DEBUG ("slice %d (%u bytes)", slice_hdr->mb_row, unit->size);
1181 slice = GST_VAAPI_SLICE_NEW (MPEG2, decoder,
1182 (map_info.data + unit->offset), unit->size);
1183 gst_buffer_unmap (buffer, &map_info);
1185 GST_ERROR ("failed to allocate slice");
1186 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1188 gst_vaapi_picture_add_slice (picture, slice);
1190 /* Fill in VASliceParameterBufferMPEG2 */
1191 slice_param = slice->param;
1192 slice_param->macroblock_offset = slice_hdr->header_size + 32;
1193 slice_param->slice_horizontal_position = slice_hdr->mb_column;
1194 slice_param->slice_vertical_position = slice_hdr->mb_row;
1195 slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1196 slice_param->intra_slice_flag = slice_hdr->intra_slice;
1198 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SLICE;
1199 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1203 scan_for_start_code (const guchar * buf, guint buf_size,
1204 GstMpegVideoPacketTypeCode * type_ptr)
1208 while (i <= (buf_size - 4)) {
1211 else if (buf[i + 1])
1213 else if (buf[i] || buf[i + 2] != 1)
1219 if (i <= (buf_size - 4)) {
1221 *type_ptr = buf[i + 3];
1227 static GstVaapiDecoderStatus
1228 parse_unit (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit,
1229 GstMpegVideoPacket * packet)
1231 GstMpegVideoPacketTypeCode type;
1232 GstMpegVideoPacketExtensionCode ext_type;
1233 GstVaapiDecoderStatus status;
1235 type = packet->type;
1237 case GST_MPEG_VIDEO_PACKET_PICTURE:
1238 status = parse_picture (decoder, unit, packet);
1240 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1241 status = parse_sequence (decoder, unit, packet);
1243 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1244 ext_type = packet->data[4] >> 4;
1246 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1247 status = parse_sequence_ext (decoder, unit, packet);
1249 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1250 status = parse_sequence_display_ext (decoder, unit, packet);
1252 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1253 status = parse_sequence_scalable_ext (decoder, unit, packet);
1255 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1256 status = parse_quant_matrix_ext (decoder, unit, packet);
1258 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1259 status = parse_picture_ext (decoder, unit, packet);
1262 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1266 case GST_MPEG_VIDEO_PACKET_GOP:
1267 status = parse_gop (decoder, unit, packet);
1270 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1271 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1272 status = parse_slice (decoder, unit, packet);
1275 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1281 static GstVaapiDecoderStatus
1282 decode_unit (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit,
1283 GstMpegVideoPacket * packet)
1285 GstMpegVideoPacketTypeCode type;
1286 GstMpegVideoPacketExtensionCode ext_type;
1287 GstVaapiDecoderStatus status;
1289 type = packet->type;
1291 case GST_MPEG_VIDEO_PACKET_PICTURE:
1292 status = decode_picture (decoder, unit);
1294 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1295 status = decode_sequence (decoder, unit);
1297 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1298 ext_type = packet->data[4] >> 4;
1300 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1301 status = decode_sequence_ext (decoder, unit);
1303 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1304 status = decode_sequence_display_ext (decoder, unit);
1306 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1307 status = decode_sequence_scalable_ext (decoder, unit);
1309 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1310 status = decode_quant_matrix_ext (decoder, unit);
1312 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1313 status = decode_picture_ext (decoder, unit);
1316 // Ignore unknown start-code extensions
1317 GST_WARNING ("unsupported packet extension type 0x%02x", ext_type);
1318 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1322 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1323 status = decode_sequence_end (decoder);
1325 case GST_MPEG_VIDEO_PACKET_GOP:
1326 status = decode_gop (decoder, unit);
1329 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1330 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1331 status = decode_slice (decoder, unit);
1334 GST_WARNING ("unsupported packet type 0x%02x", type);
1335 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1341 static GstVaapiDecoderStatus
1342 ensure_decoder (GstVaapiDecoderMpeg2 * decoder)
1344 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1346 if (!priv->is_opened) {
1347 priv->is_opened = gst_vaapi_decoder_mpeg2_open (decoder);
1348 if (!priv->is_opened)
1349 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1351 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1354 static GstVaapiDecoderStatus
1355 gst_vaapi_decoder_mpeg2_parse (GstVaapiDecoder * base_decoder,
1356 GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
1358 GstVaapiDecoderMpeg2 *const decoder =
1359 GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1360 GstVaapiParserState *const ps = GST_VAAPI_PARSER_STATE (base_decoder);
1361 GstVaapiDecoderStatus status;
1362 GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1364 guint buf_size, flags;
1365 gint ofs, ofs1, ofs2;
1367 status = ensure_decoder (decoder);
1368 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1371 buf_size = gst_adapter_available (adapter);
1373 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1375 buf = gst_adapter_map (adapter, buf_size);
1377 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1379 ofs = scan_for_start_code (buf, buf_size, &type);
1381 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1384 ofs2 = ps->input_offset2 - 4;
1385 if (ofs2 < ofs1 + 4)
1388 ofs = G_UNLIKELY (buf_size < ofs2 + 4) ? -1 :
1389 scan_for_start_code (&buf[ofs2], buf_size - ofs2, &type2);
1391 // Assume the whole packet is present if end-of-stream
1393 ps->input_offset2 = buf_size;
1394 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1396 ofs = buf_size - ofs2;
1400 unit->size = ofs2 - ofs1;
1401 gst_adapter_flush (adapter, ofs1);
1402 ps->input_offset2 = 4;
1404 /* Check for start of new picture */
1407 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1408 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1409 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1411 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1412 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1414 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1415 case GST_MPEG_VIDEO_PACKET_GOP:
1416 case GST_MPEG_VIDEO_PACKET_PICTURE:
1417 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1419 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1420 if (G_UNLIKELY (unit->size < 5))
1421 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1424 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1425 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1426 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1428 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1429 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1430 case GST_MPEG_VIDEO_PACKET_GOP:
1431 case GST_MPEG_VIDEO_PACKET_PICTURE:
1432 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1438 // Ignore system start codes (PES headers)
1439 else if (type >= 0xb9 && type <= 0xff)
1440 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1443 GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
1444 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1447 static GstVaapiDecoderStatus
1448 gst_vaapi_decoder_mpeg2_decode (GstVaapiDecoder * base_decoder,
1449 GstVaapiDecoderUnit * unit)
1451 GstVaapiDecoderMpeg2 *const decoder =
1452 GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1453 GstVaapiDecoderStatus status;
1454 GstMpegVideoPacket packet;
1455 GstBuffer *const buffer =
1456 GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
1457 GstMapInfo map_info;
1459 status = ensure_decoder (decoder);
1460 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1463 if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
1464 GST_ERROR ("failed to map buffer");
1465 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1468 packet.data = map_info.data + unit->offset;
1469 packet.size = unit->size;
1470 packet.type = packet.data[3];
1473 status = parse_unit (decoder, unit, &packet);
1474 gst_buffer_unmap (buffer, &map_info);
1475 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1477 return decode_unit (decoder, unit, &packet);
1480 static GstVaapiDecoderStatus
1481 gst_vaapi_decoder_mpeg2_start_frame (GstVaapiDecoder * base_decoder,
1482 GstVaapiDecoderUnit * base_unit)
1484 GstVaapiDecoderMpeg2 *const decoder =
1485 GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1486 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1487 GstMpegVideoSequenceHdr *seq_hdr;
1488 GstMpegVideoSequenceExt *seq_ext;
1489 GstMpegVideoSequenceDisplayExt *seq_display_ext;
1490 GstVaapiPicture *picture;
1491 GstVaapiDecoderStatus status;
1493 if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1494 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1495 priv->state &= ~GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1497 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1498 seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1499 seq_display_ext = priv->seq_display_ext ?
1500 &priv->seq_display_ext->data.seq_display_ext : NULL;
1501 if (gst_mpeg_video_finalise_mpeg2_sequence_header (seq_hdr, seq_ext,
1503 gst_vaapi_decoder_set_pixel_aspect_ratio (base_decoder,
1504 seq_hdr->par_w, seq_hdr->par_h);
1506 status = ensure_context (decoder);
1507 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1508 GST_ERROR ("failed to reset context");
1512 if (priv->current_picture) {
1513 /* Re-use current picture where the first field was decoded */
1514 picture = gst_vaapi_picture_new_field (priv->current_picture);
1516 GST_ERROR ("failed to allocate field picture");
1517 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1520 /* Create new picture */
1521 picture = GST_VAAPI_PICTURE_NEW (MPEG2, decoder);
1523 GST_ERROR ("failed to allocate picture");
1524 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1527 gst_vaapi_picture_replace (&priv->current_picture, picture);
1528 gst_vaapi_picture_unref (picture);
1530 /* Update cropping rectangle */
1531 /* XXX: handle picture_display_extension() */
1532 if (seq_display_ext && priv->pic_display_ext) {
1533 GstVaapiRectangle *const crop_rect = &priv->crop_rect;
1534 if (crop_rect->x + crop_rect->width <= priv->width &&
1535 crop_rect->y + crop_rect->height <= priv->height)
1536 gst_vaapi_picture_set_crop_rect (picture, crop_rect);
1539 status = ensure_quant_matrix (decoder, picture);
1540 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1541 GST_ERROR ("failed to reset quantizer matrix");
1545 status = init_picture (decoder, picture);
1546 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1549 fill_picture (decoder, picture);
1551 priv->state |= GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1552 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1555 static GstVaapiDecoderStatus
1556 gst_vaapi_decoder_mpeg2_end_frame (GstVaapiDecoder * base_decoder)
1558 GstVaapiDecoderMpeg2 *const decoder =
1559 GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1561 return decode_current_picture (decoder);
1564 static GstVaapiDecoderStatus
1565 gst_vaapi_decoder_mpeg2_flush (GstVaapiDecoder * base_decoder)
1567 GstVaapiDecoderMpeg2 *const decoder =
1568 GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1569 GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1572 gst_vaapi_dpb_flush (priv->dpb);
1573 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1577 gst_vaapi_decoder_mpeg2_finalize (GObject * object)
1579 GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (object);
1581 gst_vaapi_decoder_mpeg2_destroy (base_decoder);
1582 G_OBJECT_CLASS (gst_vaapi_decoder_mpeg2_parent_class)->finalize (object);
1586 gst_vaapi_decoder_mpeg2_class_init (GstVaapiDecoderMpeg2Class * klass)
1588 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
1589 GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
1591 object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
1593 decoder_class->reset = gst_vaapi_decoder_mpeg2_reset;
1594 decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1595 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1596 decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1597 decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1598 decoder_class->flush = gst_vaapi_decoder_mpeg2_flush;
1602 gst_vaapi_decoder_mpeg2_init (GstVaapiDecoderMpeg2 * decoder)
1604 GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (decoder);
1606 gst_vaapi_decoder_mpeg2_create (base_decoder);
1610 * gst_vaapi_decoder_mpeg2_new:
1611 * @display: a #GstVaapiDisplay
1612 * @caps: a #GstCaps holding codec information
1614 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1615 * hold extra information like codec-data and pictured coded size.
1617 * Return value: the newly allocated #GstVaapiDecoder object
1620 gst_vaapi_decoder_mpeg2_new (GstVaapiDisplay * display, GstCaps * caps)
1622 return g_object_new (GST_TYPE_VAAPI_DECODER_MPEG2, "display", display,
1623 "caps", caps, NULL);