mpeg2: fix crash when there is no free surface to decode into.
[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_priv.h"
34 #include "gstvaapidisplay_priv.h"
35 #include "gstvaapiobject_priv.h"
36
37 #define DEBUG 1
38 #include "gstvaapidebug.h"
39
40 G_DEFINE_TYPE(GstVaapiDecoderMpeg2,
41               gst_vaapi_decoder_mpeg2,
42               GST_VAAPI_TYPE_DECODER);
43
44 #define GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(obj)                \
45     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
46                                  GST_VAAPI_TYPE_DECODER_MPEG2,  \
47                                  GstVaapiDecoderMpeg2Private))
48
49 #define READ_UINT8(br, val, nbits) G_STMT_START {  \
50   if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
51     GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
52     goto failed; \
53   } \
54 } G_STMT_END
55
56 struct _GstVaapiDecoderMpeg2Private {
57     GstVaapiProfile             profile;
58     guint                       width;
59     guint                       height;
60     guint                       fps_n;
61     guint                       fps_d;
62     GstMpegVideoSequenceHdr     seq_hdr;
63     GstMpegVideoSequenceExt     seq_ext;
64     GstMpegVideoPictureHdr      pic_hdr;
65     GstMpegVideoPictureExt      pic_ext;
66     GstMpegVideoQuantMatrixExt  quant_matrix_ext;
67     GstVaapiPicture            *current_picture;
68     GstVaapiPicture            *next_picture;
69     GstVaapiPicture            *prev_picture;
70     GstAdapter                 *adapter;
71     guint                       mb_y;
72     guint                       mb_height;
73     GstClockTime                seq_pts;
74     GstClockTime                gop_pts;
75     GstClockTime                pts_diff;
76     guint                       is_constructed          : 1;
77     guint                       is_opened               : 1;
78     guint                       is_first_field          : 1;
79     guint                       has_seq_ext             : 1;
80     guint                       has_seq_scalable_ext    : 1;
81     guint                       has_pic_ext             : 1;
82     guint                       has_quant_matrix_ext    : 1;
83     guint                       size_changed            : 1;
84     guint                       profile_changed         : 1;
85     guint                       quant_matrix_changed    : 1;
86     guint                       progressive_sequence    : 1;
87     guint                       closed_gop              : 1;
88     guint                       broken_link             : 1;
89 };
90
91 static void
92 gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
93 {
94     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
95
96     gst_vaapi_picture_replace(&priv->current_picture, NULL);
97     gst_vaapi_picture_replace(&priv->next_picture,    NULL);
98     gst_vaapi_picture_replace(&priv->prev_picture,    NULL);
99
100     if (priv->adapter) {
101         gst_adapter_clear(priv->adapter);
102         g_object_unref(priv->adapter);
103         priv->adapter = NULL;
104     }
105 }
106
107 static gboolean
108 gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
109 {
110     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
111
112     gst_vaapi_decoder_mpeg2_close(decoder);
113
114     priv->adapter = gst_adapter_new();
115     if (!priv->adapter)
116         return FALSE;
117     return TRUE;
118 }
119
120 static void
121 gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
122 {
123     gst_vaapi_decoder_mpeg2_close(decoder);
124 }
125
126 static gboolean
127 gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
128 {
129     if (!GST_VAAPI_DECODER_CODEC(decoder))
130         return FALSE;
131     return TRUE;
132 }
133
134 static inline void
135 copy_quant_matrix(guint8 dst[64], const guint8 src[64])
136 {
137     memcpy(dst, src, 64);
138 }
139
140 static GstVaapiDecoderStatus
141 ensure_context(GstVaapiDecoderMpeg2 *decoder)
142 {
143     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
144     GstVaapiProfile profiles[2];
145     GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
146     guint i, n_profiles = 0;
147     gboolean reset_context = FALSE;
148
149     if (priv->profile_changed) {
150         GST_DEBUG("profile changed");
151         priv->profile_changed = FALSE;
152         reset_context         = TRUE;
153
154         profiles[n_profiles++] = priv->profile;
155         if (priv->profile == GST_VAAPI_PROFILE_MPEG2_SIMPLE)
156             profiles[n_profiles++] = GST_VAAPI_PROFILE_MPEG2_MAIN;
157
158         for (i = 0; i < n_profiles; i++) {
159             if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
160                                               profiles[i], entrypoint))
161                 break;
162         }
163         if (i == n_profiles)
164             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
165         priv->profile = profiles[i];
166     }
167
168     if (priv->size_changed) {
169         GST_DEBUG("size changed");
170         priv->size_changed = FALSE;
171         reset_context      = TRUE;
172
173         if (priv->progressive_sequence)
174             priv->mb_height = (priv->height + 15) / 16;
175         else
176             priv->mb_height = (priv->height + 31) / 32 * 2;
177     }
178
179     if (reset_context) {
180         reset_context = gst_vaapi_decoder_ensure_context(
181             GST_VAAPI_DECODER(decoder),
182             priv->profile,
183             entrypoint,
184             priv->width, priv->height
185         );
186         if (!reset_context)
187             return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
188     }
189     return GST_VAAPI_DECODER_STATUS_SUCCESS;
190 }
191
192 static GstVaapiDecoderStatus
193 ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
194 {
195     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
196     VAIQMatrixBufferMPEG2 *iq_matrix;
197     guint8 *intra_quant_matrix = NULL;
198     guint8 *non_intra_quant_matrix = NULL;
199     guint8 *chroma_intra_quant_matrix = NULL;
200     guint8 *chroma_non_intra_quant_matrix = NULL;
201
202     if (!priv->quant_matrix_changed)
203         return GST_VAAPI_DECODER_STATUS_SUCCESS;
204
205     priv->quant_matrix_changed = FALSE;
206
207     picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
208     if (!picture->iq_matrix) {
209         GST_DEBUG("failed to allocate IQ matrix");
210         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
211     }
212     iq_matrix = picture->iq_matrix->param;
213
214     intra_quant_matrix     = priv->seq_hdr.intra_quantizer_matrix;
215     non_intra_quant_matrix = priv->seq_hdr.non_intra_quantizer_matrix;
216     if (priv->has_quant_matrix_ext) {
217         if (priv->quant_matrix_ext.load_intra_quantiser_matrix)
218             intra_quant_matrix = priv->quant_matrix_ext.intra_quantiser_matrix;
219         if (priv->quant_matrix_ext.load_non_intra_quantiser_matrix)
220             non_intra_quant_matrix = priv->quant_matrix_ext.non_intra_quantiser_matrix;
221         if (priv->quant_matrix_ext.load_chroma_intra_quantiser_matrix)
222             chroma_intra_quant_matrix = priv->quant_matrix_ext.chroma_intra_quantiser_matrix;
223         if (priv->quant_matrix_ext.load_chroma_non_intra_quantiser_matrix)
224             chroma_non_intra_quant_matrix = priv->quant_matrix_ext.chroma_non_intra_quantiser_matrix;
225     }
226
227     iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
228     if (intra_quant_matrix)
229         copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
230                           intra_quant_matrix);
231
232     iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
233     if (non_intra_quant_matrix)
234         copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
235                           non_intra_quant_matrix);
236
237     iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
238     if (chroma_intra_quant_matrix)
239         copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
240                           chroma_intra_quant_matrix);
241
242     iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
243     if (chroma_non_intra_quant_matrix)
244         copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
245                           chroma_non_intra_quant_matrix);
246     return GST_VAAPI_DECODER_STATUS_SUCCESS;
247 }
248
249 static inline GstVaapiDecoderStatus
250 render_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
251 {
252     if (!gst_vaapi_picture_output(picture))
253         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
254     return GST_VAAPI_DECODER_STATUS_SUCCESS;
255 }
256
257 static GstVaapiDecoderStatus
258 decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
259 {
260     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
261     GstVaapiPicture * const picture = priv->current_picture;
262     GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
263
264     if (picture) {
265         if (!gst_vaapi_picture_decode(picture))
266             status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
267         if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
268             if ((priv->prev_picture && priv->next_picture) ||
269                 (priv->closed_gop && priv->next_picture))
270                 status = render_picture(decoder, picture);
271         }
272         gst_vaapi_picture_replace(&priv->current_picture, NULL);
273     }
274     return status;
275 }
276
277 static GstVaapiDecoderStatus
278 decode_sequence(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
279 {
280     GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
281     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
282     GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr;
283
284     if (!gst_mpeg_video_parse_sequence_header(seq_hdr, buf, buf_size, 0)) {
285         GST_DEBUG("failed to parse sequence header");
286         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
287     }
288
289     priv->fps_n = seq_hdr->fps_n;
290     priv->fps_d = seq_hdr->fps_d;
291     gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
292
293     priv->seq_pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
294
295     priv->width                 = seq_hdr->width;
296     priv->height                = seq_hdr->height;
297     priv->has_seq_ext           = FALSE;
298     priv->size_changed          = TRUE;
299     priv->quant_matrix_changed  = TRUE;
300     priv->progressive_sequence  = TRUE;
301     return GST_VAAPI_DECODER_STATUS_SUCCESS;
302 }
303
304 static GstVaapiDecoderStatus
305 decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
306 {
307     GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
308     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
309     GstMpegVideoSequenceExt * const seq_ext = &priv->seq_ext;
310     GstVaapiProfile profile;
311     guint width, height;
312
313     if (!gst_mpeg_video_parse_sequence_extension(seq_ext, buf, buf_size, 0)) {
314         GST_DEBUG("failed to parse sequence-extension");
315         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
316     }
317     priv->has_seq_ext = TRUE;
318     priv->progressive_sequence = seq_ext->progressive;
319
320     width  = (priv->width  & 0xffff) | ((guint32)seq_ext->horiz_size_ext << 16);
321     height = (priv->height & 0xffff) | ((guint32)seq_ext->vert_size_ext  << 16);
322     GST_DEBUG("video resolution %ux%u", width, height);
323
324     if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
325         priv->fps_n *= seq_ext->fps_n_ext + 1;
326         priv->fps_d *= seq_ext->fps_d_ext + 1;
327         gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
328     }
329
330     if (priv->width != width) {
331         priv->width = width;
332         priv->size_changed = TRUE;
333     }
334
335     if (priv->height != height) {
336         priv->height = height;
337         priv->size_changed = TRUE;
338     }
339
340     switch (seq_ext->profile) {
341     case GST_MPEG_VIDEO_PROFILE_SIMPLE:
342         profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
343         break;
344     case GST_MPEG_VIDEO_PROFILE_MAIN:
345         profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
346         break;
347     default:
348         GST_DEBUG("unsupported profile %d", seq_ext->profile);
349         return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
350     }
351     if (priv->profile != profile) {
352         priv->profile = profile;
353         priv->profile_changed = TRUE;
354     }
355     return GST_VAAPI_DECODER_STATUS_SUCCESS;
356 }
357
358 static GstVaapiDecoderStatus
359 decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
360 {
361     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
362     GstVaapiDecoderStatus status;
363
364     if (priv->current_picture) {
365         status = decode_current_picture(decoder);
366         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
367             return status;
368         status = render_picture(decoder, priv->current_picture);
369         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
370             return status;
371     }
372
373     if (priv->next_picture) {
374         status = render_picture(decoder, priv->next_picture);
375         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
376             return status;
377     }
378     return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
379 }
380
381 static GstVaapiDecoderStatus
382 decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
383 {
384     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
385     GstMpegVideoQuantMatrixExt * const quant_matrix_ext = &priv->quant_matrix_ext;
386
387     if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix_ext, buf, buf_size, 0)) {
388         GST_DEBUG("failed to parse quant-matrix-extension");
389         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
390     }
391     priv->has_quant_matrix_ext = TRUE;
392     priv->quant_matrix_changed = TRUE;
393     return GST_VAAPI_DECODER_STATUS_SUCCESS;
394 }
395
396 static GstVaapiDecoderStatus
397 decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
398 {
399     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
400     GstMpegVideoGop gop;
401     GstClockTime pts;
402
403     if (!gst_mpeg_video_parse_gop(&gop, buf, buf_size, 0)) {
404         GST_DEBUG("failed to parse GOP");
405         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
406     }
407
408     priv->closed_gop  = gop.closed_gop;
409     priv->broken_link = gop.broken_link;
410
411     GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
412               gop.hour, gop.minute, gop.second, gop.frame,
413               priv->closed_gop, priv->broken_link);
414
415     pts = GST_SECOND * (gop.hour * 3600 + gop.minute * 60 + gop.second);
416     pts += gst_util_uint64_scale(gop.frame, GST_SECOND * priv->fps_d, priv->fps_n);
417     priv->gop_pts = pts;
418     if (!priv->pts_diff)
419         priv->pts_diff = priv->seq_pts - priv->gop_pts;
420
421     priv->is_first_field = TRUE;
422     return GST_VAAPI_DECODER_STATUS_SUCCESS;
423 }
424
425 static GstVaapiDecoderStatus
426 decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
427 {
428     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
429     GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
430     GstVaapiPicture *picture;
431     GstVaapiDecoderStatus status;
432     GstClockTime pts;
433
434     status = ensure_context(decoder);
435     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
436         GST_DEBUG("failed to reset context");
437         return status;
438     }
439
440     if (priv->current_picture) {
441         status = decode_current_picture(decoder);
442         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
443             return status;
444     }
445
446     priv->current_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
447     if (!priv->current_picture) {
448         GST_DEBUG("failed to allocate picture");
449         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
450     }
451     picture = priv->current_picture;
452
453     status = ensure_quant_matrix(decoder, picture);
454     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
455         GST_DEBUG("failed to reset quantizer matrix");
456         return status;
457     }
458
459     if (!gst_mpeg_video_parse_picture_header(pic_hdr, buf, buf_size, 0)) {
460         GST_DEBUG("failed to parse picture header");
461         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
462     }
463     priv->has_pic_ext = FALSE;
464
465     switch (pic_hdr->pic_type) {
466     case GST_MPEG_VIDEO_PICTURE_TYPE_I:
467         picture->type = GST_VAAPI_PICTURE_TYPE_I;
468         break;
469     case GST_MPEG_VIDEO_PICTURE_TYPE_P:
470         picture->type = GST_VAAPI_PICTURE_TYPE_P;
471         break;
472     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
473         picture->type = GST_VAAPI_PICTURE_TYPE_B;
474         break;
475     default:
476         GST_DEBUG("unsupported picture type %d", pic_hdr->pic_type);
477         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
478     }
479
480     priv->mb_y = 0;
481
482     /* Update presentation time */
483     pts = priv->gop_pts;
484     pts += gst_util_uint64_scale(pic_hdr->tsn, GST_SECOND * priv->fps_d, priv->fps_n);
485     picture->pts = pts + priv->pts_diff;
486
487     /* Update reference pictures */
488     if (pic_hdr->pic_type != GST_MPEG_VIDEO_PICTURE_TYPE_B) {
489         GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
490         if (priv->next_picture)
491             status = render_picture(decoder, priv->next_picture);
492         gst_vaapi_picture_replace(&priv->prev_picture, priv->next_picture);
493         gst_vaapi_picture_replace(&priv->next_picture, picture);
494     }
495     return status;
496 }
497
498 static GstVaapiDecoderStatus
499 decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
500 {
501     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
502     GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
503
504     if (!gst_mpeg_video_parse_picture_extension(pic_ext, buf, buf_size, 0)) {
505         GST_DEBUG("failed to parse picture-extension");
506         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
507     }
508     priv->has_pic_ext = TRUE;
509     return GST_VAAPI_DECODER_STATUS_SUCCESS;
510 }
511
512 static inline guint32
513 pack_f_code(guint8 f_code[2][2])
514 {
515     return (((guint32)f_code[0][0] << 12) |
516             ((guint32)f_code[0][1] <<  8) |
517             ((guint32)f_code[1][0] <<  4) |
518             (         f_code[1][1]      ));
519 }
520
521 static gboolean
522 fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
523 {
524     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
525     VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
526     GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
527     GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
528
529     if (!priv->has_pic_ext)
530         return FALSE;
531
532     /* Fill in VAPictureParameterBufferMPEG2 */
533     pic_param->horizontal_size                                          = priv->width;
534     pic_param->vertical_size                                            = priv->height;
535     pic_param->forward_reference_picture                                = VA_INVALID_ID;
536     pic_param->backward_reference_picture                               = VA_INVALID_ID;
537     pic_param->picture_coding_type                                      = pic_hdr->pic_type;
538     pic_param->f_code                                                   = pack_f_code(pic_ext->f_code);
539
540 #define COPY_FIELD(a, b, f) \
541     pic_param->a.b.f = pic_ext->f
542     pic_param->picture_coding_extension.value                           = 0;
543     pic_param->picture_coding_extension.bits.is_first_field             = priv->is_first_field;
544     COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
545     COPY_FIELD(picture_coding_extension, bits, picture_structure);
546     COPY_FIELD(picture_coding_extension, bits, top_field_first);
547     COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
548     COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
549     COPY_FIELD(picture_coding_extension, bits, q_scale_type);
550     COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
551     COPY_FIELD(picture_coding_extension, bits, alternate_scan);
552     COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
553     COPY_FIELD(picture_coding_extension, bits, progressive_frame);
554
555     switch (pic_hdr->pic_type) {
556     case GST_MPEG_VIDEO_PICTURE_TYPE_B:
557         if (priv->next_picture)
558             pic_param->backward_reference_picture = priv->next_picture->surface_id;
559         // fall-through
560     case GST_MPEG_VIDEO_PICTURE_TYPE_P:
561         if (priv->prev_picture)
562             pic_param->forward_reference_picture = priv->prev_picture->surface_id;
563         break;
564     }
565     return TRUE;
566 }
567
568 static GstVaapiDecoderStatus
569 decode_slice(
570     GstVaapiDecoderMpeg2 *decoder,
571     int                   slice_no,
572     guchar               *buf,
573     guint                 buf_size
574 )
575 {
576     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
577     GstVaapiPicture * const picture = priv->current_picture;
578     GstVaapiSlice *slice;
579     VASliceParameterBufferMPEG2 *slice_param;
580     GstVaapiDecoderStatus status;
581     GstBitReader br;
582     guint8 slice_vertical_position_extension;
583     guint8 quantiser_scale_code;
584     guint8 intra_slice_flag, intra_slice = 0;
585     guint8 extra_bit_slice, junk8;
586
587     GST_DEBUG("slice %d @ %p, %u bytes)", slice_no, buf, buf_size);
588
589     if (picture->slices->len == 0) {
590         if (!fill_picture(decoder, picture))
591             return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
592
593         if (!priv->pic_ext.progressive_frame)
594             priv->is_first_field ^= 1;
595     }
596
597     priv->mb_y = slice_no;
598
599     slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder, buf, buf_size);
600     if (!slice) {
601         GST_DEBUG("failed to allocate slice");
602         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
603     }
604     gst_vaapi_picture_add_slice(picture, slice);
605
606     /* Parse slice */
607     gst_bit_reader_init(&br, buf, buf_size);
608     if (priv->height > 2800)
609         READ_UINT8(&br, slice_vertical_position_extension, 3);
610     if (priv->has_seq_scalable_ext) {
611         GST_DEBUG("failed to parse slice %d. Unsupported sequence_scalable_extension()", slice_no);
612         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
613     }
614     READ_UINT8(&br, quantiser_scale_code, 5);
615     READ_UINT8(&br, extra_bit_slice, 1);
616     if (extra_bit_slice == 1) {
617         READ_UINT8(&br, intra_slice_flag, 1);
618         if (intra_slice_flag) {
619             READ_UINT8(&br, intra_slice, 1);
620             READ_UINT8(&br, junk8, 7);
621         }
622         READ_UINT8(&br, extra_bit_slice, 1);
623         while (extra_bit_slice == 1) {
624             READ_UINT8(&br, junk8, 8);
625             READ_UINT8(&br, extra_bit_slice, 1);
626         }
627     }
628
629     /* Fill in VASliceParameterBufferMPEG2 */
630     slice_param                            = slice->param;
631     slice_param->macroblock_offset         = gst_bit_reader_get_pos(&br);
632     slice_param->slice_horizontal_position = 0;
633     slice_param->slice_vertical_position   = priv->mb_y;
634     slice_param->quantiser_scale_code      = quantiser_scale_code;
635     slice_param->intra_slice_flag          = intra_slice;
636
637     /* Commit picture for decoding if we reached the last slice */
638     if (++priv->mb_y >= priv->mb_height) {
639         status = decode_current_picture(decoder);
640         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
641             return status;
642         GST_DEBUG("done");
643     }
644     return GST_VAAPI_DECODER_STATUS_SUCCESS;
645
646 failed:
647     return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
648 }
649
650 static inline gint
651 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
652 {
653     return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
654                                                      0xffffff00, 0x00000100,
655                                                      ofs, size,
656                                                      scp);
657 }
658
659 static GstVaapiDecoderStatus
660 decode_buffer(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
661 {
662     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
663     GstVaapiDecoderStatus status;
664     guchar *buf;
665     guint buf_size, size;
666     guint32 start_code;
667     guint8 type;
668     gint ofs;
669
670     buf      = GST_BUFFER_DATA(buffer);
671     buf_size = GST_BUFFER_SIZE(buffer);
672     if (!buf && buf_size == 0)
673         return decode_sequence_end(decoder);
674
675     gst_adapter_push(priv->adapter, gst_buffer_ref(buffer));
676
677     size   = gst_adapter_available(priv->adapter);
678     status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
679     do {
680         if (size < 8)
681             break;
682         ofs = scan_for_start_code(priv->adapter, 0, size, &start_code);
683         if (ofs < 0)
684             break;
685         gst_adapter_flush(priv->adapter, ofs);
686         size -= ofs;
687
688         status = gst_vaapi_decoder_check_status(decoder);
689         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
690             break;
691
692         if (size < 8)
693             break;
694         ofs = scan_for_start_code(priv->adapter, 4, size - 4, NULL);
695         if (ofs < 0)
696             break;
697         gst_adapter_flush(priv->adapter, 4);
698         size -= ofs;
699
700         buffer   = gst_adapter_take_buffer(priv->adapter, ofs - 4);
701         buf      = GST_BUFFER_DATA(buffer);
702         buf_size = GST_BUFFER_SIZE(buffer);
703
704         type = start_code & 0xff;
705         switch (type) {
706         case GST_MPEG_VIDEO_PACKET_PICTURE:
707             status = decode_picture(decoder, buf, buf_size);
708             break;
709         case GST_MPEG_VIDEO_PACKET_SEQUENCE:
710             status = decode_sequence(decoder, buf, buf_size);
711             break;
712         case GST_MPEG_VIDEO_PACKET_EXTENSION: {
713             const guchar id = buf[0] >> 4;
714             switch (id) {
715             case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
716                 status = decode_sequence_ext(decoder, buf, buf_size);
717                 break;
718             case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
719                 status = decode_quant_matrix_ext(decoder, buf, buf_size);
720                 break;
721             case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
722                 status = decode_picture_ext(decoder, buf, buf_size);
723                 break;
724             default:
725                 // Ignore unknown extensions
726                 GST_DEBUG("unsupported start-code extension (0x%02x)", id);
727                 break;
728             }
729             break;
730         }
731         case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
732             status = decode_sequence_end(decoder);
733             break;
734         case GST_MPEG_VIDEO_PACKET_GOP:
735             status = decode_gop(decoder, buf, buf_size);
736             break;
737         case GST_MPEG_VIDEO_PACKET_USER_DATA:
738             // Ignore user-data packets
739             status = GST_VAAPI_DECODER_STATUS_SUCCESS;
740             break;
741         default:
742             if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
743                 type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
744                 status = decode_slice(
745                     decoder,
746                     type - GST_MPEG_VIDEO_PACKET_SLICE_MIN,
747                     buf, buf_size
748                 );
749                 break;
750             }
751             else if (type >= 0xb9 && type <= 0xff) {
752                 // Ignore system start codes (PES headers)
753                 status = GST_VAAPI_DECODER_STATUS_SUCCESS;
754                 break;
755             }
756             GST_DEBUG("unsupported start code (0x%02x)", type);
757             status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
758             break;
759         }
760         gst_buffer_unref(buffer);
761     } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
762     return status;
763 }
764
765 GstVaapiDecoderStatus
766 gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base, GstBuffer *buffer)
767 {
768     GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(base);
769     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
770
771     g_return_val_if_fail(priv->is_constructed,
772                          GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
773
774     if (!priv->is_opened) {
775         priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder, buffer);
776         if (!priv->is_opened)
777             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
778     }
779     return decode_buffer(decoder, buffer);
780 }
781
782 static void
783 gst_vaapi_decoder_mpeg2_finalize(GObject *object)
784 {
785     GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
786
787     gst_vaapi_decoder_mpeg2_destroy(decoder);
788
789     G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
790 }
791
792 static void
793 gst_vaapi_decoder_mpeg2_constructed(GObject *object)
794 {
795     GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
796     GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
797     GObjectClass *parent_class;
798
799     parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
800     if (parent_class->constructed)
801         parent_class->constructed(object);
802
803     priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
804 }
805
806 static void
807 gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
808 {
809     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
810     GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
811
812     g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
813
814     object_class->finalize      = gst_vaapi_decoder_mpeg2_finalize;
815     object_class->constructed   = gst_vaapi_decoder_mpeg2_constructed;
816
817     decoder_class->decode       = gst_vaapi_decoder_mpeg2_decode;
818 }
819
820 static void
821 gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
822 {
823     GstVaapiDecoderMpeg2Private *priv;
824
825     priv                        = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
826     decoder->priv               = priv;
827     priv->width                 = 0;
828     priv->height                = 0;
829     priv->fps_n                 = 0;
830     priv->fps_d                 = 0;
831     priv->profile               = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
832     priv->current_picture       = NULL;
833     priv->next_picture          = NULL;
834     priv->prev_picture          = NULL;
835     priv->adapter               = NULL;
836     priv->mb_y                  = 0;
837     priv->mb_height             = 0;
838     priv->seq_pts               = GST_CLOCK_TIME_NONE;
839     priv->gop_pts               = GST_CLOCK_TIME_NONE;
840     priv->pts_diff              = 0;
841     priv->is_constructed        = FALSE;
842     priv->is_opened             = FALSE;
843     priv->is_first_field        = FALSE;
844     priv->has_seq_ext           = FALSE;
845     priv->has_seq_scalable_ext  = FALSE;
846     priv->has_pic_ext           = FALSE;
847     priv->has_quant_matrix_ext  = FALSE;
848     priv->size_changed          = FALSE;
849     priv->profile_changed       = FALSE;
850     priv->quant_matrix_changed  = FALSE;
851     priv->progressive_sequence  = FALSE;
852     priv->closed_gop            = FALSE;
853     priv->broken_link           = FALSE;
854 }
855
856 /**
857  * gst_vaapi_decoder_mpeg2_new:
858  * @display: a #GstVaapiDisplay
859  * @caps: a #GstCaps holding codec information
860  *
861  * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
862  * hold extra information like codec-data and pictured coded size.
863  *
864  * Return value: the newly allocated #GstVaapiDecoder object
865  */
866 GstVaapiDecoder *
867 gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
868 {
869     GstVaapiDecoderMpeg2 *decoder;
870
871     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
872     g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
873
874     decoder = g_object_new(
875         GST_VAAPI_TYPE_DECODER_MPEG2,
876         "display",      display,
877         "caps",         caps,
878         NULL
879     );
880     if (!decoder->priv->is_constructed) {
881         g_object_unref(decoder);
882         return NULL;
883     }
884     return GST_VAAPI_DECODER_CAST(decoder);
885 }