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
30 #include <gst/base/gstbitreader.h>
31 #include <gst/codecparsers/gstmpegvideoparser.h>
32 #include "gstvaapidecoder_mpeg2.h"
33 #include "gstvaapidecoder_objects.h"
34 #include "gstvaapidecoder_dpb.h"
35 #include "gstvaapidecoder_priv.h"
36 #include "gstvaapidisplay_priv.h"
37 #include "gstvaapiobject_priv.h"
40 #include "gstvaapidebug.h"
42 /* ------------------------------------------------------------------------- */
43 /* --- PTS Generator --- */
44 /* ------------------------------------------------------------------------- */
46 typedef struct _PTSGenerator PTSGenerator;
47 struct _PTSGenerator {
48 GstClockTime gop_pts; // Current GOP PTS
49 GstClockTime max_pts; // Max picture PTS
50 guint gop_tsn; // Absolute GOP TSN
51 guint max_tsn; // Max picture TSN, relative to last GOP TSN
52 guint ovl_tsn; // How many times TSN overflowed since GOP
53 guint lst_tsn; // Last picture TSN
59 pts_init(PTSGenerator *tsg)
61 tsg->gop_pts = GST_CLOCK_TIME_NONE;
62 tsg->max_pts = GST_CLOCK_TIME_NONE;
71 static inline GstClockTime
72 pts_get_duration(PTSGenerator *tsg, guint num_frames)
74 return gst_util_uint64_scale(num_frames,
75 GST_SECOND * tsg->fps_d, tsg->fps_n);
79 pts_get_poc(PTSGenerator *tsg)
81 return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
85 pts_set_framerate(PTSGenerator *tsg, guint fps_n, guint fps_d)
92 pts_sync(PTSGenerator *tsg, GstClockTime gop_pts)
96 if (!GST_CLOCK_TIME_IS_VALID(gop_pts) ||
97 (GST_CLOCK_TIME_IS_VALID(tsg->max_pts) && tsg->max_pts >= gop_pts)) {
98 /* Invalid GOP PTS, interpolate from the last known picture PTS */
99 if (GST_CLOCK_TIME_IS_VALID(tsg->max_pts)) {
100 gop_pts = tsg->max_pts + pts_get_duration(tsg, 1);
101 gop_tsn = tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->max_tsn + 1;
109 /* Interpolate GOP TSN from this valid PTS */
110 if (GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
111 gop_tsn = tsg->gop_tsn + gst_util_uint64_scale(
112 gop_pts - tsg->gop_pts + pts_get_duration(tsg, 1) - 1,
113 tsg->fps_n, GST_SECOND * tsg->fps_d);
118 tsg->gop_pts = gop_pts;
119 tsg->gop_tsn = gop_tsn;
126 pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
130 if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
133 pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
135 if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
138 if (tsg->max_tsn < pic_tsn)
139 tsg->max_tsn = pic_tsn;
140 else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
141 tsg->max_tsn = pic_tsn;
144 tsg->lst_tsn = pic_tsn;
148 /* ------------------------------------------------------------------------- */
149 /* --- MPEG-2 Parser Info --- */
150 /* ------------------------------------------------------------------------- */
152 typedef struct _GstVaapiParserInfoMpeg2 GstVaapiParserInfoMpeg2;
153 struct _GstVaapiParserInfoMpeg2 {
154 GstVaapiMiniObject parent_instance;
155 GstMpegVideoPacket packet;
156 guint8 extension_type; /* for Extension packets */
158 GstMpegVideoSequenceHdr seq_hdr;
159 GstMpegVideoSequenceExt seq_ext;
160 GstMpegVideoSequenceDisplayExt seq_display_ext;
161 GstMpegVideoSequenceScalableExt seq_scalable_ext;
163 GstMpegVideoQuantMatrixExt quant_matrix;
164 GstMpegVideoPictureHdr pic_hdr;
165 GstMpegVideoPictureExt pic_ext;
166 GstMpegVideoSliceHdr slice_hdr;
170 static inline const GstVaapiMiniObjectClass *
171 gst_vaapi_parser_info_mpeg2_class(void)
173 static const GstVaapiMiniObjectClass GstVaapiParserInfoMpeg2Class = {
174 sizeof(GstVaapiParserInfoMpeg2),
177 return &GstVaapiParserInfoMpeg2Class;
180 static inline GstVaapiParserInfoMpeg2 *
181 gst_vaapi_parser_info_mpeg2_new(void)
183 return (GstVaapiParserInfoMpeg2 *)
184 gst_vaapi_mini_object_new(gst_vaapi_parser_info_mpeg2_class());
187 static inline GstVaapiParserInfoMpeg2 *
188 gst_vaapi_parser_info_mpeg2_ensure(GstVaapiParserInfoMpeg2 **pi_ptr)
190 GstVaapiParserInfoMpeg2 *pi = *pi_ptr;
192 if (G_LIKELY(pi != NULL))
195 *pi_ptr = pi = gst_vaapi_parser_info_mpeg2_new();
199 #define gst_vaapi_parser_info_mpeg2_ref(pi) \
200 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
202 #define gst_vaapi_parser_info_mpeg2_unref(pi) \
203 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
205 #define gst_vaapi_parser_info_mpeg2_replace(old_pi_ptr, new_pi) \
206 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr), \
207 (GstVaapiMiniObject *)(new_pi))
209 /* ------------------------------------------------------------------------- */
210 /* --- MPEG-2 Decoder --- */
211 /* ------------------------------------------------------------------------- */
213 #define GST_VAAPI_DECODER_MPEG2_CAST(decoder) \
214 ((GstVaapiDecoderMpeg2 *)(decoder))
216 typedef struct _GstVaapiDecoderMpeg2Private GstVaapiDecoderMpeg2Private;
217 typedef struct _GstVaapiDecoderMpeg2Class GstVaapiDecoderMpeg2Class;
220 GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR = 1 << 0,
221 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT = 1 << 1,
222 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR = 1 << 2,
223 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT = 1 << 3,
224 GST_MPEG_VIDEO_STATE_GOT_SLICE = 1 << 4,
226 GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS = (
227 GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
228 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT),
229 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS = (
230 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR|
231 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT),
232 GST_MPEG_VIDEO_STATE_VALID_PICTURE = (
233 GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS|
234 GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS|
235 GST_MPEG_VIDEO_STATE_GOT_SLICE)
238 struct _GstVaapiDecoderMpeg2Private {
239 GstVaapiProfile profile;
240 GstVaapiProfile hw_profile;
246 GstVaapiRectangle crop_rect;
247 GstVaapiParserInfoMpeg2 *seq_hdr;
248 GstVaapiParserInfoMpeg2 *seq_ext;
249 GstVaapiParserInfoMpeg2 *seq_display_ext;
250 GstVaapiParserInfoMpeg2 *seq_scalable_ext;
251 GstVaapiParserInfoMpeg2 *gop;
252 GstVaapiParserInfoMpeg2 *pic_hdr;
253 GstVaapiParserInfoMpeg2 *pic_ext;
254 GstVaapiParserInfoMpeg2 *pic_display_ext;
255 GstVaapiParserInfoMpeg2 *quant_matrix;
256 GstVaapiParserInfoMpeg2 *slice_hdr;
257 GstVaapiPicture *current_picture;
261 guint size_changed : 1;
262 guint profile_changed : 1;
263 guint quant_matrix_changed : 1;
264 guint progressive_sequence : 1;
265 guint closed_gop : 1;
266 guint broken_link : 1;
270 * GstVaapiDecoderMpeg2:
272 * A decoder based on Mpeg2.
274 struct _GstVaapiDecoderMpeg2 {
276 GstVaapiDecoder parent_instance;
277 GstVaapiDecoderMpeg2Private priv;
281 * GstVaapiDecoderMpeg2Class:
283 * A decoder class based on Mpeg2.
285 struct _GstVaapiDecoderMpeg2Class {
287 GstVaapiDecoderClass parent_class;
291 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
293 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
295 gst_vaapi_picture_replace(&priv->current_picture, NULL);
297 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_hdr, NULL);
298 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
299 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
300 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_scalable_ext, NULL);
301 gst_vaapi_parser_info_mpeg2_replace(&priv->gop, NULL);
302 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_hdr, NULL);
303 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
304 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_display_ext, NULL);
305 gst_vaapi_parser_info_mpeg2_replace(&priv->quant_matrix, NULL);
306 gst_vaapi_parser_info_mpeg2_replace(&priv->slice_hdr, NULL);
308 gst_vaapi_dpb_replace(&priv->dpb, NULL);
312 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
314 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
316 gst_vaapi_decoder_mpeg2_close(decoder);
318 priv->dpb = gst_vaapi_dpb_new(2);
322 pts_init(&priv->tsg);
327 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoder *base_decoder)
329 GstVaapiDecoderMpeg2 * const decoder =
330 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
332 gst_vaapi_decoder_mpeg2_close(decoder);
336 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoder *base_decoder)
338 GstVaapiDecoderMpeg2 * const decoder =
339 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
340 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
342 priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
343 priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
344 priv->profile_changed = TRUE; /* Allow fallbacks to work */
349 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
351 memcpy(dst, src, 64);
355 get_profile_str(GstVaapiProfile profile)
360 case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
361 case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
362 case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
363 default: str = "<unknown>"; break;
368 static GstVaapiProfile
369 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
371 GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
372 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
373 GstVaapiProfile profile = priv->profile;
376 /* Return immediately if the exact same profile was found */
377 if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
380 /* Otherwise, try to map to a higher profile */
382 case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
383 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
385 case GST_VAAPI_PROFILE_MPEG2_MAIN:
386 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
388 case GST_VAAPI_PROFILE_MPEG2_HIGH:
389 // Try to map to main profile if no high profile specific bits used
390 if (priv->profile == profile &&
391 !priv->seq_scalable_ext &&
393 priv->seq_ext->data.seq_ext.chroma_format == 1)) {
394 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
399 profile = GST_VAAPI_PROFILE_UNKNOWN;
402 } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
404 if (profile != priv->profile)
405 GST_INFO("forced %s profile to %s profile",
406 get_profile_str(priv->profile), get_profile_str(profile));
410 static GstVaapiDecoderStatus
411 ensure_context(GstVaapiDecoderMpeg2 *decoder)
413 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
414 GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
415 gboolean reset_context = FALSE;
417 if (priv->profile_changed) {
418 GST_DEBUG("profile changed");
419 priv->profile_changed = FALSE;
420 reset_context = TRUE;
422 priv->hw_profile = get_profile(decoder, entrypoint);
423 if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
424 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
427 if (priv->size_changed) {
428 GST_DEBUG("size changed");
429 priv->size_changed = FALSE;
430 reset_context = TRUE;
434 GstVaapiContextInfo info;
436 info.profile = priv->hw_profile;
437 info.entrypoint = entrypoint;
438 info.chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
439 info.width = priv->width;
440 info.height = priv->height;
442 reset_context = gst_vaapi_decoder_ensure_context(
443 GST_VAAPI_DECODER_CAST(decoder),
447 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
449 return GST_VAAPI_DECODER_STATUS_SUCCESS;
452 static GstVaapiDecoderStatus
453 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
455 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
456 GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr->data.seq_hdr;
457 VAIQMatrixBufferMPEG2 *iq_matrix;
458 guint8 *intra_quant_matrix = NULL;
459 guint8 *non_intra_quant_matrix = NULL;
460 guint8 *chroma_intra_quant_matrix = NULL;
461 guint8 *chroma_non_intra_quant_matrix = NULL;
463 if (!priv->quant_matrix_changed)
464 return GST_VAAPI_DECODER_STATUS_SUCCESS;
466 priv->quant_matrix_changed = FALSE;
468 picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
469 if (!picture->iq_matrix) {
470 GST_ERROR("failed to allocate IQ matrix");
471 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
473 iq_matrix = picture->iq_matrix->param;
475 intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
476 non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
478 if (priv->quant_matrix) {
479 GstMpegVideoQuantMatrixExt * const quant_matrix =
480 &priv->quant_matrix->data.quant_matrix;
481 if (quant_matrix->load_intra_quantiser_matrix)
482 intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
483 if (quant_matrix->load_non_intra_quantiser_matrix)
484 non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
485 if (quant_matrix->load_chroma_intra_quantiser_matrix)
486 chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
487 if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
488 chroma_non_intra_quant_matrix = quant_matrix->chroma_non_intra_quantiser_matrix;
491 iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
492 if (intra_quant_matrix)
493 copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
496 iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
497 if (non_intra_quant_matrix)
498 copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
499 non_intra_quant_matrix);
501 iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
502 if (chroma_intra_quant_matrix)
503 copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
504 chroma_intra_quant_matrix);
506 iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
507 if (chroma_non_intra_quant_matrix)
508 copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
509 chroma_non_intra_quant_matrix);
510 return GST_VAAPI_DECODER_STATUS_SUCCESS;
513 static inline gboolean
514 is_valid_state(GstVaapiDecoderMpeg2 *decoder, guint state)
516 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
518 return (priv->state & state) == state;
521 static GstVaapiDecoderStatus
522 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
524 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
525 GstVaapiPicture * const picture = priv->current_picture;
527 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PICTURE))
529 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
532 return GST_VAAPI_DECODER_STATUS_SUCCESS;
534 if (!gst_vaapi_picture_decode(picture))
536 if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
537 if (!gst_vaapi_dpb_add(priv->dpb, picture))
539 gst_vaapi_picture_replace(&priv->current_picture, NULL);
541 return GST_VAAPI_DECODER_STATUS_SUCCESS;
544 /* XXX: fix for cases where first field failed to be decoded */
545 gst_vaapi_picture_replace(&priv->current_picture, NULL);
546 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
549 priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
550 return GST_VAAPI_DECODER_STATUS_DROP_FRAME;
553 static GstVaapiDecoderStatus
554 parse_sequence(GstVaapiDecoderMpeg2 *decoder,
555 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
557 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
558 GstMpegVideoSequenceHdr *seq_hdr;
562 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_hdr)) {
563 GST_ERROR("failed to allocate parser info for sequence header");
564 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
567 seq_hdr = &priv->seq_hdr->data.seq_hdr;
569 if (!gst_mpeg_video_packet_parse_sequence_header(packet, seq_hdr)) {
570 GST_ERROR("failed to parse sequence header");
571 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
574 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_hdr, NULL);
575 return GST_VAAPI_DECODER_STATUS_SUCCESS;
578 static GstVaapiDecoderStatus
579 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
581 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
582 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
583 GstMpegVideoSequenceHdr * const seq_hdr = unit->parsed_info;
585 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_ext, NULL);
586 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_display_ext, NULL);
587 gst_vaapi_parser_info_mpeg2_replace(&priv->seq_scalable_ext, NULL);
588 gst_vaapi_parser_info_mpeg2_replace(&priv->quant_matrix, NULL);
589 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_display_ext, NULL);
591 priv->fps_n = seq_hdr->fps_n;
592 priv->fps_d = seq_hdr->fps_d;
593 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
594 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
596 priv->width = seq_hdr->width;
597 priv->height = seq_hdr->height;
598 priv->size_changed = TRUE;
599 priv->quant_matrix_changed = TRUE;
600 priv->progressive_sequence = TRUE;
602 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
603 return GST_VAAPI_DECODER_STATUS_SUCCESS;
606 static GstVaapiDecoderStatus
607 parse_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
608 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
610 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
611 GstMpegVideoSequenceExt *seq_ext;
613 priv->state &= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
615 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_ext)) {
616 GST_ERROR("failed to allocate parser info for sequence extension");
617 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
620 seq_ext = &priv->seq_ext->data.seq_ext;
622 if (!gst_mpeg_video_packet_parse_sequence_extension(packet, seq_ext)) {
623 GST_ERROR("failed to parse sequence-extension");
624 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
627 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_ext, NULL);
628 return GST_VAAPI_DECODER_STATUS_SUCCESS;
631 static GstVaapiDecoderStatus
632 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
634 GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
635 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
636 GstMpegVideoSequenceExt * const seq_ext = unit->parsed_info;
637 GstVaapiProfile profile;
640 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR))
641 return GST_VAAPI_DECODER_STATUS_SUCCESS;
643 priv->progressive_sequence = seq_ext->progressive;
644 gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
646 width = (priv->width & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
647 height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext << 12);
648 GST_DEBUG("video resolution %ux%u", width, height);
650 if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
651 priv->fps_n *= seq_ext->fps_n_ext + 1;
652 priv->fps_d *= seq_ext->fps_d_ext + 1;
653 pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
654 gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
657 if (priv->width != width) {
659 priv->size_changed = TRUE;
662 if (priv->height != height) {
663 priv->height = height;
664 priv->size_changed = TRUE;
667 switch (seq_ext->profile) {
668 case GST_MPEG_VIDEO_PROFILE_SIMPLE:
669 profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
671 case GST_MPEG_VIDEO_PROFILE_MAIN:
672 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
674 case GST_MPEG_VIDEO_PROFILE_HIGH:
675 profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
678 GST_ERROR("unsupported profile %d", seq_ext->profile);
679 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
681 if (priv->profile != profile) {
682 priv->profile = profile;
683 priv->profile_changed = TRUE;
686 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT;
687 return GST_VAAPI_DECODER_STATUS_SUCCESS;
690 static GstVaapiDecoderStatus
691 parse_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
692 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
694 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
695 GstMpegVideoSequenceDisplayExt *seq_display_ext;
697 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_display_ext)) {
698 GST_ERROR("failed to allocate parser info for sequence display extension");
699 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
702 seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
704 if (!gst_mpeg_video_packet_parse_sequence_display_extension(packet,
706 GST_ERROR("failed to parse sequence-display-extension");
707 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
710 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_display_ext, NULL);
711 return GST_VAAPI_DECODER_STATUS_SUCCESS;
714 static GstVaapiDecoderStatus
715 decode_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
716 GstVaapiDecoderUnit *unit)
718 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
719 GstMpegVideoSequenceDisplayExt *seq_display_ext;
721 seq_display_ext = priv->seq_display_ext ?
722 &priv->seq_display_ext->data.seq_display_ext : NULL;
724 /* Update cropping rectangle */
725 if (seq_display_ext) {
726 GstVaapiRectangle * const crop_rect = &priv->crop_rect;
729 crop_rect->width = seq_display_ext->display_horizontal_size;
730 crop_rect->height = seq_display_ext->display_vertical_size;
733 /* XXX: handle color primaries */
734 return GST_VAAPI_DECODER_STATUS_SUCCESS;
737 static GstVaapiDecoderStatus
738 parse_sequence_scalable_ext(GstVaapiDecoderMpeg2 *decoder,
739 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
741 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
742 GstMpegVideoSequenceScalableExt *seq_scalable_ext;
744 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->seq_scalable_ext)) {
745 GST_ERROR("failed to allocate parser info for sequence scalable extension");
746 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
749 seq_scalable_ext = &priv->seq_scalable_ext->data.seq_scalable_ext;
751 if (!gst_mpeg_video_packet_parse_sequence_scalable_extension(packet,
753 GST_ERROR("failed to parse sequence-scalable-extension");
754 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
757 gst_vaapi_decoder_unit_set_parsed_info(unit, seq_scalable_ext, NULL);
758 return GST_VAAPI_DECODER_STATUS_SUCCESS;
761 static GstVaapiDecoderStatus
762 decode_sequence_scalable_ext(GstVaapiDecoderMpeg2 *decoder,
763 GstVaapiDecoderUnit *unit)
765 /* XXX: unsupported header -- ignore */
766 return GST_VAAPI_DECODER_STATUS_SUCCESS;
769 static GstVaapiDecoderStatus
770 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
772 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
774 gst_vaapi_dpb_flush(priv->dpb);
775 return GST_VAAPI_DECODER_STATUS_SUCCESS;
778 static GstVaapiDecoderStatus
779 parse_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
780 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
782 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
783 GstMpegVideoQuantMatrixExt *quant_matrix;
785 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->quant_matrix)) {
786 GST_ERROR("failed to allocate parser info for quantization matrix");
787 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
790 quant_matrix = &priv->quant_matrix->data.quant_matrix;
792 if (!gst_mpeg_video_packet_parse_quant_matrix_extension(packet,
794 GST_ERROR("failed to parse quant-matrix-extension");
795 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
798 gst_vaapi_decoder_unit_set_parsed_info(unit, quant_matrix, NULL);
799 return GST_VAAPI_DECODER_STATUS_SUCCESS;
802 static GstVaapiDecoderStatus
803 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
804 GstVaapiDecoderUnit *unit)
806 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
808 priv->quant_matrix_changed = TRUE;
809 return GST_VAAPI_DECODER_STATUS_SUCCESS;
812 static GstVaapiDecoderStatus
813 parse_gop(GstVaapiDecoderMpeg2 *decoder,
814 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
816 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
817 GstMpegVideoGop *gop;
819 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->gop)) {
820 GST_ERROR("failed to allocate parser info for GOP");
821 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
824 gop = &priv->gop->data.gop;
826 if (!gst_mpeg_video_packet_parse_gop(packet, gop)) {
827 GST_ERROR("failed to parse GOP");
828 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
831 gst_vaapi_decoder_unit_set_parsed_info(unit, gop, NULL);
832 return GST_VAAPI_DECODER_STATUS_SUCCESS;
835 static GstVaapiDecoderStatus
836 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
838 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
839 GstMpegVideoGop * const gop = unit->parsed_info;
841 priv->closed_gop = gop->closed_gop;
842 priv->broken_link = gop->broken_link;
844 GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
845 gop->hour, gop->minute, gop->second, gop->frame,
846 priv->closed_gop, priv->broken_link);
848 pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
849 return GST_VAAPI_DECODER_STATUS_SUCCESS;
852 static GstVaapiDecoderStatus
853 parse_picture(GstVaapiDecoderMpeg2 *decoder,
854 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
856 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
857 GstMpegVideoPictureHdr *pic_hdr;
859 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
860 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT);
862 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_hdr)) {
863 GST_ERROR("failed to allocate parser info for picture header");
864 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
867 pic_hdr = &priv->pic_hdr->data.pic_hdr;
869 if (!gst_mpeg_video_packet_parse_picture_header(packet, pic_hdr)) {
870 GST_ERROR("failed to parse picture header");
871 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
874 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_hdr, NULL);
875 return GST_VAAPI_DECODER_STATUS_SUCCESS;
878 static GstVaapiDecoderStatus
879 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
881 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
883 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS))
884 return GST_VAAPI_DECODER_STATUS_SUCCESS;
886 gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
888 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_HDR;
889 return GST_VAAPI_DECODER_STATUS_SUCCESS;
892 static GstVaapiDecoderStatus
893 parse_picture_ext(GstVaapiDecoderMpeg2 *decoder,
894 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
896 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
897 GstMpegVideoPictureExt *pic_ext;
899 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
900 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT|
901 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR);
903 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->pic_ext)) {
904 GST_ERROR("failed to allocate parser info for picture extension");
905 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
908 pic_ext = &priv->pic_ext->data.pic_ext;
910 if (!gst_mpeg_video_packet_parse_picture_extension(packet, pic_ext)) {
911 GST_ERROR("failed to parse picture-extension");
912 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
915 gst_vaapi_decoder_unit_set_parsed_info(unit, pic_ext, NULL);
916 return GST_VAAPI_DECODER_STATUS_SUCCESS;
919 static GstVaapiDecoderStatus
920 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
922 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
923 GstMpegVideoPictureExt * const pic_ext = unit->parsed_info;
925 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_PIC_HDR))
926 return GST_VAAPI_DECODER_STATUS_SUCCESS;
928 if (priv->progressive_sequence && !pic_ext->progressive_frame) {
929 GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
930 pic_ext->progressive_frame = 1;
933 if (pic_ext->picture_structure == 0 ||
934 (pic_ext->progressive_frame &&
935 pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
936 GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
937 pic_ext->picture_structure);
938 pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
941 priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_EXT;
942 return GST_VAAPI_DECODER_STATUS_SUCCESS;
945 static inline guint32
946 pack_f_code(guint8 f_code[2][2])
948 return (((guint32)f_code[0][0] << 12) |
949 ((guint32)f_code[0][1] << 8) |
950 ((guint32)f_code[1][0] << 4) |
954 static GstVaapiDecoderStatus
955 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
957 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
958 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
959 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
961 switch (pic_hdr->pic_type) {
962 case GST_MPEG_VIDEO_PICTURE_TYPE_I:
963 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
964 picture->type = GST_VAAPI_PICTURE_TYPE_I;
966 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
967 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
968 picture->type = GST_VAAPI_PICTURE_TYPE_P;
970 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
971 picture->type = GST_VAAPI_PICTURE_TYPE_B;
974 GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
975 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
978 if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
979 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
980 if (pic_ext->top_field_first)
981 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
984 switch (pic_ext->picture_structure) {
985 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
986 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
988 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
989 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
991 case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
992 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
996 /* Allocate dummy picture for first field based I-frame */
997 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
998 !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
999 gst_vaapi_dpb_size(priv->dpb) == 0) {
1000 GstVaapiPicture *dummy_picture;
1003 dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1004 if (!dummy_picture) {
1005 GST_ERROR("failed to allocate dummy picture");
1006 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1009 dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
1010 dummy_picture->pts = GST_CLOCK_TIME_NONE;
1011 dummy_picture->poc = -1;
1012 dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1014 GST_VAAPI_PICTURE_FLAG_SET(
1016 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
1017 GST_VAAPI_PICTURE_FLAG_OUTPUT |
1018 GST_VAAPI_PICTURE_FLAG_REFERENCE)
1021 success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
1022 gst_vaapi_picture_unref(dummy_picture);
1024 GST_ERROR("failed to add dummy picture into DPB");
1025 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1027 GST_INFO("allocated dummy picture for first field based I-frame");
1030 /* Update presentation time */
1031 picture->pts = pts_eval(&priv->tsg,
1032 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
1033 picture->poc = pts_get_poc(&priv->tsg);
1034 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1038 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
1040 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1041 VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
1042 GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1043 GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
1044 GstVaapiPicture *prev_picture, *next_picture;
1046 /* Fill in VAPictureParameterBufferMPEG2 */
1047 pic_param->horizontal_size = priv->width;
1048 pic_param->vertical_size = priv->height;
1049 pic_param->forward_reference_picture = VA_INVALID_ID;
1050 pic_param->backward_reference_picture = VA_INVALID_ID;
1051 pic_param->picture_coding_type = pic_hdr->pic_type;
1052 pic_param->f_code = pack_f_code(pic_ext->f_code);
1054 #define COPY_FIELD(a, b, f) \
1055 pic_param->a.b.f = pic_ext->f
1056 pic_param->picture_coding_extension.value = 0;
1057 pic_param->picture_coding_extension.bits.is_first_field =
1058 GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
1059 COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
1060 COPY_FIELD(picture_coding_extension, bits, picture_structure);
1061 COPY_FIELD(picture_coding_extension, bits, top_field_first);
1062 COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
1063 COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
1064 COPY_FIELD(picture_coding_extension, bits, q_scale_type);
1065 COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
1066 COPY_FIELD(picture_coding_extension, bits, alternate_scan);
1067 COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
1068 COPY_FIELD(picture_coding_extension, bits, progressive_frame);
1070 gst_vaapi_dpb_get_neighbours(priv->dpb, picture,
1071 &prev_picture, &next_picture);
1073 switch (pic_hdr->pic_type) {
1074 case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1076 pic_param->backward_reference_picture = next_picture->surface_id;
1078 pic_param->forward_reference_picture = prev_picture->surface_id;
1079 else if (!priv->closed_gop)
1080 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1082 case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1084 pic_param->forward_reference_picture = prev_picture->surface_id;
1089 static GstVaapiDecoderStatus
1090 parse_slice(GstVaapiDecoderMpeg2 *decoder,
1091 GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
1093 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1094 GstMpegVideoSliceHdr *slice_hdr;
1095 GstMpegVideoSequenceHdr *seq_hdr;
1096 GstMpegVideoSequenceScalableExt *seq_scalable_ext;
1098 priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
1099 GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT|
1100 GST_MPEG_VIDEO_STATE_GOT_PIC_HDR|
1101 GST_MPEG_VIDEO_STATE_GOT_PIC_EXT);
1103 if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->slice_hdr)) {
1104 GST_ERROR("failed to allocate parser info for slice header");
1105 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1108 slice_hdr = &priv->slice_hdr->data.slice_hdr;
1109 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1110 seq_scalable_ext = priv->seq_scalable_ext ?
1111 &priv->seq_scalable_ext->data.seq_scalable_ext : NULL;
1113 if (!gst_mpeg_video_packet_parse_slice_header(packet, slice_hdr,
1114 seq_hdr, seq_scalable_ext)) {
1115 GST_ERROR("failed to parse slice header");
1116 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1119 gst_vaapi_decoder_unit_set_parsed_info(unit, slice_hdr, NULL);
1120 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1123 static GstVaapiDecoderStatus
1124 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
1126 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1127 GstVaapiPicture * const picture = priv->current_picture;
1128 GstVaapiSlice *slice;
1129 VASliceParameterBufferMPEG2 *slice_param;
1130 GstMpegVideoSliceHdr * const slice_hdr = unit->parsed_info;
1131 GstBuffer * const buffer =
1132 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1133 GstMapInfo map_info;
1135 GST_DEBUG("slice %d (%u bytes)", slice_hdr->mb_row, unit->size);
1137 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1138 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1140 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1141 GST_ERROR("failed to map buffer");
1142 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1145 slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1146 (map_info.data + unit->offset), unit->size);
1147 gst_buffer_unmap(buffer, &map_info);
1149 GST_ERROR("failed to allocate slice");
1150 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1152 gst_vaapi_picture_add_slice(picture, slice);
1154 /* Fill in VASliceParameterBufferMPEG2 */
1155 slice_param = slice->param;
1156 slice_param->macroblock_offset = slice_hdr->header_size + 32;
1157 slice_param->slice_horizontal_position = slice_hdr->mb_column;
1158 slice_param->slice_vertical_position = slice_hdr->mb_row;
1159 slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1160 slice_param->intra_slice_flag = slice_hdr->intra_slice;
1162 priv->state |= GST_MPEG_VIDEO_STATE_GOT_SLICE;
1163 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1167 scan_for_start_code(const guchar *buf, guint buf_size,
1168 GstMpegVideoPacketTypeCode *type_ptr)
1172 while (i <= (buf_size - 4)) {
1175 else if (buf[i + 1])
1177 else if (buf[i] || buf[i + 2] != 1)
1183 if (i <= (buf_size - 4)) {
1185 *type_ptr = buf[i + 3];
1191 static GstVaapiDecoderStatus
1192 parse_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1193 GstMpegVideoPacket *packet)
1195 GstMpegVideoPacketTypeCode type;
1196 GstMpegVideoPacketExtensionCode ext_type;
1197 GstVaapiDecoderStatus status;
1199 type = packet->type;
1201 case GST_MPEG_VIDEO_PACKET_PICTURE:
1202 status = parse_picture(decoder, unit, packet);
1204 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1205 status = parse_sequence(decoder, unit, packet);
1207 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1208 ext_type = packet->data[4] >> 4;
1210 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1211 status = parse_sequence_ext(decoder, unit, packet);
1213 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1214 status = parse_sequence_display_ext(decoder, unit, packet);
1216 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1217 status = parse_sequence_scalable_ext(decoder, unit, packet);
1219 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1220 status = parse_quant_matrix_ext(decoder, unit, packet);
1222 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1223 status = parse_picture_ext(decoder, unit, packet);
1226 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1230 case GST_MPEG_VIDEO_PACKET_GOP:
1231 status = parse_gop(decoder, unit, packet);
1234 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1235 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1236 status = parse_slice(decoder, unit, packet);
1239 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1245 static GstVaapiDecoderStatus
1246 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1247 GstMpegVideoPacket *packet)
1249 GstMpegVideoPacketTypeCode type;
1250 GstMpegVideoPacketExtensionCode ext_type;
1251 GstVaapiDecoderStatus status;
1253 type = packet->type;
1255 case GST_MPEG_VIDEO_PACKET_PICTURE:
1256 status = decode_picture(decoder, unit);
1258 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1259 status = decode_sequence(decoder, unit);
1261 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1262 ext_type = packet->data[4] >> 4;
1264 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1265 status = decode_sequence_ext(decoder, unit);
1267 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1268 status = decode_sequence_display_ext(decoder, unit);
1270 case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1271 status = decode_sequence_scalable_ext(decoder, unit);
1273 case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1274 status = decode_quant_matrix_ext(decoder, unit);
1276 case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1277 status = decode_picture_ext(decoder, unit);
1280 // Ignore unknown start-code extensions
1281 GST_WARNING("unsupported packet extension type 0x%02x", ext_type);
1282 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1286 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1287 status = decode_sequence_end(decoder);
1289 case GST_MPEG_VIDEO_PACKET_GOP:
1290 status = decode_gop(decoder, unit);
1293 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1294 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1295 status = decode_slice(decoder, unit);
1298 GST_WARNING("unsupported packet type 0x%02x", type);
1299 status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1305 static GstVaapiDecoderStatus
1306 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1308 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1310 if (!priv->is_opened) {
1311 priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1312 if (!priv->is_opened)
1313 return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1315 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1318 static GstVaapiDecoderStatus
1319 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1320 GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
1322 GstVaapiDecoderMpeg2 * const decoder =
1323 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1324 GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
1325 GstVaapiDecoderStatus status;
1326 GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1328 guint buf_size, flags;
1329 gint ofs, ofs1, ofs2;
1331 status = ensure_decoder(decoder);
1332 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1335 buf_size = gst_adapter_available(adapter);
1337 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1339 buf = gst_adapter_map(adapter, buf_size);
1341 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1343 ofs = scan_for_start_code(buf, buf_size, &type);
1345 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1348 ofs2 = ps->input_offset2 - 4;
1349 if (ofs2 < ofs1 + 4)
1352 ofs = G_UNLIKELY(buf_size < ofs2 + 4) ? -1 :
1353 scan_for_start_code(&buf[ofs2], buf_size - ofs2, &type2);
1355 // Assume the whole packet is present if end-of-stream
1357 ps->input_offset2 = buf_size;
1358 return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1360 ofs = buf_size - ofs2;
1364 unit->size = ofs2 - ofs1;
1365 gst_adapter_flush(adapter, ofs1);
1366 ps->input_offset2 = 4;
1368 /* Check for start of new picture */
1371 case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1372 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1373 flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1375 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1376 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1378 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1379 case GST_MPEG_VIDEO_PACKET_GOP:
1380 case GST_MPEG_VIDEO_PACKET_PICTURE:
1381 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1383 case GST_MPEG_VIDEO_PACKET_EXTENSION:
1384 if (G_UNLIKELY(unit->size < 5))
1385 return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1388 if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1389 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1390 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1392 case GST_MPEG_VIDEO_PACKET_USER_DATA:
1393 case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1394 case GST_MPEG_VIDEO_PACKET_GOP:
1395 case GST_MPEG_VIDEO_PACKET_PICTURE:
1396 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1403 // Ignore system start codes (PES headers)
1404 else if (type >= 0xb9 && type <= 0xff)
1405 flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1408 GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1409 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1412 static GstVaapiDecoderStatus
1413 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1414 GstVaapiDecoderUnit *unit)
1416 GstVaapiDecoderMpeg2 * const decoder =
1417 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1418 GstVaapiDecoderStatus status;
1419 GstMpegVideoPacket packet;
1420 GstBuffer * const buffer =
1421 GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1422 GstMapInfo map_info;
1424 status = ensure_decoder(decoder);
1425 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1428 if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1429 GST_ERROR("failed to map buffer");
1430 return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1433 packet.data = map_info.data + unit->offset;
1434 packet.size = unit->size;
1435 packet.type = packet.data[3];
1438 status = parse_unit(decoder, unit, &packet);
1439 gst_buffer_unmap(buffer, &map_info);
1440 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1442 return decode_unit(decoder, unit, &packet);
1445 static GstVaapiDecoderStatus
1446 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1447 GstVaapiDecoderUnit *base_unit)
1449 GstVaapiDecoderMpeg2 * const decoder =
1450 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1451 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1452 GstMpegVideoSequenceHdr *seq_hdr;
1453 GstMpegVideoSequenceExt *seq_ext;
1454 GstMpegVideoSequenceDisplayExt *seq_display_ext;
1455 GstVaapiPicture *picture;
1456 GstVaapiDecoderStatus status;
1458 if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1459 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1460 priv->state &= ~GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1462 seq_hdr = &priv->seq_hdr->data.seq_hdr;
1463 seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1464 seq_display_ext = priv->seq_display_ext ?
1465 &priv->seq_display_ext->data.seq_display_ext : NULL;
1466 if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext,
1468 gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
1469 seq_hdr->par_w, seq_hdr->par_h);
1471 status = ensure_context(decoder);
1472 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1473 GST_ERROR("failed to reset context");
1477 if (priv->current_picture) {
1478 /* Re-use current picture where the first field was decoded */
1479 picture = gst_vaapi_picture_new_field(priv->current_picture);
1481 GST_ERROR("failed to allocate field picture");
1482 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1486 /* Create new picture */
1487 picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1489 GST_ERROR("failed to allocate picture");
1490 return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1493 gst_vaapi_picture_replace(&priv->current_picture, picture);
1494 gst_vaapi_picture_unref(picture);
1496 /* Update cropping rectangle */
1497 /* XXX: handle picture_display_extension() */
1498 if (seq_display_ext && priv->pic_display_ext) {
1499 GstVaapiRectangle * const crop_rect = &priv->crop_rect;
1500 if (crop_rect->x + crop_rect->width <= priv->width &&
1501 crop_rect->y + crop_rect->height <= priv->height)
1502 gst_vaapi_picture_set_crop_rect(picture, crop_rect);
1505 status = ensure_quant_matrix(decoder, picture);
1506 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1507 GST_ERROR("failed to reset quantizer matrix");
1511 status = init_picture(decoder, picture);
1512 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1515 fill_picture(decoder, picture);
1517 priv->state |= GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1518 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1521 static GstVaapiDecoderStatus
1522 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1524 GstVaapiDecoderMpeg2 * const decoder =
1525 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1527 return decode_current_picture(decoder);
1530 static GstVaapiDecoderStatus
1531 gst_vaapi_decoder_mpeg2_flush(GstVaapiDecoder *base_decoder)
1533 GstVaapiDecoderMpeg2 * const decoder =
1534 GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1535 GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1537 gst_vaapi_dpb_flush(priv->dpb);
1538 return GST_VAAPI_DECODER_STATUS_SUCCESS;
1542 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1544 GstVaapiMiniObjectClass * const object_class =
1545 GST_VAAPI_MINI_OBJECT_CLASS(klass);
1546 GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1548 object_class->size = sizeof(GstVaapiDecoderMpeg2);
1549 object_class->finalize = (GDestroyNotify)gst_vaapi_decoder_finalize;
1551 decoder_class->create = gst_vaapi_decoder_mpeg2_create;
1552 decoder_class->destroy = gst_vaapi_decoder_mpeg2_destroy;
1553 decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1554 decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1555 decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1556 decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1557 decoder_class->flush = gst_vaapi_decoder_mpeg2_flush;
1560 static inline const GstVaapiDecoderClass *
1561 gst_vaapi_decoder_mpeg2_class(void)
1563 static GstVaapiDecoderMpeg2Class g_class;
1564 static gsize g_class_init = FALSE;
1566 if (g_once_init_enter(&g_class_init)) {
1567 gst_vaapi_decoder_mpeg2_class_init(&g_class);
1568 g_once_init_leave(&g_class_init, TRUE);
1570 return GST_VAAPI_DECODER_CLASS(&g_class);
1574 * gst_vaapi_decoder_mpeg2_new:
1575 * @display: a #GstVaapiDisplay
1576 * @caps: a #GstCaps holding codec information
1578 * Creates a new #GstVaapiDecoder for MPEG-2 decoding. The @caps can
1579 * hold extra information like codec-data and pictured coded size.
1581 * Return value: the newly allocated #GstVaapiDecoder object
1584 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1586 return gst_vaapi_decoder_new(gst_vaapi_decoder_mpeg2_class(),