Merge branch 'move_subdir_editing-services' into tizen_gst_1.19.2_mono
[platform/upstream/gstreamer.git] / subprojects / gstreamer-vaapi / gst-libs / gst / vaapi / gstvaapidecoder_mpeg2.c
1 /*
2  *  gstvaapidecoder_mpeg2.c - MPEG-2 decoder
3  *
4  *  Copyright (C) 2011-2013 Intel Corporation
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
6  *
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.
11  *
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.
16  *
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
21  */
22
23 /**
24  * SECTION:gstvaapidecoder_mpeg2
25  * @short_description: MPEG-2 decoder
26  */
27
28 #include "sysdeps.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
37 #define DEBUG 1
38 #include "gstvaapidebug.h"
39
40 /* ------------------------------------------------------------------------- */
41 /* --- PTS Generator                                                     --- */
42 /* ------------------------------------------------------------------------- */
43
44 typedef struct _PTSGenerator PTSGenerator;
45 struct _PTSGenerator
46 {
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     } else {
102       gop_pts = 0;
103       gop_tsn = 0;
104     }
105   } else {
106     /* Interpolate GOP TSN from this valid PTS */
107     if (GST_CLOCK_TIME_IS_VALID (tsg->gop_pts))
108       gop_tsn =
109           tsg->gop_tsn + gst_util_uint64_scale (gop_pts - tsg->gop_pts +
110           pts_get_duration (tsg, 1) - 1, tsg->fps_n, GST_SECOND * tsg->fps_d);
111     else
112       gop_tsn = 0;
113   }
114
115   tsg->gop_pts = gop_pts;
116   tsg->gop_tsn = gop_tsn;
117   tsg->max_tsn = 0;
118   tsg->ovl_tsn = 0;
119   tsg->lst_tsn = 0;
120 }
121
122 static GstClockTime
123 pts_eval (PTSGenerator * tsg, GstClockTime pic_pts, guint pic_tsn)
124 {
125   GstClockTime pts;
126
127   if (!GST_CLOCK_TIME_IS_VALID (tsg->gop_pts))
128     tsg->gop_pts = pts_get_duration (tsg, pic_tsn);
129
130   pts = pic_pts;
131   if (!GST_CLOCK_TIME_IS_VALID (pts))
132     pts = tsg->gop_pts + pts_get_duration (tsg, tsg->ovl_tsn * 1024 + pic_tsn);
133   else if (pts == tsg->gop_pts) {
134     /* The picture following the GOP header shall be an I-frame.
135        So we can compensate for the GOP start time from here */
136     tsg->gop_pts -= pts_get_duration (tsg, pic_tsn);
137   }
138
139   if (!GST_CLOCK_TIME_IS_VALID (tsg->max_pts) || tsg->max_pts < pts)
140     tsg->max_pts = pts;
141
142   if (tsg->max_tsn < pic_tsn)
143     tsg->max_tsn = pic_tsn;
144   else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) {    /* TSN wrapped */
145     tsg->max_tsn = pic_tsn;
146     tsg->ovl_tsn++;
147   }
148   tsg->lst_tsn = pic_tsn;
149
150   return pts;
151 }
152
153 /* ------------------------------------------------------------------------- */
154 /* --- MPEG-2 Parser Info                                                --- */
155 /* ------------------------------------------------------------------------- */
156
157 typedef struct _GstVaapiParserInfoMpeg2 GstVaapiParserInfoMpeg2;
158 struct _GstVaapiParserInfoMpeg2
159 {
160   GstVaapiMiniObject parent_instance;
161   GstMpegVideoPacket packet;
162   guint8 extension_type;        /* for Extension packets */
163   union
164   {
165     GstMpegVideoSequenceHdr seq_hdr;
166     GstMpegVideoSequenceExt seq_ext;
167     GstMpegVideoSequenceDisplayExt seq_display_ext;
168     GstMpegVideoSequenceScalableExt seq_scalable_ext;
169     GstMpegVideoGop gop;
170     GstMpegVideoQuantMatrixExt quant_matrix;
171     GstMpegVideoPictureHdr pic_hdr;
172     GstMpegVideoPictureExt pic_ext;
173     GstMpegVideoSliceHdr slice_hdr;
174   } data;
175 };
176
177 static inline const GstVaapiMiniObjectClass *
178 gst_vaapi_parser_info_mpeg2_class (void)
179 {
180   static const GstVaapiMiniObjectClass GstVaapiParserInfoMpeg2Class = {
181     sizeof (GstVaapiParserInfoMpeg2),
182     NULL
183   };
184   return &GstVaapiParserInfoMpeg2Class;
185 }
186
187 static inline GstVaapiParserInfoMpeg2 *
188 gst_vaapi_parser_info_mpeg2_new (void)
189 {
190   return (GstVaapiParserInfoMpeg2 *)
191       gst_vaapi_mini_object_new (gst_vaapi_parser_info_mpeg2_class ());
192 }
193
194 static inline GstVaapiParserInfoMpeg2 *
195 gst_vaapi_parser_info_mpeg2_ensure (GstVaapiParserInfoMpeg2 ** pi_ptr)
196 {
197   GstVaapiParserInfoMpeg2 *pi = *pi_ptr;
198
199   if (G_LIKELY (pi != NULL))
200     return pi;
201
202   *pi_ptr = pi = gst_vaapi_parser_info_mpeg2_new ();
203   return pi;
204 }
205
206 #define gst_vaapi_parser_info_mpeg2_ref(pi) \
207     gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(pi))
208
209 #define gst_vaapi_parser_info_mpeg2_unref(pi) \
210     gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(pi))
211
212 #define gst_vaapi_parser_info_mpeg2_replace(old_pi_ptr, new_pi)         \
213     gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_pi_ptr),  \
214         (GstVaapiMiniObject *)(new_pi))
215
216 /* ------------------------------------------------------------------------- */
217 /* --- MPEG-2 Decoder                                                    --- */
218 /* ------------------------------------------------------------------------- */
219
220 #define GST_VAAPI_DECODER_MPEG2_CAST(decoder) \
221     ((GstVaapiDecoderMpeg2 *)(decoder))
222
223 typedef struct _GstVaapiDecoderMpeg2Private GstVaapiDecoderMpeg2Private;
224 typedef struct _GstVaapiDecoderMpeg2Class GstVaapiDecoderMpeg2Class;
225
226 typedef enum
227 {
228   GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR = 1 << 0,
229   GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT = 1 << 1,
230   GST_MPEG_VIDEO_STATE_GOT_PIC_HDR = 1 << 2,
231   GST_MPEG_VIDEO_STATE_GOT_PIC_EXT = 1 << 3,
232   GST_MPEG_VIDEO_STATE_GOT_SLICE = 1 << 4,
233
234   GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS = (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
235       GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT),
236   GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS = (GST_MPEG_VIDEO_STATE_GOT_PIC_HDR |
237       GST_MPEG_VIDEO_STATE_GOT_PIC_EXT),
238   GST_MPEG_VIDEO_STATE_VALID_PICTURE = (GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS |
239       GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS | GST_MPEG_VIDEO_STATE_GOT_SLICE)
240 } GstMpegVideoState;
241
242 struct _GstVaapiDecoderMpeg2Private
243 {
244   GstVaapiProfile profile;
245   GstVaapiProfile hw_profile;
246   guint width;
247   guint height;
248   guint fps_n;
249   guint fps_d;
250   guint state;
251   GstVaapiRectangle crop_rect;
252   GstVaapiParserInfoMpeg2 *seq_hdr;
253   GstVaapiParserInfoMpeg2 *seq_ext;
254   GstVaapiParserInfoMpeg2 *seq_display_ext;
255   GstVaapiParserInfoMpeg2 *seq_scalable_ext;
256   GstVaapiParserInfoMpeg2 *gop;
257   GstVaapiParserInfoMpeg2 *pic_hdr;
258   GstVaapiParserInfoMpeg2 *pic_ext;
259   GstVaapiParserInfoMpeg2 *pic_display_ext;
260   GstVaapiParserInfoMpeg2 *quant_matrix;
261   GstVaapiParserInfoMpeg2 *slice_hdr;
262   GstVaapiPicture *current_picture;
263   GstVaapiDpb *dpb;
264   PTSGenerator tsg;
265   guint is_opened:1;
266   guint size_changed:1;
267   guint profile_changed:1;
268   guint quant_matrix_changed:1;
269   guint progressive_sequence:1;
270   guint closed_gop:1;
271   guint broken_link:1;
272 };
273
274 /**
275  * GstVaapiDecoderMpeg2:
276  *
277  * A decoder based on Mpeg2.
278  */
279 struct _GstVaapiDecoderMpeg2
280 {
281   /*< private > */
282   GstVaapiDecoder parent_instance;
283   GstVaapiDecoderMpeg2Private priv;
284 };
285
286 /**
287  * GstVaapiDecoderMpeg2Class:
288  *
289  * A decoder class based on Mpeg2.
290  */
291 struct _GstVaapiDecoderMpeg2Class
292 {
293   /*< private > */
294   GstVaapiDecoderClass parent_class;
295 };
296
297 G_DEFINE_TYPE (GstVaapiDecoderMpeg2, gst_vaapi_decoder_mpeg2,
298     GST_TYPE_VAAPI_DECODER);
299
300 static void
301 gst_vaapi_decoder_mpeg2_close (GstVaapiDecoderMpeg2 * decoder)
302 {
303   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
304
305   gst_vaapi_picture_replace (&priv->current_picture, NULL);
306
307   gst_vaapi_parser_info_mpeg2_replace (&priv->seq_hdr, NULL);
308   gst_vaapi_parser_info_mpeg2_replace (&priv->seq_ext, NULL);
309   gst_vaapi_parser_info_mpeg2_replace (&priv->seq_display_ext, NULL);
310   gst_vaapi_parser_info_mpeg2_replace (&priv->seq_scalable_ext, NULL);
311   gst_vaapi_parser_info_mpeg2_replace (&priv->gop, NULL);
312   gst_vaapi_parser_info_mpeg2_replace (&priv->pic_hdr, NULL);
313   gst_vaapi_parser_info_mpeg2_replace (&priv->pic_ext, NULL);
314   gst_vaapi_parser_info_mpeg2_replace (&priv->pic_display_ext, NULL);
315   gst_vaapi_parser_info_mpeg2_replace (&priv->quant_matrix, NULL);
316   gst_vaapi_parser_info_mpeg2_replace (&priv->slice_hdr, NULL);
317
318   priv->state = 0;
319
320   gst_vaapi_dpb_replace (&priv->dpb, NULL);
321
322   priv->is_opened = FALSE;
323 }
324
325 static gboolean
326 gst_vaapi_decoder_mpeg2_open (GstVaapiDecoderMpeg2 * decoder)
327 {
328   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
329
330   gst_vaapi_decoder_mpeg2_close (decoder);
331
332   priv->dpb = gst_vaapi_dpb_new (2);
333   if (!priv->dpb)
334     return FALSE;
335
336   pts_init (&priv->tsg);
337   return TRUE;
338 }
339
340 static void
341 gst_vaapi_decoder_mpeg2_destroy (GstVaapiDecoder * base_decoder)
342 {
343   GstVaapiDecoderMpeg2 *const decoder =
344       GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
345
346   gst_vaapi_decoder_mpeg2_close (decoder);
347 }
348
349 static gboolean
350 gst_vaapi_decoder_mpeg2_create (GstVaapiDecoder * base_decoder)
351 {
352   GstVaapiDecoderMpeg2 *const decoder =
353       GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
354   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
355
356   priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
357   priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
358   priv->profile_changed = TRUE; /* Allow fallbacks to work */
359   return TRUE;
360 }
361
362 static GstVaapiDecoderStatus
363 gst_vaapi_decoder_mpeg2_reset (GstVaapiDecoder * base_decoder)
364 {
365   gst_vaapi_decoder_mpeg2_destroy (base_decoder);
366   gst_vaapi_decoder_mpeg2_create (base_decoder);
367   return GST_VAAPI_DECODER_STATUS_SUCCESS;
368 }
369
370 static inline void
371 copy_quant_matrix (guint8 dst[64], const guint8 src[64])
372 {
373   memcpy (dst, src, 64);
374 }
375
376 static const char *
377 get_profile_str (GstVaapiProfile profile)
378 {
379   const char *str;
380
381   switch (profile) {
382     case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
383       str = "simple";
384       break;
385     case GST_VAAPI_PROFILE_MPEG2_MAIN:
386       str = "main";
387       break;
388     case GST_VAAPI_PROFILE_MPEG2_HIGH:
389       str = "high";
390       break;
391     default:
392       str = "<unknown>";
393       break;
394   }
395   return str;
396 }
397
398 static GstVaapiProfile
399 get_profile (GstVaapiDecoderMpeg2 * decoder, GstVaapiEntrypoint entrypoint)
400 {
401   GstVaapiDisplay *const va_display = GST_VAAPI_DECODER_DISPLAY (decoder);
402   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
403   GstVaapiProfile profile = priv->profile;
404
405   do {
406     /* Return immediately if the exact same profile was found */
407     if (gst_vaapi_display_has_decoder (va_display, profile, entrypoint))
408       break;
409
410     /* Otherwise, try to map to a higher profile */
411     switch (profile) {
412       case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
413         profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
414         break;
415       case GST_VAAPI_PROFILE_MPEG2_MAIN:
416         profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
417         break;
418       case GST_VAAPI_PROFILE_MPEG2_HIGH:
419         // Try to map to main profile if no high profile specific bits used
420         if (priv->profile == profile &&
421             !priv->seq_scalable_ext &&
422             (priv->seq_ext && priv->seq_ext->data.seq_ext.chroma_format == 1)) {
423           profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
424           break;
425         }
426         // fall-through
427       default:
428         profile = GST_VAAPI_PROFILE_UNKNOWN;
429         break;
430     }
431   } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
432
433   if (profile != priv->profile)
434     GST_INFO ("forced %s profile to %s profile",
435         get_profile_str (priv->profile), get_profile_str (profile));
436   return profile;
437 }
438
439 static GstVaapiDecoderStatus
440 ensure_context (GstVaapiDecoderMpeg2 * decoder)
441 {
442   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
443   GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
444   gboolean reset_context = FALSE;
445
446   if (priv->profile_changed) {
447     GST_DEBUG ("profile changed");
448     priv->profile_changed = FALSE;
449     reset_context = TRUE;
450
451     priv->hw_profile = get_profile (decoder, entrypoint);
452     if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
453       return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
454   }
455
456   if (priv->size_changed) {
457     GST_DEBUG ("size changed");
458     priv->size_changed = FALSE;
459     reset_context = TRUE;
460   }
461
462   if (reset_context) {
463     GstVaapiContextInfo info;
464
465     info.profile = priv->hw_profile;
466     info.entrypoint = entrypoint;
467     info.chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
468     info.width = priv->width;
469     info.height = priv->height;
470     info.ref_frames = 2;
471     reset_context =
472         gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER_CAST (decoder),
473         &info);
474     if (!reset_context)
475       return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
476   }
477   return GST_VAAPI_DECODER_STATUS_SUCCESS;
478 }
479
480 static GstVaapiDecoderStatus
481 ensure_quant_matrix (GstVaapiDecoderMpeg2 * decoder, GstVaapiPicture * picture)
482 {
483   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
484   GstMpegVideoSequenceHdr *const seq_hdr = &priv->seq_hdr->data.seq_hdr;
485   VAIQMatrixBufferMPEG2 *iq_matrix;
486   guint8 *intra_quant_matrix = NULL;
487   guint8 *non_intra_quant_matrix = NULL;
488   guint8 *chroma_intra_quant_matrix = NULL;
489   guint8 *chroma_non_intra_quant_matrix = NULL;
490
491   if (!priv->quant_matrix_changed)
492     return GST_VAAPI_DECODER_STATUS_SUCCESS;
493
494   priv->quant_matrix_changed = FALSE;
495
496   picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (MPEG2, decoder);
497   if (!picture->iq_matrix) {
498     GST_ERROR ("failed to allocate IQ matrix");
499     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
500   }
501   iq_matrix = picture->iq_matrix->param;
502
503   intra_quant_matrix = seq_hdr->intra_quantizer_matrix;
504   non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
505
506   if (priv->quant_matrix) {
507     GstMpegVideoQuantMatrixExt *const quant_matrix =
508         &priv->quant_matrix->data.quant_matrix;
509     if (quant_matrix->load_intra_quantiser_matrix)
510       intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
511     if (quant_matrix->load_non_intra_quantiser_matrix)
512       non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
513     if (quant_matrix->load_chroma_intra_quantiser_matrix)
514       chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
515     if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
516       chroma_non_intra_quant_matrix =
517           quant_matrix->chroma_non_intra_quantiser_matrix;
518   }
519
520   iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
521   if (intra_quant_matrix)
522     copy_quant_matrix (iq_matrix->intra_quantiser_matrix, intra_quant_matrix);
523
524   iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
525   if (non_intra_quant_matrix)
526     copy_quant_matrix (iq_matrix->non_intra_quantiser_matrix,
527         non_intra_quant_matrix);
528
529   iq_matrix->load_chroma_intra_quantiser_matrix =
530       chroma_intra_quant_matrix != NULL;
531   if (chroma_intra_quant_matrix)
532     copy_quant_matrix (iq_matrix->chroma_intra_quantiser_matrix,
533         chroma_intra_quant_matrix);
534
535   iq_matrix->load_chroma_non_intra_quantiser_matrix =
536       chroma_non_intra_quant_matrix != NULL;
537   if (chroma_non_intra_quant_matrix)
538     copy_quant_matrix (iq_matrix->chroma_non_intra_quantiser_matrix,
539         chroma_non_intra_quant_matrix);
540   return GST_VAAPI_DECODER_STATUS_SUCCESS;
541 }
542
543 static inline gboolean
544 is_valid_state (GstVaapiDecoderMpeg2 * decoder, guint state)
545 {
546   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
547
548   return (priv->state & state) == state;
549 }
550
551 static GstVaapiDecoderStatus
552 decode_current_picture (GstVaapiDecoderMpeg2 * decoder)
553 {
554   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
555   GstVaapiPicture *const picture = priv->current_picture;
556
557   if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PICTURE))
558     goto drop_frame;
559   priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
560
561   if (!picture)
562     return GST_VAAPI_DECODER_STATUS_SUCCESS;
563
564   if (!gst_vaapi_picture_decode (picture))
565     goto error;
566   if (GST_VAAPI_PICTURE_IS_COMPLETE (picture)) {
567     if (!gst_vaapi_dpb_add (priv->dpb, picture))
568       goto error;
569     gst_vaapi_picture_replace (&priv->current_picture, NULL);
570   }
571   return GST_VAAPI_DECODER_STATUS_SUCCESS;
572
573   /* ERRORS */
574 error:
575   {
576     /* XXX: fix for cases where first field failed to be decoded */
577     gst_vaapi_picture_replace (&priv->current_picture, NULL);
578     return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
579   }
580
581 drop_frame:
582   {
583     priv->state &= GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS;
584     return (GstVaapiDecoderStatus) GST_VAAPI_DECODER_STATUS_DROP_FRAME;
585   }
586 }
587
588 static GstVaapiDecoderStatus
589 parse_sequence (GstVaapiDecoderMpeg2 * decoder,
590     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
591 {
592   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
593   GstMpegVideoSequenceHdr *seq_hdr;
594
595   priv->state = 0;
596
597   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_hdr)) {
598     GST_ERROR ("failed to allocate parser info for sequence header");
599     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
600   }
601
602   seq_hdr = &priv->seq_hdr->data.seq_hdr;
603
604   if (!gst_mpeg_video_packet_parse_sequence_header (packet, seq_hdr)) {
605     GST_ERROR ("failed to parse sequence header");
606     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
607   }
608
609   gst_vaapi_decoder_unit_set_parsed_info (unit, seq_hdr, NULL);
610   return GST_VAAPI_DECODER_STATUS_SUCCESS;
611 }
612
613 static GstVaapiDecoderStatus
614 decode_sequence (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
615 {
616   GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER_CAST (decoder);
617   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
618   GstMpegVideoSequenceHdr *const seq_hdr = unit->parsed_info;
619
620   gst_vaapi_parser_info_mpeg2_replace (&priv->seq_ext, NULL);
621   gst_vaapi_parser_info_mpeg2_replace (&priv->seq_display_ext, NULL);
622   gst_vaapi_parser_info_mpeg2_replace (&priv->seq_scalable_ext, NULL);
623   gst_vaapi_parser_info_mpeg2_replace (&priv->quant_matrix, NULL);
624   gst_vaapi_parser_info_mpeg2_replace (&priv->pic_display_ext, NULL);
625
626   priv->fps_n = seq_hdr->fps_n;
627   priv->fps_d = seq_hdr->fps_d;
628   pts_set_framerate (&priv->tsg, priv->fps_n, priv->fps_d);
629   gst_vaapi_decoder_set_framerate (base_decoder, priv->fps_n, priv->fps_d);
630
631   priv->width = seq_hdr->width;
632   priv->height = seq_hdr->height;
633   priv->size_changed = TRUE;
634   priv->quant_matrix_changed = TRUE;
635   priv->progressive_sequence = TRUE;
636
637   priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
638   return GST_VAAPI_DECODER_STATUS_SUCCESS;
639 }
640
641 static GstVaapiDecoderStatus
642 parse_sequence_ext (GstVaapiDecoderMpeg2 * decoder,
643     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
644 {
645   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
646   GstMpegVideoSequenceExt *seq_ext;
647
648   priv->state &= GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR;
649
650   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_ext)) {
651     GST_ERROR ("failed to allocate parser info for sequence extension");
652     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
653   }
654
655   seq_ext = &priv->seq_ext->data.seq_ext;
656
657   if (!gst_mpeg_video_packet_parse_sequence_extension (packet, seq_ext)) {
658     GST_ERROR ("failed to parse sequence-extension");
659     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
660   }
661
662   gst_vaapi_decoder_unit_set_parsed_info (unit, seq_ext, NULL);
663   return GST_VAAPI_DECODER_STATUS_SUCCESS;
664 }
665
666 static GstVaapiDecoderStatus
667 decode_sequence_ext (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
668 {
669   GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER_CAST (decoder);
670   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
671   GstMpegVideoSequenceExt *const seq_ext = unit->parsed_info;
672   GstVaapiProfile profile;
673   guint width, height;
674
675   if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR))
676     return GST_VAAPI_DECODER_STATUS_SUCCESS;
677
678   priv->progressive_sequence = seq_ext->progressive;
679   gst_vaapi_decoder_set_interlaced (base_decoder, !priv->progressive_sequence);
680
681   width = (priv->width & 0x0fff) | ((guint32) seq_ext->horiz_size_ext << 12);
682   height = (priv->height & 0x0fff) | ((guint32) seq_ext->vert_size_ext << 12);
683   GST_DEBUG ("video resolution %ux%u", width, height);
684
685   if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
686     priv->fps_n *= seq_ext->fps_n_ext + 1;
687     priv->fps_d *= seq_ext->fps_d_ext + 1;
688     pts_set_framerate (&priv->tsg, priv->fps_n, priv->fps_d);
689     gst_vaapi_decoder_set_framerate (base_decoder, priv->fps_n, priv->fps_d);
690   }
691
692   if (priv->width != width) {
693     priv->width = width;
694     priv->size_changed = TRUE;
695   }
696
697   if (priv->height != height) {
698     priv->height = height;
699     priv->size_changed = TRUE;
700   }
701
702   switch (seq_ext->profile) {
703     case GST_MPEG_VIDEO_PROFILE_SIMPLE:
704       profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
705       break;
706     case GST_MPEG_VIDEO_PROFILE_MAIN:
707       profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
708       break;
709     case GST_MPEG_VIDEO_PROFILE_HIGH:
710       profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
711       break;
712     default:
713       GST_ERROR ("unsupported profile %d", seq_ext->profile);
714       return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
715   }
716   if (priv->profile != profile) {
717     priv->profile = profile;
718     priv->profile_changed = TRUE;
719   }
720
721   priv->state |= GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT;
722   return GST_VAAPI_DECODER_STATUS_SUCCESS;
723 }
724
725 static GstVaapiDecoderStatus
726 parse_sequence_display_ext (GstVaapiDecoderMpeg2 * decoder,
727     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
728 {
729   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
730   GstMpegVideoSequenceDisplayExt *seq_display_ext;
731
732   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_display_ext)) {
733     GST_ERROR ("failed to allocate parser info for sequence display extension");
734     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
735   }
736
737   seq_display_ext = &priv->seq_display_ext->data.seq_display_ext;
738
739   if (!gst_mpeg_video_packet_parse_sequence_display_extension (packet,
740           seq_display_ext)) {
741     GST_ERROR ("failed to parse sequence-display-extension");
742     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
743   }
744
745   gst_vaapi_decoder_unit_set_parsed_info (unit, seq_display_ext, NULL);
746   return GST_VAAPI_DECODER_STATUS_SUCCESS;
747 }
748
749 static GstVaapiDecoderStatus
750 decode_sequence_display_ext (GstVaapiDecoderMpeg2 * decoder,
751     GstVaapiDecoderUnit * unit)
752 {
753   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
754   GstMpegVideoSequenceDisplayExt *seq_display_ext;
755
756   seq_display_ext = priv->seq_display_ext ?
757       &priv->seq_display_ext->data.seq_display_ext : NULL;
758
759   /* Update cropping rectangle */
760   if (seq_display_ext) {
761     GstVaapiRectangle *const crop_rect = &priv->crop_rect;
762     crop_rect->x = 0;
763     crop_rect->y = 0;
764     crop_rect->width = seq_display_ext->display_horizontal_size;
765     crop_rect->height = seq_display_ext->display_vertical_size;
766   }
767
768   /* XXX: handle color primaries */
769   return GST_VAAPI_DECODER_STATUS_SUCCESS;
770 }
771
772 static GstVaapiDecoderStatus
773 parse_sequence_scalable_ext (GstVaapiDecoderMpeg2 * decoder,
774     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
775 {
776   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
777   GstMpegVideoSequenceScalableExt *seq_scalable_ext;
778
779   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->seq_scalable_ext)) {
780     GST_ERROR
781         ("failed to allocate parser info for sequence scalable extension");
782     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
783   }
784
785   seq_scalable_ext = &priv->seq_scalable_ext->data.seq_scalable_ext;
786
787   if (!gst_mpeg_video_packet_parse_sequence_scalable_extension (packet,
788           seq_scalable_ext)) {
789     GST_ERROR ("failed to parse sequence-scalable-extension");
790     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
791   }
792
793   gst_vaapi_decoder_unit_set_parsed_info (unit, seq_scalable_ext, NULL);
794   return GST_VAAPI_DECODER_STATUS_SUCCESS;
795 }
796
797 static GstVaapiDecoderStatus
798 decode_sequence_scalable_ext (GstVaapiDecoderMpeg2 * decoder,
799     GstVaapiDecoderUnit * unit)
800 {
801   /* XXX: unsupported header -- ignore */
802   return GST_VAAPI_DECODER_STATUS_SUCCESS;
803 }
804
805 static GstVaapiDecoderStatus
806 decode_sequence_end (GstVaapiDecoderMpeg2 * decoder)
807 {
808   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
809
810   if (priv->dpb)
811     gst_vaapi_dpb_flush (priv->dpb);
812   return GST_VAAPI_DECODER_STATUS_SUCCESS;
813 }
814
815 static GstVaapiDecoderStatus
816 parse_quant_matrix_ext (GstVaapiDecoderMpeg2 * decoder,
817     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
818 {
819   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
820   GstMpegVideoQuantMatrixExt *quant_matrix;
821
822   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->quant_matrix)) {
823     GST_ERROR ("failed to allocate parser info for quantization matrix");
824     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
825   }
826
827   quant_matrix = &priv->quant_matrix->data.quant_matrix;
828
829   if (!gst_mpeg_video_packet_parse_quant_matrix_extension (packet,
830           quant_matrix)) {
831     GST_ERROR ("failed to parse quant-matrix-extension");
832     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
833   }
834
835   gst_vaapi_decoder_unit_set_parsed_info (unit, quant_matrix, NULL);
836   return GST_VAAPI_DECODER_STATUS_SUCCESS;
837 }
838
839 static GstVaapiDecoderStatus
840 decode_quant_matrix_ext (GstVaapiDecoderMpeg2 * decoder,
841     GstVaapiDecoderUnit * unit)
842 {
843   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
844
845   priv->quant_matrix_changed = TRUE;
846   return GST_VAAPI_DECODER_STATUS_SUCCESS;
847 }
848
849 static GstVaapiDecoderStatus
850 parse_gop (GstVaapiDecoderMpeg2 * decoder,
851     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
852 {
853   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
854   GstMpegVideoGop *gop;
855
856   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->gop)) {
857     GST_ERROR ("failed to allocate parser info for GOP");
858     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
859   }
860
861   gop = &priv->gop->data.gop;
862
863   if (!gst_mpeg_video_packet_parse_gop (packet, gop)) {
864     GST_ERROR ("failed to parse GOP");
865     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
866   }
867
868   gst_vaapi_decoder_unit_set_parsed_info (unit, gop, NULL);
869   return GST_VAAPI_DECODER_STATUS_SUCCESS;
870 }
871
872 static GstVaapiDecoderStatus
873 decode_gop (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
874 {
875   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
876   GstMpegVideoGop *const gop = unit->parsed_info;
877
878   priv->closed_gop = gop->closed_gop;
879   priv->broken_link = gop->broken_link;
880
881   GST_DEBUG ("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
882       gop->hour, gop->minute, gop->second, gop->frame,
883       priv->closed_gop, priv->broken_link);
884
885   pts_sync (&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts);
886   return GST_VAAPI_DECODER_STATUS_SUCCESS;
887 }
888
889 static GstVaapiDecoderStatus
890 parse_picture (GstVaapiDecoderMpeg2 * decoder,
891     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
892 {
893   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
894   GstMpegVideoPictureHdr *pic_hdr;
895
896   priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
897       GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT);
898
899   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->pic_hdr)) {
900     GST_ERROR ("failed to allocate parser info for picture header");
901     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
902   }
903
904   pic_hdr = &priv->pic_hdr->data.pic_hdr;
905
906   if (!gst_mpeg_video_packet_parse_picture_header (packet, pic_hdr)) {
907     GST_ERROR ("failed to parse picture header");
908     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
909   }
910
911   gst_vaapi_decoder_unit_set_parsed_info (unit, pic_hdr, NULL);
912   return GST_VAAPI_DECODER_STATUS_SUCCESS;
913 }
914
915 static GstVaapiDecoderStatus
916 decode_picture (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
917 {
918   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
919
920   if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_SEQ_HEADERS))
921     return GST_VAAPI_DECODER_STATUS_SUCCESS;
922
923   gst_vaapi_parser_info_mpeg2_replace (&priv->pic_ext, NULL);
924
925   priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_HDR;
926   return GST_VAAPI_DECODER_STATUS_SUCCESS;
927 }
928
929 static GstVaapiDecoderStatus
930 parse_picture_ext (GstVaapiDecoderMpeg2 * decoder,
931     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
932 {
933   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
934   GstMpegVideoPictureExt *pic_ext;
935
936   priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
937       GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT | GST_MPEG_VIDEO_STATE_GOT_PIC_HDR);
938
939   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->pic_ext)) {
940     GST_ERROR ("failed to allocate parser info for picture extension");
941     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
942   }
943
944   pic_ext = &priv->pic_ext->data.pic_ext;
945
946   if (!gst_mpeg_video_packet_parse_picture_extension (packet, pic_ext)) {
947     GST_ERROR ("failed to parse picture-extension");
948     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
949   }
950
951   gst_vaapi_decoder_unit_set_parsed_info (unit, pic_ext, NULL);
952   return GST_VAAPI_DECODER_STATUS_SUCCESS;
953 }
954
955 static GstVaapiDecoderStatus
956 decode_picture_ext (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
957 {
958   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
959   GstMpegVideoPictureExt *const pic_ext = unit->parsed_info;
960
961   if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_GOT_PIC_HDR))
962     return GST_VAAPI_DECODER_STATUS_SUCCESS;
963
964   if (priv->progressive_sequence && !pic_ext->progressive_frame) {
965     GST_WARNING ("invalid interlaced frame in progressive sequence, fixing");
966     pic_ext->progressive_frame = 1;
967   }
968
969   if (pic_ext->picture_structure == 0 ||
970       (pic_ext->progressive_frame &&
971           pic_ext->picture_structure !=
972           GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
973     GST_WARNING ("invalid picture_structure %d, replacing with \"frame\"",
974         pic_ext->picture_structure);
975     pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
976   }
977
978   priv->state |= GST_MPEG_VIDEO_STATE_GOT_PIC_EXT;
979   return GST_VAAPI_DECODER_STATUS_SUCCESS;
980 }
981
982 static inline guint32
983 pack_f_code (guint8 f_code[2][2])
984 {
985   return (((guint32) f_code[0][0] << 12) |
986       ((guint32) f_code[0][1] << 8) |
987       ((guint32) f_code[1][0] << 4) | (f_code[1][1]));
988 }
989
990 static GstVaapiDecoderStatus
991 init_picture (GstVaapiDecoderMpeg2 * decoder, GstVaapiPicture * picture)
992 {
993   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
994   GstMpegVideoPictureHdr *const pic_hdr = &priv->pic_hdr->data.pic_hdr;
995   GstMpegVideoPictureExt *const pic_ext = &priv->pic_ext->data.pic_ext;
996
997   switch (pic_hdr->pic_type) {
998     case GST_MPEG_VIDEO_PICTURE_TYPE_I:
999       GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
1000       picture->type = GST_VAAPI_PICTURE_TYPE_I;
1001       break;
1002     case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1003       GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
1004       picture->type = GST_VAAPI_PICTURE_TYPE_P;
1005       break;
1006     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1007       picture->type = GST_VAAPI_PICTURE_TYPE_B;
1008       break;
1009     default:
1010       GST_ERROR ("unsupported picture type %d", pic_hdr->pic_type);
1011       return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1012   }
1013
1014   if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
1015     GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
1016     if (pic_ext->top_field_first)
1017       GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_TFF);
1018   }
1019
1020   switch (pic_ext->picture_structure) {
1021     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
1022       picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
1023       break;
1024     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
1025       picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
1026       break;
1027     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
1028       picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1029       break;
1030   }
1031
1032   /* Allocate dummy picture for first field based I-frame */
1033   if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
1034       !GST_VAAPI_PICTURE_IS_FRAME (picture) &&
1035       gst_vaapi_dpb_size (priv->dpb) == 0) {
1036     GstVaapiPicture *dummy_picture;
1037     gboolean success;
1038
1039     dummy_picture = GST_VAAPI_PICTURE_NEW (MPEG2, decoder);
1040     if (!dummy_picture) {
1041       GST_ERROR ("failed to allocate dummy picture");
1042       return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1043     }
1044
1045     dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I;
1046     dummy_picture->pts = GST_CLOCK_TIME_NONE;
1047     dummy_picture->poc = -1;
1048     dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
1049
1050     GST_VAAPI_PICTURE_FLAG_SET (dummy_picture,
1051         (GST_VAAPI_PICTURE_FLAG_SKIPPED |
1052             GST_VAAPI_PICTURE_FLAG_OUTPUT | GST_VAAPI_PICTURE_FLAG_REFERENCE)
1053         );
1054
1055     success = gst_vaapi_dpb_add (priv->dpb, dummy_picture);
1056     gst_vaapi_picture_unref (dummy_picture);
1057     if (!success) {
1058       GST_ERROR ("failed to add dummy picture into DPB");
1059       return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1060     }
1061     GST_INFO ("allocated dummy picture for first field based I-frame");
1062   }
1063
1064   /* Update presentation time */
1065   picture->pts = pts_eval (&priv->tsg,
1066       GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts, pic_hdr->tsn);
1067   picture->poc = pts_get_poc (&priv->tsg);
1068   return GST_VAAPI_DECODER_STATUS_SUCCESS;
1069 }
1070
1071 static void
1072 fill_picture (GstVaapiDecoderMpeg2 * decoder, GstVaapiPicture * picture)
1073 {
1074   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1075   VAPictureParameterBufferMPEG2 *const pic_param = picture->param;
1076   GstMpegVideoPictureHdr *const pic_hdr = &priv->pic_hdr->data.pic_hdr;
1077   GstMpegVideoPictureExt *const pic_ext = &priv->pic_ext->data.pic_ext;
1078   GstVaapiPicture *prev_picture, *next_picture;
1079
1080   /* Fill in VAPictureParameterBufferMPEG2 */
1081   pic_param->horizontal_size = priv->width;
1082   pic_param->vertical_size = priv->height;
1083   pic_param->forward_reference_picture = VA_INVALID_ID;
1084   pic_param->backward_reference_picture = VA_INVALID_ID;
1085   pic_param->picture_coding_type = pic_hdr->pic_type;
1086   pic_param->f_code = pack_f_code (pic_ext->f_code);
1087
1088 #define COPY_FIELD(a, b, f) \
1089     pic_param->a.b.f = pic_ext->f
1090   pic_param->picture_coding_extension.value = 0;
1091   pic_param->picture_coding_extension.bits.is_first_field =
1092       GST_VAAPI_PICTURE_IS_FIRST_FIELD (picture);
1093   COPY_FIELD (picture_coding_extension, bits, intra_dc_precision);
1094   COPY_FIELD (picture_coding_extension, bits, picture_structure);
1095   COPY_FIELD (picture_coding_extension, bits, top_field_first);
1096   COPY_FIELD (picture_coding_extension, bits, frame_pred_frame_dct);
1097   COPY_FIELD (picture_coding_extension, bits, concealment_motion_vectors);
1098   COPY_FIELD (picture_coding_extension, bits, q_scale_type);
1099   COPY_FIELD (picture_coding_extension, bits, intra_vlc_format);
1100   COPY_FIELD (picture_coding_extension, bits, alternate_scan);
1101   COPY_FIELD (picture_coding_extension, bits, repeat_first_field);
1102   COPY_FIELD (picture_coding_extension, bits, progressive_frame);
1103
1104   gst_vaapi_dpb_get_neighbours (priv->dpb, picture,
1105       &prev_picture, &next_picture);
1106
1107   switch (pic_hdr->pic_type) {
1108     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1109       if (next_picture)
1110         pic_param->backward_reference_picture = next_picture->surface_id;
1111       if (prev_picture)
1112         pic_param->forward_reference_picture = prev_picture->surface_id;
1113       else if (!priv->closed_gop)
1114         GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1115       break;
1116     case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1117       if (prev_picture)
1118         pic_param->forward_reference_picture = prev_picture->surface_id;
1119       break;
1120   }
1121 }
1122
1123 static GstVaapiDecoderStatus
1124 parse_slice (GstVaapiDecoderMpeg2 * decoder,
1125     GstVaapiDecoderUnit * unit, const GstMpegVideoPacket * packet)
1126 {
1127   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1128   GstMpegVideoSliceHdr *slice_hdr;
1129   GstMpegVideoSequenceHdr *seq_hdr;
1130   GstMpegVideoSequenceScalableExt *seq_scalable_ext;
1131
1132   priv->state &= (GST_MPEG_VIDEO_STATE_GOT_SEQ_HDR |
1133       GST_MPEG_VIDEO_STATE_GOT_SEQ_EXT |
1134       GST_MPEG_VIDEO_STATE_GOT_PIC_HDR | GST_MPEG_VIDEO_STATE_GOT_PIC_EXT);
1135
1136   if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1137     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1138
1139   if (!gst_vaapi_parser_info_mpeg2_ensure (&priv->slice_hdr)) {
1140     GST_ERROR ("failed to allocate parser info for slice header");
1141     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1142   }
1143
1144   slice_hdr = &priv->slice_hdr->data.slice_hdr;
1145   seq_hdr = &priv->seq_hdr->data.seq_hdr;
1146   seq_scalable_ext = priv->seq_scalable_ext ?
1147       &priv->seq_scalable_ext->data.seq_scalable_ext : NULL;
1148
1149   if (!gst_mpeg_video_packet_parse_slice_header (packet, slice_hdr,
1150           seq_hdr, seq_scalable_ext)) {
1151     GST_ERROR ("failed to parse slice header");
1152     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1153   }
1154
1155   gst_vaapi_decoder_unit_set_parsed_info (unit, slice_hdr, NULL);
1156   return GST_VAAPI_DECODER_STATUS_SUCCESS;
1157 }
1158
1159 static GstVaapiDecoderStatus
1160 decode_slice (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit)
1161 {
1162   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1163   GstVaapiPicture *const picture = priv->current_picture;
1164   GstVaapiSlice *slice;
1165   VASliceParameterBufferMPEG2 *slice_param;
1166   GstMpegVideoSliceHdr *const slice_hdr = unit->parsed_info;
1167   GstBuffer *const buffer =
1168       GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
1169   GstMapInfo map_info;
1170
1171   if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1172     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1173
1174   if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
1175     GST_ERROR ("failed to map buffer");
1176     return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1177   }
1178
1179   GST_DEBUG ("slice %d (%u bytes)", slice_hdr->mb_row, unit->size);
1180
1181   slice = GST_VAAPI_SLICE_NEW (MPEG2, decoder,
1182       (map_info.data + unit->offset), unit->size);
1183   gst_buffer_unmap (buffer, &map_info);
1184   if (!slice) {
1185     GST_ERROR ("failed to allocate slice");
1186     return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1187   }
1188   gst_vaapi_picture_add_slice (picture, slice);
1189
1190   /* Fill in VASliceParameterBufferMPEG2 */
1191   slice_param = slice->param;
1192   slice_param->macroblock_offset = slice_hdr->header_size + 32;
1193   slice_param->slice_horizontal_position = slice_hdr->mb_column;
1194   slice_param->slice_vertical_position = slice_hdr->mb_row;
1195   slice_param->quantiser_scale_code = slice_hdr->quantiser_scale_code;
1196   slice_param->intra_slice_flag = slice_hdr->intra_slice;
1197
1198   priv->state |= GST_MPEG_VIDEO_STATE_GOT_SLICE;
1199   return GST_VAAPI_DECODER_STATUS_SUCCESS;
1200 }
1201
1202 static inline gint
1203 scan_for_start_code (const guchar * buf, guint buf_size,
1204     GstMpegVideoPacketTypeCode * type_ptr)
1205 {
1206   guint i = 0;
1207
1208   while (i <= (buf_size - 4)) {
1209     if (buf[i + 2] > 1)
1210       i += 3;
1211     else if (buf[i + 1])
1212       i += 2;
1213     else if (buf[i] || buf[i + 2] != 1)
1214       i++;
1215     else
1216       break;
1217   }
1218
1219   if (i <= (buf_size - 4)) {
1220     if (type_ptr)
1221       *type_ptr = buf[i + 3];
1222     return i;
1223   }
1224   return -1;
1225 }
1226
1227 static GstVaapiDecoderStatus
1228 parse_unit (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit,
1229     GstMpegVideoPacket * packet)
1230 {
1231   GstMpegVideoPacketTypeCode type;
1232   GstMpegVideoPacketExtensionCode ext_type;
1233   GstVaapiDecoderStatus status;
1234
1235   type = packet->type;
1236   switch (type) {
1237     case GST_MPEG_VIDEO_PACKET_PICTURE:
1238       status = parse_picture (decoder, unit, packet);
1239       break;
1240     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1241       status = parse_sequence (decoder, unit, packet);
1242       break;
1243     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1244       ext_type = packet->data[4] >> 4;
1245       switch (ext_type) {
1246         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1247           status = parse_sequence_ext (decoder, unit, packet);
1248           break;
1249         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1250           status = parse_sequence_display_ext (decoder, unit, packet);
1251           break;
1252         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1253           status = parse_sequence_scalable_ext (decoder, unit, packet);
1254           break;
1255         case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1256           status = parse_quant_matrix_ext (decoder, unit, packet);
1257           break;
1258         case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1259           status = parse_picture_ext (decoder, unit, packet);
1260           break;
1261         default:
1262           status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1263           break;
1264       }
1265       break;
1266     case GST_MPEG_VIDEO_PACKET_GOP:
1267       status = parse_gop (decoder, unit, packet);
1268       break;
1269     default:
1270       if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1271           type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1272         status = parse_slice (decoder, unit, packet);
1273         break;
1274       }
1275       status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1276       break;
1277   }
1278   return status;
1279 }
1280
1281 static GstVaapiDecoderStatus
1282 decode_unit (GstVaapiDecoderMpeg2 * decoder, GstVaapiDecoderUnit * unit,
1283     GstMpegVideoPacket * packet)
1284 {
1285   GstMpegVideoPacketTypeCode type;
1286   GstMpegVideoPacketExtensionCode ext_type;
1287   GstVaapiDecoderStatus status;
1288
1289   type = packet->type;
1290   switch (type) {
1291     case GST_MPEG_VIDEO_PACKET_PICTURE:
1292       status = decode_picture (decoder, unit);
1293       break;
1294     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1295       status = decode_sequence (decoder, unit);
1296       break;
1297     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1298       ext_type = packet->data[4] >> 4;
1299       switch (ext_type) {
1300         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1301           status = decode_sequence_ext (decoder, unit);
1302           break;
1303         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1304           status = decode_sequence_display_ext (decoder, unit);
1305           break;
1306         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_SCALABLE:
1307           status = decode_sequence_scalable_ext (decoder, unit);
1308           break;
1309         case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1310           status = decode_quant_matrix_ext (decoder, unit);
1311           break;
1312         case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1313           status = decode_picture_ext (decoder, unit);
1314           break;
1315         default:
1316           // Ignore unknown start-code extensions
1317           GST_WARNING ("unsupported packet extension type 0x%02x", ext_type);
1318           status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1319           break;
1320       }
1321       break;
1322     case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1323       status = decode_sequence_end (decoder);
1324       break;
1325     case GST_MPEG_VIDEO_PACKET_GOP:
1326       status = decode_gop (decoder, unit);
1327       break;
1328     default:
1329       if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1330           type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1331         status = decode_slice (decoder, unit);
1332         break;
1333       }
1334       GST_WARNING ("unsupported packet type 0x%02x", type);
1335       status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1336       break;
1337   }
1338   return status;
1339 }
1340
1341 static GstVaapiDecoderStatus
1342 ensure_decoder (GstVaapiDecoderMpeg2 * decoder)
1343 {
1344   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1345
1346   if (!priv->is_opened) {
1347     priv->is_opened = gst_vaapi_decoder_mpeg2_open (decoder);
1348     if (!priv->is_opened)
1349       return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1350   }
1351   return GST_VAAPI_DECODER_STATUS_SUCCESS;
1352 }
1353
1354 static GstVaapiDecoderStatus
1355 gst_vaapi_decoder_mpeg2_parse (GstVaapiDecoder * base_decoder,
1356     GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
1357 {
1358   GstVaapiDecoderMpeg2 *const decoder =
1359       GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1360   GstVaapiParserState *const ps = GST_VAAPI_PARSER_STATE (base_decoder);
1361   GstVaapiDecoderStatus status;
1362   GstMpegVideoPacketTypeCode type, type2 = GST_MPEG_VIDEO_PACKET_NONE;
1363   const guchar *buf;
1364   guint buf_size, flags;
1365   gint ofs, ofs1, ofs2;
1366
1367   status = ensure_decoder (decoder);
1368   if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1369     return status;
1370
1371   buf_size = gst_adapter_available (adapter);
1372   if (buf_size < 4)
1373     return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1374
1375   buf = gst_adapter_map (adapter, buf_size);
1376   if (!buf)
1377     return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1378
1379   ofs = scan_for_start_code (buf, buf_size, &type);
1380   if (ofs < 0)
1381     return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1382   ofs1 = ofs;
1383
1384   ofs2 = ps->input_offset2 - 4;
1385   if (ofs2 < ofs1 + 4)
1386     ofs2 = ofs1 + 4;
1387
1388   ofs = G_UNLIKELY (buf_size < ofs2 + 4) ? -1 :
1389       scan_for_start_code (&buf[ofs2], buf_size - ofs2, &type2);
1390   if (ofs < 0) {
1391     // Assume the whole packet is present if end-of-stream
1392     if (!at_eos) {
1393       ps->input_offset2 = buf_size;
1394       return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1395     }
1396     ofs = buf_size - ofs2;
1397   }
1398   ofs2 += ofs;
1399
1400   unit->size = ofs2 - ofs1;
1401   gst_adapter_flush (adapter, ofs1);
1402   ps->input_offset2 = 4;
1403
1404   /* Check for start of new picture */
1405   flags = 0;
1406   switch (type) {
1407     case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1408       flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1409       flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1410       break;
1411     case GST_MPEG_VIDEO_PACKET_USER_DATA:
1412       flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1413       /* fall-through */
1414     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1415     case GST_MPEG_VIDEO_PACKET_GOP:
1416     case GST_MPEG_VIDEO_PACKET_PICTURE:
1417       flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1418       break;
1419     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1420       if (G_UNLIKELY (unit->size < 5))
1421         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1422       break;
1423     default:
1424       if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1425           type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1426         flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1427         switch (type2) {
1428           case GST_MPEG_VIDEO_PACKET_USER_DATA:
1429           case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1430           case GST_MPEG_VIDEO_PACKET_GOP:
1431           case GST_MPEG_VIDEO_PACKET_PICTURE:
1432             flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1433             break;
1434           default:
1435             break;
1436         }
1437       }
1438       // Ignore system start codes (PES headers)
1439       else if (type >= 0xb9 && type <= 0xff)
1440         flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1441       break;
1442   }
1443   GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
1444   return GST_VAAPI_DECODER_STATUS_SUCCESS;
1445 }
1446
1447 static GstVaapiDecoderStatus
1448 gst_vaapi_decoder_mpeg2_decode (GstVaapiDecoder * base_decoder,
1449     GstVaapiDecoderUnit * unit)
1450 {
1451   GstVaapiDecoderMpeg2 *const decoder =
1452       GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1453   GstVaapiDecoderStatus status;
1454   GstMpegVideoPacket packet;
1455   GstBuffer *const buffer =
1456       GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
1457   GstMapInfo map_info;
1458
1459   status = ensure_decoder (decoder);
1460   if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1461     return status;
1462
1463   if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
1464     GST_ERROR ("failed to map buffer");
1465     return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1466   }
1467
1468   packet.data = map_info.data + unit->offset;
1469   packet.size = unit->size;
1470   packet.type = packet.data[3];
1471   packet.offset = 4;
1472
1473   status = parse_unit (decoder, unit, &packet);
1474   gst_buffer_unmap (buffer, &map_info);
1475   if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1476     return status;
1477   return decode_unit (decoder, unit, &packet);
1478 }
1479
1480 static GstVaapiDecoderStatus
1481 gst_vaapi_decoder_mpeg2_start_frame (GstVaapiDecoder * base_decoder,
1482     GstVaapiDecoderUnit * base_unit)
1483 {
1484   GstVaapiDecoderMpeg2 *const decoder =
1485       GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1486   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1487   GstMpegVideoSequenceHdr *seq_hdr;
1488   GstMpegVideoSequenceExt *seq_ext;
1489   GstMpegVideoSequenceDisplayExt *seq_display_ext;
1490   GstVaapiPicture *picture;
1491   GstVaapiDecoderStatus status;
1492
1493   if (!is_valid_state (decoder, GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS))
1494     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1495   priv->state &= ~GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1496
1497   seq_hdr = &priv->seq_hdr->data.seq_hdr;
1498   seq_ext = priv->seq_ext ? &priv->seq_ext->data.seq_ext : NULL;
1499   seq_display_ext = priv->seq_display_ext ?
1500       &priv->seq_display_ext->data.seq_display_ext : NULL;
1501   if (gst_mpeg_video_finalise_mpeg2_sequence_header (seq_hdr, seq_ext,
1502           seq_display_ext))
1503     gst_vaapi_decoder_set_pixel_aspect_ratio (base_decoder,
1504         seq_hdr->par_w, seq_hdr->par_h);
1505
1506   status = ensure_context (decoder);
1507   if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1508     GST_ERROR ("failed to reset context");
1509     return status;
1510   }
1511
1512   if (priv->current_picture) {
1513     /* Re-use current picture where the first field was decoded */
1514     picture = gst_vaapi_picture_new_field (priv->current_picture);
1515     if (!picture) {
1516       GST_ERROR ("failed to allocate field picture");
1517       return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1518     }
1519   } else {
1520     /* Create new picture */
1521     picture = GST_VAAPI_PICTURE_NEW (MPEG2, decoder);
1522     if (!picture) {
1523       GST_ERROR ("failed to allocate picture");
1524       return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1525     }
1526   }
1527   gst_vaapi_picture_replace (&priv->current_picture, picture);
1528   gst_vaapi_picture_unref (picture);
1529
1530   /* Update cropping rectangle */
1531   /* XXX: handle picture_display_extension() */
1532   if (seq_display_ext && priv->pic_display_ext) {
1533     GstVaapiRectangle *const crop_rect = &priv->crop_rect;
1534     if (crop_rect->x + crop_rect->width <= priv->width &&
1535         crop_rect->y + crop_rect->height <= priv->height)
1536       gst_vaapi_picture_set_crop_rect (picture, crop_rect);
1537   }
1538
1539   status = ensure_quant_matrix (decoder, picture);
1540   if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1541     GST_ERROR ("failed to reset quantizer matrix");
1542     return status;
1543   }
1544
1545   status = init_picture (decoder, picture);
1546   if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1547     return status;
1548
1549   fill_picture (decoder, picture);
1550
1551   priv->state |= GST_MPEG_VIDEO_STATE_VALID_PIC_HEADERS;
1552   return GST_VAAPI_DECODER_STATUS_SUCCESS;
1553 }
1554
1555 static GstVaapiDecoderStatus
1556 gst_vaapi_decoder_mpeg2_end_frame (GstVaapiDecoder * base_decoder)
1557 {
1558   GstVaapiDecoderMpeg2 *const decoder =
1559       GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1560
1561   return decode_current_picture (decoder);
1562 }
1563
1564 static GstVaapiDecoderStatus
1565 gst_vaapi_decoder_mpeg2_flush (GstVaapiDecoder * base_decoder)
1566 {
1567   GstVaapiDecoderMpeg2 *const decoder =
1568       GST_VAAPI_DECODER_MPEG2_CAST (base_decoder);
1569   GstVaapiDecoderMpeg2Private *const priv = &decoder->priv;
1570
1571   if (priv->dpb)
1572     gst_vaapi_dpb_flush (priv->dpb);
1573   return GST_VAAPI_DECODER_STATUS_SUCCESS;
1574 }
1575
1576 static void
1577 gst_vaapi_decoder_mpeg2_finalize (GObject * object)
1578 {
1579   GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (object);
1580
1581   gst_vaapi_decoder_mpeg2_destroy (base_decoder);
1582   G_OBJECT_CLASS (gst_vaapi_decoder_mpeg2_parent_class)->finalize (object);
1583 }
1584
1585 static void
1586 gst_vaapi_decoder_mpeg2_class_init (GstVaapiDecoderMpeg2Class * klass)
1587 {
1588   GObjectClass *const object_class = G_OBJECT_CLASS (klass);
1589   GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
1590
1591   object_class->finalize = gst_vaapi_decoder_mpeg2_finalize;
1592
1593   decoder_class->reset = gst_vaapi_decoder_mpeg2_reset;
1594   decoder_class->parse = gst_vaapi_decoder_mpeg2_parse;
1595   decoder_class->decode = gst_vaapi_decoder_mpeg2_decode;
1596   decoder_class->start_frame = gst_vaapi_decoder_mpeg2_start_frame;
1597   decoder_class->end_frame = gst_vaapi_decoder_mpeg2_end_frame;
1598   decoder_class->flush = gst_vaapi_decoder_mpeg2_flush;
1599 }
1600
1601 static void
1602 gst_vaapi_decoder_mpeg2_init (GstVaapiDecoderMpeg2 * decoder)
1603 {
1604   GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (decoder);
1605
1606   gst_vaapi_decoder_mpeg2_create (base_decoder);
1607 }
1608
1609 /**
1610  * gst_vaapi_decoder_mpeg2_new:
1611  * @display: a #GstVaapiDisplay
1612  * @caps: a #GstCaps holding codec information
1613  *
1614  * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
1615  * hold extra information like codec-data and pictured coded size.
1616  *
1617  * Return value: the newly allocated #GstVaapiDecoder object
1618  */
1619 GstVaapiDecoder *
1620 gst_vaapi_decoder_mpeg2_new (GstVaapiDisplay * display, GstCaps * caps)
1621 {
1622   return g_object_new (GST_TYPE_VAAPI_DECODER_MPEG2, "display", display,
1623       "caps", caps, NULL);
1624 }