2 * gstvaapidecoder_mpeg2.c - MPEG-2 decoder
4 * Copyright (C) 2011-2013 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
23 * SECTION:gstvaapidecoder_mpeg2
24 * @short_description: MPEG-2 decoder
29 #include <gst/base/gstbitreader.h>
30 #include <gst/codecparsers/gstmpegvideoparser.h>
31 #include "gstvaapidecoder_mpeg2.h"
32 #include "gstvaapidecoder_objects.h"
33 #include "gstvaapidecoder_dpb.h"
34 #include "gstvaapidecoder_priv.h"
35 #include "gstvaapidisplay_priv.h"
36 #include "gstvaapiobject_priv.h"
39 #include "gstvaapidebug.h"
41 /* ------------------------------------------------------------------------- */
42 /* --- PTS Generator --- */
43 /* ------------------------------------------------------------------------- */
45 typedef struct _PTSGenerator PTSGenerator;
46 struct _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;
108 /* Interpolate GOP TSN from this valid PTS */
109 if (GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
110 gop_tsn = tsg->gop_tsn + gst_util_uint64_scale(
111 gop_pts - tsg->gop_pts + pts_get_duration(tsg, 1) - 1,
112 tsg->fps_n, GST_SECOND * tsg->fps_d);
117 tsg->gop_pts = gop_pts;
118 tsg->gop_tsn = gop_tsn;
125 pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
129 if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
132 pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
134 if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
137 if (tsg->max_tsn < pic_tsn)
138 tsg->max_tsn = pic_tsn;
139 else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
140 tsg->max_tsn = pic_tsn;
143 tsg->lst_tsn = pic_tsn;
147 /* ------------------------------------------------------------------------- */
148 /* --- MPEG-2 Parser Info --- */
149 /* ------------------------------------------------------------------------- */
151 typedef struct _GstVaapiParserInfoMpeg2 GstVaapiParserInfoMpeg2;
152 struct _GstVaapiParserInfoMpeg2 {
153 GstVaapiMiniObject parent_instance;
154 GstMpegVideoPacket packet;
155 guint8 extension_type; /* for Extension packets */
157 GstMpegVideoSequenceHdr seq_hdr;
158 GstMpegVideoSequenceExt seq_ext;
159 GstMpegVideoSequenceDisplayExt seq_display_ext;
160 GstMpegVideoSequenceScalableExt seq_scalable_ext;
162 GstMpegVideoQuantMatrixExt quant_matrix;
163 GstMpegVideoPictureHdr pic_hdr;
164 GstMpegVideoPictureExt pic_ext;
165 GstMpegVideoSliceHdr slice_hdr;
169 static inline const GstVaapiMiniObjectClass *
170 gst_vaapi_parser_info_mpeg2_class(void)
172 static const GstVaapiMiniObjectClass GstVaapiParserInfoMpeg2Class = {
173 sizeof(GstVaapiParserInfoMpeg2),
176 return &GstVaapiParserInfoMpeg2Class;
179 static inline GstVaapiParserInfoMpeg2 *
180 gst_vaapi_parser_info_mpeg2_new(void)
182 return (GstVaapiParserInfoMpeg2 *)
183 gst_vaapi_mini_object_new(gst_vaapi_parser_info_mpeg2_class());
186 static inline GstVaapiParserInfoMpeg2 *
187 gst_vaapi_parser_info_mpeg2_ensure(GstVaapiParserInfoMpeg2 **pi_ptr)
189 GstVaapiParserInfoMpeg2 *pi = *pi_ptr;
191 if (G_LIKELY(pi != NULL))
194 *pi_ptr = pi = gst_vaapi_parser_info_mpeg2_new();
198 #define gst_vaapi_parser_info_mpeg2_ref(pi) \
199 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
201 #define gst_vaapi_parser_info_mpeg2_unref(pi) \
202 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
204 #define gst_vaapi_parser_info_mpeg2_replace(old_pi_ptr, new_pi) \
205 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr), \
206 (GstVaapiMiniObject *)(new_pi))
208 /* ------------------------------------------------------------------------- */
209 /* --- MPEG-2 Decoder --- */
210 /* ------------------------------------------------------------------------- */
212 #define GST_VAAPI_DECODER_MPEG2_CAST(decoder) \
213 ((GstVaapiDecoderMpeg2 *)(decoder))
215 typedef struct _GstVaapiDecoderMpeg2Private GstVaapiDecoderMpeg2Private;
216 typedef struct _GstVaapiDecoderMpeg2Class GstVaapiDecoderMpeg2Class;
219 GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR = 1 << 0,
220 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT = 1 << 1,
221 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR = 1 << 2,
222 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT = 1 << 3,
223 GST_MPEG_VIDEO_STATE_GOT_SLICE = 1 << 4,
225 GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS = (
226 GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
227 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT),
228 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS = (
229 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR|
230 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT),
231 GST_MPEG_VIDEO_STATE_VALID_PICTURE = (
232 GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS|
233 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS|
234 GST_MPEG_VIDEO_STATE_GOT_SLICE)
237 struct _GstVaapiDecoderMpeg2Private {
238 GstVaapiProfile profile;
239 GstVaapiProfile hw_profile;
245 GstVaapiParserInfoMpeg2 *seq_hdr;
246 GstVaapiParserInfoMpeg2 *seq_ext;
247 GstVaapiParserInfoMpeg2 *seq_display_ext;
248 GstVaapiParserInfoMpeg2 *seq_scalable_ext;
249 GstVaapiParserInfoMpeg2 *gop;
250 GstVaapiParserInfoMpeg2 *pic_hdr;
251 GstVaapiParserInfoMpeg2 *pic_ext;
252 GstVaapiParserInfoMpeg2 *quant_matrix;
253 GstVaapiParserInfoMpeg2 *slice_hdr;
254 GstVaapiPicture *current_picture;
258 guint size_changed : 1;
259 guint profile_changed : 1;
260 guint quant_matrix_changed : 1;
261 guint progressive_sequence : 1;
262 guint closed_gop : 1;
263 guint broken_link : 1;
267 * GstVaapiDecoderMpeg2:
269 * A decoder based on Mpeg2.
271 struct _GstVaapiDecoderMpeg2 {
273 GstVaapiDecoder parent_instance;
274 GstVaapiDecoderMpeg2Private priv;
278 * GstVaapiDecoderMpeg2Class:
280 * A decoder class based on Mpeg2.
282 struct _GstVaapiDecoderMpeg2Class {
284 GstVaapiDecoderClass parent_class;
288 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
290 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
292 gst_vaapi_picture_replace(&priv->current_picture, NULL);
294 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_hdr, NULL);
295 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
296 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
297 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_scalable_ext, NULL);
298 gst_vaapi_parser_info_mpeg2_replace(&priv->gop, NULL);
299 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_hdr, NULL);
300 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
301 gst_vaapi_parser_info_mpeg2_replace(&priv->quant_matrix, NULL);
302 gst_vaapi_parser_info_mpeg2_replace(&priv->slice_hdr, NULL);
304 gst_vaapi_dpb_replace(&priv->dpb, NULL);
308 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
310 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
312 gst_vaapi_decoder_mpeg2_close(decoder);
314 priv->dpb = gst_vaapi_dpb_new(2);
318 pts_init(&priv->tsg);
323 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoder *base_decoder)
325 GstVaapiDecoderMpeg2 * const decoder =
326 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
328 gst_vaapi_decoder_mpeg2_close(decoder);
332 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoder *base_decoder)
334 GstVaapiDecoderMpeg2 * const decoder =
335 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
336 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
338 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
339 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
340 priv->profile_changed = TRUE; /* Allow fallbacks to work */
345 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
347 memcpy(dst, src, 64);
351 get_profile_str(GstVaapiProfile profile)
356 case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
357 case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
358 case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
359 default: str = "<unknown>"; break;
364 static GstVaapiProfile
365 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
367 GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
368 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
369 GstVaapiProfile profile = priv->profile;
372 /* Return immediately if the exact same profile was found */
373 if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
376 /* Otherwise, try to map to a higher profile */
378 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
379 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
381 case GST_VAAPI_PROFILE_MPEG2_MAIN:
382 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
384 case GST_VAAPI_PROFILE_MPEG2_HIGH:
385 // Try to map to main profile if no high profile specific bits used
386 if (priv->profile == profile &&
387 !priv->seq_scalable_ext &&
389 priv->seq_ext->data.seq_ext.chroma_format == 1)) {
390 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
395 profile = GST_VAAPI_PROFILE_UNKNOWN;
398 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
400 if (profile != priv->profile)
401 GST_INFO("forced %s profile to %s profile",
402 get_profile_str(priv->profile), get_profile_str(profile));
406 static GstVaapiDecoderStatus
407 ensure_context(GstVaapiDecoderMpeg2 *decoder)
409 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
410 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
411 gboolean reset_context = FALSE;
413 if (priv->profile_changed) {
414 GST_DEBUG("profile changed");
415 priv->profile_changed = FALSE;
416 reset_context = TRUE;
418 priv->hw_profile = get_profile(decoder, entrypoint);
419 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
420 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
423 if (priv->size_changed) {
424 GST_DEBUG("size changed");
425 priv->size_changed = FALSE;
426 reset_context = TRUE;
430 GstVaapiContextInfo info;
432 info.profile = priv->hw_profile;
433 info.entrypoint = entrypoint;
434 info.width = priv->width;
435 info.height = priv->height;
437 reset_context = gst_vaapi_decoder_ensure_context(
438 GST_VAAPI_DECODER_CAST(decoder),
442 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
444 return GST_VAAPI_DECODER_STATUS_SUCCESS;
447 static GstVaapiDecoderStatus
448 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
450 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
451 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr->data.seq_hdr;
452 VAIQMatrixBufferMPEG2 *iq_matrix;
453 guint8 *intra_quant_matrix = NULL;
454 guint8 *non_intra_quant_matrix = NULL;
455 guint8 *chroma_intra_quant_matrix = NULL;
456 guint8 *chroma_non_intra_quant_matrix = NULL;
458 if (!priv->quant_matrix_changed)
459 return GST_VAAPI_DECODER_STATUS_SUCCESS;
461 priv->quant_matrix_changed = FALSE;
463 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
464 if (!picture->iq_matrix) {
465 GST_ERROR("failed to allocate IQ matrix");
466 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
468 iq_matrix = picture->iq_matrix->param;
470 intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
471 non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
473 if (priv->quant_matrix) {
474 GstMpegVideoQuantMatrixExt * const quant_matrix =
475 &priv->quant_matrix->data.quant_matrix;
476 if (quant_matrix->load_intra_quantiser_matrix)
477 intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
478 if (quant_matrix->load_non_intra_quantiser_matrix)
479 non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
480 if (quant_matrix->load_chroma_intra_quantiser_matrix)
481 chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
482 if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
483 chroma_non_intra_quant_matrix = quant_matrix->chroma_non_intra_quantiser_matrix;
486 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
487 if (intra_quant_matrix)
488 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
491 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
492 if (non_intra_quant_matrix)
493 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
494 non_intra_quant_matrix);
496 iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
497 if (chroma_intra_quant_matrix)
498 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
499 chroma_intra_quant_matrix);
501 iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
502 if (chroma_non_intra_quant_matrix)
503 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
504 chroma_non_intra_quant_matrix);
505 return GST_VAAPI_DECODER_STATUS_SUCCESS;
508 static inline gboolean
509 is_valid_state(GstVaapiDecoderMpeg2 *decoder, guint state)
511 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
513 return (priv->state & state) == state;
516 static GstVaapiDecoderStatus
517 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
519 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
520 GstVaapiPicture * const picture = priv->current_picture;
522 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PICTURE))
524 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
527 return GST_VAAPI_DECODER_STATUS_SUCCESS;
529 if (!gst_vaapi_picture_decode(picture))
531 if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
532 if (!gst_vaapi_dpb_add(priv->dpb, picture))
534 gst_vaapi_picture_replace(&priv->current_picture, NULL);
536 return GST_VAAPI_DECODER_STATUS_SUCCESS;
539 /* XXX: fix for cases where first field failed to be decoded */
540 gst_vaapi_picture_replace(&priv->current_picture, NULL);
541 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
544 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
545 return GST_VAAPI_DECODER_STATUS_DROP_FRAME;
548 static GstVaapiDecoderStatus
549 parse_sequence(GstVaapiDecoderMpeg2 *decoder,
550 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
552 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
553 GstMpegVideoSequenceHdr *seq_hdr;
557 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_hdr)) {
558 GST_ERROR("failed to allocate parser info for sequence header");
559 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
562 seq_hdr = &priv->seq_hdr->data.seq_hdr;
564 if (!gst_mpeg_video_packet_parse_sequence_header(packet, seq_hdr)) {
565 GST_ERROR("failed to parse sequence header");
566 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
569 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_hdr, NULL);
570 return GST_VAAPI_DECODER_STATUS_SUCCESS;
573 static GstVaapiDecoderStatus
574 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
576 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
577 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
578 GstMpegVideoSequenceHdr * const seq_hdr = unit->parsed_info;
580 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
581 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
582 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_scalable_ext, NULL);
583 gst_vaapi_parser_info_mpeg2_replace(&priv->quant_matrix, NULL);
585 priv->fps_n = seq_hdr->fps_n;
586 priv->fps_d = seq_hdr->fps_d;
587 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
588 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
590 priv->width = seq_hdr->width;
591 priv->height = seq_hdr->height;
592 priv->size_changed = TRUE;
593 priv->quant_matrix_changed = TRUE;
594 priv->progressive_sequence = TRUE;
596 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
597 return GST_VAAPI_DECODER_STATUS_SUCCESS;
600 static GstVaapiDecoderStatus
601 parse_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
602 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
604 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
605 GstMpegVideoSequenceExt *seq_ext;
607 priv->state &= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
609 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_ext)) {
610 GST_ERROR("failed to allocate parser info for sequence extension");
611 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
614 seq_ext = &priv->seq_ext->data.seq_ext;
616 if (!gst_mpeg_video_packet_parse_sequence_extension(packet, seq_ext)) {
617 GST_ERROR("failed to parse sequence-extension");
618 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
621 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_ext, NULL);
622 return GST_VAAPI_DECODER_STATUS_SUCCESS;
625 static GstVaapiDecoderStatus
626 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
628 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
629 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
630 GstMpegVideoSequenceExt * const seq_ext = unit->parsed_info;
631 GstVaapiProfile profile;
634 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR))
635 return GST_VAAPI_DECODER_STATUS_SUCCESS;
637 priv->progressive_sequence = seq_ext->progressive;
638 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
640 width = (priv->width & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
641 height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext << 12);
642 GST_DEBUG("video resolution %ux%u", width, height);
644 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
645 priv->fps_n *= seq_ext->fps_n_ext + 1;
646 priv->fps_d *= seq_ext->fps_d_ext + 1;
647 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
648 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
651 if (priv->width != width) {
653 priv->size_changed = TRUE;
656 if (priv->height != height) {
657 priv->height = height;
658 priv->size_changed = TRUE;
661 switch (seq_ext->profile) {
662 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
663 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
665 case GST_MPEG_VIDEO_PROFILE_MAIN:
666 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
668 case GST_MPEG_VIDEO_PROFILE_HIGH:
669 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
672 GST_ERROR("unsupported profile %d", seq_ext->profile);
673 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
675 if (priv->profile != profile) {
676 priv->profile = profile;
677 priv->profile_changed = TRUE;
680 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT;
681 return GST_VAAPI_DECODER_STATUS_SUCCESS;
684 static GstVaapiDecoderStatus
685 parse_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
686 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
688 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
689 GstMpegVideoSequenceDisplayExt *seq_display_ext;
691 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_display_ext)) {
692 GST_ERROR("failed to allocate parser info for sequence display extension");
693 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
696 seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
698 if (!gst_mpeg_video_packet_parse_sequence_display_extension(packet,
700 GST_ERROR("failed to parse sequence-display-extension");
701 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
704 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_display_ext, NULL);
705 return GST_VAAPI_DECODER_STATUS_SUCCESS;
708 static GstVaapiDecoderStatus
709 decode_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
710 GstVaapiDecoderUnit *unit)
712 /* XXX: handle color primaries and cropping */
713 return GST_VAAPI_DECODER_STATUS_SUCCESS;
716 static GstVaapiDecoderStatus
717 parse_sequence_scalable_ext(GstVaapiDecoderMpeg2 *decoder,
718 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
720 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
721 GstMpegVideoSequenceScalableExt *seq_scalable_ext;
723 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_scalable_ext)) {
724 GST_ERROR("failed to allocate parser info for sequence scalable extension");
725 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
728 seq_scalable_ext = &priv->seq_scalable_ext->data.seq_scalable_ext;
730 if (!gst_mpeg_video_packet_parse_sequence_scalable_extension(packet,
732 GST_ERROR("failed to parse sequence-scalable-extension");
733 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
736 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_scalable_ext, NULL);
737 return GST_VAAPI_DECODER_STATUS_SUCCESS;
740 static GstVaapiDecoderStatus
741 decode_sequence_scalable_ext(GstVaapiDecoderMpeg2 *decoder,
742 GstVaapiDecoderUnit *unit)
744 /* XXX: unsupported header -- ignore */
745 return GST_VAAPI_DECODER_STATUS_SUCCESS;
748 static GstVaapiDecoderStatus
749 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
751 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
753 gst_vaapi_dpb_flush(priv->dpb);
754 return GST_VAAPI_DECODER_STATUS_SUCCESS;
757 static GstVaapiDecoderStatus
758 parse_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
759 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
761 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
762 GstMpegVideoQuantMatrixExt *quant_matrix;
764 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->quant_matrix)) {
765 GST_ERROR("failed to allocate parser info for quantization matrix");
766 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
769 quant_matrix = &priv->quant_matrix->data.quant_matrix;
771 if (!gst_mpeg_video_packet_parse_quant_matrix_extension(packet,
773 GST_ERROR("failed to parse quant-matrix-extension");
774 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
777 gst_vaapi_decoder_unit_set_parsed_info(unit, quant_matrix, NULL);
778 return GST_VAAPI_DECODER_STATUS_SUCCESS;
781 static GstVaapiDecoderStatus
782 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
783 GstVaapiDecoderUnit *unit)
785 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
787 priv->quant_matrix_changed = TRUE;
788 return GST_VAAPI_DECODER_STATUS_SUCCESS;
791 static GstVaapiDecoderStatus
792 parse_gop(GstVaapiDecoderMpeg2 *decoder,
793 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
795 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
796 GstMpegVideoGop *gop;
798 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->gop)) {
799 GST_ERROR("failed to allocate parser info for GOP");
800 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
803 gop = &priv->gop->data.gop;
805 if (!gst_mpeg_video_packet_parse_gop(packet, gop)) {
806 GST_ERROR("failed to parse GOP");
807 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
810 gst_vaapi_decoder_unit_set_parsed_info(unit, gop, NULL);
811 return GST_VAAPI_DECODER_STATUS_SUCCESS;
814 static GstVaapiDecoderStatus
815 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
817 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
818 GstMpegVideoGop * const gop = unit->parsed_info;
820 priv->closed_gop = gop->closed_gop;
821 priv->broken_link = gop->broken_link;
823 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
824 gop->hour, gop->minute, gop->second, gop->frame,
825 priv->closed_gop, priv->broken_link);
827 pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
828 return GST_VAAPI_DECODER_STATUS_SUCCESS;
831 static GstVaapiDecoderStatus
832 parse_picture(GstVaapiDecoderMpeg2 *decoder,
833 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
835 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
836 GstMpegVideoPictureHdr *pic_hdr;
838 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
839 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT);
841 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_hdr)) {
842 GST_ERROR("failed to allocate parser info for picture header");
843 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
846 pic_hdr = &priv->pic_hdr->data.pic_hdr;
848 if (!gst_mpeg_video_packet_parse_picture_header(packet, pic_hdr)) {
849 GST_ERROR("failed to parse picture header");
850 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
853 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_hdr, NULL);
854 return GST_VAAPI_DECODER_STATUS_SUCCESS;
857 static GstVaapiDecoderStatus
858 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
860 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
862 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS))
863 return GST_VAAPI_DECODER_STATUS_SUCCESS;
865 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
867 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_HDR;
868 return GST_VAAPI_DECODER_STATUS_SUCCESS;
871 static GstVaapiDecoderStatus
872 parse_picture_ext(GstVaapiDecoderMpeg2 *decoder,
873 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
875 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
876 GstMpegVideoPictureExt *pic_ext;
878 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
879 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT|
880 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR);
882 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_ext)) {
883 GST_ERROR("failed to allocate parser info for picture extension");
884 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
887 pic_ext = &priv->pic_ext->data.pic_ext;
889 if (!gst_mpeg_video_packet_parse_picture_extension(packet, pic_ext)) {
890 GST_ERROR("failed to parse picture-extension");
891 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
894 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_ext, NULL);
895 return GST_VAAPI_DECODER_STATUS_SUCCESS;
898 static GstVaapiDecoderStatus
899 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
901 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
902 GstMpegVideoPictureExt * const pic_ext = unit->parsed_info;
904 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_PIC_HDR))
905 return GST_VAAPI_DECODER_STATUS_SUCCESS;
907 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
908 GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
909 pic_ext->progressive_frame = 1;
912 if (pic_ext->picture_structure == 0 ||
913 (pic_ext->progressive_frame &&
914 pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
915 GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
916 pic_ext->picture_structure);
917 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
920 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_EXT;
921 return GST_VAAPI_DECODER_STATUS_SUCCESS;
924 static inline guint32
925 pack_f_code(guint8 f_code[2][2])
927 return (((guint32)f_code[0][0] << 12) |
928 ((guint32)f_code[0][1] << 8) |
929 ((guint32)f_code[1][0] << 4) |
933 static GstVaapiDecoderStatus
934 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
936 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
937 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
938 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
940 switch (pic_hdr->pic_type) {
941 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
942 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
943 picture->type = GST_VAAPI_PICTURE_TYPE_I;
945 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
946 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
947 picture->type = GST_VAAPI_PICTURE_TYPE_P;
949 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
950 picture->type = GST_VAAPI_PICTURE_TYPE_B;
953 GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
954 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
957 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
958 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
959 if (pic_ext->top_field_first)
960 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
963 switch (pic_ext->picture_structure) {
964 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
965 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
967 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
968 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
970 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
971 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
975 /* Allocate dummy picture for first field based I-frame */
976 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
977 !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
978 gst_vaapi_dpb_size(priv->dpb) == 0) {
979 GstVaapiPicture *dummy_picture;
982 dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
983 if (!dummy_picture) {
984 GST_ERROR("failed to allocate dummy picture");
985 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
988 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
989 dummy_picture->pts = GST_CLOCK_TIME_NONE;
990 dummy_picture->poc = -1;
991 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
993 GST_VAAPI_PICTURE_FLAG_SET(
995 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
996 GST_VAAPI_PICTURE_FLAG_OUTPUT |
997 GST_VAAPI_PICTURE_FLAG_REFERENCE)
1000 success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
1001 gst_vaapi_picture_unref(dummy_picture);
1003 GST_ERROR("failed to add dummy picture into DPB");
1004 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1006 GST_INFO("allocated dummy picture for first field based I-frame");
1009 /* Update presentation time */
1010 picture->pts = pts_eval(&priv->tsg,
1011 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
1012 picture->poc = pts_get_poc(&priv->tsg);
1013 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1017 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
1019 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1020 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
1021 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1022 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
1023 GstVaapiPicture *prev_picture, *next_picture;
1025 /* Fill in VAPictureParameterBufferMPEG2 */
1026 pic_param->horizontal_size = priv->width;
1027 pic_param->vertical_size = priv->height;
1028 pic_param->forward_reference_picture = VA_INVALID_ID;
1029 pic_param->backward_reference_picture = VA_INVALID_ID;
1030 pic_param->picture_coding_type = pic_hdr->pic_type;
1031 pic_param->f_code = pack_f_code(pic_ext->f_code);
1033 #define COPY_FIELD(a, b, f) \
1034 pic_param->a.b.f = pic_ext->f
1035 pic_param->picture_coding_extension.value = 0;
1036 pic_param->picture_coding_extension.bits.is_first_field =
1037 GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
1038 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
1039 COPY_FIELD(picture_coding_extension, bits, picture_structure);
1040 COPY_FIELD(picture_coding_extension, bits, top_field_first);
1041 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
1042 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
1043 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
1044 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
1045 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
1046 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
1047 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
1049 gst_vaapi_dpb_get_neighbours(priv->dpb, picture,
1050 &prev_picture, &next_picture);
1052 switch (pic_hdr->pic_type) {
1053 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1055 pic_param->backward_reference_picture = next_picture->surface_id;
1057 pic_param->forward_reference_picture = prev_picture->surface_id;
1058 else if (!priv->closed_gop)
1059 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1061 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1063 pic_param->forward_reference_picture = prev_picture->surface_id;
1068 static GstVaapiDecoderStatus
1069 parse_slice(GstVaapiDecoderMpeg2 *decoder,
1070 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
1072 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1073 GstMpegVideoSliceHdr *slice_hdr;
1074 GstMpegVideoSequenceHdr *seq_hdr;
1075 GstMpegVideoSequenceScalableExt *seq_scalable_ext;
1077 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
1078 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT|
1079 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR|
1080 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT);
1082 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->slice_hdr)) {
1083 GST_ERROR("failed to allocate parser info for slice header");
1084 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1087 slice_hdr = &priv->slice_hdr->data.slice_hdr;
1088 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1089 seq_scalable_ext = priv->seq_scalable_ext ?
1090 &priv->seq_scalable_ext->data.seq_scalable_ext : NULL;
1092 if (!gst_mpeg_video_packet_parse_slice_header(packet, slice_hdr,
1093 seq_hdr, seq_scalable_ext)) {
1094 GST_ERROR("failed to parse slice header");
1095 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1098 gst_vaapi_decoder_unit_set_parsed_info(unit, slice_hdr, NULL);
1099 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1102 static GstVaapiDecoderStatus
1103 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
1105 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1106 GstVaapiPicture * const picture = priv->current_picture;
1107 GstVaapiSlice *slice;
1108 VASliceParameterBufferMPEG2 *slice_param;
1109 GstMpegVideoSliceHdr * const slice_hdr = unit->parsed_info;
1110 GstBuffer * const buffer =
1111 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1112 GstMapInfo map_info;
1114 GST_DEBUG("slice %d (%u bytes)", slice_hdr->mb_row, unit->size);
1116 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1117 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1119 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1120 GST_ERROR("failed to map buffer");
1121 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1124 slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1125 (map_info.data + unit->offset), unit->size);
1126 gst_buffer_unmap(buffer, &map_info);
1128 GST_ERROR("failed to allocate slice");
1129 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1131 gst_vaapi_picture_add_slice(picture, slice);
1133 /* Fill in VASliceParameterBufferMPEG2 */
1134 slice_param = slice->param;
1135 slice_param->macroblock_offset = slice_hdr->header_size + 32;
1136 slice_param->slice_horizontal_position = slice_hdr->mb_column;
1137 slice_param->slice_vertical_position = slice_hdr->mb_row;
1138 slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1139 slice_param->intra_slice_flag = slice_hdr->intra_slice;
1141 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SLICE;
1142 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1146 scan_for_start_code(const guchar *buf, guint buf_size,
1147 GstMpegVideoPacketTypeCode *type_ptr)
1151 while (i <= (buf_size - 4)) {
1154 else if (buf[i + 1])
1156 else if (buf[i] || buf[i + 2] != 1)
1162 if (i <= (buf_size - 4)) {
1164 *type_ptr = buf[i + 3];
1170 static GstVaapiDecoderStatus
1171 parse_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1172 GstMpegVideoPacket *packet)
1174 GstMpegVideoPacketTypeCode type;
1175 GstMpegVideoPacketExtensionCode ext_type;
1176 GstVaapiDecoderStatus status;
1178 type = packet->type;
1180 case GST_MPEG_VIDEO_PACKET_PICTURE:
1181 status = parse_picture(decoder, unit, packet);
1183 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1184 status = parse_sequence(decoder, unit, packet);
1186 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1187 ext_type = packet->data[4] >> 4;
1189 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1190 status = parse_sequence_ext(decoder, unit, packet);
1192 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1193 status = parse_sequence_display_ext(decoder, unit, packet);
1195 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1196 status = parse_sequence_scalable_ext(decoder, unit, packet);
1198 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1199 status = parse_quant_matrix_ext(decoder, unit, packet);
1201 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1202 status = parse_picture_ext(decoder, unit, packet);
1205 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1209 case GST_MPEG_VIDEO_PACKET_GOP:
1210 status = parse_gop(decoder, unit, packet);
1213 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1214 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1215 status = parse_slice(decoder, unit, packet);
1218 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1224 static GstVaapiDecoderStatus
1225 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1226 GstMpegVideoPacket *packet)
1228 GstMpegVideoPacketTypeCode type;
1229 GstMpegVideoPacketExtensionCode ext_type;
1230 GstVaapiDecoderStatus status;
1232 type = packet->type;
1234 case GST_MPEG_VIDEO_PACKET_PICTURE:
1235 status = decode_picture(decoder, unit);
1237 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1238 status = decode_sequence(decoder, unit);
1240 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1241 ext_type = packet->data[4] >> 4;
1243 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1244 status = decode_sequence_ext(decoder, unit);
1246 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1247 status = decode_sequence_display_ext(decoder, unit);
1249 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1250 status = decode_sequence_scalable_ext(decoder, unit);
1252 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1253 status = decode_quant_matrix_ext(decoder, unit);
1255 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1256 status = decode_picture_ext(decoder, unit);
1259 // Ignore unknown start-code extensions
1260 GST_WARNING("unsupported packet extension type 0x%02x", ext_type);
1261 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1265 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1266 status = decode_sequence_end(decoder);
1268 case GST_MPEG_VIDEO_PACKET_GOP:
1269 status = decode_gop(decoder, unit);
1272 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1273 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1274 status = decode_slice(decoder, unit);
1277 GST_WARNING("unsupported packet type 0x%02x", type);
1278 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1284 static GstVaapiDecoderStatus
1285 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1287 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1289 if (!priv->is_opened) {
1290 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1291 if (!priv->is_opened)
1292 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1294 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1297 static GstVaapiDecoderStatus
1298 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1299 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
1301 GstVaapiDecoderMpeg2 * const decoder =
1302 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1303 GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
1304 GstVaapiDecoderStatus status;
1305 GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1307 guint buf_size, flags;
1308 gint ofs, ofs1, ofs2;
1310 status = ensure_decoder(decoder);
1311 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1314 buf_size = gst_adapter_available(adapter);
1316 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1318 buf = gst_adapter_map(adapter, buf_size);
1320 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1322 ofs = scan_for_start_code(buf, buf_size, &type);
1324 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1327 ofs2 = ps->input_offset2 - 4;
1328 if (ofs2 < ofs1 + 4)
1331 ofs = G_UNLIKELY(buf_size < ofs2 + 4) ? -1 :
1332 scan_for_start_code(&buf[ofs2], buf_size - ofs2, &type2);
1334 // Assume the whole packet is present if end-of-stream
1336 ps->input_offset2 = buf_size;
1337 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1339 ofs = buf_size - ofs2;
1343 unit->size = ofs2 - ofs1;
1344 gst_adapter_flush(adapter, ofs1);
1345 ps->input_offset2 = 4;
1347 /* Check for start of new picture */
1350 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1351 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1352 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1354 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1355 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1357 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1358 case GST_MPEG_VIDEO_PACKET_GOP:
1359 case GST_MPEG_VIDEO_PACKET_PICTURE:
1360 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1362 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1363 if (G_UNLIKELY(unit->size < 5))
1364 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1367 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1368 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1369 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1371 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1372 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1373 case GST_MPEG_VIDEO_PACKET_GOP:
1374 case GST_MPEG_VIDEO_PACKET_PICTURE:
1375 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1382 // Ignore system start codes (PES headers)
1383 else if (type >= 0xb9 && type <= 0xff)
1384 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1387 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1388 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1391 static GstVaapiDecoderStatus
1392 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1393 GstVaapiDecoderUnit *unit)
1395 GstVaapiDecoderMpeg2 * const decoder =
1396 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1397 GstVaapiDecoderStatus status;
1398 GstMpegVideoPacket packet;
1399 GstBuffer * const buffer =
1400 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1401 GstMapInfo map_info;
1403 status = ensure_decoder(decoder);
1404 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1407 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1408 GST_ERROR("failed to map buffer");
1409 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1412 packet.data = map_info.data + unit->offset;
1413 packet.size = unit->size;
1414 packet.type = packet.data[3];
1417 status = parse_unit(decoder, unit, &packet);
1418 gst_buffer_unmap(buffer, &map_info);
1419 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1421 return decode_unit(decoder, unit, &packet);
1424 static GstVaapiDecoderStatus
1425 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1426 GstVaapiDecoderUnit *base_unit)
1428 GstVaapiDecoderMpeg2 * const decoder =
1429 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1430 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1431 GstMpegVideoSequenceHdr *seq_hdr;
1432 GstMpegVideoSequenceExt *seq_ext;
1433 GstMpegVideoSequenceDisplayExt *seq_display_ext;
1434 GstVaapiPicture *picture;
1435 GstVaapiDecoderStatus status;
1437 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1438 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1439 priv->state &= ~GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1441 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1442 seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1443 seq_display_ext = priv->seq_display_ext ?
1444 &priv->seq_display_ext->data.seq_display_ext : NULL;
1445 if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext,
1447 gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
1448 seq_hdr->par_w, seq_hdr->par_h);
1450 status = ensure_context(decoder);
1451 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1452 GST_ERROR("failed to reset context");
1456 if (priv->current_picture) {
1457 /* Re-use current picture where the first field was decoded */
1458 picture = gst_vaapi_picture_new_field(priv->current_picture);
1460 GST_ERROR("failed to allocate field picture");
1461 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1465 /* Create new picture */
1466 picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1468 GST_ERROR("failed to allocate picture");
1469 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1472 gst_vaapi_picture_replace(&priv->current_picture, picture);
1473 gst_vaapi_picture_unref(picture);
1475 /* Update cropping rectangle */
1476 if (seq_display_ext) {
1477 GstVaapiRectangle crop_rect;
1480 crop_rect.width = seq_display_ext->display_horizontal_size;
1481 crop_rect.height = seq_display_ext->display_vertical_size;
1482 if (crop_rect.width <= priv->width && crop_rect.height <= priv->height)
1483 gst_vaapi_picture_set_crop_rect(picture, &crop_rect);
1486 status = ensure_quant_matrix(decoder, picture);
1487 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1488 GST_ERROR("failed to reset quantizer matrix");
1492 status = init_picture(decoder, picture);
1493 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1496 fill_picture(decoder, picture);
1498 priv->state |= GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1499 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1502 static GstVaapiDecoderStatus
1503 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1505 GstVaapiDecoderMpeg2 * const decoder =
1506 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1508 return decode_current_picture(decoder);
1511 static GstVaapiDecoderStatus
1512 gst_vaapi_decoder_mpeg2_flush(GstVaapiDecoder *base_decoder)
1514 GstVaapiDecoderMpeg2 * const decoder =
1515 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1516 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1518 gst_vaapi_dpb_flush(priv->dpb);
1519 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1523 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1525 GstVaapiMiniObjectClass * const object_class =
1526 GST_VAAPI_MINI_OBJECT_CLASS(klass);
1527 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1529 object_class->size = sizeof(GstVaapiDecoderMpeg2);
1530 object_class->finalize = (GDestroyNotify)gst_vaapi_decoder_finalize;
1532 decoder_class->create = gst_vaapi_decoder_mpeg2_create;
1533 decoder_class->destroy = gst_vaapi_decoder_mpeg2_destroy;
1534 decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1535 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1536 decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1537 decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1538 decoder_class->flush = gst_vaapi_decoder_mpeg2_flush;
1541 static inline const GstVaapiDecoderClass *
1542 gst_vaapi_decoder_mpeg2_class(void)
1544 static GstVaapiDecoderMpeg2Class g_class;
1545 static gsize g_class_init = FALSE;
1547 if (g_once_init_enter(&g_class_init)) {
1548 gst_vaapi_decoder_mpeg2_class_init(&g_class);
1549 g_once_init_leave(&g_class_init, TRUE);
1551 return GST_VAAPI_DECODER_CLASS(&g_class);
1555 * gst_vaapi_decoder_mpeg2_new:
1556 * @display: a #GstVaapiDisplay
1557 * @caps: a #GstCaps holding codec information
1559 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1560 * hold extra information like codec-data and pictured coded size.
1562 * Return value: the newly allocated #GstVaapiDecoder object
1565 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1567 return gst_vaapi_decoder_new(gst_vaapi_decoder_mpeg2_class(),