bb67bd5c899d0f7a3bd7b8e27e2ee545caa3e288
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapidecoder_mpeg2.c
1 /*
2  *  gstvaapidecoder_mpeg2.c - MPEG-2 decoder
3  *
4  *  Copyright (C) 2011-2013 Intel Corporation
5  *
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.
10  *
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.
15  *
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
20  */
21
22 /**
23  * SECTION:gstvaapidecoder_mpeg2
24  * @short_description: MPEG-2 decoder
25  */
26
27 #include "sysdeps.h"
28 #include <string.h>
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"
37
38 #define DEBUG 1
39 #include "gstvaapidebug.h"
40
41 /* ------------------------------------------------------------------------- */
42 /* --- PTS Generator                                                     --- */
43 /* ------------------------------------------------------------------------- */
44
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
53     guint               fps_n;
54     guint               fps_d;
55 };
56
57 static void
58 pts_init(PTSGenerator *tsg)
59 {
60     tsg->gop_pts = GST_CLOCK_TIME_NONE;
61     tsg->max_pts = GST_CLOCK_TIME_NONE;
62     tsg->gop_tsn = 0;
63     tsg->max_tsn = 0;
64     tsg->ovl_tsn = 0;
65     tsg->lst_tsn = 0;
66     tsg->fps_n   = 0;
67     tsg->fps_d   = 0;
68 }
69
70 static inline GstClockTime
71 pts_get_duration(PTSGenerator *tsg, guint num_frames)
72 {
73     return gst_util_uint64_scale(num_frames,
74                                  GST_SECOND * tsg->fps_d, tsg->fps_n);
75 }
76
77 static inline guint
78 pts_get_poc(PTSGenerator *tsg)
79 {
80     return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
81 }
82
83 static void
84 pts_set_framerate(PTSGenerator *tsg, guint fps_n, guint fps_d)
85 {
86     tsg->fps_n = fps_n;
87     tsg->fps_d = fps_d;
88 }
89
90 static void
91 pts_sync(PTSGenerator *tsg, GstClockTime gop_pts)
92 {
93     guint gop_tsn;
94
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;
101         }
102         else {
103             gop_pts = 0;
104             gop_tsn = 0;
105         }
106     }
107     else {
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);
113         else
114             gop_tsn = 0;
115     }
116
117     tsg->gop_pts = gop_pts;
118     tsg->gop_tsn = gop_tsn;
119     tsg->max_tsn = 0;
120     tsg->ovl_tsn = 0;
121     tsg->lst_tsn = 0;
122 }
123
124 static GstClockTime
125 pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
126 {
127     GstClockTime pts;
128
129     if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
130         tsg->gop_pts = 0;
131
132     pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
133
134     if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
135         tsg->max_pts = pts;
136
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;
141         tsg->ovl_tsn++;
142     }
143     tsg->lst_tsn = pic_tsn;
144     return pts;
145 }
146
147 /* ------------------------------------------------------------------------- */
148 /* --- MPEG-2 Parser Info                                                --- */
149 /* ------------------------------------------------------------------------- */
150
151 typedef struct _GstVaapiParserInfoMpeg2 GstVaapiParserInfoMpeg2;
152 struct _GstVaapiParserInfoMpeg2 {
153     GstVaapiMiniObject  parent_instance;
154     GstMpegVideoPacket  packet;
155     guint8              extension_type; /* for Extension packets */
156     union {
157         GstMpegVideoSequenceHdr         seq_hdr;
158         GstMpegVideoSequenceExt         seq_ext;
159         GstMpegVideoSequenceDisplayExt  seq_display_ext;
160         GstMpegVideoSequenceScalableExt seq_scalable_ext;
161         GstMpegVideoGop                 gop;
162         GstMpegVideoQuantMatrixExt      quant_matrix;
163         GstMpegVideoPictureHdr          pic_hdr;
164         GstMpegVideoPictureExt          pic_ext;
165         GstMpegVideoSliceHdr            slice_hdr;
166     }                                   data;
167 };
168
169 static inline const GstVaapiMiniObjectClass *
170 gst_vaapi_parser_info_mpeg2_class(void)
171 {
172     static const GstVaapiMiniObjectClass GstVaapiParserInfoMpeg2Class = {
173         sizeof(GstVaapiParserInfoMpeg2),
174         NULL
175     };
176     return &GstVaapiParserInfoMpeg2Class;
177 }
178
179 static inline GstVaapiParserInfoMpeg2 *
180 gst_vaapi_parser_info_mpeg2_new(void)
181 {
182     return (GstVaapiParserInfoMpeg2 *)
183         gst_vaapi_mini_object_new(gst_vaapi_parser_info_mpeg2_class());
184 }
185
186 static inline GstVaapiParserInfoMpeg2 *
187 gst_vaapi_parser_info_mpeg2_ensure(GstVaapiParserInfoMpeg2 **pi_ptr)
188 {
189     GstVaapiParserInfoMpeg2 *pi = *pi_ptr;
190
191     if (G_LIKELY(pi != NULL))
192         return pi;
193
194     *pi_ptr = pi = gst_vaapi_parser_info_mpeg2_new();
195     return pi;
196 }
197
198 #define gst_vaapi_parser_info_mpeg2_ref(pi) \
199     gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
200
201 #define gst_vaapi_parser_info_mpeg2_unref(pi) \
202     gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
203
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))
207
208 /* ------------------------------------------------------------------------- */
209 /* --- MPEG-2 Decoder                                                    --- */
210 /* ------------------------------------------------------------------------- */
211
212 #define GST_VAAPI_DECODER_MPEG2_CAST(decoder) \
213     ((GstVaapiDecoderMpeg2 *)(decoder))
214
215 typedef struct _GstVaapiDecoderMpeg2Private     GstVaapiDecoderMpeg2Private;
216 typedef struct _GstVaapiDecoderMpeg2Class       GstVaapiDecoderMpeg2Class;
217
218 typedef enum {
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,
224
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)
235 } GstMpegVideoState;
236
237 struct _GstVaapiDecoderMpeg2Private {
238     GstVaapiProfile             profile;
239     GstVaapiProfile             hw_profile;
240     guint                       width;
241     guint                       height;
242     guint                       fps_n;
243     guint                       fps_d;
244     guint                       state;
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;
255     GstVaapiDpb                *dpb;
256     PTSGenerator                tsg;
257     guint                       is_opened               : 1;
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;
264 };
265
266 /**
267  * GstVaapiDecoderMpeg2:
268  *
269  * A decoder based on Mpeg2.
270  */
271 struct _GstVaapiDecoderMpeg2 {
272     /*< private >*/
273     GstVaapiDecoder             parent_instance;
274     GstVaapiDecoderMpeg2Private priv;
275 };
276
277 /**
278  * GstVaapiDecoderMpeg2Class:
279  *
280  * A decoder class based on Mpeg2.
281  */
282 struct _GstVaapiDecoderMpeg2Class {
283     /*< private >*/
284     GstVaapiDecoderClass parent_class;
285 };
286
287 static void
288 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
289 {
290     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
291
292     gst_vaapi_picture_replace(&priv->current_picture, NULL);
293
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);
303
304     gst_vaapi_dpb_replace(&priv->dpb, NULL);
305 }
306
307 static gboolean
308 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
309 {
310     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
311
312     gst_vaapi_decoder_mpeg2_close(decoder);
313
314     priv->dpb = gst_vaapi_dpb_new(2);
315     if (!priv->dpb)
316         return FALSE;
317
318     pts_init(&priv->tsg);
319     return TRUE;
320 }
321
322 static void
323 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoder *base_decoder)
324 {
325     GstVaapiDecoderMpeg2 * const decoder =
326         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
327
328     gst_vaapi_decoder_mpeg2_close(decoder);
329 }
330
331 static gboolean
332 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoder *base_decoder)
333 {
334     GstVaapiDecoderMpeg2 * const decoder =
335         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
336     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
337
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 */
341     return TRUE;
342 }
343
344 static inline void
345 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
346 {
347     memcpy(dst, src, 64);
348 }
349
350 static const char *
351 get_profile_str(GstVaapiProfile profile)
352 {
353     char *str;
354
355     switch (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;
360     }
361     return str;
362 }
363
364 static GstVaapiProfile
365 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
366 {
367     GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
368     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
369     GstVaapiProfile profile = priv->profile;
370
371     do {
372         /* Return immediately if the exact same profile was found */
373         if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
374             break;
375
376         /* Otherwise, try to map to a higher profile */
377         switch (profile) {
378         case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
379             profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
380             break;
381         case GST_VAAPI_PROFILE_MPEG2_MAIN:
382             profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
383             break;
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 &&
388                 (priv->seq_ext &&
389                  priv->seq_ext->data.seq_ext.chroma_format == 1)) {
390                 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
391                 break;
392             }
393             // fall-through
394         default:
395             profile = GST_VAAPI_PROFILE_UNKNOWN;
396             break;
397         }
398     } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
399
400     if (profile != priv->profile)
401         GST_INFO("forced %s profile to %s profile",
402                  get_profile_str(priv->profile), get_profile_str(profile));
403     return profile;
404 }
405
406 static GstVaapiDecoderStatus
407 ensure_context(GstVaapiDecoderMpeg2 *decoder)
408 {
409     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
410     GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
411     gboolean reset_context = FALSE;
412
413     if (priv->profile_changed) {
414         GST_DEBUG("profile changed");
415         priv->profile_changed = FALSE;
416         reset_context         = TRUE;
417
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;
421     }
422
423     if (priv->size_changed) {
424         GST_DEBUG("size changed");
425         priv->size_changed = FALSE;
426         reset_context      = TRUE;
427     }
428
429     if (reset_context) {
430         GstVaapiContextInfo info;
431
432         info.profile    = priv->hw_profile;
433         info.entrypoint = entrypoint;
434         info.width      = priv->width;
435         info.height     = priv->height;
436         info.ref_frames = 2;
437         reset_context   = gst_vaapi_decoder_ensure_context(
438             GST_VAAPI_DECODER_CAST(decoder),
439             &info
440         );
441         if (!reset_context)
442             return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
443     }
444     return GST_VAAPI_DECODER_STATUS_SUCCESS;
445 }
446
447 static GstVaapiDecoderStatus
448 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
449 {
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;
457
458     if (!priv->quant_matrix_changed)
459         return GST_VAAPI_DECODER_STATUS_SUCCESS;
460
461     priv->quant_matrix_changed = FALSE;
462
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;
467     }
468     iq_matrix = picture->iq_matrix->param;
469
470     intra_quant_matrix     = seq_hdr->intra_quantizer_matrix;
471     non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
472
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;
484     }
485
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,
489                           intra_quant_matrix);
490
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);
495
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);
500
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;
506 }
507
508 static inline gboolean
509 is_valid_state(GstVaapiDecoderMpeg2 *decoder, guint state)
510 {
511     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
512
513     return (priv->state & state) == state;
514 }
515
516 static GstVaapiDecoderStatus
517 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
518 {
519     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
520     GstVaapiPicture * const picture = priv->current_picture;
521
522     if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PICTURE))
523         goto drop_frame;
524     priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
525
526     if (!picture)
527         return GST_VAAPI_DECODER_STATUS_SUCCESS;
528
529     if (!gst_vaapi_picture_decode(picture))
530         goto error;
531     if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
532         if (!gst_vaapi_dpb_add(priv->dpb, picture))
533             goto error;
534         gst_vaapi_picture_replace(&priv->current_picture, NULL);
535     }
536     return GST_VAAPI_DECODER_STATUS_SUCCESS;
537
538 error:
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;
542
543 drop_frame:
544     priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
545     return GST_VAAPI_DECODER_STATUS_DROP_FRAME;
546 }
547
548 static GstVaapiDecoderStatus
549 parse_sequence(GstVaapiDecoderMpeg2 *decoder,
550     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
551 {
552     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
553     GstMpegVideoSequenceHdr *seq_hdr;
554
555     priv->state = 0;
556
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;
560     }
561
562     seq_hdr = &priv->seq_hdr->data.seq_hdr;
563
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;
567     }
568
569     gst_vaapi_decoder_unit_set_parsed_info(unit, seq_hdr, NULL);
570     return GST_VAAPI_DECODER_STATUS_SUCCESS;
571 }
572
573 static GstVaapiDecoderStatus
574 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
575 {
576     GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
577     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
578     GstMpegVideoSequenceHdr * const seq_hdr = unit->parsed_info;
579
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);
584
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);
589
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;
595
596     priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
597     return GST_VAAPI_DECODER_STATUS_SUCCESS;
598 }
599
600 static GstVaapiDecoderStatus
601 parse_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
602     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
603 {
604     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
605     GstMpegVideoSequenceExt *seq_ext;
606
607     priv->state &= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
608
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;
612     }
613
614     seq_ext = &priv->seq_ext->data.seq_ext;
615
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;
619     }
620
621     gst_vaapi_decoder_unit_set_parsed_info(unit, seq_ext, NULL);
622     return GST_VAAPI_DECODER_STATUS_SUCCESS;
623 }
624
625 static GstVaapiDecoderStatus
626 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
627 {
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;
632     guint width, height;
633
634     if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR))
635         return GST_VAAPI_DECODER_STATUS_SUCCESS;
636
637     priv->progressive_sequence = seq_ext->progressive;
638     gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
639
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);
643
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);
649     }
650
651     if (priv->width != width) {
652         priv->width = width;
653         priv->size_changed = TRUE;
654     }
655
656     if (priv->height != height) {
657         priv->height = height;
658         priv->size_changed = TRUE;
659     }
660
661     switch (seq_ext->profile) {
662     case GST_MPEG_VIDEO_PROFILE_SIMPLE:
663         profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
664         break;
665     case GST_MPEG_VIDEO_PROFILE_MAIN:
666         profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
667         break;
668     case GST_MPEG_VIDEO_PROFILE_HIGH:
669         profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
670         break;
671     default:
672         GST_ERROR("unsupported profile %d", seq_ext->profile);
673         return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
674     }
675     if (priv->profile != profile) {
676         priv->profile = profile;
677         priv->profile_changed = TRUE;
678     }
679
680     priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT;
681     return GST_VAAPI_DECODER_STATUS_SUCCESS;
682 }
683
684 static GstVaapiDecoderStatus
685 parse_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
686     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
687 {
688     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
689     GstMpegVideoSequenceDisplayExt *seq_display_ext;
690
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;
694     }
695
696     seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
697
698     if (!gst_mpeg_video_packet_parse_sequence_display_extension(packet,
699             seq_display_ext)) {
700         GST_ERROR("failed to parse sequence-display-extension");
701         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
702     }
703
704     gst_vaapi_decoder_unit_set_parsed_info(unit, seq_display_ext, NULL);
705     return GST_VAAPI_DECODER_STATUS_SUCCESS;
706 }
707
708 static GstVaapiDecoderStatus
709 decode_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
710     GstVaapiDecoderUnit *unit)
711 {
712     /* XXX: handle color primaries and cropping */
713     return GST_VAAPI_DECODER_STATUS_SUCCESS;
714 }
715
716 static GstVaapiDecoderStatus
717 parse_sequence_scalable_ext(GstVaapiDecoderMpeg2 *decoder,
718     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
719 {
720     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
721     GstMpegVideoSequenceScalableExt *seq_scalable_ext;
722
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;
726     }
727
728     seq_scalable_ext = &priv->seq_scalable_ext->data.seq_scalable_ext;
729
730     if (!gst_mpeg_video_packet_parse_sequence_scalable_extension(packet,
731             seq_scalable_ext)) {
732         GST_ERROR("failed to parse sequence-scalable-extension");
733         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
734     }
735
736     gst_vaapi_decoder_unit_set_parsed_info(unit, seq_scalable_ext, NULL);
737     return GST_VAAPI_DECODER_STATUS_SUCCESS;
738 }
739
740 static GstVaapiDecoderStatus
741 decode_sequence_scalable_ext(GstVaapiDecoderMpeg2 *decoder,
742     GstVaapiDecoderUnit *unit)
743 {
744     /* XXX: unsupported header -- ignore */
745     return GST_VAAPI_DECODER_STATUS_SUCCESS;
746 }
747
748 static GstVaapiDecoderStatus
749 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
750 {
751     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
752
753     gst_vaapi_dpb_flush(priv->dpb);
754     return GST_VAAPI_DECODER_STATUS_SUCCESS;
755 }
756
757 static GstVaapiDecoderStatus
758 parse_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
759     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
760 {
761     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
762     GstMpegVideoQuantMatrixExt *quant_matrix;
763
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;
767     }
768
769     quant_matrix = &priv->quant_matrix->data.quant_matrix;
770
771     if (!gst_mpeg_video_packet_parse_quant_matrix_extension(packet,
772             quant_matrix)) {
773         GST_ERROR("failed to parse quant-matrix-extension");
774         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
775     }
776
777     gst_vaapi_decoder_unit_set_parsed_info(unit, quant_matrix, NULL);
778     return GST_VAAPI_DECODER_STATUS_SUCCESS;
779 }
780
781 static GstVaapiDecoderStatus
782 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
783     GstVaapiDecoderUnit *unit)
784 {
785     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
786
787     priv->quant_matrix_changed = TRUE;
788     return GST_VAAPI_DECODER_STATUS_SUCCESS;
789 }
790
791 static GstVaapiDecoderStatus
792 parse_gop(GstVaapiDecoderMpeg2 *decoder,
793     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
794 {
795     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
796     GstMpegVideoGop *gop;
797
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;
801     }
802
803     gop = &priv->gop->data.gop;
804
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;
808     }
809
810     gst_vaapi_decoder_unit_set_parsed_info(unit, gop, NULL);
811     return GST_VAAPI_DECODER_STATUS_SUCCESS;
812 }
813
814 static GstVaapiDecoderStatus
815 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
816 {
817     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
818     GstMpegVideoGop * const gop = unit->parsed_info;
819
820     priv->closed_gop  = gop->closed_gop;
821     priv->broken_link = gop->broken_link;
822
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);
826
827     pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
828     return GST_VAAPI_DECODER_STATUS_SUCCESS;
829 }
830
831 static GstVaapiDecoderStatus
832 parse_picture(GstVaapiDecoderMpeg2 *decoder,
833     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
834 {
835     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
836     GstMpegVideoPictureHdr *pic_hdr;
837
838     priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
839                     GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT);
840
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;
844     }
845
846     pic_hdr = &priv->pic_hdr->data.pic_hdr;
847
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;
851     }
852
853     gst_vaapi_decoder_unit_set_parsed_info(unit, pic_hdr, NULL);
854     return GST_VAAPI_DECODER_STATUS_SUCCESS;
855 }
856
857 static GstVaapiDecoderStatus
858 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
859 {
860     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
861
862     if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS))
863         return GST_VAAPI_DECODER_STATUS_SUCCESS;
864
865     gst_vaapi_parser_info_mpeg2_replace(&priv->pic_ext, NULL);
866
867     priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_HDR;
868     return GST_VAAPI_DECODER_STATUS_SUCCESS;
869 }
870
871 static GstVaapiDecoderStatus
872 parse_picture_ext(GstVaapiDecoderMpeg2 *decoder,
873     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
874 {
875     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
876     GstMpegVideoPictureExt *pic_ext;
877
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);
881
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;
885     }
886
887     pic_ext = &priv->pic_ext->data.pic_ext;
888
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;
892     }
893
894     gst_vaapi_decoder_unit_set_parsed_info(unit, pic_ext, NULL);
895     return GST_VAAPI_DECODER_STATUS_SUCCESS;
896 }
897
898 static GstVaapiDecoderStatus
899 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
900 {
901     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
902     GstMpegVideoPictureExt * const pic_ext = unit->parsed_info;
903
904     if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_GOT_PIC_HDR))
905         return GST_VAAPI_DECODER_STATUS_SUCCESS;
906
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;
910     }
911
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;
918     }
919
920     priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_EXT;
921     return GST_VAAPI_DECODER_STATUS_SUCCESS;
922 }
923
924 static inline guint32
925 pack_f_code(guint8 f_code[2][2])
926 {
927     return (((guint32)f_code[0][0] << 12) |
928             ((guint32)f_code[0][1] <<  8) |
929             ((guint32)f_code[1][0] <<  4) |
930             (         f_code[1][1]      ));
931 }
932
933 static GstVaapiDecoderStatus
934 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
935 {
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;
939
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;
944         break;
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;
948         break;
949     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
950         picture->type = GST_VAAPI_PICTURE_TYPE_B;
951         break;
952     default:
953         GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
954         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
955     }
956
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);
961     }
962
963     switch (pic_ext->picture_structure) {
964     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
965         picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
966         break;
967     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
968         picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
969         break;
970     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
971         picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
972         break;
973     }
974
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;
980         gboolean success;
981
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;
986         }
987
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;
992
993         GST_VAAPI_PICTURE_FLAG_SET(
994             dummy_picture,
995             (GST_VAAPI_PICTURE_FLAG_SKIPPED |
996              GST_VAAPI_PICTURE_FLAG_REFERENCE)
997         );
998
999         success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
1000         gst_vaapi_picture_unref(dummy_picture);
1001         if (!success) {
1002             GST_ERROR("failed to add dummy picture into DPB");
1003             return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1004         }
1005         GST_INFO("allocated dummy picture for first field based I-frame");
1006     }
1007
1008     /* Update presentation time */
1009     picture->pts = pts_eval(&priv->tsg,
1010         GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
1011     picture->poc = pts_get_poc(&priv->tsg);
1012     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1013 }
1014
1015 static void
1016 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
1017 {
1018     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1019     VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
1020     GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1021     GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext->data.pic_ext;
1022     GstVaapiPicture *prev_picture, *next_picture;
1023
1024     /* Fill in VAPictureParameterBufferMPEG2 */
1025     pic_param->horizontal_size            = priv->width;
1026     pic_param->vertical_size              = priv->height;
1027     pic_param->forward_reference_picture  = VA_INVALID_ID;
1028     pic_param->backward_reference_picture = VA_INVALID_ID;
1029     pic_param->picture_coding_type        = pic_hdr->pic_type;
1030     pic_param->f_code                     = pack_f_code(pic_ext->f_code);
1031
1032 #define COPY_FIELD(a, b, f) \
1033     pic_param->a.b.f = pic_ext->f
1034     pic_param->picture_coding_extension.value = 0;
1035     pic_param->picture_coding_extension.bits.is_first_field =
1036         GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
1037     COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
1038     COPY_FIELD(picture_coding_extension, bits, picture_structure);
1039     COPY_FIELD(picture_coding_extension, bits, top_field_first);
1040     COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
1041     COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
1042     COPY_FIELD(picture_coding_extension, bits, q_scale_type);
1043     COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
1044     COPY_FIELD(picture_coding_extension, bits, alternate_scan);
1045     COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
1046     COPY_FIELD(picture_coding_extension, bits, progressive_frame);
1047
1048     gst_vaapi_dpb_get_neighbours(priv->dpb, picture,
1049         &prev_picture, &next_picture);
1050
1051     switch (pic_hdr->pic_type) {
1052     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1053         if (next_picture)
1054             pic_param->backward_reference_picture = next_picture->surface_id;
1055         if (prev_picture)
1056             pic_param->forward_reference_picture = prev_picture->surface_id;
1057         else if (!priv->closed_gop)
1058             GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1059         break;
1060     case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1061         if (prev_picture)
1062             pic_param->forward_reference_picture = prev_picture->surface_id;
1063         break;
1064     }
1065 }
1066
1067 static GstVaapiDecoderStatus
1068 parse_slice(GstVaapiDecoderMpeg2 *decoder,
1069     GstVaapiDecoderUnit *unit, const GstMpegVideoPacket *packet)
1070 {
1071     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1072     GstMpegVideoSliceHdr *slice_hdr;
1073     GstMpegVideoSequenceHdr *seq_hdr;
1074     GstMpegVideoSequenceScalableExt *seq_scalable_ext;
1075
1076     priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR|
1077                     GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT|
1078                     GST_MPEG_VIDEO_STATE_GOT_PIC_HDR|
1079                     GST_MPEG_VIDEO_STATE_GOT_PIC_EXT);
1080
1081     if (!gst_vaapi_parser_info_mpeg2_ensure(&priv->slice_hdr)) {
1082         GST_ERROR("failed to allocate parser info for slice header");
1083         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1084     }
1085
1086     slice_hdr = &priv->slice_hdr->data.slice_hdr;
1087     seq_hdr = &priv->seq_hdr->data.seq_hdr;
1088     seq_scalable_ext = priv->seq_scalable_ext ?
1089         &priv->seq_scalable_ext->data.seq_scalable_ext : NULL;
1090
1091     if (!gst_mpeg_video_packet_parse_slice_header(packet, slice_hdr,
1092             seq_hdr, seq_scalable_ext)) {
1093         GST_ERROR("failed to parse slice header");
1094         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1095     }
1096
1097     gst_vaapi_decoder_unit_set_parsed_info(unit, slice_hdr, NULL);
1098     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1099 }
1100
1101 static GstVaapiDecoderStatus
1102 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit)
1103 {
1104     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1105     GstVaapiPicture * const picture = priv->current_picture;
1106     GstVaapiSlice *slice;
1107     VASliceParameterBufferMPEG2 *slice_param;
1108     GstMpegVideoSliceHdr * const slice_hdr = unit->parsed_info;
1109     GstBuffer * const buffer =
1110         GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1111     GstMapInfo map_info;
1112
1113     GST_DEBUG("slice %d (%u bytes)", slice_hdr->mb_row, unit->size);
1114
1115     if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1116         return GST_VAAPI_DECODER_STATUS_SUCCESS;
1117
1118     if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1119         GST_ERROR("failed to map buffer");
1120         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1121     }
1122
1123     slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1124         (map_info.data + unit->offset), unit->size);
1125     gst_buffer_unmap(buffer, &map_info);
1126     if (!slice) {
1127         GST_ERROR("failed to allocate slice");
1128         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1129     }
1130     gst_vaapi_picture_add_slice(picture, slice);
1131
1132     /* Fill in VASliceParameterBufferMPEG2 */
1133     slice_param                            = slice->param;
1134     slice_param->macroblock_offset         = slice_hdr->header_size + 32;
1135     slice_param->slice_horizontal_position = slice_hdr->mb_column;
1136     slice_param->slice_vertical_position   = slice_hdr->mb_row;
1137     slice_param->quantiser_scale_code      = slice_hdr->quantiser_scale_code;
1138     slice_param->intra_slice_flag          = slice_hdr->intra_slice;
1139
1140     priv->state |= GST_MPEG_VIDEO_STATE_GOT_SLICE;
1141     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1142 }
1143
1144 static inline gint
1145 scan_for_start_code(const guchar *buf, guint buf_size,
1146     GstMpegVideoPacketTypeCode *type_ptr)
1147 {
1148     guint i = 0;
1149
1150     while (i <= (buf_size - 4)) {
1151         if (buf[i + 2] > 1)
1152             i += 3;
1153         else if (buf[i + 1])
1154             i += 2;
1155         else if (buf[i] || buf[i + 2] != 1)
1156             i++;
1157         else
1158             break;
1159     }
1160
1161     if (i <= (buf_size - 4)) {
1162         if (type_ptr)
1163             *type_ptr = buf[i + 3];
1164         return i;
1165     }
1166     return -1;
1167 }
1168
1169 static GstVaapiDecoderStatus
1170 parse_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1171     GstMpegVideoPacket *packet)
1172 {
1173     GstMpegVideoPacketTypeCode type;
1174     GstMpegVideoPacketExtensionCode ext_type;
1175     GstVaapiDecoderStatus status;
1176
1177     type = packet->type;
1178     switch (type) {
1179     case GST_MPEG_VIDEO_PACKET_PICTURE:
1180         status = parse_picture(decoder, unit, packet);
1181         break;
1182     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1183         status = parse_sequence(decoder, unit, packet);
1184         break;
1185     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1186         ext_type = packet->data[4] >> 4;
1187         switch (ext_type) {
1188         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1189             status = parse_sequence_ext(decoder, unit, packet);
1190             break;
1191         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1192             status = parse_sequence_display_ext(decoder, unit, packet);
1193             break;
1194         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1195             status = parse_sequence_scalable_ext(decoder, unit, packet);
1196             break;
1197         case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1198             status = parse_quant_matrix_ext(decoder, unit, packet);
1199             break;
1200         case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1201             status = parse_picture_ext(decoder, unit, packet);
1202             break;
1203         default:
1204             status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1205             break;
1206         }
1207         break;
1208     case GST_MPEG_VIDEO_PACKET_GOP:
1209         status = parse_gop(decoder, unit, packet);
1210         break;
1211     default:
1212         if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1213             type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1214             status = parse_slice(decoder, unit, packet);
1215             break;
1216         }
1217         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1218         break;
1219     }
1220     return status;
1221 }
1222
1223 static GstVaapiDecoderStatus
1224 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnit *unit,
1225     GstMpegVideoPacket *packet)
1226 {
1227     GstMpegVideoPacketTypeCode type;
1228     GstMpegVideoPacketExtensionCode ext_type;
1229     GstVaapiDecoderStatus status;
1230
1231     type = packet->type;
1232     switch (type) {
1233     case GST_MPEG_VIDEO_PACKET_PICTURE:
1234         status = decode_picture(decoder, unit);
1235         break;
1236     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1237         status = decode_sequence(decoder, unit);
1238         break;
1239     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1240         ext_type = packet->data[4] >> 4;
1241         switch (ext_type) {
1242         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1243             status = decode_sequence_ext(decoder, unit);
1244             break;
1245         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1246             status = decode_sequence_display_ext(decoder, unit);
1247             break;
1248         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1249             status = decode_sequence_scalable_ext(decoder, unit);
1250             break;
1251         case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1252             status = decode_quant_matrix_ext(decoder, unit);
1253             break;
1254         case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1255             status = decode_picture_ext(decoder, unit);
1256             break;
1257         default:
1258             // Ignore unknown start-code extensions
1259             GST_WARNING("unsupported packet extension type 0x%02x", ext_type);
1260             status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1261             break;
1262         }
1263         break;
1264     case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1265         status = decode_sequence_end(decoder);
1266         break;
1267     case GST_MPEG_VIDEO_PACKET_GOP:
1268         status = decode_gop(decoder, unit);
1269         break;
1270     default:
1271         if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1272             type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1273             status = decode_slice(decoder, unit);
1274             break;
1275         }
1276         GST_WARNING("unsupported packet type 0x%02x", type);
1277         status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1278         break;
1279     }
1280     return status;
1281 }
1282
1283 static GstVaapiDecoderStatus
1284 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1285 {
1286     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1287
1288     if (!priv->is_opened) {
1289         priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1290         if (!priv->is_opened)
1291             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1292     }
1293     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1294 }
1295
1296 static GstVaapiDecoderStatus
1297 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1298     GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit *unit)
1299 {
1300     GstVaapiDecoderMpeg2 * const decoder =
1301         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1302     GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
1303     GstVaapiDecoderStatus status;
1304     GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1305     const guchar *buf;
1306     guint buf_size, flags;
1307     gint ofs, ofs1, ofs2;
1308
1309     status = ensure_decoder(decoder);
1310     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1311         return status;
1312
1313     buf_size = gst_adapter_available(adapter);
1314     if (buf_size < 4)
1315         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1316
1317     buf = gst_adapter_map(adapter, buf_size);
1318     if (!buf)
1319         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1320
1321     ofs = scan_for_start_code(buf, buf_size, &type);
1322     if (ofs < 0)
1323         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1324     ofs1 = ofs;
1325
1326     ofs2 = ps->input_offset2 - 4;
1327     if (ofs2 < ofs1 + 4)
1328         ofs2 = ofs1 + 4;
1329
1330     ofs = G_UNLIKELY(buf_size < ofs2 + 4) ? -1 :
1331         scan_for_start_code(&buf[ofs2], buf_size - ofs2, &type2);
1332     if (ofs < 0) {
1333         // Assume the whole packet is present if end-of-stream
1334         if (!at_eos) {
1335             ps->input_offset2 = buf_size;
1336             return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1337         }
1338         ofs = buf_size - ofs2;
1339     }
1340     ofs2 += ofs;
1341
1342     unit->size = ofs2 - ofs1;
1343     gst_adapter_flush(adapter, ofs1);
1344     ps->input_offset2 = 4;
1345
1346     /* Check for start of new picture */
1347     flags = 0;
1348     switch (type) {
1349     case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1350         flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1351         flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1352         break;
1353     case GST_MPEG_VIDEO_PACKET_USER_DATA:
1354         flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1355         /* fall-through */
1356     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1357     case GST_MPEG_VIDEO_PACKET_GOP:
1358     case GST_MPEG_VIDEO_PACKET_PICTURE:
1359         flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1360         break;
1361     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1362         if (G_UNLIKELY(unit->size < 5))
1363             return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1364         break;
1365     default:
1366         if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1367             type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1368             flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1369             switch (type2) {
1370             case GST_MPEG_VIDEO_PACKET_USER_DATA:
1371             case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1372             case GST_MPEG_VIDEO_PACKET_GOP:
1373             case GST_MPEG_VIDEO_PACKET_PICTURE:
1374                 flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1375                 break;
1376             default:
1377                 break;
1378             }
1379         }
1380
1381         // Ignore system start codes (PES headers)
1382         else if (type >= 0xb9 && type <= 0xff)
1383             flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1384         break;
1385     }
1386     GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1387     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1388 }
1389
1390 static GstVaapiDecoderStatus
1391 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1392     GstVaapiDecoderUnit *unit)
1393 {
1394     GstVaapiDecoderMpeg2 * const decoder =
1395         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1396     GstVaapiDecoderStatus status;
1397     GstMpegVideoPacket packet;
1398     GstBuffer * const buffer =
1399         GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer;
1400     GstMapInfo map_info;
1401
1402     status = ensure_decoder(decoder);
1403     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1404         return status;
1405
1406     if (!gst_buffer_map(buffer, &map_info, GST_MAP_READ)) {
1407         GST_ERROR("failed to map buffer");
1408         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1409     }
1410
1411     packet.data = map_info.data + unit->offset;
1412     packet.size = unit->size;
1413     packet.type = packet.data[3];
1414     packet.offset = 4;
1415
1416     status = parse_unit(decoder, unit, &packet);
1417     gst_buffer_unmap(buffer, &map_info);
1418     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1419         return status;
1420     return decode_unit(decoder, unit, &packet);
1421 }
1422
1423 static GstVaapiDecoderStatus
1424 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1425     GstVaapiDecoderUnit *base_unit)
1426 {
1427     GstVaapiDecoderMpeg2 * const decoder =
1428         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1429     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1430     GstMpegVideoSequenceHdr *seq_hdr;
1431     GstMpegVideoSequenceExt *seq_ext;
1432     GstMpegVideoSequenceDisplayExt *seq_display_ext;
1433     GstVaapiPicture *picture;
1434     GstVaapiDecoderStatus status;
1435
1436     if (!is_valid_state(decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1437         return GST_VAAPI_DECODER_STATUS_SUCCESS;
1438     priv->state &= ~GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1439
1440     seq_hdr = &priv->seq_hdr->data.seq_hdr;
1441     seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1442     seq_display_ext = priv->seq_display_ext ?
1443         &priv->seq_display_ext->data.seq_display_ext : NULL;
1444     if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext,
1445             seq_display_ext))
1446         gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
1447             seq_hdr->par_w, seq_hdr->par_h);
1448
1449     status = ensure_context(decoder);
1450     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1451         GST_ERROR("failed to reset context");
1452         return status;
1453     }
1454
1455     if (priv->current_picture) {
1456         /* Re-use current picture where the first field was decoded */
1457         picture = gst_vaapi_picture_new_field(priv->current_picture);
1458         if (!picture) {
1459             GST_ERROR("failed to allocate field picture");
1460             return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1461         }
1462     }
1463     else {
1464         /* Create new picture */
1465         picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1466         if (!picture) {
1467             GST_ERROR("failed to allocate picture");
1468             return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1469         }
1470     }
1471     gst_vaapi_picture_replace(&priv->current_picture, picture);
1472     gst_vaapi_picture_unref(picture);
1473
1474     status = ensure_quant_matrix(decoder, picture);
1475     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1476         GST_ERROR("failed to reset quantizer matrix");
1477         return status;
1478     }
1479
1480     status = init_picture(decoder, picture);
1481     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1482         return status;
1483
1484     fill_picture(decoder, picture);
1485
1486     priv->state |= GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1487     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1488 }
1489
1490 static GstVaapiDecoderStatus
1491 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1492 {
1493     GstVaapiDecoderMpeg2 * const decoder =
1494         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1495
1496     return decode_current_picture(decoder);
1497 }
1498
1499 static GstVaapiDecoderStatus
1500 gst_vaapi_decoder_mpeg2_flush(GstVaapiDecoder *base_decoder)
1501 {
1502     GstVaapiDecoderMpeg2 * const decoder =
1503         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1504     GstVaapiDecoderMpeg2Private * const priv = &decoder->priv;
1505
1506     gst_vaapi_dpb_flush(priv->dpb);
1507     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1508 }
1509
1510 static void
1511 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1512 {
1513     GstVaapiMiniObjectClass * const object_class =
1514         GST_VAAPI_MINI_OBJECT_CLASS(klass);
1515     GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1516
1517     object_class->size          = sizeof(GstVaapiDecoderMpeg2);
1518     object_class->finalize      = (GDestroyNotify)gst_vaapi_decoder_finalize;
1519
1520     decoder_class->create       = gst_vaapi_decoder_mpeg2_create;
1521     decoder_class->destroy      = gst_vaapi_decoder_mpeg2_destroy;
1522     decoder_class->parse        = gst_vaapi_decoder_mpeg2_parse;
1523     decoder_class->decode       = gst_vaapi_decoder_mpeg2_decode;
1524     decoder_class->start_frame  = gst_vaapi_decoder_mpeg2_start_frame;
1525     decoder_class->end_frame    = gst_vaapi_decoder_mpeg2_end_frame;
1526     decoder_class->flush        = gst_vaapi_decoder_mpeg2_flush;
1527 }
1528
1529 static inline const GstVaapiDecoderClass *
1530 gst_vaapi_decoder_mpeg2_class(void)
1531 {
1532     static GstVaapiDecoderMpeg2Class g_class;
1533     static gsize g_class_init = FALSE;
1534
1535     if (g_once_init_enter(&g_class_init)) {
1536         gst_vaapi_decoder_mpeg2_class_init(&g_class);
1537         g_once_init_leave(&g_class_init, TRUE);
1538     }
1539     return GST_VAAPI_DECODER_CLASS(&g_class);
1540 }
1541
1542 /**
1543  * gst_vaapi_decoder_mpeg2_new:
1544  * @display: a #GstVaapiDisplay
1545  * @caps: a #GstCaps holding codec information
1546  *
1547  * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
1548  * hold extra information like codec-data and pictured coded size.
1549  *
1550  * Return value: the newly allocated #GstVaapiDecoder object
1551  */
1552 GstVaapiDecoder *
1553 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1554 {
1555     return gst_vaapi_decoder_new(gst_vaapi_decoder_mpeg2_class(),
1556         display, caps);
1557 }