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