mpeg2: minor clean-ups.
[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 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 /* --- VLC Reader                                                        --- */
43 /* ------------------------------------------------------------------------- */
44
45 #define READ_UINT8(br, val, nbits) G_STMT_START {  \
46   if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
47     GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
48     goto failed; \
49   } \
50 } G_STMT_END
51
52 #define SKIP(reader, nbits) G_STMT_START { \
53   if (!gst_bit_reader_skip (reader, nbits)) { \
54     GST_WARNING ("failed to skip nbits: %d", nbits); \
55     goto failed; \
56   } \
57 } G_STMT_END
58
59 /* VLC decoder from gst-plugins-bad */
60 typedef struct _VLCTable VLCTable;
61 struct _VLCTable {
62     gint  value;
63     guint cword;
64     guint cbits;
65 };
66
67 static gboolean
68 decode_vlc(GstBitReader *br, gint *res, const VLCTable *table, guint length)
69 {
70     guint8 i;
71     guint cbits = 0;
72     guint32 value = 0;
73
74     for (i = 0; i < length; i++) {
75         if (cbits != table[i].cbits) {
76             cbits = table[i].cbits;
77             if (!gst_bit_reader_peek_bits_uint32(br, &value, cbits)) {
78                 goto failed;
79             }
80         }
81
82         if (value == table[i].cword) {
83             SKIP(br, cbits);
84             if (res)
85                 *res = table[i].value;
86             return TRUE;
87         }
88     }
89     GST_DEBUG("failed to find VLC code");
90
91 failed:
92     GST_WARNING("failed to decode VLC, returning");
93     return FALSE;
94 }
95
96 enum {
97     GST_MPEG_VIDEO_MACROBLOCK_ESCAPE = -1,
98 };
99
100 /* Table B-1: Variable length codes for macroblock_address_increment */
101 static const VLCTable mpeg2_mbaddr_vlc_table[] = {
102     {  1, 0x01,  1 },
103     {  2, 0x03,  3 },
104     {  3, 0x02,  3 },
105     {  4, 0x03,  4 },
106     {  5, 0x02,  4 },
107     {  6, 0x03,  5 },
108     {  7, 0x02,  5 },
109     {  8, 0x07,  7 },
110     {  9, 0x06,  7 },
111     { 10, 0x0b,  8 },
112     { 11, 0x0a,  8 },
113     { 12, 0x09,  8 },
114     { 13, 0x08,  8 },
115     { 14, 0x07,  8 },
116     { 15, 0x06,  8 },
117     { 16, 0x17, 10 },
118     { 17, 0x16, 10 },
119     { 18, 0x15, 10 },
120     { 19, 0x14, 10 },
121     { 20, 0x13, 10 },
122     { 21, 0x12, 10 },
123     { 22, 0x23, 11 },
124     { 23, 0x22, 11 },
125     { 24, 0x21, 11 },
126     { 25, 0x20, 11 },
127     { 26, 0x1f, 11 },
128     { 27, 0x1e, 11 },
129     { 28, 0x1d, 11 },
130     { 29, 0x1c, 11 },
131     { 30, 0x1b, 11 },
132     { 31, 0x1a, 11 },
133     { 32, 0x19, 11 },
134     { 33, 0x18, 11 },
135     { GST_MPEG_VIDEO_MACROBLOCK_ESCAPE, 0x08, 11 }
136 };
137
138 /* ------------------------------------------------------------------------- */
139 /* --- PTS Generator                                                     --- */
140 /* ------------------------------------------------------------------------- */
141
142 typedef struct _PTSGenerator PTSGenerator;
143 struct _PTSGenerator {
144     GstClockTime        gop_pts; // Current GOP PTS
145     GstClockTime        max_pts; // Max picture PTS
146     guint               gop_tsn; // Absolute GOP TSN
147     guint               max_tsn; // Max picture TSN, relative to last GOP TSN
148     guint               ovl_tsn; // How many times TSN overflowed since GOP
149     guint               lst_tsn; // Last picture TSN
150     guint               fps_n;
151     guint               fps_d;
152 };
153
154 static void
155 pts_init(PTSGenerator *tsg)
156 {
157     tsg->gop_pts = GST_CLOCK_TIME_NONE;
158     tsg->max_pts = GST_CLOCK_TIME_NONE;
159     tsg->gop_tsn = 0;
160     tsg->max_tsn = 0;
161     tsg->ovl_tsn = 0;
162     tsg->lst_tsn = 0;
163     tsg->fps_n   = 0;
164     tsg->fps_d   = 0;
165 }
166
167 static inline GstClockTime
168 pts_get_duration(PTSGenerator *tsg, guint num_frames)
169 {
170     return gst_util_uint64_scale(num_frames,
171                                  GST_SECOND * tsg->fps_d, tsg->fps_n);
172 }
173
174 static inline guint
175 pts_get_poc(PTSGenerator *tsg)
176 {
177     return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
178 }
179
180 static void
181 pts_set_framerate(PTSGenerator *tsg, guint fps_n, guint fps_d)
182 {
183     tsg->fps_n = fps_n;
184     tsg->fps_d = fps_d;
185 }
186
187 static void
188 pts_sync(PTSGenerator *tsg, GstClockTime gop_pts)
189 {
190     guint gop_tsn;
191
192     if (!GST_CLOCK_TIME_IS_VALID(gop_pts) ||
193         (GST_CLOCK_TIME_IS_VALID(tsg->max_pts) && tsg->max_pts >= gop_pts)) {
194         /* Invalid GOP PTS, interpolate from the last known picture PTS */
195         if (GST_CLOCK_TIME_IS_VALID(tsg->max_pts)) {
196             gop_pts = tsg->max_pts + pts_get_duration(tsg, 1);
197             gop_tsn = tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->max_tsn + 1;
198         }
199         else {
200             gop_pts = 0;
201             gop_tsn = 0;
202         }
203     }
204     else {
205         /* Interpolate GOP TSN from this valid PTS */
206         if (GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
207             gop_tsn = tsg->gop_tsn + gst_util_uint64_scale(
208                 gop_pts - tsg->gop_pts + pts_get_duration(tsg, 1) - 1,
209                 tsg->fps_n, GST_SECOND * tsg->fps_d);
210         else
211             gop_tsn = 0;
212     }
213
214     tsg->gop_pts = gop_pts;
215     tsg->gop_tsn = gop_tsn;
216     tsg->max_tsn = 0;
217     tsg->ovl_tsn = 0;
218     tsg->lst_tsn = 0;
219 }
220
221 static GstClockTime
222 pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
223 {
224     GstClockTime pts;
225
226     if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
227         tsg->gop_pts = 0;
228
229     pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
230
231     if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
232         tsg->max_pts = pts;
233
234     if (tsg->max_tsn < pic_tsn)
235         tsg->max_tsn = pic_tsn;
236     else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
237         tsg->max_tsn = pic_tsn;
238         tsg->ovl_tsn++;
239     }
240     tsg->lst_tsn = pic_tsn;
241     return pts;
242 }
243
244 /* ------------------------------------------------------------------------- */
245 /* --- MPEG-2 Decoder Units                                              --- */
246 /* ------------------------------------------------------------------------- */
247
248 typedef struct _GstMpegVideoSliceHdr GstMpegVideoSliceHdr;
249 struct _GstMpegVideoSliceHdr {
250     guint16 slice_horizontal_position;
251     guint16 slice_vertical_position;
252     guint8 quantiser_scale_code;
253     guint8 intra_slice;
254
255     /* Size of the slice() header in bits */
256     guint header_size;
257 };
258
259 typedef struct _GstVaapiDecoderUnitMpeg2 GstVaapiDecoderUnitMpeg2;
260 struct _GstVaapiDecoderUnitMpeg2 {
261     GstVaapiDecoderUnit         base;
262     GstMpegVideoPacket          packet;
263     guint8                      extension_type; /* for Extension packets */
264     union {
265         GstMpegVideoSequenceHdr         seq_hdr;
266         GstMpegVideoSequenceExt         seq_ext;
267         GstMpegVideoSequenceDisplayExt  seq_display_ext;
268         GstMpegVideoGop                 gop;
269         GstMpegVideoQuantMatrixExt      quant_matrix;
270         GstMpegVideoPictureHdr          pic_hdr;
271         GstMpegVideoPictureExt          pic_ext;
272         GstMpegVideoSliceHdr            slice_hdr;
273     }                                   data;
274 };
275
276 static GstVaapiDecoderUnitMpeg2 *
277 gst_vaapi_decoder_unit_mpeg2_new(guint size)
278 {
279     GstVaapiDecoderUnitMpeg2 *unit;
280
281     static const GstVaapiMiniObjectClass GstVaapiDecoderUnitMpeg2Class = {
282         sizeof(GstVaapiDecoderUnitMpeg2),
283         (GDestroyNotify)gst_vaapi_decoder_unit_finalize
284     };
285
286     unit = (GstVaapiDecoderUnitMpeg2 *)
287         gst_vaapi_mini_object_new(&GstVaapiDecoderUnitMpeg2Class);
288     if (!unit)
289         return NULL;
290
291     gst_vaapi_decoder_unit_init(&unit->base, size);
292     return unit;
293 }
294
295 /* ------------------------------------------------------------------------- */
296 /* --- MPEG-2 Decoder                                                    --- */
297 /* ------------------------------------------------------------------------- */
298
299 G_DEFINE_TYPE(GstVaapiDecoderMpeg2,
300               gst_vaapi_decoder_mpeg2,
301               GST_VAAPI_TYPE_DECODER)
302
303 #define GST_VAAPI_DECODER_MPEG2_CAST(decoder) \
304     ((GstVaapiDecoderMpeg2 *)(decoder))
305
306 #define GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(obj)                \
307     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
308                                  GST_VAAPI_TYPE_DECODER_MPEG2,  \
309                                  GstVaapiDecoderMpeg2Private))
310
311 struct _GstVaapiDecoderMpeg2Private {
312     GstVaapiProfile             profile;
313     GstVaapiProfile             hw_profile;
314     guint                       width;
315     guint                       height;
316     guint                       fps_n;
317     guint                       fps_d;
318     GstVaapiDecoderUnitMpeg2   *seq_hdr_unit;
319     GstVaapiDecoderUnitMpeg2   *seq_ext_unit;
320     GstVaapiDecoderUnitMpeg2   *seq_display_ext_unit;
321     GstVaapiDecoderUnitMpeg2   *seq_scalable_ext_unit;
322     GstVaapiDecoderUnitMpeg2   *pic_hdr_unit;
323     GstVaapiDecoderUnitMpeg2   *pic_ext_unit;
324     GstVaapiDecoderUnitMpeg2   *quant_matrix_unit;
325     GstVaapiPicture            *current_picture;
326     GstVaapiDpb                *dpb;
327     PTSGenerator                tsg;
328     guint                       is_constructed          : 1;
329     guint                       is_opened               : 1;
330     guint                       size_changed            : 1;
331     guint                       profile_changed         : 1;
332     guint                       quant_matrix_changed    : 1;
333     guint                       progressive_sequence    : 1;
334     guint                       closed_gop              : 1;
335     guint                       broken_link             : 1;
336 };
337
338 static void
339 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
340 {
341     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
342
343     gst_vaapi_picture_replace(&priv->current_picture, NULL);
344
345     gst_vaapi_decoder_unit_replace(&priv->seq_hdr_unit, NULL);
346     gst_vaapi_decoder_unit_replace(&priv->seq_ext_unit, NULL);
347     gst_vaapi_decoder_unit_replace(&priv->seq_display_ext_unit, NULL);
348     gst_vaapi_decoder_unit_replace(&priv->seq_scalable_ext_unit, NULL);
349     gst_vaapi_decoder_unit_replace(&priv->pic_hdr_unit, NULL);
350     gst_vaapi_decoder_unit_replace(&priv->pic_ext_unit, NULL);
351     gst_vaapi_decoder_unit_replace(&priv->quant_matrix_unit, NULL);
352
353     if (priv->dpb) {
354         gst_vaapi_dpb_unref(priv->dpb);
355         priv->dpb = NULL;
356     }
357 }
358
359 static gboolean
360 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder)
361 {
362     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
363
364     gst_vaapi_decoder_mpeg2_close(decoder);
365
366     priv->dpb = gst_vaapi_dpb_mpeg2_new();
367     if (!priv->dpb)
368         return FALSE;
369
370     pts_init(&priv->tsg);
371     return TRUE;
372 }
373
374 static void
375 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
376 {
377     gst_vaapi_decoder_mpeg2_close(decoder);
378 }
379
380 static gboolean
381 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
382 {
383     if (!GST_VAAPI_DECODER_CODEC(decoder))
384         return FALSE;
385     return TRUE;
386 }
387
388 static inline void
389 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
390 {
391     memcpy(dst, src, 64);
392 }
393
394 static const char *
395 get_profile_str(GstVaapiProfile profile)
396 {
397     char *str;
398
399     switch (profile) {
400     case GST_VAAPI_PROFILE_MPEG2_SIMPLE:    str = "simple";     break;
401     case GST_VAAPI_PROFILE_MPEG2_MAIN:      str = "main";       break;
402     case GST_VAAPI_PROFILE_MPEG2_HIGH:      str = "high";       break;
403     default:                                str = "<unknown>";  break;
404     }
405     return str;
406 }
407
408 static GstVaapiProfile
409 get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
410 {
411     GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
412     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
413     GstVaapiProfile profile = priv->profile;
414
415     do {
416         /* Return immediately if the exact same profile was found */
417         if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
418             break;
419
420         /* Otherwise, try to map to a higher profile */
421         switch (profile) {
422         case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
423             profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
424             break;
425         case GST_VAAPI_PROFILE_MPEG2_MAIN:
426             profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
427             break;
428         case GST_VAAPI_PROFILE_MPEG2_HIGH:
429             // Try to map to main profile if no high profile specific bits used
430             if (priv->profile == profile &&
431                 !priv->seq_scalable_ext_unit &&
432                 (priv->seq_ext_unit &&
433                  priv->seq_ext_unit->data.seq_ext.chroma_format == 1)) {
434                 profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
435                 break;
436             }
437             // fall-through
438         default:
439             profile = GST_VAAPI_PROFILE_UNKNOWN;
440             break;
441         }
442     } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
443
444     if (profile != priv->profile)
445         GST_INFO("forced %s profile to %s profile",
446                  get_profile_str(priv->profile), get_profile_str(profile));
447     return profile;
448 }
449
450 static GstVaapiDecoderStatus
451 ensure_context(GstVaapiDecoderMpeg2 *decoder)
452 {
453     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
454     GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
455     gboolean reset_context = FALSE;
456
457     if (priv->profile_changed) {
458         GST_DEBUG("profile changed");
459         priv->profile_changed = FALSE;
460         reset_context         = TRUE;
461
462         priv->hw_profile = get_profile(decoder, entrypoint);
463         if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
464             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
465     }
466
467     if (priv->size_changed) {
468         GST_DEBUG("size changed");
469         priv->size_changed = FALSE;
470         reset_context      = TRUE;
471     }
472
473     if (reset_context) {
474         GstVaapiContextInfo info;
475
476         info.profile    = priv->hw_profile;
477         info.entrypoint = entrypoint;
478         info.width      = priv->width;
479         info.height     = priv->height;
480         info.ref_frames = 2;
481         reset_context   = gst_vaapi_decoder_ensure_context(
482             GST_VAAPI_DECODER_CAST(decoder),
483             &info
484         );
485         if (!reset_context)
486             return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
487     }
488     return GST_VAAPI_DECODER_STATUS_SUCCESS;
489 }
490
491 static GstVaapiDecoderStatus
492 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
493 {
494     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
495     GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr_unit->data.seq_hdr;
496     VAIQMatrixBufferMPEG2 *iq_matrix;
497     guint8 *intra_quant_matrix = NULL;
498     guint8 *non_intra_quant_matrix = NULL;
499     guint8 *chroma_intra_quant_matrix = NULL;
500     guint8 *chroma_non_intra_quant_matrix = NULL;
501
502     if (!priv->quant_matrix_changed)
503         return GST_VAAPI_DECODER_STATUS_SUCCESS;
504
505     priv->quant_matrix_changed = FALSE;
506
507     picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
508     if (!picture->iq_matrix) {
509         GST_ERROR("failed to allocate IQ matrix");
510         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
511     }
512     iq_matrix = picture->iq_matrix->param;
513
514     intra_quant_matrix     = seq_hdr->intra_quantizer_matrix;
515     non_intra_quant_matrix = seq_hdr->non_intra_quantizer_matrix;
516
517     if (priv->quant_matrix_unit) {
518         GstMpegVideoQuantMatrixExt * const quant_matrix =
519             &priv->quant_matrix_unit->data.quant_matrix;
520         if (quant_matrix->load_intra_quantiser_matrix)
521             intra_quant_matrix = quant_matrix->intra_quantiser_matrix;
522         if (quant_matrix->load_non_intra_quantiser_matrix)
523             non_intra_quant_matrix = quant_matrix->non_intra_quantiser_matrix;
524         if (quant_matrix->load_chroma_intra_quantiser_matrix)
525             chroma_intra_quant_matrix = quant_matrix->chroma_intra_quantiser_matrix;
526         if (quant_matrix->load_chroma_non_intra_quantiser_matrix)
527             chroma_non_intra_quant_matrix = quant_matrix->chroma_non_intra_quantiser_matrix;
528     }
529
530     iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
531     if (intra_quant_matrix)
532         copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
533                           intra_quant_matrix);
534
535     iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
536     if (non_intra_quant_matrix)
537         copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
538                           non_intra_quant_matrix);
539
540     iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
541     if (chroma_intra_quant_matrix)
542         copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
543                           chroma_intra_quant_matrix);
544
545     iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
546     if (chroma_non_intra_quant_matrix)
547         copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
548                           chroma_non_intra_quant_matrix);
549     return GST_VAAPI_DECODER_STATUS_SUCCESS;
550 }
551
552 static GstVaapiDecoderStatus
553 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
554 {
555     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
556     GstVaapiPicture * const picture = priv->current_picture;
557
558     if (!picture)
559         return GST_VAAPI_DECODER_STATUS_SUCCESS;
560
561     if (!gst_vaapi_picture_decode(picture))
562         goto error;
563     if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
564         if (!gst_vaapi_dpb_add(priv->dpb, picture))
565             goto error;
566         gst_vaapi_picture_replace(&priv->current_picture, NULL);
567     }
568     return GST_VAAPI_DECODER_STATUS_SUCCESS;
569
570 error:
571     /* XXX: fix for cases where first field failed to be decoded */
572     gst_vaapi_picture_replace(&priv->current_picture, NULL);
573     return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
574 }
575
576 static GstVaapiDecoderStatus
577 parse_sequence(GstVaapiDecoderUnitMpeg2 *unit)
578 {
579     GstMpegVideoPacket * const packet = &unit->packet;
580
581     if (!gst_mpeg_video_parse_sequence_header(&unit->data.seq_hdr,
582             packet->data, packet->size, packet->offset)) {
583         GST_ERROR("failed to parse sequence header");
584         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
585     }
586     return GST_VAAPI_DECODER_STATUS_SUCCESS;
587 }
588
589 static GstVaapiDecoderStatus
590 decode_sequence(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
591 {
592     GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
593     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
594     GstMpegVideoSequenceHdr *seq_hdr;
595
596     gst_vaapi_decoder_unit_replace(&priv->seq_hdr_unit, unit);
597     seq_hdr = &priv->seq_hdr_unit->data.seq_hdr;
598     gst_vaapi_decoder_unit_replace(&priv->seq_ext_unit, NULL);
599     gst_vaapi_decoder_unit_replace(&priv->seq_display_ext_unit, NULL);
600
601     priv->fps_n = seq_hdr->fps_n;
602     priv->fps_d = seq_hdr->fps_d;
603     pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
604     gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
605
606     priv->width                 = seq_hdr->width;
607     priv->height                = seq_hdr->height;
608     priv->size_changed          = TRUE;
609     priv->quant_matrix_changed  = TRUE;
610     priv->progressive_sequence  = TRUE;
611     return GST_VAAPI_DECODER_STATUS_SUCCESS;
612 }
613
614 static GstVaapiDecoderStatus
615 parse_sequence_ext(GstVaapiDecoderUnitMpeg2 *unit)
616 {
617     GstMpegVideoPacket * const packet = &unit->packet;
618
619     if (!gst_mpeg_video_parse_sequence_extension(&unit->data.seq_ext,
620             packet->data, packet->size, packet->offset)) {
621         GST_ERROR("failed to parse sequence-extension");
622         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
623     }
624     return GST_VAAPI_DECODER_STATUS_SUCCESS;
625 }
626
627 static GstVaapiDecoderStatus
628 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder,
629     GstVaapiDecoderUnitMpeg2 *unit)
630 {
631     GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
632     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
633     GstMpegVideoSequenceExt *seq_ext;
634     GstVaapiProfile profile;
635     guint width, height;
636
637     gst_vaapi_decoder_unit_replace(&priv->seq_ext_unit, unit);
638     seq_ext = &priv->seq_ext_unit->data.seq_ext;
639
640     priv->progressive_sequence = seq_ext->progressive;
641     gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
642
643     width  = (priv->width  & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
644     height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext  << 12);
645     GST_DEBUG("video resolution %ux%u", width, height);
646
647     if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
648         priv->fps_n *= seq_ext->fps_n_ext + 1;
649         priv->fps_d *= seq_ext->fps_d_ext + 1;
650         pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
651         gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
652     }
653
654     if (priv->width != width) {
655         priv->width = width;
656         priv->size_changed = TRUE;
657     }
658
659     if (priv->height != height) {
660         priv->height = height;
661         priv->size_changed = TRUE;
662     }
663
664     switch (seq_ext->profile) {
665     case GST_MPEG_VIDEO_PROFILE_SIMPLE:
666         profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
667         break;
668     case GST_MPEG_VIDEO_PROFILE_MAIN:
669         profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
670         break;
671     case GST_MPEG_VIDEO_PROFILE_HIGH:
672         profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
673         break;
674     default:
675         GST_ERROR("unsupported profile %d", seq_ext->profile);
676         return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
677     }
678     if (priv->profile != profile) {
679         priv->profile = profile;
680         priv->profile_changed = TRUE;
681     }
682     return GST_VAAPI_DECODER_STATUS_SUCCESS;
683 }
684
685 static GstVaapiDecoderStatus
686 parse_sequence_display_ext(GstVaapiDecoderUnitMpeg2 *unit)
687 {
688     GstMpegVideoPacket * const packet = &unit->packet;
689
690     if (!gst_mpeg_video_parse_sequence_display_extension(
691             &unit->data.seq_display_ext,
692             packet->data, packet->size, packet->offset)) {
693         GST_ERROR("failed to parse sequence-display-extension");
694         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
695     }
696     return GST_VAAPI_DECODER_STATUS_SUCCESS;
697 }
698
699 static GstVaapiDecoderStatus
700 decode_sequence_display_ext(GstVaapiDecoderMpeg2 *decoder,
701     GstVaapiDecoderUnitMpeg2 *unit)
702 {
703     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
704
705     gst_vaapi_decoder_unit_replace(&priv->seq_display_ext_unit, unit);
706
707     /* XXX: handle color primaries and cropping */
708     return GST_VAAPI_DECODER_STATUS_SUCCESS;
709 }
710
711 static GstVaapiDecoderStatus
712 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
713 {
714     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
715     GstVaapiDecoderStatus status;
716
717     status = decode_current_picture(decoder);
718     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
719         return status;
720
721     gst_vaapi_dpb_flush(priv->dpb);
722     return GST_VAAPI_DECODER_STATUS_SUCCESS;
723 }
724
725 static GstVaapiDecoderStatus
726 parse_quant_matrix_ext(GstVaapiDecoderUnitMpeg2 *unit)
727 {
728     GstMpegVideoPacket * const packet = &unit->packet;
729
730     if (!gst_mpeg_video_parse_quant_matrix_extension(&unit->data.quant_matrix,
731             packet->data, packet->size, packet->offset)) {
732         GST_ERROR("failed to parse quant-matrix-extension");
733         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
734     }
735     return GST_VAAPI_DECODER_STATUS_SUCCESS;
736 }
737
738 static GstVaapiDecoderStatus
739 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder,
740     GstVaapiDecoderUnitMpeg2 *unit)
741 {
742     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
743
744     gst_vaapi_decoder_unit_replace(&priv->quant_matrix_unit, unit);
745     priv->quant_matrix_changed = TRUE;
746     return GST_VAAPI_DECODER_STATUS_SUCCESS;
747 }
748
749 static GstVaapiDecoderStatus
750 parse_gop(GstVaapiDecoderUnitMpeg2 *unit)
751 {
752     GstMpegVideoPacket * const packet = &unit->packet;
753
754     if (!gst_mpeg_video_parse_gop(&unit->data.gop,
755             packet->data, packet->size, packet->offset)) {
756         GST_ERROR("failed to parse GOP");
757         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
758     }
759     return GST_VAAPI_DECODER_STATUS_SUCCESS;
760 }
761
762 static GstVaapiDecoderStatus
763 decode_gop(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
764 {
765     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
766     GstMpegVideoGop * const gop = &unit->data.gop;
767
768     priv->closed_gop  = gop->closed_gop;
769     priv->broken_link = gop->broken_link;
770
771     GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
772               gop->hour, gop->minute, gop->second, gop->frame,
773               priv->closed_gop, priv->broken_link);
774
775     pts_sync(&priv->tsg, GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts);
776     return GST_VAAPI_DECODER_STATUS_SUCCESS;
777 }
778
779 static GstVaapiDecoderStatus
780 parse_picture(GstVaapiDecoderUnitMpeg2 *unit)
781 {
782     GstMpegVideoPacket * const packet = &unit->packet;
783
784     if (!gst_mpeg_video_parse_picture_header(&unit->data.pic_hdr,
785             packet->data, packet->size, packet->offset)) {
786         GST_ERROR("failed to parse picture header");
787         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
788     }
789     return GST_VAAPI_DECODER_STATUS_SUCCESS;
790 }
791
792 static GstVaapiDecoderStatus
793 parse_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
794 {
795     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
796     GstMpegVideoSliceHdr * const slice_hdr = &unit->data.slice_hdr;
797     GstMpegVideoPacket * const packet = &unit->packet;
798     GstBitReader br;
799     gint mb_x, mb_y, mb_inc;
800     guint8 slice_vertical_position_extension;
801     guint8 extra_bit_slice, junk8;
802
803     gst_bit_reader_init(&br, packet->data + packet->offset, packet->size);
804     if (priv->height > 2800)
805         READ_UINT8(&br, slice_vertical_position_extension, 3);
806     if (priv->seq_scalable_ext_unit) {
807         GST_ERROR("failed to parse slice with sequence_scalable_extension()");
808         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
809     }
810     READ_UINT8(&br, slice_hdr->quantiser_scale_code, 5);
811     READ_UINT8(&br, extra_bit_slice, 1);
812     if (!extra_bit_slice)
813         slice_hdr->intra_slice = 0;
814     else {
815         READ_UINT8(&br, slice_hdr->intra_slice, 1);
816         READ_UINT8(&br, junk8, 7);
817         READ_UINT8(&br, extra_bit_slice, 1);
818         while (extra_bit_slice) {
819             READ_UINT8(&br, junk8, 8);
820             READ_UINT8(&br, extra_bit_slice, 1);
821         }
822     }
823     slice_hdr->header_size = 32 + gst_bit_reader_get_pos(&br);
824
825     mb_y = packet->type - GST_MPEG_VIDEO_PACKET_SLICE_MIN;
826     mb_x = -1;
827     do {
828         if (!decode_vlc(&br, &mb_inc, mpeg2_mbaddr_vlc_table,
829                 G_N_ELEMENTS(mpeg2_mbaddr_vlc_table))) {
830             GST_WARNING("failed to decode first macroblock_address_increment");
831             goto failed;
832         }
833         mb_x += mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
834     } while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
835
836     slice_hdr->slice_horizontal_position = mb_x;
837     slice_hdr->slice_vertical_position   = mb_y;
838     return GST_VAAPI_DECODER_STATUS_SUCCESS;
839
840 failed:
841     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
842 }
843
844 static GstVaapiDecoderStatus
845 decode_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
846 {
847     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
848
849     gst_vaapi_decoder_unit_replace(&priv->pic_hdr_unit, unit);
850     gst_vaapi_decoder_unit_replace(&priv->pic_ext_unit, NULL);
851     return GST_VAAPI_DECODER_STATUS_SUCCESS;
852 }
853
854 static GstVaapiDecoderStatus
855 parse_picture_ext(GstVaapiDecoderUnitMpeg2 *unit)
856 {
857     GstMpegVideoPacket * const packet = &unit->packet;
858
859     if (!gst_mpeg_video_parse_picture_extension(&unit->data.pic_ext,
860             packet->data, packet->size, packet->offset)) {
861         GST_ERROR("failed to parse picture-extension");
862         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
863     }
864     return GST_VAAPI_DECODER_STATUS_SUCCESS;
865 }
866
867 static GstVaapiDecoderStatus
868 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder,
869     GstVaapiDecoderUnitMpeg2 *unit)
870 {
871     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
872     GstMpegVideoPictureExt *pic_ext;
873
874     gst_vaapi_decoder_unit_replace(&priv->pic_ext_unit, unit);
875     pic_ext = &priv->pic_ext_unit->data.pic_ext;
876
877     if (priv->progressive_sequence && !pic_ext->progressive_frame) {
878         GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
879         pic_ext->progressive_frame = 1;
880     }
881
882     if (pic_ext->picture_structure == 0 ||
883         (pic_ext->progressive_frame &&
884          pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
885         GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
886                     pic_ext->picture_structure);
887         pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
888     }
889     return GST_VAAPI_DECODER_STATUS_SUCCESS;
890 }
891
892 static inline guint32
893 pack_f_code(guint8 f_code[2][2])
894 {
895     return (((guint32)f_code[0][0] << 12) |
896             ((guint32)f_code[0][1] <<  8) |
897             ((guint32)f_code[1][0] <<  4) |
898             (         f_code[1][1]      ));
899 }
900
901 static GstVaapiDecoderStatus
902 init_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
903 {
904     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
905     GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr_unit->data.pic_hdr;
906     GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext_unit->data.pic_ext;
907
908     switch (pic_hdr->pic_type) {
909     case GST_MPEG_VIDEO_PICTURE_TYPE_I:
910         GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
911         picture->type = GST_VAAPI_PICTURE_TYPE_I;
912         break;
913     case GST_MPEG_VIDEO_PICTURE_TYPE_P:
914         GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
915         picture->type = GST_VAAPI_PICTURE_TYPE_P;
916         break;
917     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
918         picture->type = GST_VAAPI_PICTURE_TYPE_B;
919         break;
920     default:
921         GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
922         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
923     }
924
925     if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
926         GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
927         if (pic_ext->top_field_first)
928             GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
929     }
930
931     switch (pic_ext->picture_structure) {
932     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
933         picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
934         break;
935     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
936         picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
937         break;
938     case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
939         picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
940         break;
941     }
942
943     /* Allocate dummy picture for first field based I-frame */
944     if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
945         !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
946         gst_vaapi_dpb_size(priv->dpb) == 0) {
947         GstVaapiPicture *dummy_picture;
948         gboolean success;
949
950         dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
951         if (!dummy_picture) {
952             GST_ERROR("failed to allocate dummy picture");
953             return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
954         }
955
956         dummy_picture->type      = GST_VAAPI_PICTURE_TYPE_I;
957         dummy_picture->pts       = GST_CLOCK_TIME_NONE;
958         dummy_picture->poc       = -1;
959         dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
960
961         GST_VAAPI_PICTURE_FLAG_SET(
962             dummy_picture,
963             (GST_VAAPI_PICTURE_FLAG_SKIPPED |
964              GST_VAAPI_PICTURE_FLAG_REFERENCE)
965         );
966
967         success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
968         gst_vaapi_picture_unref(dummy_picture);
969         if (!success) {
970             GST_ERROR("failed to add dummy picture into DPB");
971             return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
972         }
973         GST_INFO("allocated dummy picture for first field based I-frame");
974     }
975
976     /* Update presentation time */
977     picture->pts = pts_eval(&priv->tsg,
978         GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts, pic_hdr->tsn);
979     picture->poc = pts_get_poc(&priv->tsg);
980     return GST_VAAPI_DECODER_STATUS_SUCCESS;
981 }
982
983 static void
984 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
985 {
986     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
987     VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
988     GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr_unit->data.pic_hdr;
989     GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext_unit->data.pic_ext;
990     GstVaapiPicture *prev_picture, *next_picture;
991
992     /* Fill in VAPictureParameterBufferMPEG2 */
993     pic_param->horizontal_size            = priv->width;
994     pic_param->vertical_size              = priv->height;
995     pic_param->forward_reference_picture  = VA_INVALID_ID;
996     pic_param->backward_reference_picture = VA_INVALID_ID;
997     pic_param->picture_coding_type        = pic_hdr->pic_type;
998     pic_param->f_code                     = pack_f_code(pic_ext->f_code);
999
1000 #define COPY_FIELD(a, b, f) \
1001     pic_param->a.b.f = pic_ext->f
1002     pic_param->picture_coding_extension.value = 0;
1003     pic_param->picture_coding_extension.bits.is_first_field =
1004         GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
1005     COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
1006     COPY_FIELD(picture_coding_extension, bits, picture_structure);
1007     COPY_FIELD(picture_coding_extension, bits, top_field_first);
1008     COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
1009     COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
1010     COPY_FIELD(picture_coding_extension, bits, q_scale_type);
1011     COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
1012     COPY_FIELD(picture_coding_extension, bits, alternate_scan);
1013     COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
1014     COPY_FIELD(picture_coding_extension, bits, progressive_frame);
1015
1016     gst_vaapi_dpb_mpeg2_get_references(priv->dpb, picture,
1017         &prev_picture, &next_picture);
1018
1019     switch (pic_hdr->pic_type) {
1020     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
1021         if (next_picture)
1022             pic_param->backward_reference_picture = next_picture->surface_id;
1023         if (prev_picture)
1024             pic_param->forward_reference_picture = prev_picture->surface_id;
1025         else if (!priv->closed_gop)
1026             GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
1027         break;
1028     case GST_MPEG_VIDEO_PICTURE_TYPE_P:
1029         if (prev_picture)
1030             pic_param->forward_reference_picture = prev_picture->surface_id;
1031         break;
1032     }
1033 }
1034
1035 static GstVaapiDecoderStatus
1036 decode_slice(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
1037 {
1038     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1039     GstVaapiPicture * const picture = priv->current_picture;
1040     GstVaapiSlice *slice;
1041     VASliceParameterBufferMPEG2 *slice_param;
1042     GstMpegVideoPacket * const packet = &unit->packet;
1043     GstMpegVideoSliceHdr * const slice_hdr = &unit->data.slice_hdr;
1044
1045     GST_DEBUG("slice %d (%u bytes)", slice_hdr->slice_vertical_position,
1046               packet->size);
1047
1048     unit->base.buffer = gst_buffer_create_sub(
1049         GST_VAAPI_DECODER_CODEC_FRAME(decoder)->input_buffer,
1050         unit->base.offset, unit->base.size);
1051     if (!unit->base.buffer) {
1052         GST_ERROR("failed to allocate slice data");
1053         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1054     }
1055
1056     slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder,
1057         GST_BUFFER_DATA(unit->base.buffer), packet->size);
1058     if (!slice) {
1059         GST_ERROR("failed to allocate slice");
1060         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1061     }
1062     gst_vaapi_picture_add_slice(picture, slice);
1063
1064     /* Fill in VASliceParameterBufferMPEG2 */
1065     slice_param                            = slice->param;
1066     slice_param->macroblock_offset         = slice_hdr->header_size;
1067     slice_param->slice_horizontal_position = slice_hdr->slice_horizontal_position;
1068     slice_param->slice_vertical_position   = slice_hdr->slice_vertical_position;
1069     slice_param->quantiser_scale_code      = slice_hdr->quantiser_scale_code;
1070     slice_param->intra_slice_flag          = slice_hdr->intra_slice;
1071     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1072 }
1073
1074 static inline gint
1075 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
1076 {
1077     return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
1078                                                      0xffffff00, 0x00000100,
1079                                                      ofs, size,
1080                                                      scp);
1081 }
1082
1083 static GstVaapiDecoderStatus
1084 decode_unit(GstVaapiDecoderMpeg2 *decoder, GstVaapiDecoderUnitMpeg2 *unit)
1085 {
1086     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1087     const GstMpegVideoPacketTypeCode type = unit->packet.type;
1088     GstVaapiDecoderStatus status;
1089
1090     switch (type) {
1091     case GST_MPEG_VIDEO_PACKET_PICTURE:
1092         if (!priv->width || !priv->height)
1093             goto unknown_picture_size;
1094         status = decode_picture(decoder, unit);
1095         break;
1096     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1097         status = decode_sequence(decoder, unit);
1098         break;
1099     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1100         switch (unit->extension_type) {
1101         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1102             status = decode_sequence_ext(decoder, unit);
1103             break;
1104         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1105             status = decode_sequence_display_ext(decoder, unit);
1106             break;
1107         case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1108             status = decode_quant_matrix_ext(decoder, unit);
1109             break;
1110         case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1111             if (!priv->width || !priv->height)
1112                 goto unknown_picture_size;
1113             status = decode_picture_ext(decoder, unit);
1114             break;
1115         default:
1116             // Ignore unknown start-code extensions
1117             GST_WARNING("unsupported packet extension type 0x%02x",
1118                         unit->extension_type);
1119             status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1120             break;
1121         }
1122         break;
1123     case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1124         status = decode_sequence_end(decoder);
1125         break;
1126     case GST_MPEG_VIDEO_PACKET_GOP:
1127         status = decode_gop(decoder, unit);
1128         break;
1129     default:
1130         if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1131             type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1132             status = decode_slice(decoder, unit);
1133             break;
1134         }
1135         GST_WARNING("unsupported packet type 0x%02x", type);
1136         status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1137         break;
1138     }
1139     return status;
1140
1141 unknown_picture_size:
1142     // Ignore packet while picture size is undefined
1143     // i.e. missing sequence headers, or not parsed correctly
1144     GST_WARNING("failed to parse picture of unknown size");
1145     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1146 }
1147
1148 static GstVaapiDecoderStatus
1149 ensure_decoder(GstVaapiDecoderMpeg2 *decoder)
1150 {
1151     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1152
1153     g_return_val_if_fail(priv->is_constructed,
1154                          GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
1155
1156     if (!priv->is_opened) {
1157         priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder);
1158         if (!priv->is_opened)
1159             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
1160     }
1161     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1162 }
1163
1164 static GstVaapiDecoderStatus
1165 gst_vaapi_decoder_mpeg2_parse(GstVaapiDecoder *base_decoder,
1166     GstAdapter *adapter, gboolean at_eos, GstVaapiDecoderUnit **unit_ptr)
1167 {
1168     GstVaapiDecoderMpeg2 * const decoder =
1169         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1170     GstVaapiParserState * const ps = GST_VAAPI_PARSER_STATE(base_decoder);
1171     GstVaapiDecoderUnitMpeg2 *unit;
1172     GstVaapiDecoderStatus status;
1173     GstMpegVideoPacket *packet;
1174     const guchar *buf;
1175     guint32 start_code;
1176     guint size, buf_size, flags;
1177     gint ofs, ofs2;
1178
1179     status = ensure_decoder(decoder);
1180     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1181         return status;
1182
1183     size = gst_adapter_available(adapter);
1184     if (size < 4)
1185         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1186
1187     ofs = scan_for_start_code(adapter, 0, size, &start_code);
1188     if (ofs < 0)
1189         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1190
1191     if (ofs > 0) {
1192         gst_adapter_flush(adapter, ofs);
1193         size -= ofs;
1194     }
1195
1196     ofs2 = ps->input_offset2 - ofs - 4;
1197     if (ofs2 < 4)
1198         ofs2 = 4;
1199
1200     ofs = G_UNLIKELY(size < ofs2 + 4) ? -1 :
1201         scan_for_start_code(adapter, ofs2, size - ofs2, NULL);
1202     if (ofs < 0) {
1203         // Assume the whole packet is present if end-of-stream
1204         if (!at_eos) {
1205             ps->input_offset2 = size;
1206             return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1207         }
1208         ofs = size;
1209     }
1210     buf_size = ofs;
1211     ps->input_offset2 = 0;
1212
1213     buf = gst_adapter_peek(adapter, buf_size);
1214     if (!buf)
1215         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
1216
1217     unit = gst_vaapi_decoder_unit_mpeg2_new(buf_size);
1218     if (!unit)
1219         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1220
1221     packet         = &unit->packet;
1222     packet->data   = buf;
1223     packet->size   = buf_size;
1224     packet->offset = 4;
1225     packet->type   = start_code & 0xff;
1226
1227     /* Parse data */
1228     switch (packet->type) {
1229     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1230         status = parse_sequence(unit);
1231         break;
1232     case GST_MPEG_VIDEO_PACKET_GOP:
1233         status = parse_gop(unit);
1234         break;
1235     case GST_MPEG_VIDEO_PACKET_PICTURE:
1236         status = parse_picture(unit);
1237         break;
1238     case GST_MPEG_VIDEO_PACKET_EXTENSION:
1239         if (G_UNLIKELY(buf_size < 5)) {
1240             status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
1241             break;
1242         }
1243         unit->extension_type = buf[4] >> 4;
1244         switch (unit->extension_type) {
1245         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
1246             status = parse_sequence_ext(unit);
1247             break;
1248         case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY:
1249             status = parse_sequence_display_ext(unit);
1250             break;
1251         case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
1252             status = parse_quant_matrix_ext(unit);
1253             break;
1254         case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
1255             status = parse_picture_ext(unit);
1256             break;
1257         default:
1258             status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1259             break;
1260         }
1261         break;
1262     default:
1263         if (packet->type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1264             packet->type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
1265             status = parse_slice(decoder, unit);
1266             break;
1267         }
1268
1269         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
1270         break;
1271     }
1272     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1273         return status;
1274
1275     /* Check for start of new picture */
1276     flags = 0;
1277     switch (packet->type) {
1278     case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
1279         flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
1280         flags |= GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END;
1281         break;
1282     case GST_MPEG_VIDEO_PACKET_USER_DATA:
1283         flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1284         /* fall-through */
1285     case GST_MPEG_VIDEO_PACKET_SEQUENCE:
1286     case GST_MPEG_VIDEO_PACKET_GOP:
1287     case GST_MPEG_VIDEO_PACKET_PICTURE:
1288         flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
1289         break;
1290     default:
1291         if (packet->type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
1292             packet->type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX)
1293             flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
1294
1295         // Ignore system start codes (PES headers)
1296         else if (packet->type >= 0xb9 && packet->type <= 0xff)
1297             flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
1298         break;
1299     }
1300     GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags);
1301
1302     unit->packet.data = NULL;
1303     *unit_ptr = &unit->base;
1304     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1305 }
1306
1307 static GstVaapiDecoderStatus
1308 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base_decoder,
1309     GstVaapiDecoderUnit *unit)
1310 {
1311     GstVaapiDecoderMpeg2 * const decoder =
1312         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1313     GstVaapiDecoderStatus status;
1314
1315     status = ensure_decoder(decoder);
1316     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1317         return status;
1318     return decode_unit(decoder, (GstVaapiDecoderUnitMpeg2 *)unit);
1319 }
1320
1321 static GstVaapiDecoderStatus
1322 gst_vaapi_decoder_mpeg2_start_frame(GstVaapiDecoder *base_decoder,
1323     GstVaapiDecoderUnit *base_unit)
1324 {
1325     GstVaapiDecoderMpeg2 * const decoder =
1326         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1327     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1328     GstMpegVideoSequenceHdr *seq_hdr;
1329     GstMpegVideoSequenceExt *seq_ext;
1330     GstMpegVideoSequenceDisplayExt *seq_display_ext;
1331     GstVaapiPicture *picture;
1332     GstVaapiDecoderStatus status;
1333
1334     if (!priv->width || !priv->height) {
1335         // Ignore packet while picture size is undefined
1336         // i.e. missing sequence headers, or not parsed correctly
1337         GST_WARNING("failed to decode picture of unknown size");
1338         return GST_VAAPI_DECODER_STATUS_SUCCESS;
1339     }
1340
1341     seq_hdr = &priv->seq_hdr_unit->data.seq_hdr;
1342     seq_ext = priv->seq_ext_unit ? &priv->seq_ext_unit->data.seq_ext : NULL;
1343     seq_display_ext = priv->seq_display_ext_unit ?
1344         &priv->seq_display_ext_unit->data.seq_display_ext : NULL;
1345     if (gst_mpeg_video_finalise_mpeg2_sequence_header(seq_hdr, seq_ext,
1346             seq_display_ext))
1347         gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder,
1348             seq_hdr->par_w, seq_hdr->par_h);
1349
1350     status = ensure_context(decoder);
1351     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1352         GST_ERROR("failed to reset context");
1353         return status;
1354     }
1355
1356     if (priv->current_picture) {
1357         /* Re-use current picture where the first field was decoded */
1358         picture = gst_vaapi_picture_new_field(priv->current_picture);
1359         if (!picture) {
1360             GST_ERROR("failed to allocate field picture");
1361             return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1362         }
1363     }
1364     else {
1365         /* Create new picture */
1366         picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
1367         if (!picture) {
1368             GST_ERROR("failed to allocate picture");
1369             return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1370         }
1371     }
1372     gst_vaapi_picture_replace(&priv->current_picture, picture);
1373     gst_vaapi_picture_unref(picture);
1374
1375     status = ensure_quant_matrix(decoder, picture);
1376     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
1377         GST_ERROR("failed to reset quantizer matrix");
1378         return status;
1379     }
1380
1381     status = init_picture(decoder, picture);
1382     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1383         return status;
1384
1385     fill_picture(decoder, picture);
1386     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1387 }
1388
1389 static GstVaapiDecoderStatus
1390 gst_vaapi_decoder_mpeg2_end_frame(GstVaapiDecoder *base_decoder)
1391 {
1392     GstVaapiDecoderMpeg2 * const decoder =
1393         GST_VAAPI_DECODER_MPEG2_CAST(base_decoder);
1394
1395     return decode_current_picture(decoder);
1396 }
1397
1398 static void
1399 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
1400 {
1401     GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1402
1403     gst_vaapi_decoder_mpeg2_destroy(decoder);
1404
1405     G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
1406 }
1407
1408 static void
1409 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
1410 {
1411     GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2_CAST(object);
1412     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
1413     GObjectClass *parent_class;
1414
1415     parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
1416     if (parent_class->constructed)
1417         parent_class->constructed(object);
1418
1419     priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
1420 }
1421
1422 static void
1423 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
1424 {
1425     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
1426     GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
1427
1428     g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
1429
1430     object_class->finalize      = gst_vaapi_decoder_mpeg2_finalize;
1431     object_class->constructed   = gst_vaapi_decoder_mpeg2_constructed;
1432
1433     decoder_class->parse        = gst_vaapi_decoder_mpeg2_parse;
1434     decoder_class->decode       = gst_vaapi_decoder_mpeg2_decode;
1435     decoder_class->start_frame  = gst_vaapi_decoder_mpeg2_start_frame;
1436     decoder_class->end_frame    = gst_vaapi_decoder_mpeg2_end_frame;
1437 }
1438
1439 static void
1440 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
1441 {
1442     GstVaapiDecoderMpeg2Private *priv;
1443
1444     priv                        = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
1445     decoder->priv               = priv;
1446     priv->hw_profile            = GST_VAAPI_PROFILE_UNKNOWN;
1447     priv->profile               = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
1448     priv->profile_changed       = TRUE; /* Allow fallbacks to work */
1449 }
1450
1451 /**
1452  * gst_vaapi_decoder_mpeg2_new:
1453  * @display: a #GstVaapiDisplay
1454  * @caps: a #GstCaps holding codec information
1455  *
1456  * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
1457  * hold extra information like codec-data and pictured coded size.
1458  *
1459  * Return value: the newly allocated #GstVaapiDecoder object
1460  */
1461 GstVaapiDecoder *
1462 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
1463 {
1464     GstVaapiDecoderMpeg2 *decoder;
1465
1466     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
1467     g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
1468
1469     decoder = g_object_new(
1470         GST_VAAPI_TYPE_DECODER_MPEG2,
1471         "display",      display,
1472         "caps",         caps,
1473         NULL
1474     );
1475     if (!decoder->priv->is_constructed) {
1476         g_object_unref(decoder);
1477         return NULL;
1478     }
1479     return GST_VAAPI_DECODER_CAST(decoder);
1480 }