6fed7ef0ac1615d2c8f45c86127a24f2e80f9412
[profile/ivi/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapidecoder_h264.c
1 /*
2  *  gstvaapidecoder_h264.c - H.264 decoder
3  *
4  *  Copyright (C) 2011-2012 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_h264
24  * @short_description: H.264 decoder
25  */
26
27 #include "sysdeps.h"
28 #include <string.h>
29 #include <stdlib.h>
30 #include <gst/base/gstadapter.h>
31 #include <gst/codecparsers/gsth264parser.h>
32 #include "gstvaapidecoder_h264.h"
33 #include "gstvaapidecoder_objects.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 /* Defined to 1 if strict ordering of DPB is needed. Only useful for debug */
42 #define USE_STRICT_DPB_ORDERING 0
43
44 typedef struct _GstVaapiFrameStore              GstVaapiFrameStore;
45 typedef struct _GstVaapiFrameStoreClass         GstVaapiFrameStoreClass;
46 typedef struct _GstVaapiPictureH264             GstVaapiPictureH264;
47 typedef struct _GstVaapiPictureH264Class        GstVaapiPictureH264Class;
48 typedef struct _GstVaapiSliceH264               GstVaapiSliceH264;
49 typedef struct _GstVaapiSliceH264Class          GstVaapiSliceH264Class;
50
51 // Used for field_poc[]
52 #define TOP_FIELD       0
53 #define BOTTOM_FIELD    1
54
55 /* ------------------------------------------------------------------------- */
56 /* --- H.264 Pictures                                                    --- */
57 /* ------------------------------------------------------------------------- */
58
59 #define GST_VAAPI_TYPE_PICTURE_H264 \
60     (gst_vaapi_picture_h264_get_type())
61
62 #define GST_VAAPI_PICTURE_H264_CAST(obj) \
63     ((GstVaapiPictureH264 *)(obj))
64
65 #define GST_VAAPI_PICTURE_H264(obj)                             \
66     (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
67                                 GST_VAAPI_TYPE_PICTURE_H264,    \
68                                 GstVaapiPictureH264))
69
70 #define GST_VAAPI_PICTURE_H264_CLASS(klass)                     \
71     (G_TYPE_CHECK_CLASS_CAST((klass),                           \
72                              GST_VAAPI_TYPE_PICTURE_H264,       \
73                              GstVaapiPictureH264Class))
74
75 #define GST_VAAPI_IS_PICTURE_H264(obj) \
76     (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_PICTURE_H264))
77
78 #define GST_VAAPI_IS_PICTURE_H264_CLASS(klass) \
79     (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_PICTURE_H264))
80
81 #define GST_VAAPI_PICTURE_H264_GET_CLASS(obj)                   \
82     (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
83                                GST_VAAPI_TYPE_PICTURE_H264,     \
84                                GstVaapiPictureH264Class))
85
86 /*
87  * Extended picture flags:
88  *
89  * @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
90  * @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
91  *     "used for short-term reference"
92  * @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
93  *     "used for long-term reference"
94  * @GST_VAAPI_PICTURE_FLAGS_REFERENCE: mask covering any kind of
95  *     reference picture (short-term reference or long-term reference)
96  */
97 enum {
98     GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
99
100     GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE = (
101         GST_VAAPI_PICTURE_FLAG_REFERENCE),
102     GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE = (
103         GST_VAAPI_PICTURE_FLAG_REFERENCE | (GST_VAAPI_PICTURE_FLAG_LAST << 1)),
104     GST_VAAPI_PICTURE_FLAGS_REFERENCE = (
105         GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
106         GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE),
107 };
108
109 #define GST_VAAPI_PICTURE_IS_IDR(picture) \
110     (GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR))
111
112 #define GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture)      \
113     ((GST_VAAPI_PICTURE_FLAGS(picture) &                        \
114       GST_VAAPI_PICTURE_FLAGS_REFERENCE) ==                     \
115      GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE)
116
117 #define GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture)       \
118     ((GST_VAAPI_PICTURE_FLAGS(picture) &                        \
119       GST_VAAPI_PICTURE_FLAGS_REFERENCE) ==                     \
120      GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE)
121
122 struct _GstVaapiPictureH264 {
123     GstVaapiPicture             base;
124     GstH264PPS                 *pps;
125     guint                       structure;
126     gint32                      field_poc[2];
127     gint32                      frame_num;              // Original frame_num from slice_header()
128     gint32                      frame_num_wrap;         // Temporary for ref pic marking: FrameNumWrap
129     gint32                      long_term_frame_idx;    // Temporary for ref pic marking: LongTermFrameIdx
130     gint32                      pic_num;                // Temporary for ref pic marking: PicNum
131     gint32                      long_term_pic_num;      // Temporary for ref pic marking: LongTermPicNum
132     GstVaapiPictureH264        *other_field;            // Temporary for ref pic marking: other field in the same frame store
133     guint                       output_flag             : 1;
134     guint                       output_needed           : 1;
135 };
136
137 struct _GstVaapiPictureH264Class {
138     /*< private >*/
139     GstVaapiPictureClass        parent_class;
140 };
141
142 GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiPictureH264,
143                             gst_vaapi_picture_h264,
144                             GST_VAAPI_TYPE_PICTURE)
145
146 static void
147 gst_vaapi_picture_h264_destroy(GstVaapiPictureH264 *decoder)
148 {
149 }
150
151 static gboolean
152 gst_vaapi_picture_h264_create(
153     GstVaapiPictureH264                      *picture,
154     const GstVaapiCodecObjectConstructorArgs *args
155 )
156 {
157     return TRUE;
158 }
159
160 static void
161 gst_vaapi_picture_h264_init(GstVaapiPictureH264 *picture)
162 {
163     picture->field_poc[0]       = G_MAXINT32;
164     picture->field_poc[1]       = G_MAXINT32;
165     picture->output_needed      = FALSE;
166 }
167
168 static inline GstVaapiPictureH264 *
169 gst_vaapi_picture_h264_new(GstVaapiDecoderH264 *decoder)
170 {
171     GstVaapiCodecObject *object;
172
173     g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
174
175     object = gst_vaapi_codec_object_new(
176         GST_VAAPI_TYPE_PICTURE_H264,
177         GST_VAAPI_CODEC_BASE(decoder),
178         NULL, sizeof(VAPictureParameterBufferH264),
179         NULL, 0
180     );
181     if (!object)
182         return NULL;
183     return GST_VAAPI_PICTURE_H264_CAST(object);
184 }
185
186 static inline void
187 gst_vaapi_picture_h264_set_reference(
188     GstVaapiPictureH264 *picture,
189     guint                reference_flags,
190     gboolean             other_field
191 )
192 {
193     g_return_if_fail(GST_VAAPI_IS_PICTURE_H264(picture));
194
195     GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
196     GST_VAAPI_PICTURE_FLAG_SET(picture, reference_flags);
197
198     if (!other_field || !(picture = picture->other_field))
199         return;
200     GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
201     GST_VAAPI_PICTURE_FLAG_SET(picture, reference_flags);
202 }
203
204 static inline GstVaapiPictureH264 *
205 gst_vaapi_picture_h264_new_field(GstVaapiPictureH264 *picture)
206 {
207     GstVaapiPicture *base_picture;
208
209     g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), NULL);
210
211     base_picture = gst_vaapi_picture_new_field(&picture->base);
212     if (!base_picture)
213         return NULL;
214     return GST_VAAPI_PICTURE_H264_CAST(base_picture);
215 }
216
217 static inline GstVaapiSliceH264 *
218 gst_vaapi_picture_h264_get_last_slice(GstVaapiPictureH264 *picture)
219 {
220     g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), NULL);
221
222     if (G_UNLIKELY(picture->base.slices->len < 1))
223         return NULL;
224     return g_ptr_array_index(picture->base.slices,
225         picture->base.slices->len - 1);
226 }
227
228 /* ------------------------------------------------------------------------- */
229 /* --- Slices                                                            --- */
230 /* ------------------------------------------------------------------------- */
231
232 #define GST_VAAPI_TYPE_SLICE_H264 \
233     (gst_vaapi_slice_h264_get_type())
234
235 #define GST_VAAPI_SLICE_H264_CAST(obj) \
236     ((GstVaapiSliceH264 *)(obj))
237
238 #define GST_VAAPI_SLICE_H264(obj)                               \
239     (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
240                                 GST_VAAPI_TYPE_SLICE_H264,      \
241                                 GstVaapiSliceH264))
242
243 #define GST_VAAPI_SLICE_H264_CLASS(klass)                       \
244     (G_TYPE_CHECK_CLASS_CAST((klass),                           \
245                              GST_VAAPI_TYPE_SLICE_H264,         \
246                              GstVaapiSliceH264Class))
247
248 #define GST_VAAPI_IS_SLICE_H264(obj) \
249     (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SLICE_H264))
250
251 #define GST_VAAPI_IS_SLICE_H264_CLASS(klass) \
252     (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SLICE_H264))
253
254 #define GST_VAAPI_SLICE_H264_GET_CLASS(obj)                     \
255     (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
256                                GST_VAAPI_TYPE_SLICE_H264,       \
257                                GstVaapiSliceH264Class))
258
259 struct _GstVaapiSliceH264 {
260     GstVaapiSlice               base;
261     GstH264SliceHdr             slice_hdr;              // parsed slice_header()
262 };
263
264 struct _GstVaapiSliceH264Class {
265     /*< private >*/
266     GstVaapiSliceClass          parent_class;
267 };
268
269 GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiSliceH264,
270                             gst_vaapi_slice_h264,
271                             GST_VAAPI_TYPE_SLICE)
272
273 static void
274 gst_vaapi_slice_h264_destroy(GstVaapiSliceH264 *slice)
275 {
276 }
277
278 static gboolean
279 gst_vaapi_slice_h264_create(
280     GstVaapiSliceH264                        *slice,
281     const GstVaapiCodecObjectConstructorArgs *args
282 )
283 {
284     return TRUE;
285 }
286
287 static void
288 gst_vaapi_slice_h264_init(GstVaapiSliceH264 *slice)
289 {
290 }
291
292 static inline GstVaapiSliceH264 *
293 gst_vaapi_slice_h264_new(
294     GstVaapiDecoderH264 *decoder,
295     const guint8        *data,
296     guint                data_size
297 )
298 {
299     GstVaapiCodecObject *object;
300
301     g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
302
303     object = gst_vaapi_codec_object_new(
304         GST_VAAPI_TYPE_SLICE_H264,
305         GST_VAAPI_CODEC_BASE(decoder),
306         NULL, sizeof(VASliceParameterBufferH264),
307         data, data_size
308     );
309     if (!object)
310         return NULL;
311     return GST_VAAPI_SLICE_H264_CAST(object);
312 }
313
314 /* ------------------------------------------------------------------------- */
315 /* --- Frame Buffers (DPB)                                               --- */
316 /* ------------------------------------------------------------------------- */
317
318 #define GST_VAAPI_TYPE_FRAME_STORE \
319     (gst_vaapi_frame_store_get_type())
320
321 #define GST_VAAPI_FRAME_STORE_CAST(obj) \
322     ((GstVaapiFrameStore *)(obj))
323
324 #define GST_VAAPI_FRAME_STORE(obj)                              \
325     (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
326                                 GST_VAAPI_TYPE_FRAME_STORE,     \
327                                 GstVaapiFrameStore))
328
329 #define GST_VAAPI_FRAME_STORE_CLASS(klass)                      \
330     (G_TYPE_CHECK_CLASS_CAST((klass),                           \
331                              GST_VAAPI_TYPE_FRAME_STORE,        \
332                              GstVaapiFrameStoreClass))
333
334 #define GST_VAAPI_IS_FRAME_STORE(obj) \
335     (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_FRAME_STORE))
336
337 #define GST_VAAPI_IS_FRAME_STORE_CLASS(klass) \
338     (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_FRAME_STORE))
339
340 #define GST_VAAPI_FRAME_STORE_GET_CLASS(obj)                   \
341     (G_TYPE_INSTANCE_GET_CLASS((obj),                          \
342                                GST_VAAPI_TYPE_FRAME_STORE,     \
343                                GstVaapiFrameStoreClass))
344
345 struct _GstVaapiFrameStore {
346     /*< private >*/
347     GstMiniObject               parent_instance;
348
349     guint                       structure;
350     GstVaapiPictureH264        *buffers[2];
351     guint                       num_buffers;
352     guint                       output_needed;
353 };
354
355 struct _GstVaapiFrameStoreClass {
356     /*< private >*/
357     GstMiniObjectClass          parent_class;
358 };
359
360 G_DEFINE_TYPE(GstVaapiFrameStore, gst_vaapi_frame_store, GST_TYPE_MINI_OBJECT)
361
362 static void
363 gst_vaapi_frame_store_finalize(GstMiniObject *object)
364 {
365     GstVaapiFrameStore * const fs = GST_VAAPI_FRAME_STORE_CAST(object);
366     GstMiniObjectClass *parent_class;
367     guint i;
368
369     for (i = 0; i < fs->num_buffers; i++)
370         gst_vaapi_picture_replace(&fs->buffers[i], NULL);
371
372     parent_class = GST_MINI_OBJECT_CLASS(gst_vaapi_frame_store_parent_class);
373     if (parent_class->finalize)
374         parent_class->finalize(object);
375 }
376
377 static void
378 gst_vaapi_frame_store_init(GstVaapiFrameStore *fs)
379 {
380 }
381
382 static void
383 gst_vaapi_frame_store_class_init(GstVaapiFrameStoreClass *klass)
384 {
385     GstMiniObjectClass * const object_class = GST_MINI_OBJECT_CLASS(klass);
386
387     object_class->finalize = gst_vaapi_frame_store_finalize;
388 }
389
390 static inline gpointer
391 _gst_vaapi_frame_store_new(void)
392 {
393     return gst_mini_object_new(GST_VAAPI_TYPE_FRAME_STORE);
394 }
395
396 static GstVaapiFrameStore *
397 gst_vaapi_frame_store_new(GstVaapiPictureH264 *picture)
398 {
399     GstVaapiFrameStore *fs;
400
401     g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), NULL);
402
403     fs = _gst_vaapi_frame_store_new();
404     if (!fs)
405         return NULL;
406
407     fs->structure       = picture->structure;
408     fs->buffers[0]      = gst_vaapi_picture_ref(picture);
409     fs->num_buffers     = 1;
410     fs->output_needed   = picture->output_needed;
411     return fs;
412 }
413
414 static gboolean
415 gst_vaapi_frame_store_add(GstVaapiFrameStore *fs, GstVaapiPictureH264 *picture)
416 {
417     guint field;
418
419     g_return_val_if_fail(GST_VAAPI_IS_FRAME_STORE(fs), FALSE);
420     g_return_val_if_fail(fs->num_buffers == 1, FALSE);
421     g_return_val_if_fail(GST_VAAPI_IS_PICTURE_H264(picture), FALSE);
422     g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FRAME(picture), FALSE);
423
424     gst_vaapi_picture_replace(&fs->buffers[fs->num_buffers++], picture);
425     if (picture->output_flag) {
426         picture->output_needed = TRUE;
427         fs->output_needed++;
428     }
429
430     fs->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
431
432     field = picture->structure == GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD ?
433         TOP_FIELD : BOTTOM_FIELD;
434     g_return_val_if_fail(fs->buffers[0]->field_poc[field] == G_MAXINT32, FALSE);
435     fs->buffers[0]->field_poc[field] = picture->field_poc[field];
436     g_return_val_if_fail(picture->field_poc[!field] == G_MAXINT32, FALSE);
437     picture->field_poc[!field] = fs->buffers[0]->field_poc[!field];
438     return TRUE;
439 }
440
441 static gboolean
442 gst_vaapi_frame_store_split_fields(GstVaapiFrameStore *fs)
443 {
444     GstVaapiPictureH264 * const first_field = fs->buffers[0];
445     GstVaapiPictureH264 *second_field;
446
447     g_return_val_if_fail(fs->num_buffers == 1, FALSE);
448
449     first_field->base.structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
450     GST_VAAPI_PICTURE_FLAG_SET(first_field, GST_VAAPI_PICTURE_FLAG_INTERLACED);
451
452     second_field = gst_vaapi_picture_h264_new_field(first_field);
453     if (!second_field)
454         return FALSE;
455     gst_vaapi_picture_replace(&fs->buffers[fs->num_buffers++], second_field);
456     gst_vaapi_picture_unref(second_field);
457
458     second_field->frame_num    = first_field->frame_num;
459     second_field->field_poc[0] = first_field->field_poc[0];
460     second_field->field_poc[1] = first_field->field_poc[1];
461     second_field->output_flag  = first_field->output_flag;
462     if (second_field->output_flag) {
463         second_field->output_needed = TRUE;
464         fs->output_needed++;
465     }
466     return TRUE;
467 }
468
469 static inline gboolean
470 gst_vaapi_frame_store_has_frame(GstVaapiFrameStore *fs)
471 {
472     return fs->structure == GST_VAAPI_PICTURE_STRUCTURE_FRAME;
473 }
474
475 static inline gboolean
476 gst_vaapi_frame_store_has_reference(GstVaapiFrameStore *fs)
477 {
478     guint i;
479
480     for (i = 0; i < fs->num_buffers; i++) {
481         if (GST_VAAPI_PICTURE_IS_REFERENCE(fs->buffers[i]))
482             return TRUE;
483     }
484     return FALSE;
485 }
486
487 #define gst_vaapi_frame_store_ref(fs) \
488     gst_mini_object_ref(GST_MINI_OBJECT(fs))
489
490 #define gst_vaapi_frame_store_unref(fs) \
491     gst_mini_object_unref(GST_MINI_OBJECT(fs))
492
493 #define gst_vaapi_frame_store_replace(old_fs_p, new_fs)         \
494     gst_mini_object_replace((GstMiniObject **)(old_fs_p),       \
495                             (GstMiniObject *)(new_fs))
496
497 /* ------------------------------------------------------------------------- */
498 /* --- H.264 Decoder                                                     --- */
499 /* ------------------------------------------------------------------------- */
500
501 G_DEFINE_TYPE(GstVaapiDecoderH264,
502               gst_vaapi_decoder_h264,
503               GST_VAAPI_TYPE_DECODER)
504
505 #define GST_VAAPI_DECODER_H264_GET_PRIVATE(obj)                 \
506     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
507                                  GST_VAAPI_TYPE_DECODER_H264,   \
508                                  GstVaapiDecoderH264Private))
509
510 struct _GstVaapiDecoderH264Private {
511     GstAdapter                 *adapter;
512     GstH264NalParser           *parser;
513     /* Last decoded SPS. May not be the last activated one. Just here because
514        it may not fit stack memory allocation in decode_sps() */
515     GstH264SPS                  last_sps;
516     /* Last decoded PPS. May not be the last activated one. Just here because
517        it may not fit stack memory allocation in decode_pps() */
518     GstH264PPS                  last_pps;
519     /* Temporary slice header. Just here because it may not fit stack
520        memory allocation in decode_slice() */
521     GstH264SliceHdr             temp_slice_hdr;
522     GstVaapiPictureH264        *current_picture;
523     GstVaapiFrameStore         *prev_frame;
524     GstVaapiFrameStore         *dpb[16];
525     guint                       dpb_count;
526     guint                       dpb_size;
527     GstVaapiProfile             profile;
528     GstVaapiEntrypoint          entrypoint;
529     GstVaapiChromaType          chroma_type;
530     GstVaapiPictureH264        *short_ref[32];
531     guint                       short_ref_count;
532     GstVaapiPictureH264        *long_ref[32];
533     guint                       long_ref_count;
534     GstVaapiPictureH264        *RefPicList0[32];
535     guint                       RefPicList0_count;
536     GstVaapiPictureH264        *RefPicList1[32];
537     guint                       RefPicList1_count;
538     guint                       nal_length_size;
539     guint                       mb_width;
540     guint                       mb_height;
541     gint32                      field_poc[2];           // 0:TopFieldOrderCnt / 1:BottomFieldOrderCnt
542     gint32                      poc_msb;                // PicOrderCntMsb
543     gint32                      poc_lsb;                // pic_order_cnt_lsb (from slice_header())
544     gint32                      prev_poc_msb;           // prevPicOrderCntMsb
545     gint32                      prev_poc_lsb;           // prevPicOrderCntLsb
546     gint32                      frame_num_offset;       // FrameNumOffset
547     gint32                      frame_num;              // frame_num (from slice_header())
548     gint32                      prev_frame_num;         // prevFrameNum
549     gboolean                    prev_pic_has_mmco5;     // prevMmco5Pic
550     gboolean                    prev_pic_structure;     // previous picture structure
551     guint                       is_constructed          : 1;
552     guint                       is_opened               : 1;
553     guint                       is_avc                  : 1;
554     guint                       got_sps                 : 1;
555     guint                       got_pps                 : 1;
556     guint                       has_context             : 1;
557     guint                       progressive_sequence    : 1;
558 };
559
560 static gboolean
561 exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
562
563 /* Get number of reference frames to use */
564 static guint
565 get_max_dec_frame_buffering(GstH264SPS *sps)
566 {
567     guint max_dec_frame_buffering, MaxDpbMbs, PicSizeMbs;
568
569     /* Table A-1 - Level limits */
570     switch (sps->level_idc) {
571     case 10: MaxDpbMbs = 396;    break;
572     case 11: MaxDpbMbs = 900;    break;
573     case 12: MaxDpbMbs = 2376;   break;
574     case 13: MaxDpbMbs = 2376;   break;
575     case 20: MaxDpbMbs = 2376;   break;
576     case 21: MaxDpbMbs = 4752;   break;
577     case 22: MaxDpbMbs = 8100;   break;
578     case 30: MaxDpbMbs = 8100;   break;
579     case 31: MaxDpbMbs = 18000;  break;
580     case 32: MaxDpbMbs = 20480;  break;
581     case 40: MaxDpbMbs = 32768;  break;
582     case 41: MaxDpbMbs = 32768;  break;
583     case 42: MaxDpbMbs = 34816;  break;
584     case 50: MaxDpbMbs = 110400; break;
585     case 51: MaxDpbMbs = 184320; break;
586     default:
587         g_assert(0 && "unhandled level");
588         break;
589     }
590
591     PicSizeMbs = ((sps->pic_width_in_mbs_minus1 + 1) *
592                   (sps->pic_height_in_map_units_minus1 + 1) *
593                   (sps->frame_mbs_only_flag ? 1 : 2));
594     max_dec_frame_buffering = MaxDpbMbs / PicSizeMbs;
595
596     /* VUI parameters */
597     if (sps->vui_parameters_present_flag) {
598         GstH264VUIParams * const vui_params = &sps->vui_parameters;
599         if (vui_params->bitstream_restriction_flag)
600             max_dec_frame_buffering = vui_params->max_dec_frame_buffering;
601         else {
602             switch (sps->profile_idc) {
603             case 44:  // CAVLC 4:4:4 Intra profile
604             case 86:  // Scalable High profile
605             case 100: // High profile
606             case 110: // High 10 profile
607             case 122: // High 4:2:2 profile
608             case 244: // High 4:4:4 Predictive profile
609                 if (sps->constraint_set3_flag)
610                     max_dec_frame_buffering = 0;
611                 break;
612             }
613         }
614     }
615
616     if (max_dec_frame_buffering > 16)
617         max_dec_frame_buffering = 16;
618     else if (max_dec_frame_buffering < sps->num_ref_frames)
619         max_dec_frame_buffering = sps->num_ref_frames;
620     return MAX(1, max_dec_frame_buffering);
621 }
622
623 static void
624 array_remove_index_fast(void *array, guint *array_length_ptr, guint index)
625 {
626     gpointer * const entries = array;
627     guint num_entries = *array_length_ptr;
628
629     g_return_if_fail(index < num_entries);
630
631     if (index != --num_entries)
632         entries[index] = entries[num_entries];
633     entries[num_entries] = NULL;
634     *array_length_ptr = num_entries;
635 }
636
637 #if 1
638 static inline void
639 array_remove_index(void *array, guint *array_length_ptr, guint index)
640 {
641     array_remove_index_fast(array, array_length_ptr, index);
642 }
643 #else
644 static void
645 array_remove_index(void *array, guint *array_length_ptr, guint index)
646 {
647     gpointer * const entries = array;
648     const guint num_entries = *array_length_ptr - 1;
649     guint i;
650
651     g_return_if_fail(index <= num_entries);
652
653     for (i = index; i < num_entries; i++)
654         entries[i] = entries[i + 1];
655     entries[num_entries] = NULL;
656     *array_length_ptr = num_entries;
657 }
658 #endif
659
660 #define ARRAY_REMOVE_INDEX(array, index) \
661     array_remove_index(array, &array##_count, index)
662
663 static void
664 dpb_remove_index(GstVaapiDecoderH264 *decoder, guint index)
665 {
666     GstVaapiDecoderH264Private * const priv = decoder->priv;
667     guint i, num_frames = --priv->dpb_count;
668
669     if (USE_STRICT_DPB_ORDERING) {
670         for (i = index; i < num_frames; i++)
671             gst_vaapi_frame_store_replace(&priv->dpb[i], priv->dpb[i + 1]);
672     }
673     else if (index != num_frames)
674         gst_vaapi_frame_store_replace(&priv->dpb[index], priv->dpb[num_frames]);
675     gst_vaapi_frame_store_replace(&priv->dpb[num_frames], NULL);
676 }
677
678 static gboolean
679 dpb_output(
680     GstVaapiDecoderH264 *decoder,
681     GstVaapiFrameStore  *fs,
682     GstVaapiPictureH264 *picture
683 )
684 {
685     picture->output_needed = FALSE;
686
687     if (fs) {
688         if (--fs->output_needed > 0)
689             return TRUE;
690         picture = fs->buffers[0];
691     }
692
693     /* XXX: update cropping rectangle */
694     return gst_vaapi_picture_output(GST_VAAPI_PICTURE_CAST(picture));
695 }
696
697 static inline void
698 dpb_evict(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture, guint i)
699 {
700     GstVaapiFrameStore * const fs = decoder->priv->dpb[i];
701
702     if (!fs->output_needed && !gst_vaapi_frame_store_has_reference(fs))
703         dpb_remove_index(decoder, i);
704 }
705
706 static gboolean
707 dpb_bump(GstVaapiDecoderH264 *decoder)
708 {
709     GstVaapiDecoderH264Private * const priv = decoder->priv;
710     GstVaapiPictureH264 *found_picture = NULL;
711     guint i, j, found_index;
712     gboolean success;
713
714     for (i = 0; i < priv->dpb_count; i++) {
715         GstVaapiFrameStore * const fs = priv->dpb[i];
716         if (!fs->output_needed)
717             continue;
718         for (j = 0; j < fs->num_buffers; j++) {
719             GstVaapiPictureH264 * const picture = fs->buffers[j];
720             if (!picture->output_needed)
721                 continue;
722             if (!found_picture || found_picture->base.poc > picture->base.poc)
723                 found_picture = picture, found_index = i;
724         }
725     }
726     if (!found_picture)
727         return FALSE;
728
729     success = dpb_output(decoder, priv->dpb[found_index], found_picture);
730     dpb_evict(decoder, found_picture, found_index);
731     return success;
732 }
733
734 static void
735 dpb_clear(GstVaapiDecoderH264 *decoder)
736 {
737     GstVaapiDecoderH264Private * const priv = decoder->priv;
738     guint i;
739
740     for (i = 0; i < priv->dpb_count; i++)
741         gst_vaapi_frame_store_replace(&priv->dpb[i], NULL);
742     priv->dpb_count = 0;
743
744     gst_vaapi_frame_store_replace(&priv->prev_frame, NULL);
745 }
746
747 static void
748 dpb_flush(GstVaapiDecoderH264 *decoder)
749 {
750     while (dpb_bump(decoder))
751         ;
752     dpb_clear(decoder);
753 }
754
755 static gboolean
756 dpb_add(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
757 {
758     GstVaapiDecoderH264Private * const priv = decoder->priv;
759     GstVaapiFrameStore *fs;
760     guint i, j;
761
762     // Remove all unused pictures
763     if (!GST_VAAPI_PICTURE_IS_IDR(picture)) {
764         i = 0;
765         while (i < priv->dpb_count) {
766             GstVaapiFrameStore * const fs = priv->dpb[i];
767             if (!fs->output_needed && !gst_vaapi_frame_store_has_reference(fs))
768                 dpb_remove_index(decoder, i);
769             else
770                 i++;
771         }
772     }
773
774     // Check if picture is the second field and the first field is still in DPB
775     fs = priv->prev_frame;
776     if (fs && !gst_vaapi_frame_store_has_frame(fs)) {
777         g_return_val_if_fail(fs->num_buffers == 1, FALSE);
778         g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FRAME(picture), FALSE);
779         g_return_val_if_fail(!GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture), FALSE);
780         return gst_vaapi_frame_store_add(fs, picture);
781     }
782
783     // Create new frame store, and split fields if necessary
784     fs = gst_vaapi_frame_store_new(picture);
785     if (!fs)
786         return FALSE;
787     gst_vaapi_frame_store_replace(&priv->prev_frame, fs);
788     gst_vaapi_frame_store_unref(fs);
789
790     if (!priv->progressive_sequence && gst_vaapi_frame_store_has_frame(fs)) {
791         if (!gst_vaapi_frame_store_split_fields(fs))
792             return FALSE;
793     }
794
795     // C.4.5.1 - Storage and marking of a reference decoded picture into the DPB
796     if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
797         while (priv->dpb_count == priv->dpb_size) {
798             if (!dpb_bump(decoder))
799                 return FALSE;
800         }
801         gst_vaapi_frame_store_replace(&priv->dpb[priv->dpb_count++], fs);
802         if (picture->output_flag) {
803             picture->output_needed = TRUE;
804             fs->output_needed++;
805         }
806     }
807
808     // C.4.5.2 - Storage and marking of a non-reference decoded picture into the DPB
809     else {
810         if (!picture->output_flag)
811             return TRUE;
812         while (priv->dpb_count == priv->dpb_size) {
813             gboolean found_picture = FALSE;
814             for (i = 0; !found_picture && i < priv->dpb_count; i++) {
815                 GstVaapiFrameStore * const fs = priv->dpb[i];
816                 if (!fs->output_needed)
817                     continue;
818                 for (j = 0; !found_picture && j < fs->num_buffers; j++)
819                     found_picture = fs->buffers[j]->output_needed &&
820                         fs->buffers[j]->base.poc < picture->base.poc;
821             }
822             if (!found_picture)
823                 return dpb_output(decoder, NULL, picture);
824             if (!dpb_bump(decoder))
825                 return FALSE;
826         }
827         gst_vaapi_frame_store_replace(&priv->dpb[priv->dpb_count++], fs);
828         picture->output_needed = TRUE;
829         fs->output_needed++;
830     }
831     return TRUE;
832 }
833
834 static inline void
835 dpb_reset(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
836 {
837     GstVaapiDecoderH264Private * const priv = decoder->priv;
838
839     priv->dpb_size = get_max_dec_frame_buffering(sps);
840     GST_DEBUG("DPB size %u", priv->dpb_size);
841 }
842
843 static GstVaapiDecoderStatus
844 get_status(GstH264ParserResult result)
845 {
846     GstVaapiDecoderStatus status;
847
848     switch (result) {
849     case GST_H264_PARSER_OK:
850         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
851         break;
852     case GST_H264_PARSER_NO_NAL_END:
853         status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
854         break;
855     case GST_H264_PARSER_ERROR:
856         status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
857         break;
858     default:
859         status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
860         break;
861     }
862     return status;
863 }
864
865 static void
866 gst_vaapi_decoder_h264_clear_buffer(GstVaapiDecoder *base)
867 {
868     GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(base);
869     GstVaapiDecoderH264Private * const priv = decoder->priv;
870
871     gst_vaapi_picture_replace(&priv->current_picture, NULL);
872
873     dpb_clear(decoder);
874
875     if (priv->adapter) {
876         gst_adapter_clear(priv->adapter);
877     }
878 }
879
880 static void
881 gst_vaapi_decoder_h264_close(GstVaapiDecoderH264 *decoder)
882 {
883     GstVaapiDecoderH264Private * const priv = decoder->priv;
884
885     gst_vaapi_decoder_h264_clear_buffer(GST_VAAPI_DECODER_CAST(decoder));
886
887     if (priv->parser) {
888         gst_h264_nal_parser_free(priv->parser);
889         priv->parser = NULL;
890     }
891
892     if (priv->adapter) {
893         g_object_unref(priv->adapter);
894         priv->adapter = NULL;
895     }
896 }
897
898 static gboolean
899 gst_vaapi_decoder_h264_open(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
900 {
901     GstVaapiDecoderH264Private * const priv = decoder->priv;
902
903     gst_vaapi_decoder_h264_close(decoder);
904
905     priv->adapter = gst_adapter_new();
906     if (!priv->adapter)
907         return FALSE;
908
909     priv->parser = gst_h264_nal_parser_new();
910     if (!priv->parser)
911         return FALSE;
912     return TRUE;
913 }
914
915 static void
916 gst_vaapi_decoder_h264_destroy(GstVaapiDecoderH264 *decoder)
917 {
918     gst_vaapi_decoder_h264_close(decoder);
919 }
920
921 static gboolean
922 gst_vaapi_decoder_h264_create(GstVaapiDecoderH264 *decoder)
923 {
924     if (!GST_VAAPI_DECODER_CODEC(decoder))
925         return FALSE;
926     return TRUE;
927 }
928
929 static guint
930 h264_get_profile(GstH264SPS *sps)
931 {
932     guint profile = 0;
933
934     switch (sps->profile_idc) {
935     case 66:
936         profile = GST_VAAPI_PROFILE_H264_BASELINE;
937         break;
938     case 77:
939         profile = GST_VAAPI_PROFILE_H264_MAIN;
940         break;
941     case 100:
942         profile = GST_VAAPI_PROFILE_H264_HIGH;
943         break;
944     }
945     return profile;
946 }
947
948 static guint
949 h264_get_chroma_type(GstH264SPS *sps)
950 {
951     guint chroma_type = 0;
952
953     switch (sps->chroma_format_idc) {
954     case 1:
955         chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
956         break;
957     case 2:
958         chroma_type = GST_VAAPI_CHROMA_TYPE_YUV422;
959         break;
960     case 3:
961         if (!sps->separate_colour_plane_flag)
962             chroma_type = GST_VAAPI_CHROMA_TYPE_YUV444;
963         break;
964     }
965     return chroma_type;
966 }
967
968 static GstVaapiProfile
969 get_profile(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
970 {
971     GstVaapiDecoderH264Private * const priv = decoder->priv;
972     GstVaapiDisplay * const display = GST_VAAPI_DECODER_DISPLAY(decoder);
973     GstVaapiProfile profile, profiles[2];
974     guint i, n_profiles = 0;
975
976     profile = h264_get_profile(sps);
977     if (!profile)
978         return GST_VAAPI_PROFILE_UNKNOWN;
979
980     profiles[n_profiles++] = profile;
981     switch (profile) {
982     case GST_VAAPI_PROFILE_H264_MAIN:
983         profiles[n_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
984         break;
985     default:
986         break;
987     }
988
989     /* If the preferred profile (profiles[0]) matches one that we already
990        found, then just return it now instead of searching for it again */
991     if (profiles[0] == priv->profile)
992         return priv->profile;
993
994     for (i = 0; i < n_profiles; i++) {
995         if (gst_vaapi_display_has_decoder(display, profiles[i], priv->entrypoint))
996             return profiles[i];
997     }
998     return GST_VAAPI_PROFILE_UNKNOWN;
999 }
1000
1001 static GstVaapiDecoderStatus
1002 ensure_context(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
1003 {
1004     GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER_CAST(decoder);
1005     GstVaapiDecoderH264Private * const priv = decoder->priv;
1006     GstVaapiContextInfo info;
1007     GstVaapiProfile profile;
1008     GstVaapiChromaType chroma_type;
1009     gboolean reset_context = FALSE;
1010     guint mb_width, mb_height;
1011
1012     profile = get_profile(decoder, sps);
1013     if (!profile) {
1014         GST_ERROR("unsupported profile_idc %u", sps->profile_idc);
1015         return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
1016     }
1017
1018     if (priv->profile != profile) {
1019         GST_DEBUG("profile changed");
1020         reset_context = TRUE;
1021         priv->profile = profile;
1022     }
1023
1024     chroma_type = h264_get_chroma_type(sps);
1025     if (!chroma_type || chroma_type != GST_VAAPI_CHROMA_TYPE_YUV420) {
1026         GST_ERROR("unsupported chroma_format_idc %u", sps->chroma_format_idc);
1027         return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1028     }
1029
1030     if (priv->chroma_type != chroma_type) {
1031         GST_DEBUG("chroma format changed");
1032         reset_context     = TRUE;
1033         priv->chroma_type = chroma_type;
1034     }
1035
1036     mb_width  = sps->pic_width_in_mbs_minus1 + 1;
1037     mb_height = (sps->pic_height_in_map_units_minus1 + 1) <<
1038         !sps->frame_mbs_only_flag;
1039     if (priv->mb_width != mb_width || priv->mb_height != mb_height) {
1040         GST_DEBUG("size changed");
1041         reset_context   = TRUE;
1042         priv->mb_width  = mb_width;
1043         priv->mb_height = mb_height;
1044     }
1045
1046     priv->progressive_sequence = sps->frame_mbs_only_flag;
1047 #if 0
1048     /* XXX: we only output complete frames for now */
1049     gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
1050 #endif
1051
1052     gst_vaapi_decoder_set_pixel_aspect_ratio(
1053         base_decoder,
1054         sps->vui_parameters.par_n,
1055         sps->vui_parameters.par_d
1056     );
1057
1058     if (!reset_context && priv->has_context)
1059         return GST_VAAPI_DECODER_STATUS_SUCCESS;
1060
1061     /* XXX: fix surface size when cropping is implemented */
1062     info.profile    = priv->profile;
1063     info.entrypoint = priv->entrypoint;
1064     info.width      = sps->width;
1065     info.height     = sps->height;
1066     info.ref_frames = get_max_dec_frame_buffering(sps);
1067
1068     if (!gst_vaapi_decoder_ensure_context(GST_VAAPI_DECODER(decoder), &info))
1069         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1070     priv->has_context = TRUE;
1071
1072     /* Reset DPB */
1073     dpb_reset(decoder, sps);
1074     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1075 }
1076
1077 static void
1078 fill_iq_matrix_4x4(VAIQMatrixBufferH264 *iq_matrix, const GstH264PPS *pps)
1079 {
1080     const guint8 (* const ScalingList4x4)[6][16] = &pps->scaling_lists_4x4;
1081     guint i, j;
1082
1083     /* There are always 6 4x4 scaling lists */
1084     g_assert(G_N_ELEMENTS(iq_matrix->ScalingList4x4) == 6);
1085     g_assert(G_N_ELEMENTS(iq_matrix->ScalingList4x4[0]) == 16);
1086
1087     if (sizeof(iq_matrix->ScalingList4x4[0][0]) == 1)
1088         memcpy(iq_matrix->ScalingList4x4, *ScalingList4x4,
1089                sizeof(iq_matrix->ScalingList4x4));
1090     else {
1091         for (i = 0; i < G_N_ELEMENTS(iq_matrix->ScalingList4x4); i++) {
1092             for (j = 0; j < G_N_ELEMENTS(iq_matrix->ScalingList4x4[i]); j++)
1093                 iq_matrix->ScalingList4x4[i][j] = (*ScalingList4x4)[i][j];
1094         }
1095     }
1096 }
1097
1098 static void
1099 fill_iq_matrix_8x8(VAIQMatrixBufferH264 *iq_matrix, const GstH264PPS *pps)
1100 {
1101     const guint8 (* const ScalingList8x8)[6][64] = &pps->scaling_lists_8x8;
1102     const GstH264SPS * const sps = pps->sequence;
1103     guint i, j, n;
1104
1105     /* If chroma_format_idc != 3, there are up to 2 8x8 scaling lists */
1106     if (!pps->transform_8x8_mode_flag)
1107         return;
1108
1109     g_assert(G_N_ELEMENTS(iq_matrix->ScalingList8x8) >= 2);
1110     g_assert(G_N_ELEMENTS(iq_matrix->ScalingList8x8[0]) == 64);
1111
1112     if (sizeof(iq_matrix->ScalingList8x8[0][0]) == 1)
1113         memcpy(iq_matrix->ScalingList8x8, *ScalingList8x8,
1114                sizeof(iq_matrix->ScalingList8x8));
1115     else {
1116         n = (sps->chroma_format_idc != 3) ? 2 : 6;
1117         for (i = 0; i < n; i++) {
1118             for (j = 0; j < G_N_ELEMENTS(iq_matrix->ScalingList8x8[i]); j++)
1119                 iq_matrix->ScalingList8x8[i][j] = (*ScalingList8x8)[i][j];
1120         }
1121     }
1122 }
1123
1124 static GstVaapiDecoderStatus
1125 ensure_quant_matrix(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
1126 {
1127     GstVaapiPicture * const base_picture = &picture->base;
1128     GstH264PPS * const pps = picture->pps;
1129     GstH264SPS * const sps = pps->sequence;
1130     VAIQMatrixBufferH264 *iq_matrix;
1131
1132     base_picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(H264, decoder);
1133     if (!base_picture->iq_matrix) {
1134         GST_ERROR("failed to allocate IQ matrix");
1135         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
1136     }
1137     iq_matrix = base_picture->iq_matrix->param;
1138
1139     /* XXX: we can only support 4:2:0 or 4:2:2 since ScalingLists8x8[]
1140        is not large enough to hold lists for 4:4:4 */
1141     if (sps->chroma_format_idc == 3)
1142         return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
1143
1144     fill_iq_matrix_4x4(iq_matrix, pps);
1145     fill_iq_matrix_8x8(iq_matrix, pps);
1146
1147     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1148 }
1149
1150 static GstVaapiDecoderStatus
1151 decode_current_picture(GstVaapiDecoderH264 *decoder)
1152 {
1153     GstVaapiDecoderH264Private * const priv = decoder->priv;
1154     GstVaapiPictureH264 * const picture = priv->current_picture;
1155     GstVaapiDecoderStatus status;
1156
1157     if (!picture)
1158         return GST_VAAPI_DECODER_STATUS_SUCCESS;
1159
1160     status = ensure_context(decoder, picture->pps->sequence);
1161     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1162         return status;
1163
1164     if (!exec_ref_pic_marking(decoder, picture))
1165         goto error;
1166     if (!dpb_add(decoder, picture))
1167         goto error;
1168     if (!gst_vaapi_picture_decode(GST_VAAPI_PICTURE_CAST(picture)))
1169         goto error;
1170     if (priv->prev_frame && gst_vaapi_frame_store_has_frame(priv->prev_frame))
1171         gst_vaapi_picture_replace(&priv->current_picture, NULL);
1172     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1173
1174 error:
1175     /* XXX: fix for cases where first field failed to be decoded */
1176     gst_vaapi_picture_replace(&priv->current_picture, NULL);
1177     return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
1178 }
1179
1180 static GstVaapiDecoderStatus
1181 decode_sps(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
1182 {
1183     GstVaapiDecoderH264Private * const priv = decoder->priv;
1184     GstH264SPS * const sps = &priv->last_sps;
1185     GstH264ParserResult result;
1186
1187     GST_DEBUG("decode SPS");
1188
1189     memset(sps, 0, sizeof(*sps));
1190     result = gst_h264_parser_parse_sps(priv->parser, nalu, sps, TRUE);
1191     if (result != GST_H264_PARSER_OK) {
1192         priv->got_sps = FALSE;
1193         return get_status(result);
1194     }
1195
1196     priv->got_sps = TRUE;
1197     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1198 }
1199
1200 static GstVaapiDecoderStatus
1201 decode_pps(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
1202 {
1203     GstVaapiDecoderH264Private * const priv = decoder->priv;
1204     GstH264PPS * const pps = &priv->last_pps;
1205     GstH264ParserResult result;
1206
1207     GST_DEBUG("decode PPS");
1208
1209     memset(pps, 0, sizeof(*pps));
1210     result = gst_h264_parser_parse_pps(priv->parser, nalu, pps);
1211     if (result != GST_H264_PARSER_OK) {
1212         priv->got_pps = FALSE;
1213         return get_status(result);
1214     }
1215
1216     priv->got_pps = TRUE;
1217     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1218 }
1219
1220 static GstVaapiDecoderStatus
1221 decode_sei(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
1222 {
1223     GstVaapiDecoderH264Private * const priv = decoder->priv;
1224     GstH264SEIMessage sei;
1225     GstH264ParserResult result;
1226
1227     GST_DEBUG("decode SEI");
1228
1229     memset(&sei, 0, sizeof(sei));
1230     result = gst_h264_parser_parse_sei(priv->parser, nalu, &sei);
1231     if (result != GST_H264_PARSER_OK) {
1232         GST_WARNING("failed to decode SEI, payload type:%d", sei.payloadType);
1233         return get_status(result);
1234     }
1235
1236     return GST_VAAPI_DECODER_STATUS_SUCCESS;
1237 }
1238
1239 static GstVaapiDecoderStatus
1240 decode_sequence_end(GstVaapiDecoderH264 *decoder)
1241 {
1242     GstVaapiDecoderStatus status;
1243
1244     GST_DEBUG("decode sequence-end");
1245
1246     status = decode_current_picture(decoder);
1247     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
1248         return status;
1249
1250     dpb_flush(decoder);
1251     return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
1252 }
1253
1254 /* 8.2.1.1 - Decoding process for picture order count type 0 */
1255 static void
1256 init_picture_poc_0(
1257     GstVaapiDecoderH264 *decoder,
1258     GstVaapiPictureH264 *picture,
1259     GstH264SliceHdr     *slice_hdr
1260 )
1261 {
1262     GstVaapiDecoderH264Private * const priv = decoder->priv;
1263     GstH264PPS * const pps = slice_hdr->pps;
1264     GstH264SPS * const sps = pps->sequence;
1265     const gint32 MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1266     gint32 temp_poc;
1267
1268     GST_DEBUG("decode picture order count type 0");
1269
1270     if (GST_VAAPI_PICTURE_IS_IDR(picture)) {
1271         priv->prev_poc_msb = 0;
1272         priv->prev_poc_lsb = 0;
1273     }
1274     else if (priv->prev_pic_has_mmco5) {
1275         priv->prev_poc_msb = 0;
1276         priv->prev_poc_lsb =
1277             (priv->prev_pic_structure == GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD ?
1278              0 : priv->field_poc[TOP_FIELD]);
1279     }
1280     else {
1281         priv->prev_poc_msb = priv->poc_msb;
1282         priv->prev_poc_lsb = priv->poc_lsb;
1283     }
1284
1285     // (8-3)
1286     priv->poc_lsb = slice_hdr->pic_order_cnt_lsb;
1287     if (priv->poc_lsb < priv->prev_poc_lsb &&
1288         (priv->prev_poc_lsb - priv->poc_lsb) >= (MaxPicOrderCntLsb / 2))
1289         priv->poc_msb = priv->prev_poc_msb + MaxPicOrderCntLsb;
1290     else if (priv->poc_lsb > priv->prev_poc_lsb &&
1291              (priv->poc_lsb - priv->prev_poc_lsb) > (MaxPicOrderCntLsb / 2))
1292         priv->poc_msb = priv->prev_poc_msb - MaxPicOrderCntLsb;
1293     else
1294         priv->poc_msb = priv->prev_poc_msb;
1295
1296     temp_poc = priv->poc_msb + priv->poc_lsb;
1297     switch (picture->structure) {
1298     case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1299         // (8-4, 8-5)
1300         priv->field_poc[TOP_FIELD] = temp_poc;
1301         priv->field_poc[BOTTOM_FIELD] = temp_poc +
1302             slice_hdr->delta_pic_order_cnt_bottom;
1303         break;
1304     case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1305         // (8-4)
1306         priv->field_poc[TOP_FIELD] = temp_poc;
1307         break;
1308     case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1309         // (8-5)
1310         priv->field_poc[BOTTOM_FIELD] = temp_poc;
1311         break;
1312     }
1313 }
1314
1315 /* 8.2.1.2 - Decoding process for picture order count type 1 */
1316 static void
1317 init_picture_poc_1(
1318     GstVaapiDecoderH264 *decoder,
1319     GstVaapiPictureH264 *picture,
1320     GstH264SliceHdr     *slice_hdr
1321 )
1322 {
1323     GstVaapiDecoderH264Private * const priv = decoder->priv;
1324     GstH264PPS * const pps = slice_hdr->pps;
1325     GstH264SPS * const sps = pps->sequence;
1326     const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1327     gint32 prev_frame_num_offset, abs_frame_num, expected_poc;
1328     guint i;
1329
1330     GST_DEBUG("decode picture order count type 1");
1331
1332     if (priv->prev_pic_has_mmco5)
1333         prev_frame_num_offset = 0;
1334     else
1335         prev_frame_num_offset = priv->frame_num_offset;
1336
1337     // (8-6)
1338     if (GST_VAAPI_PICTURE_IS_IDR(picture))
1339         priv->frame_num_offset = 0;
1340     else if (priv->prev_frame_num > priv->frame_num)
1341         priv->frame_num_offset = prev_frame_num_offset + MaxFrameNum;
1342     else
1343         priv->frame_num_offset = prev_frame_num_offset;
1344
1345     // (8-7)
1346     if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
1347         abs_frame_num = priv->frame_num_offset + priv->frame_num;
1348     else
1349         abs_frame_num = 0;
1350     if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture) && abs_frame_num > 0)
1351         abs_frame_num = abs_frame_num - 1;
1352
1353     if (abs_frame_num > 0) {
1354         gint32 expected_delta_per_poc_cycle;
1355         gint32 poc_cycle_cnt, frame_num_in_poc_cycle;
1356
1357         expected_delta_per_poc_cycle = 0;
1358         for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
1359             expected_delta_per_poc_cycle += sps->offset_for_ref_frame[i];
1360
1361         // (8-8)
1362         poc_cycle_cnt = (abs_frame_num - 1) /
1363             sps->num_ref_frames_in_pic_order_cnt_cycle;
1364         frame_num_in_poc_cycle = (abs_frame_num - 1) %
1365             sps->num_ref_frames_in_pic_order_cnt_cycle;
1366
1367         // (8-9)
1368         expected_poc = poc_cycle_cnt * expected_delta_per_poc_cycle;
1369         for (i = 0; i <= frame_num_in_poc_cycle; i++)
1370             expected_poc += sps->offset_for_ref_frame[i];
1371     }
1372     else
1373         expected_poc = 0;
1374     if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
1375         expected_poc += sps->offset_for_non_ref_pic;
1376
1377     // (8-10)
1378     switch (picture->structure) {
1379     case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
1380         priv->field_poc[TOP_FIELD] = expected_poc +
1381             slice_hdr->delta_pic_order_cnt[0];
1382         priv->field_poc[BOTTOM_FIELD] = priv->field_poc[TOP_FIELD] +
1383             sps->offset_for_top_to_bottom_field +
1384             slice_hdr->delta_pic_order_cnt[1];
1385         break;
1386     case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
1387         priv->field_poc[TOP_FIELD] = expected_poc +
1388             slice_hdr->delta_pic_order_cnt[0];
1389         break;
1390     case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
1391         priv->field_poc[BOTTOM_FIELD] = expected_poc + 
1392             sps->offset_for_top_to_bottom_field +
1393             slice_hdr->delta_pic_order_cnt[0];
1394         break;
1395     }
1396 }
1397
1398 /* 8.2.1.3 - Decoding process for picture order count type 2 */
1399 static void
1400 init_picture_poc_2(
1401     GstVaapiDecoderH264 *decoder,
1402     GstVaapiPictureH264 *picture,
1403     GstH264SliceHdr     *slice_hdr
1404 )
1405 {
1406     GstVaapiDecoderH264Private * const priv = decoder->priv;
1407     GstH264PPS * const pps = slice_hdr->pps;
1408     GstH264SPS * const sps = pps->sequence;
1409     const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1410     gint32 prev_frame_num_offset, temp_poc;
1411
1412     GST_DEBUG("decode picture order count type 2");
1413
1414     if (priv->prev_pic_has_mmco5)
1415         prev_frame_num_offset = 0;
1416     else
1417         prev_frame_num_offset = priv->frame_num_offset;
1418
1419     // (8-11)
1420     if (GST_VAAPI_PICTURE_IS_IDR(picture))
1421         priv->frame_num_offset = 0;
1422     else if (priv->prev_frame_num > priv->frame_num)
1423         priv->frame_num_offset = prev_frame_num_offset + MaxFrameNum;
1424     else
1425         priv->frame_num_offset = prev_frame_num_offset;
1426
1427     // (8-12)
1428     if (GST_VAAPI_PICTURE_IS_IDR(picture))
1429         temp_poc = 0;
1430     else if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
1431         temp_poc = 2 * (priv->frame_num_offset + priv->frame_num) - 1;
1432     else
1433         temp_poc = 2 * (priv->frame_num_offset + priv->frame_num);
1434
1435     // (8-13)
1436     if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
1437         priv->field_poc[TOP_FIELD] = temp_poc;
1438     if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
1439         priv->field_poc[BOTTOM_FIELD] = temp_poc;
1440 }
1441
1442 /* 8.2.1 - Decoding process for picture order count */
1443 static void
1444 init_picture_poc(
1445     GstVaapiDecoderH264 *decoder,
1446     GstVaapiPictureH264 *picture,
1447     GstH264SliceHdr     *slice_hdr
1448 )
1449 {
1450     GstVaapiDecoderH264Private * const priv = decoder->priv;
1451     GstH264PPS * const pps = slice_hdr->pps;
1452     GstH264SPS * const sps = pps->sequence;
1453
1454     switch (sps->pic_order_cnt_type) {
1455     case 0:
1456         init_picture_poc_0(decoder, picture, slice_hdr);
1457         break;
1458     case 1:
1459         init_picture_poc_1(decoder, picture, slice_hdr);
1460         break;
1461     case 2:
1462         init_picture_poc_2(decoder, picture, slice_hdr);
1463         break;
1464     }
1465
1466     if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
1467         picture->field_poc[TOP_FIELD] = priv->field_poc[TOP_FIELD];
1468     if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
1469         picture->field_poc[BOTTOM_FIELD] = priv->field_poc[BOTTOM_FIELD];
1470     picture->base.poc = MIN(picture->field_poc[0], picture->field_poc[1]);
1471 }
1472
1473 static int
1474 compare_picture_pic_num_dec(const void *a, const void *b)
1475 {
1476     const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1477     const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1478
1479     return picB->pic_num - picA->pic_num;
1480 }
1481
1482 static int
1483 compare_picture_long_term_pic_num_inc(const void *a, const void *b)
1484 {
1485     const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1486     const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1487
1488     return picA->long_term_pic_num - picB->long_term_pic_num;
1489 }
1490
1491 static int
1492 compare_picture_poc_dec(const void *a, const void *b)
1493 {
1494     const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1495     const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1496
1497     return picB->base.poc - picA->base.poc;
1498 }
1499
1500 static int
1501 compare_picture_poc_inc(const void *a, const void *b)
1502 {
1503     const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1504     const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1505
1506     return picA->base.poc - picB->base.poc;
1507 }
1508
1509 static int
1510 compare_picture_frame_num_wrap_dec(const void *a, const void *b)
1511 {
1512     const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1513     const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1514
1515     return picB->frame_num_wrap - picA->frame_num_wrap;
1516 }
1517
1518 static int
1519 compare_picture_long_term_frame_idx_inc(const void *a, const void *b)
1520 {
1521     const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
1522     const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
1523
1524     return picA->long_term_frame_idx - picB->long_term_frame_idx;
1525 }
1526
1527 /* 8.2.4.1 - Decoding process for picture numbers */
1528 static void
1529 init_picture_refs_pic_num(
1530     GstVaapiDecoderH264 *decoder,
1531     GstVaapiPictureH264 *picture,
1532     GstH264SliceHdr     *slice_hdr
1533 )
1534 {
1535     GstVaapiDecoderH264Private * const priv = decoder->priv;
1536     GstH264PPS * const pps = slice_hdr->pps;
1537     GstH264SPS * const sps = pps->sequence;
1538     const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
1539     guint i;
1540
1541     GST_DEBUG("decode picture numbers");
1542
1543     for (i = 0; i < priv->short_ref_count; i++) {
1544         GstVaapiPictureH264 * const pic = priv->short_ref[i];
1545
1546         // (8-27)
1547         if (pic->frame_num > priv->frame_num)
1548             pic->frame_num_wrap = pic->frame_num - MaxFrameNum;
1549         else
1550             pic->frame_num_wrap = pic->frame_num;
1551
1552         // (8-28, 8-30, 8-31)
1553         if (GST_VAAPI_PICTURE_IS_FRAME(picture))
1554             pic->pic_num = pic->frame_num_wrap;
1555         else {
1556             if (pic->structure == picture->structure)
1557                 pic->pic_num = 2 * pic->frame_num_wrap + 1;
1558             else
1559                 pic->pic_num = 2 * pic->frame_num_wrap;
1560         }
1561     }
1562
1563     for (i = 0; i < priv->long_ref_count; i++) {
1564         GstVaapiPictureH264 * const pic = priv->long_ref[i];
1565
1566         // (8-29, 8-32, 8-33)
1567         if (GST_VAAPI_PICTURE_IS_FRAME(picture))
1568             pic->long_term_pic_num = pic->long_term_frame_idx;
1569         else {
1570             if (pic->structure == picture->structure)
1571                 pic->long_term_pic_num = 2 * pic->long_term_frame_idx + 1;
1572             else
1573                 pic->long_term_pic_num = 2 * pic->long_term_frame_idx;
1574         }
1575     }
1576 }
1577
1578 #define SORT_REF_LIST(list, n, compare_func) \
1579     qsort(list, n, sizeof(*(list)), compare_picture_##compare_func)
1580
1581 static void
1582 init_picture_refs_fields_1(
1583     guint                picture_structure,
1584     GstVaapiPictureH264 *RefPicList[32],
1585     guint               *RefPicList_count,
1586     GstVaapiPictureH264 *ref_list[32],
1587     guint                ref_list_count
1588 )
1589 {
1590     guint i, j, n;
1591
1592     i = 0;
1593     j = 0;
1594     n = *RefPicList_count;
1595     do {
1596         g_assert(n < 32);
1597         for (; i < ref_list_count; i++) {
1598             if (ref_list[i]->structure == picture_structure) {
1599                 RefPicList[n++] = ref_list[i++];
1600                 break;
1601             }
1602         }
1603         for (; j < ref_list_count; j++) {
1604             if (ref_list[j]->structure != picture_structure) {
1605                 RefPicList[n++] = ref_list[j++];
1606                 break;
1607             }
1608         }
1609     } while (i < ref_list_count || j < ref_list_count);
1610     *RefPicList_count = n;
1611 }
1612
1613 static inline void
1614 init_picture_refs_fields(
1615     GstVaapiPictureH264 *picture,
1616     GstVaapiPictureH264 *RefPicList[32],
1617     guint               *RefPicList_count,
1618     GstVaapiPictureH264 *short_ref[32],
1619     guint                short_ref_count,
1620     GstVaapiPictureH264 *long_ref[32],
1621     guint                long_ref_count
1622 )
1623 {
1624     guint n = 0;
1625
1626     /* 8.2.4.2.5 - reference picture lists in fields */
1627     init_picture_refs_fields_1(picture->structure, RefPicList, &n,
1628         short_ref, short_ref_count);
1629     init_picture_refs_fields_1(picture->structure, RefPicList, &n,
1630         long_ref, long_ref_count);
1631     *RefPicList_count = n;
1632 }
1633
1634 static void
1635 init_picture_refs_p_slice(
1636     GstVaapiDecoderH264 *decoder,
1637     GstVaapiPictureH264 *picture,
1638     GstH264SliceHdr     *slice_hdr
1639 )
1640 {
1641     GstVaapiDecoderH264Private * const priv = decoder->priv;
1642     GstVaapiPictureH264 **ref_list;
1643     guint i;
1644
1645     GST_DEBUG("decode reference picture list for P and SP slices");
1646
1647     if (GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1648         /* 8.2.4.2.1 - P and SP slices in frames */
1649         if (priv->short_ref_count > 0) {
1650             ref_list = priv->RefPicList0;
1651             for (i = 0; i < priv->short_ref_count; i++)
1652                 ref_list[i] = priv->short_ref[i];
1653             SORT_REF_LIST(ref_list, i, pic_num_dec);
1654             priv->RefPicList0_count += i;
1655         }
1656
1657         if (priv->long_ref_count > 0) {
1658             ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1659             for (i = 0; i < priv->long_ref_count; i++)
1660                 ref_list[i] = priv->long_ref[i];
1661             SORT_REF_LIST(ref_list, i, long_term_pic_num_inc);
1662             priv->RefPicList0_count += i;
1663         }
1664     }
1665     else {
1666         /* 8.2.4.2.2 - P and SP slices in fields */
1667         GstVaapiPictureH264 *short_ref[32];
1668         guint short_ref_count = 0;
1669         GstVaapiPictureH264 *long_ref[32];
1670         guint long_ref_count = 0;
1671
1672         if (priv->short_ref_count > 0) {
1673             for (i = 0; i < priv->short_ref_count; i++)
1674                 short_ref[i] = priv->short_ref[i];
1675             SORT_REF_LIST(short_ref, i, frame_num_wrap_dec);
1676             short_ref_count = i;
1677         }
1678
1679         if (priv->long_ref_count > 0) {
1680             for (i = 0; i < priv->long_ref_count; i++)
1681                 long_ref[i] = priv->long_ref[i];
1682             SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
1683             long_ref_count = i;
1684         }
1685
1686         init_picture_refs_fields(
1687             picture,
1688             priv->RefPicList0, &priv->RefPicList0_count,
1689             short_ref,          short_ref_count,
1690             long_ref,           long_ref_count
1691         );
1692     }
1693 }
1694
1695 static void
1696 init_picture_refs_b_slice(
1697     GstVaapiDecoderH264 *decoder,
1698     GstVaapiPictureH264 *picture,
1699     GstH264SliceHdr     *slice_hdr
1700 )
1701 {
1702     GstVaapiDecoderH264Private * const priv = decoder->priv;
1703     GstVaapiPictureH264 **ref_list;
1704     guint i, n;
1705
1706     GST_DEBUG("decode reference picture list for B slices");
1707
1708     if (GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1709         /* 8.2.4.2.3 - B slices in frames */
1710
1711         /* RefPicList0 */
1712         if (priv->short_ref_count > 0) {
1713             // 1. Short-term references
1714             ref_list = priv->RefPicList0;
1715             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1716                 if (priv->short_ref[i]->base.poc < picture->base.poc)
1717                     ref_list[n++] = priv->short_ref[i];
1718             }
1719             SORT_REF_LIST(ref_list, n, poc_dec);
1720             priv->RefPicList0_count += n;
1721
1722             ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1723             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1724                 if (priv->short_ref[i]->base.poc >= picture->base.poc)
1725                     ref_list[n++] = priv->short_ref[i];
1726             }
1727             SORT_REF_LIST(ref_list, n, poc_inc);
1728             priv->RefPicList0_count += n;
1729         }
1730
1731         if (priv->long_ref_count > 0) {
1732             // 2. Long-term references
1733             ref_list = &priv->RefPicList0[priv->RefPicList0_count];
1734             for (n = 0, i = 0; i < priv->long_ref_count; i++)
1735                 ref_list[n++] = priv->long_ref[i];
1736             SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
1737             priv->RefPicList0_count += n;
1738         }
1739
1740         /* RefPicList1 */
1741         if (priv->short_ref_count > 0) {
1742             // 1. Short-term references
1743             ref_list = priv->RefPicList1;
1744             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1745                 if (priv->short_ref[i]->base.poc > picture->base.poc)
1746                     ref_list[n++] = priv->short_ref[i];
1747             }
1748             SORT_REF_LIST(ref_list, n, poc_inc);
1749             priv->RefPicList1_count += n;
1750
1751             ref_list = &priv->RefPicList1[priv->RefPicList1_count];
1752             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1753                 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1754                     ref_list[n++] = priv->short_ref[i];
1755             }
1756             SORT_REF_LIST(ref_list, n, poc_dec);
1757             priv->RefPicList1_count += n;
1758         }
1759
1760         if (priv->long_ref_count > 0) {
1761             // 2. Long-term references
1762             ref_list = &priv->RefPicList1[priv->RefPicList1_count];
1763             for (n = 0, i = 0; i < priv->long_ref_count; i++)
1764                 ref_list[n++] = priv->long_ref[i];
1765             SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
1766             priv->RefPicList1_count += n;
1767         }
1768     }
1769     else {
1770         /* 8.2.4.2.4 - B slices in fields */
1771         GstVaapiPictureH264 *short_ref0[32];
1772         guint short_ref0_count = 0;
1773         GstVaapiPictureH264 *short_ref1[32];
1774         guint short_ref1_count = 0;
1775         GstVaapiPictureH264 *long_ref[32];
1776         guint long_ref_count = 0;
1777
1778         /* refFrameList0ShortTerm */
1779         if (priv->short_ref_count > 0) {
1780             ref_list = short_ref0;
1781             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1782                 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1783                     ref_list[n++] = priv->short_ref[i];
1784             }
1785             SORT_REF_LIST(ref_list, n, poc_dec);
1786             short_ref0_count += n;
1787
1788             ref_list = &short_ref0[short_ref0_count];
1789             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1790                 if (priv->short_ref[i]->base.poc > picture->base.poc)
1791                     ref_list[n++] = priv->short_ref[i];
1792             }
1793             SORT_REF_LIST(ref_list, n, poc_inc);
1794             short_ref0_count += n;
1795         }
1796
1797         /* refFrameList1ShortTerm */
1798         if (priv->short_ref_count > 0) {
1799             ref_list = short_ref1;
1800             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1801                 if (priv->short_ref[i]->base.poc > picture->base.poc)
1802                     ref_list[n++] = priv->short_ref[i];
1803             }
1804             SORT_REF_LIST(ref_list, n, poc_inc);
1805             short_ref1_count += n;
1806
1807             ref_list = &short_ref1[short_ref1_count];
1808             for (n = 0, i = 0; i < priv->short_ref_count; i++) {
1809                 if (priv->short_ref[i]->base.poc <= picture->base.poc)
1810                     ref_list[n++] = priv->short_ref[i];
1811             }
1812             SORT_REF_LIST(ref_list, n, poc_dec);
1813             short_ref1_count += n;
1814         }
1815
1816         /* refFrameListLongTerm */
1817         if (priv->long_ref_count > 0) {
1818             for (i = 0; i < priv->long_ref_count; i++)
1819                 long_ref[i] = priv->long_ref[i];
1820             SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
1821             long_ref_count = i;
1822         }
1823
1824         init_picture_refs_fields(
1825             picture,
1826             priv->RefPicList0, &priv->RefPicList0_count,
1827             short_ref0,         short_ref0_count,
1828             long_ref,           long_ref_count
1829         );
1830
1831         init_picture_refs_fields(
1832             picture,
1833             priv->RefPicList1, &priv->RefPicList1_count,
1834             short_ref1,         short_ref1_count,
1835             long_ref,           long_ref_count
1836         );
1837    }
1838
1839     /* Check whether RefPicList1 is identical to RefPicList0, then
1840        swap if necessary */
1841     if (priv->RefPicList1_count > 1 &&
1842         priv->RefPicList1_count == priv->RefPicList0_count &&
1843         memcmp(priv->RefPicList0, priv->RefPicList1,
1844                priv->RefPicList0_count * sizeof(priv->RefPicList0[0])) == 0) {
1845         GstVaapiPictureH264 * const tmp = priv->RefPicList1[0];
1846         priv->RefPicList1[0] = priv->RefPicList1[1];
1847         priv->RefPicList1[1] = tmp;
1848     }
1849 }
1850
1851 #undef SORT_REF_LIST
1852
1853 static gint
1854 find_short_term_reference(GstVaapiDecoderH264 *decoder, gint32 pic_num)
1855 {
1856     GstVaapiDecoderH264Private * const priv = decoder->priv;
1857     guint i;
1858
1859     for (i = 0; i < priv->short_ref_count; i++) {
1860         if (priv->short_ref[i]->pic_num == pic_num)
1861             return i;
1862     }
1863     GST_ERROR("found no short-term reference picture with PicNum = %d",
1864               pic_num);
1865     return -1;
1866 }
1867
1868 static gint
1869 find_long_term_reference(GstVaapiDecoderH264 *decoder, gint32 long_term_pic_num)
1870 {
1871     GstVaapiDecoderH264Private * const priv = decoder->priv;
1872     guint i;
1873
1874     for (i = 0; i < priv->long_ref_count; i++) {
1875         if (priv->long_ref[i]->long_term_pic_num == long_term_pic_num)
1876             return i;
1877     }
1878     GST_ERROR("found no long-term reference picture with LongTermPicNum = %d",
1879               long_term_pic_num);
1880     return -1;
1881 }
1882
1883 static void
1884 exec_picture_refs_modification_1(
1885     GstVaapiDecoderH264           *decoder,
1886     GstVaapiPictureH264           *picture,
1887     GstH264SliceHdr               *slice_hdr,
1888     guint                          list
1889 )
1890 {
1891     GstVaapiDecoderH264Private * const priv = decoder->priv;
1892     GstH264PPS * const pps = slice_hdr->pps;
1893     GstH264SPS * const sps = pps->sequence;
1894     GstH264RefPicListModification *ref_pic_list_modification;
1895     guint num_ref_pic_list_modifications;
1896     GstVaapiPictureH264 **ref_list;
1897     guint *ref_list_count_ptr, ref_list_count, ref_list_idx = 0;
1898     guint i, j, n, num_refs;
1899     gint found_ref_idx;
1900     gint32 MaxPicNum, CurrPicNum, picNumPred;
1901
1902     GST_DEBUG("modification process of reference picture list %u", list);
1903
1904     if (list == 0) {
1905         ref_pic_list_modification      = slice_hdr->ref_pic_list_modification_l0;
1906         num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l0;
1907         ref_list                       = priv->RefPicList0;
1908         ref_list_count_ptr             = &priv->RefPicList0_count;
1909         num_refs                       = slice_hdr->num_ref_idx_l0_active_minus1 + 1;
1910     }
1911     else {
1912         ref_pic_list_modification      = slice_hdr->ref_pic_list_modification_l1;
1913         num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l1;
1914         ref_list                       = priv->RefPicList1;
1915         ref_list_count_ptr             = &priv->RefPicList1_count;
1916         num_refs                       = slice_hdr->num_ref_idx_l1_active_minus1 + 1;
1917     }
1918     ref_list_count = *ref_list_count_ptr;
1919     if (num_refs > ref_list_count)
1920         num_refs = ref_list_count;
1921
1922     if (!GST_VAAPI_PICTURE_IS_FRAME(picture)) {
1923         MaxPicNum  = 1 << (sps->log2_max_frame_num_minus4 + 5); // 2 * MaxFrameNum
1924         CurrPicNum = 2 * slice_hdr->frame_num + 1;              // 2 * frame_num + 1
1925     }
1926     else {
1927         MaxPicNum  = 1 << (sps->log2_max_frame_num_minus4 + 4); // MaxFrameNum
1928         CurrPicNum = slice_hdr->frame_num;                      // frame_num
1929     }
1930
1931     picNumPred = CurrPicNum;
1932
1933     for (i = 0; i < num_ref_pic_list_modifications; i++) {
1934         GstH264RefPicListModification * const l = &ref_pic_list_modification[i];
1935         if (l->modification_of_pic_nums_idc == 3)
1936             break;
1937
1938         /* 8.2.4.3.1 - Short-term reference pictures */
1939         if (l->modification_of_pic_nums_idc == 0 || l->modification_of_pic_nums_idc == 1) {
1940             gint32 abs_diff_pic_num = l->value.abs_diff_pic_num_minus1 + 1;
1941             gint32 picNum, picNumNoWrap;
1942
1943             // (8-34)
1944             if (l->modification_of_pic_nums_idc == 0) {
1945                 picNumNoWrap = picNumPred - abs_diff_pic_num;
1946                 if (picNumNoWrap < 0)
1947                     picNumNoWrap += MaxPicNum;
1948             }
1949
1950             // (8-35)
1951             else {
1952                 picNumNoWrap = picNumPred + abs_diff_pic_num;
1953                 if (picNumNoWrap >= MaxPicNum)
1954                     picNumNoWrap -= MaxPicNum;
1955             }
1956             picNumPred = picNumNoWrap;
1957
1958             // (8-36)
1959             picNum = picNumNoWrap;
1960             if (picNum > CurrPicNum)
1961                 picNum -= MaxPicNum;
1962
1963             // (8-37)
1964             for (j = num_refs; j > ref_list_idx; j--)
1965                 ref_list[j] = ref_list[j - 1];
1966             found_ref_idx = find_short_term_reference(decoder, picNum);
1967             ref_list[ref_list_idx++] =
1968                 found_ref_idx >= 0 ? priv->short_ref[found_ref_idx] : NULL;
1969             n = ref_list_idx;
1970             for (j = ref_list_idx; j <= num_refs; j++) {
1971                 gint32 PicNumF;
1972                 if (!ref_list[j])
1973                     continue;
1974                 PicNumF =
1975                     GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(ref_list[j]) ?
1976                     ref_list[j]->pic_num : MaxPicNum;
1977                 if (PicNumF != picNum)
1978                     ref_list[n++] = ref_list[j];
1979             }
1980         }
1981
1982         /* 8.2.4.3.2 - Long-term reference pictures */
1983         else {
1984
1985             for (j = num_refs; j > ref_list_idx; j--)
1986                 ref_list[j] = ref_list[j - 1];
1987             found_ref_idx =
1988                 find_long_term_reference(decoder, l->value.long_term_pic_num);
1989             ref_list[ref_list_idx++] =
1990                 found_ref_idx >= 0 ? priv->long_ref[found_ref_idx] : NULL;
1991             n = ref_list_idx;
1992             for (j = ref_list_idx; j <= num_refs; j++) {
1993                 gint32 LongTermPicNumF;
1994                 if (!ref_list[j])
1995                     continue;
1996                 LongTermPicNumF =
1997                     GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(ref_list[j]) ?
1998                     ref_list[j]->long_term_pic_num : INT_MAX;
1999                 if (LongTermPicNumF != l->value.long_term_pic_num)
2000                     ref_list[n++] = ref_list[j];
2001             }
2002         }
2003     }
2004
2005 #if DEBUG
2006     for (i = 0; i < num_refs; i++)
2007         if (!ref_list[i])
2008             GST_ERROR("list %u entry %u is empty", list, i);
2009 #endif
2010     *ref_list_count_ptr = num_refs;
2011 }
2012
2013 /* 8.2.4.3 - Modification process for reference picture lists */
2014 static void
2015 exec_picture_refs_modification(
2016     GstVaapiDecoderH264 *decoder,
2017     GstVaapiPictureH264 *picture,
2018     GstH264SliceHdr     *slice_hdr
2019 )
2020 {
2021     GST_DEBUG("execute ref_pic_list_modification()");
2022
2023     /* RefPicList0 */
2024     if (!GST_H264_IS_I_SLICE(slice_hdr) && !GST_H264_IS_SI_SLICE(slice_hdr) &&
2025         slice_hdr->ref_pic_list_modification_flag_l0)
2026         exec_picture_refs_modification_1(decoder, picture, slice_hdr, 0);
2027
2028     /* RefPicList1 */
2029     if (GST_H264_IS_B_SLICE(slice_hdr) &&
2030         slice_hdr->ref_pic_list_modification_flag_l1)
2031         exec_picture_refs_modification_1(decoder, picture, slice_hdr, 1);
2032 }
2033
2034 static void
2035 init_picture_ref_lists(GstVaapiDecoderH264 *decoder)
2036 {
2037     GstVaapiDecoderH264Private * const priv = decoder->priv;
2038     guint i, j, short_ref_count, long_ref_count;
2039
2040     short_ref_count = 0;
2041     long_ref_count  = 0;
2042     if (GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture)) {
2043         for (i = 0; i < priv->dpb_count; i++) {
2044             GstVaapiFrameStore * const fs = priv->dpb[i];
2045             GstVaapiPictureH264 *picture;
2046             if (!gst_vaapi_frame_store_has_frame(fs))
2047                 continue;
2048             picture = fs->buffers[0];
2049             if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2050                 priv->short_ref[short_ref_count++] = picture;
2051             else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture))
2052                 priv->long_ref[long_ref_count++] = picture;
2053             picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
2054             picture->other_field = fs->buffers[1];
2055         }
2056     }
2057     else {
2058         for (i = 0; i < priv->dpb_count; i++) {
2059             GstVaapiFrameStore * const fs = priv->dpb[i];
2060             for (j = 0; j < fs->num_buffers; j++) {
2061                 GstVaapiPictureH264 * const picture = fs->buffers[j];
2062                 if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2063                     priv->short_ref[short_ref_count++] = picture;
2064                 else if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture))
2065                     priv->long_ref[long_ref_count++] = picture;
2066                 picture->structure = picture->base.structure;
2067                 picture->other_field = fs->buffers[j ^ 1];
2068             }
2069         }
2070     }
2071
2072     for (i = short_ref_count; i < priv->short_ref_count; i++)
2073         priv->short_ref[i] = NULL;
2074     priv->short_ref_count = short_ref_count;
2075
2076     for (i = long_ref_count; i < priv->long_ref_count; i++)
2077         priv->long_ref[i] = NULL;
2078     priv->long_ref_count = long_ref_count;
2079 }
2080
2081 static void
2082 remove_short_reference(GstVaapiDecoderH264* decoder, gint32 frame_num)
2083 {
2084     GstVaapiDecoderH264Private * const priv = decoder->priv;
2085     GstVaapiPictureH264 *ref_picture;
2086     guint i;
2087
2088     for (i = 0; i < priv->short_ref_count; ++i) {
2089         if (priv->short_ref[i]->frame_num == frame_num) {
2090             ref_picture = priv->short_ref[i];
2091             gst_vaapi_picture_h264_set_reference(ref_picture, 0, FALSE);
2092             ARRAY_REMOVE_INDEX(priv->short_ref, i);
2093             return;
2094         }
2095     }
2096 }
2097
2098 static void
2099 init_picture_refs(
2100     GstVaapiDecoderH264 *decoder,
2101     GstVaapiPictureH264 *picture,
2102     GstH264SliceHdr     *slice_hdr
2103 )
2104 {
2105     GstVaapiDecoderH264Private * const priv = decoder->priv;
2106     GstVaapiPicture * const base_picture = &picture->base;
2107     guint i, num_refs;
2108
2109     init_picture_ref_lists(decoder);
2110     init_picture_refs_pic_num(decoder, picture, slice_hdr);
2111
2112     priv->RefPicList0_count = 0;
2113     priv->RefPicList1_count = 0;
2114
2115     switch (base_picture->type) {
2116     case GST_VAAPI_PICTURE_TYPE_P:
2117     case GST_VAAPI_PICTURE_TYPE_SP:
2118         init_picture_refs_p_slice(decoder, picture, slice_hdr);
2119         break;
2120     case GST_VAAPI_PICTURE_TYPE_B:
2121         init_picture_refs_b_slice(decoder, picture, slice_hdr);
2122         break;
2123     default:
2124         break;
2125     }
2126
2127     exec_picture_refs_modification(decoder, picture, slice_hdr);
2128
2129     switch (base_picture->type) {
2130     case GST_VAAPI_PICTURE_TYPE_B:
2131         num_refs = 1 + slice_hdr->num_ref_idx_l1_active_minus1;
2132         for (i = priv->RefPicList1_count; i < num_refs; i++)
2133             priv->RefPicList1[i] = NULL;
2134         //priv->RefPicList1_count = num_refs;
2135
2136         // fall-through
2137     case GST_VAAPI_PICTURE_TYPE_P:
2138     case GST_VAAPI_PICTURE_TYPE_SP:
2139         num_refs = 1 + slice_hdr->num_ref_idx_l0_active_minus1;
2140         for (i = priv->RefPicList0_count; i < num_refs; i++)
2141             priv->RefPicList0[i] = NULL;
2142         //priv->RefPicList0_count = num_refs;
2143         break;
2144     default:
2145         break;
2146     }
2147 }
2148
2149 static gboolean
2150 init_picture(
2151     GstVaapiDecoderH264 *decoder,
2152     GstVaapiPictureH264 *picture,
2153     GstH264SliceHdr     *slice_hdr,
2154     GstH264NalUnit      *nalu
2155 )
2156 {
2157     GstVaapiDecoderH264Private * const priv = decoder->priv;
2158     GstVaapiPicture * const base_picture = &picture->base;
2159
2160     priv->prev_frame_num        = priv->frame_num;
2161     priv->frame_num             = slice_hdr->frame_num;
2162     picture->frame_num          = priv->frame_num;
2163     picture->frame_num_wrap     = priv->frame_num;
2164     picture->output_flag        = TRUE; /* XXX: conformant to Annex A only */
2165     base_picture->pts           = gst_adapter_prev_timestamp(priv->adapter, NULL);
2166
2167     /* Reset decoder state for IDR pictures */
2168     if (nalu->type == GST_H264_NAL_SLICE_IDR) {
2169         GST_DEBUG("<IDR>");
2170         GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR);
2171         dpb_flush(decoder);
2172     }
2173
2174     /* Initialize slice type */
2175     switch (slice_hdr->type % 5) {
2176     case GST_H264_P_SLICE:
2177         base_picture->type = GST_VAAPI_PICTURE_TYPE_P;
2178         break;
2179     case GST_H264_B_SLICE:
2180         base_picture->type = GST_VAAPI_PICTURE_TYPE_B;
2181         break;
2182     case GST_H264_I_SLICE:
2183         base_picture->type = GST_VAAPI_PICTURE_TYPE_I;
2184         break;
2185     case GST_H264_SP_SLICE:
2186         base_picture->type = GST_VAAPI_PICTURE_TYPE_SP;
2187         break;
2188     case GST_H264_SI_SLICE:
2189         base_picture->type = GST_VAAPI_PICTURE_TYPE_SI;
2190         break;
2191     }
2192
2193     /* Initialize picture structure */
2194     if (!slice_hdr->field_pic_flag)
2195         base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
2196     else {
2197         GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
2198         if (!slice_hdr->bottom_field_flag)
2199             base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
2200         else
2201             base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
2202     }
2203     picture->structure = base_picture->structure;
2204
2205     /* Initialize reference flags */
2206     if (nalu->ref_idc) {
2207         GstH264DecRefPicMarking * const dec_ref_pic_marking =
2208             &slice_hdr->dec_ref_pic_marking;
2209
2210         if (GST_VAAPI_PICTURE_IS_IDR(picture) &&
2211             dec_ref_pic_marking->long_term_reference_flag)
2212             GST_VAAPI_PICTURE_FLAG_SET(picture,
2213                 GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE);
2214         else
2215             GST_VAAPI_PICTURE_FLAG_SET(picture,
2216                 GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE);
2217     }
2218
2219     init_picture_poc(decoder, picture, slice_hdr);
2220     init_picture_refs(decoder, picture, slice_hdr);
2221     return TRUE;
2222 }
2223
2224 /* 8.2.5.3 - Sliding window decoded reference picture marking process */
2225 static gboolean
2226 exec_ref_pic_marking_sliding_window(GstVaapiDecoderH264 *decoder)
2227 {
2228     GstVaapiDecoderH264Private * const priv = decoder->priv;
2229     GstH264PPS * const pps = priv->current_picture->pps;
2230     GstH264SPS * const sps = pps->sequence;
2231     GstVaapiPictureH264 *ref_picture;
2232     guint i, m, max_num_ref_frames;
2233
2234     GST_DEBUG("reference picture marking process (sliding window)");
2235
2236     if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD(priv->current_picture))
2237         return TRUE;
2238
2239     max_num_ref_frames = sps->num_ref_frames;
2240     if (max_num_ref_frames == 0)
2241         max_num_ref_frames = 1;
2242     if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture))
2243         max_num_ref_frames <<= 1;
2244
2245     if (priv->short_ref_count + priv->long_ref_count < max_num_ref_frames)
2246         return TRUE;
2247     if (priv->short_ref_count < 1)
2248         return FALSE;
2249
2250     for (m = 0, i = 1; i < priv->short_ref_count; i++) {
2251         GstVaapiPictureH264 * const picture = priv->short_ref[i];
2252         if (picture->frame_num_wrap < priv->short_ref[m]->frame_num_wrap)
2253             m = i;
2254     }
2255
2256     ref_picture = priv->short_ref[m];
2257     gst_vaapi_picture_h264_set_reference(ref_picture, 0, TRUE);
2258     ARRAY_REMOVE_INDEX(priv->short_ref, m);
2259
2260     /* Both fields need to be marked as "unused for reference", so
2261        remove the other field from the short_ref[] list as well */
2262     if (!GST_VAAPI_PICTURE_IS_FRAME(priv->current_picture) && ref_picture->other_field) {
2263         for (i = 0; i < priv->short_ref_count; i++) {
2264             if (priv->short_ref[i] == ref_picture->other_field) {
2265                 ARRAY_REMOVE_INDEX(priv->short_ref, i);
2266                 break;
2267             }
2268         }
2269     }
2270     return TRUE;
2271 }
2272
2273 static inline gint32
2274 get_picNumX(GstVaapiPictureH264 *picture, GstH264RefPicMarking *ref_pic_marking)
2275 {
2276     gint32 pic_num;
2277
2278     if (GST_VAAPI_PICTURE_IS_FRAME(picture))
2279         pic_num = picture->frame_num_wrap;
2280     else
2281         pic_num = 2 * picture->frame_num_wrap + 1;
2282     pic_num -= ref_pic_marking->difference_of_pic_nums_minus1 + 1;
2283     return pic_num;
2284 }
2285
2286 /* 8.2.5.4.1. Mark short-term reference picture as "unused for reference" */
2287 static void
2288 exec_ref_pic_marking_adaptive_mmco_1(
2289     GstVaapiDecoderH264  *decoder,
2290     GstVaapiPictureH264  *picture,
2291     GstH264RefPicMarking *ref_pic_marking
2292 )
2293 {
2294     GstVaapiDecoderH264Private * const priv = decoder->priv;
2295     gint32 i, picNumX;
2296
2297     picNumX = get_picNumX(picture, ref_pic_marking);
2298     i = find_short_term_reference(decoder, picNumX);
2299     if (i < 0)
2300         return;
2301
2302     gst_vaapi_picture_h264_set_reference(priv->short_ref[i], 0,
2303         GST_VAAPI_PICTURE_IS_FRAME(picture));
2304     ARRAY_REMOVE_INDEX(priv->short_ref, i);
2305 }
2306
2307 /* 8.2.5.4.2. Mark long-term reference picture as "unused for reference" */
2308 static void
2309 exec_ref_pic_marking_adaptive_mmco_2(
2310     GstVaapiDecoderH264  *decoder,
2311     GstVaapiPictureH264  *picture,
2312     GstH264RefPicMarking *ref_pic_marking
2313 )
2314 {
2315     GstVaapiDecoderH264Private * const priv = decoder->priv;
2316     gint32 i;
2317
2318     i = find_long_term_reference(decoder, ref_pic_marking->long_term_pic_num);
2319     if (i < 0)
2320         return;
2321
2322     gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0,
2323         GST_VAAPI_PICTURE_IS_FRAME(picture));
2324     ARRAY_REMOVE_INDEX(priv->long_ref, i);
2325 }
2326
2327 /* 8.2.5.4.3. Assign LongTermFrameIdx to a short-term reference picture */
2328 static void
2329 exec_ref_pic_marking_adaptive_mmco_3(
2330     GstVaapiDecoderH264  *decoder,
2331     GstVaapiPictureH264  *picture,
2332     GstH264RefPicMarking *ref_pic_marking
2333 )
2334 {
2335     GstVaapiDecoderH264Private * const priv = decoder->priv;
2336     GstVaapiPictureH264 *ref_picture;
2337     gint32 i, picNumX;
2338
2339     for (i = 0; i < priv->long_ref_count; i++) {
2340         if (priv->long_ref[i]->long_term_frame_idx == ref_pic_marking->long_term_frame_idx)
2341             break;
2342     }
2343     if (i != priv->long_ref_count) {
2344         gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, TRUE);
2345         ARRAY_REMOVE_INDEX(priv->long_ref, i);
2346     }
2347
2348     picNumX = get_picNumX(picture, ref_pic_marking);
2349     i = find_short_term_reference(decoder, picNumX);
2350     if (i < 0)
2351         return;
2352
2353     ref_picture = priv->short_ref[i];
2354     ARRAY_REMOVE_INDEX(priv->short_ref, i);
2355     priv->long_ref[priv->long_ref_count++] = ref_picture;
2356
2357     ref_picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2358     gst_vaapi_picture_h264_set_reference(ref_picture,
2359         GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE,
2360         GST_VAAPI_PICTURE_IS_FRAME(picture));
2361 }
2362
2363 /* 8.2.5.4.4. Mark pictures with LongTermFramIdx > max_long_term_frame_idx
2364  * as "unused for reference" */
2365 static void
2366 exec_ref_pic_marking_adaptive_mmco_4(
2367     GstVaapiDecoderH264  *decoder,
2368     GstVaapiPictureH264  *picture,
2369     GstH264RefPicMarking *ref_pic_marking
2370 )
2371 {
2372     GstVaapiDecoderH264Private * const priv = decoder->priv;
2373     gint32 i, long_term_frame_idx;
2374
2375     long_term_frame_idx = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
2376
2377     for (i = 0; i < priv->long_ref_count; i++) {
2378         if (priv->long_ref[i]->long_term_frame_idx <= long_term_frame_idx)
2379             continue;
2380         gst_vaapi_picture_h264_set_reference(priv->long_ref[i], 0, FALSE);
2381         ARRAY_REMOVE_INDEX(priv->long_ref, i);
2382         i--;
2383     }
2384 }
2385
2386 /* 8.2.5.4.5. Mark all reference pictures as "unused for reference" */
2387 static void
2388 exec_ref_pic_marking_adaptive_mmco_5(
2389     GstVaapiDecoderH264  *decoder,
2390     GstVaapiPictureH264  *picture,
2391     GstH264RefPicMarking *ref_pic_marking
2392 )
2393 {
2394     GstVaapiDecoderH264Private * const priv = decoder->priv;
2395
2396     dpb_flush(decoder);
2397
2398     priv->prev_pic_has_mmco5 = TRUE;
2399
2400     /* The picture shall be inferred to have had frame_num equal to 0 (7.4.3) */
2401     priv->frame_num = 0;
2402     priv->frame_num_offset = 0;
2403     picture->frame_num = 0;
2404
2405     /* Update TopFieldOrderCnt and BottomFieldOrderCnt (8.2.1) */
2406     if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
2407         picture->field_poc[TOP_FIELD] -= picture->base.poc;
2408     if (picture->structure != GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
2409         picture->field_poc[BOTTOM_FIELD] -= picture->base.poc;
2410     picture->base.poc = 0;
2411 }
2412
2413 /* 8.2.5.4.6. Assign a long-term frame index to the current picture */
2414 static void
2415 exec_ref_pic_marking_adaptive_mmco_6(
2416     GstVaapiDecoderH264  *decoder,
2417     GstVaapiPictureH264  *picture,
2418     GstH264RefPicMarking *ref_pic_marking
2419 )
2420 {
2421     picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
2422     gst_vaapi_picture_h264_set_reference(picture,
2423         GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE, FALSE);
2424 }
2425
2426 /* 8.2.5.4. Adaptive memory control decoded reference picture marking process */
2427 static gboolean
2428 exec_ref_pic_marking_adaptive(
2429     GstVaapiDecoderH264     *decoder,
2430     GstVaapiPictureH264     *picture,
2431     GstH264DecRefPicMarking *dec_ref_pic_marking
2432 )
2433 {
2434     guint i;
2435
2436     GST_DEBUG("reference picture marking process (adaptive memory control)");
2437
2438     typedef void (*exec_ref_pic_marking_adaptive_mmco_func)(
2439         GstVaapiDecoderH264  *decoder,
2440         GstVaapiPictureH264  *picture,
2441         GstH264RefPicMarking *ref_pic_marking
2442     );
2443
2444     static const exec_ref_pic_marking_adaptive_mmco_func mmco_funcs[] = {
2445         NULL,
2446         exec_ref_pic_marking_adaptive_mmco_1,
2447         exec_ref_pic_marking_adaptive_mmco_2,
2448         exec_ref_pic_marking_adaptive_mmco_3,
2449         exec_ref_pic_marking_adaptive_mmco_4,
2450         exec_ref_pic_marking_adaptive_mmco_5,
2451         exec_ref_pic_marking_adaptive_mmco_6,
2452     };
2453
2454     for (i = 0; i < dec_ref_pic_marking->n_ref_pic_marking; i++) {
2455         GstH264RefPicMarking * const ref_pic_marking =
2456             &dec_ref_pic_marking->ref_pic_marking[i];
2457
2458         const guint mmco = ref_pic_marking->memory_management_control_operation;
2459         if (mmco < G_N_ELEMENTS(mmco_funcs) && mmco_funcs[mmco])
2460             mmco_funcs[mmco](decoder, picture, ref_pic_marking);
2461         else {
2462             GST_ERROR("unhandled MMCO %u", mmco);
2463             return FALSE;
2464         }
2465     }
2466     return TRUE;
2467 }
2468
2469 /* 8.2.5 - Execute reference picture marking process */
2470 static gboolean
2471 exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
2472 {
2473     GstVaapiDecoderH264Private * const priv = decoder->priv;
2474
2475     priv->prev_pic_has_mmco5 = FALSE;
2476     priv->prev_pic_structure = picture->structure;
2477
2478     if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
2479         return TRUE;
2480
2481     if (!GST_VAAPI_PICTURE_IS_IDR(picture)) {
2482         GstVaapiSliceH264 * const slice =
2483             gst_vaapi_picture_h264_get_last_slice(picture);
2484         GstH264DecRefPicMarking * const dec_ref_pic_marking =
2485             &slice->slice_hdr.dec_ref_pic_marking;
2486         if (dec_ref_pic_marking->adaptive_ref_pic_marking_mode_flag) {
2487             if (!exec_ref_pic_marking_adaptive(decoder, picture, dec_ref_pic_marking))
2488                 return FALSE;
2489         }
2490         else {
2491             if (!exec_ref_pic_marking_sliding_window(decoder))
2492                 return FALSE;
2493         }
2494         if (!priv->prev_pic_has_mmco5)
2495             remove_short_reference(decoder, picture->frame_num);
2496     }
2497     return TRUE;
2498 }
2499
2500 static void
2501 vaapi_init_picture(VAPictureH264 *pic)
2502 {
2503     pic->picture_id           = VA_INVALID_ID;
2504     pic->frame_idx            = 0;
2505     pic->flags                = VA_PICTURE_H264_INVALID;
2506     pic->TopFieldOrderCnt     = 0;
2507     pic->BottomFieldOrderCnt  = 0;
2508 }
2509
2510 static void
2511 vaapi_fill_picture(VAPictureH264 *pic, GstVaapiPictureH264 *picture,
2512     guint picture_structure)
2513 {
2514     if (!picture_structure)
2515         picture_structure = picture->structure;
2516
2517     pic->picture_id = picture->base.surface_id;
2518     pic->flags = 0;
2519
2520     if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture)) {
2521         pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
2522         pic->frame_idx = picture->long_term_frame_idx;
2523     }
2524     else {
2525         if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
2526             pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
2527         pic->frame_idx = picture->frame_num;
2528     }
2529
2530     switch (picture_structure) {
2531     case GST_VAAPI_PICTURE_STRUCTURE_FRAME:
2532         pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2533         pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2534         break;
2535     case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
2536         pic->flags |= VA_PICTURE_H264_TOP_FIELD;
2537         pic->TopFieldOrderCnt = picture->field_poc[TOP_FIELD];
2538         pic->BottomFieldOrderCnt = 0;
2539         break;
2540     case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
2541         pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
2542         pic->BottomFieldOrderCnt = picture->field_poc[BOTTOM_FIELD];
2543         pic->TopFieldOrderCnt = 0;
2544         break;
2545     }
2546 }
2547
2548 static gboolean
2549 fill_picture(
2550     GstVaapiDecoderH264 *decoder,
2551     GstVaapiPictureH264 *picture,
2552     GstH264SliceHdr     *slice_hdr,
2553     GstH264NalUnit      *nalu
2554 )
2555 {
2556     GstVaapiDecoderH264Private * const priv = decoder->priv;
2557     GstVaapiPicture * const base_picture = &picture->base;
2558     GstH264PPS * const pps = picture->pps;
2559     GstH264SPS * const sps = pps->sequence;
2560     VAPictureParameterBufferH264 * const pic_param = base_picture->param;
2561     guint i, n;
2562
2563     /* Fill in VAPictureParameterBufferH264 */
2564     vaapi_fill_picture(&pic_param->CurrPic, picture, 0);
2565
2566     for (i = 0, n = 0; i < priv->dpb_count; i++) {
2567         GstVaapiFrameStore * const fs = priv->dpb[i];
2568         if (gst_vaapi_frame_store_has_reference(fs))
2569             vaapi_fill_picture(&pic_param->ReferenceFrames[n++],
2570                 fs->buffers[0], fs->structure);
2571     }
2572     for (; n < G_N_ELEMENTS(pic_param->ReferenceFrames); n++)
2573         vaapi_init_picture(&pic_param->ReferenceFrames[n]);
2574
2575 #define COPY_FIELD(s, f) \
2576     pic_param->f = (s)->f
2577
2578 #define COPY_BFM(a, s, f) \
2579     pic_param->a.bits.f = (s)->f
2580
2581     pic_param->picture_width_in_mbs_minus1  = priv->mb_width - 1;
2582     pic_param->picture_height_in_mbs_minus1 = priv->mb_height - 1;
2583     pic_param->frame_num                    = priv->frame_num;
2584
2585     COPY_FIELD(sps, bit_depth_luma_minus8);
2586     COPY_FIELD(sps, bit_depth_chroma_minus8);
2587     COPY_FIELD(sps, num_ref_frames);
2588     COPY_FIELD(pps, num_slice_groups_minus1);
2589     COPY_FIELD(pps, slice_group_map_type);
2590     COPY_FIELD(pps, slice_group_change_rate_minus1);
2591     COPY_FIELD(pps, pic_init_qp_minus26);
2592     COPY_FIELD(pps, pic_init_qs_minus26);
2593     COPY_FIELD(pps, chroma_qp_index_offset);
2594     COPY_FIELD(pps, second_chroma_qp_index_offset);
2595
2596     pic_param->seq_fields.value                                         = 0; /* reset all bits */
2597     pic_param->seq_fields.bits.residual_colour_transform_flag           = sps->separate_colour_plane_flag;
2598     pic_param->seq_fields.bits.MinLumaBiPredSize8x8                     = sps->level_idc >= 31; /* A.3.3.2 */
2599
2600     COPY_BFM(seq_fields, sps, chroma_format_idc);
2601     COPY_BFM(seq_fields, sps, gaps_in_frame_num_value_allowed_flag);
2602     COPY_BFM(seq_fields, sps, frame_mbs_only_flag); 
2603     COPY_BFM(seq_fields, sps, mb_adaptive_frame_field_flag); 
2604     COPY_BFM(seq_fields, sps, direct_8x8_inference_flag); 
2605     COPY_BFM(seq_fields, sps, log2_max_frame_num_minus4);
2606     COPY_BFM(seq_fields, sps, pic_order_cnt_type);
2607     COPY_BFM(seq_fields, sps, log2_max_pic_order_cnt_lsb_minus4);
2608     COPY_BFM(seq_fields, sps, delta_pic_order_always_zero_flag);
2609
2610     pic_param->pic_fields.value                                         = 0; /* reset all bits */
2611     pic_param->pic_fields.bits.field_pic_flag                           = slice_hdr->field_pic_flag;
2612     pic_param->pic_fields.bits.reference_pic_flag                       = GST_VAAPI_PICTURE_IS_REFERENCE(picture);
2613
2614     COPY_BFM(pic_fields, pps, entropy_coding_mode_flag);
2615     COPY_BFM(pic_fields, pps, weighted_pred_flag);
2616     COPY_BFM(pic_fields, pps, weighted_bipred_idc);
2617     COPY_BFM(pic_fields, pps, transform_8x8_mode_flag);
2618     COPY_BFM(pic_fields, pps, constrained_intra_pred_flag);
2619     COPY_BFM(pic_fields, pps, pic_order_present_flag);
2620     COPY_BFM(pic_fields, pps, deblocking_filter_control_present_flag);
2621     COPY_BFM(pic_fields, pps, redundant_pic_cnt_present_flag);
2622     return TRUE;
2623 }
2624
2625 /* Detection of the first VCL NAL unit of a primary coded picture (7.4.1.2.4) */
2626 static gboolean
2627 is_new_picture(
2628     GstVaapiDecoderH264 *decoder,
2629     GstH264NalUnit      *nalu,
2630     GstH264SliceHdr     *slice_hdr
2631 )
2632 {
2633     GstVaapiDecoderH264Private * const priv = decoder->priv;
2634     GstH264PPS * const pps = slice_hdr->pps;
2635     GstH264SPS * const sps = pps->sequence;
2636     GstVaapiSliceH264 *slice;
2637     GstH264SliceHdr *prev_slice_hdr;
2638
2639     if (!priv->current_picture)
2640         return TRUE;
2641
2642     slice = gst_vaapi_picture_h264_get_last_slice(priv->current_picture);
2643     if (!slice)
2644         return FALSE;
2645     prev_slice_hdr = &slice->slice_hdr;
2646
2647 #define CHECK_EXPR(expr, field_name) do {              \
2648         if (!(expr)) {                                 \
2649             GST_DEBUG(field_name " differs in value"); \
2650             return TRUE;                               \
2651         }                                              \
2652     } while (0)
2653
2654 #define CHECK_VALUE(new_slice_hdr, old_slice_hdr, field) \
2655     CHECK_EXPR(((new_slice_hdr)->field == (old_slice_hdr)->field), #field)
2656
2657     /* frame_num differs in value, regardless of inferred values to 0 */
2658     CHECK_VALUE(slice_hdr, prev_slice_hdr, frame_num);
2659
2660     /* pic_parameter_set_id differs in value */
2661     CHECK_VALUE(slice_hdr, prev_slice_hdr, pps);
2662
2663     /* field_pic_flag differs in value */
2664     CHECK_VALUE(slice_hdr, prev_slice_hdr, field_pic_flag);
2665
2666     /* bottom_field_flag is present in both and differs in value */
2667     if (slice_hdr->field_pic_flag && prev_slice_hdr->field_pic_flag)
2668         CHECK_VALUE(slice_hdr, prev_slice_hdr, bottom_field_flag);
2669
2670     /* nal_ref_idc differs in value with one of the nal_ref_idc values is 0 */
2671     CHECK_EXPR(((GST_VAAPI_PICTURE_IS_REFERENCE(priv->current_picture) ^
2672                  (nalu->ref_idc != 0)) == 0), "nal_ref_idc");
2673
2674     /* POC type is 0 for both and either pic_order_cnt_lsb differs in
2675        value or delta_pic_order_cnt_bottom differs in value */
2676     if (sps->pic_order_cnt_type == 0) {
2677         CHECK_VALUE(slice_hdr, prev_slice_hdr, pic_order_cnt_lsb);
2678         if (pps->pic_order_present_flag && !slice_hdr->field_pic_flag)
2679             CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt_bottom);
2680     }
2681
2682     /* POC type is 1 for both and either delta_pic_order_cnt[0]
2683        differs in value or delta_pic_order_cnt[1] differs in value */
2684     else if (sps->pic_order_cnt_type == 1) {
2685         CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[0]);
2686         CHECK_VALUE(slice_hdr, prev_slice_hdr, delta_pic_order_cnt[1]);
2687     }
2688
2689     /* IdrPicFlag differs in value */
2690     CHECK_EXPR(((GST_VAAPI_PICTURE_IS_IDR(priv->current_picture) ^
2691                  (nalu->type == GST_H264_NAL_SLICE_IDR)) == 0), "IdrPicFlag");
2692
2693     /* IdrPicFlag is equal to 1 for both and idr_pic_id differs in value */
2694     if (GST_VAAPI_PICTURE_IS_IDR(priv->current_picture))
2695         CHECK_VALUE(slice_hdr, prev_slice_hdr, idr_pic_id);
2696
2697 #undef CHECK_EXPR
2698 #undef CHECK_VALUE
2699     return FALSE;
2700 }
2701
2702 static GstVaapiDecoderStatus
2703 decode_picture(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu, GstH264SliceHdr *slice_hdr)
2704 {
2705     GstVaapiDecoderH264Private * const priv = decoder->priv;
2706     GstVaapiPictureH264 *picture;
2707     GstVaapiDecoderStatus status;
2708     GstH264PPS * const pps = slice_hdr->pps;
2709     GstH264SPS * const sps = pps->sequence;
2710
2711     status = decode_current_picture(decoder);
2712     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2713         return status;
2714
2715     status = ensure_context(decoder, sps);
2716     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2717         return status;
2718
2719     if (priv->current_picture) {
2720         /* Re-use current picture where the first field was decoded */
2721         picture = gst_vaapi_picture_h264_new_field(priv->current_picture);
2722         if (!picture) {
2723             GST_ERROR("failed to allocate field picture");
2724             return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2725         }
2726     }
2727     else {
2728         /* Create new picture */
2729         picture = gst_vaapi_picture_h264_new(decoder);
2730         if (!picture) {
2731             GST_ERROR("failed to allocate picture");
2732             return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2733         }
2734     }
2735     gst_vaapi_picture_replace(&priv->current_picture, picture);
2736     gst_vaapi_picture_unref(picture);
2737
2738     picture->pps = pps;
2739
2740     status = ensure_quant_matrix(decoder, picture);
2741     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
2742         GST_ERROR("failed to reset quantizer matrix");
2743         return status;
2744     }
2745
2746     if (!init_picture(decoder, picture, slice_hdr, nalu))
2747         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2748     if (!fill_picture(decoder, picture, slice_hdr, nalu))
2749         return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2750     return GST_VAAPI_DECODER_STATUS_SUCCESS;
2751 }
2752
2753 static inline guint
2754 get_slice_data_bit_offset(GstH264SliceHdr *slice_hdr, GstH264NalUnit *nalu)
2755 {
2756     guint epb_count;
2757
2758     epb_count = slice_hdr->n_emulation_prevention_bytes;
2759     return 8 /* nal_unit_type */ + slice_hdr->header_size - epb_count * 8;
2760 }
2761
2762 static gboolean
2763 fill_pred_weight_table(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
2764 {
2765     GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
2766     GstH264PPS * const pps = slice_hdr->pps;
2767     GstH264SPS * const sps = pps->sequence;
2768     GstH264PredWeightTable * const w = &slice_hdr->pred_weight_table;
2769     VASliceParameterBufferH264 * const slice_param = slice->base.param;
2770     guint num_weight_tables = 0;
2771     gint i, j;
2772
2773     if (pps->weighted_pred_flag &&
2774         (GST_H264_IS_P_SLICE(slice_hdr) || GST_H264_IS_SP_SLICE(slice_hdr)))
2775         num_weight_tables = 1;
2776     else if (pps->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE(slice_hdr))
2777         num_weight_tables = 2;
2778     else
2779         num_weight_tables = 0;
2780
2781     slice_param->luma_log2_weight_denom   = w->luma_log2_weight_denom;
2782     slice_param->chroma_log2_weight_denom = w->chroma_log2_weight_denom;
2783     slice_param->luma_weight_l0_flag      = 0;
2784     slice_param->chroma_weight_l0_flag    = 0;
2785     slice_param->luma_weight_l1_flag      = 0;
2786     slice_param->chroma_weight_l1_flag    = 0;
2787
2788     if (num_weight_tables < 1)
2789         return TRUE;
2790
2791     slice_param->luma_weight_l0_flag = 1;
2792     for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2793         slice_param->luma_weight_l0[i] = w->luma_weight_l0[i];
2794         slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
2795     }
2796
2797     slice_param->chroma_weight_l0_flag = sps->chroma_array_type != 0;
2798     if (slice_param->chroma_weight_l0_flag) {
2799         for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
2800             for (j = 0; j < 2; j++) {
2801                 slice_param->chroma_weight_l0[i][j] = w->chroma_weight_l0[i][j];
2802                 slice_param->chroma_offset_l0[i][j] = w->chroma_offset_l0[i][j];
2803             }
2804         }
2805     }
2806
2807     if (num_weight_tables < 2)
2808         return TRUE;
2809
2810     slice_param->luma_weight_l1_flag = 1;
2811     for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2812         slice_param->luma_weight_l1[i] = w->luma_weight_l1[i];
2813         slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
2814     }
2815
2816     slice_param->chroma_weight_l1_flag = sps->chroma_array_type != 0;
2817     if (slice_param->chroma_weight_l1_flag) {
2818         for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
2819             for (j = 0; j < 2; j++) {
2820                 slice_param->chroma_weight_l1[i][j] = w->chroma_weight_l1[i][j];
2821                 slice_param->chroma_offset_l1[i][j] = w->chroma_offset_l1[i][j];
2822             }
2823         }
2824     }
2825     return TRUE;
2826 }
2827
2828 static gboolean
2829 fill_RefPicList(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
2830 {
2831     GstVaapiDecoderH264Private * const priv = decoder->priv;
2832     GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
2833     VASliceParameterBufferH264 * const slice_param = slice->base.param;
2834     guint i, num_ref_lists = 0;
2835
2836     slice_param->num_ref_idx_l0_active_minus1 = 0;
2837     slice_param->num_ref_idx_l1_active_minus1 = 0;
2838
2839     if (GST_H264_IS_B_SLICE(slice_hdr))
2840         num_ref_lists = 2;
2841     else if (GST_H264_IS_I_SLICE(slice_hdr))
2842         num_ref_lists = 0;
2843     else
2844         num_ref_lists = 1;
2845
2846     if (num_ref_lists < 1)
2847         return TRUE;
2848
2849     slice_param->num_ref_idx_l0_active_minus1 =
2850         slice_hdr->num_ref_idx_l0_active_minus1;
2851
2852     for (i = 0; i < priv->RefPicList0_count && priv->RefPicList0[i]; i++)
2853         vaapi_fill_picture(&slice_param->RefPicList0[i], priv->RefPicList0[i], 0);
2854     for (; i <= slice_param->num_ref_idx_l0_active_minus1; i++)
2855         vaapi_init_picture(&slice_param->RefPicList0[i]);
2856
2857     if (num_ref_lists < 2)
2858         return TRUE;
2859
2860     slice_param->num_ref_idx_l1_active_minus1 =
2861         slice_hdr->num_ref_idx_l1_active_minus1;
2862
2863     for (i = 0; i < priv->RefPicList1_count && priv->RefPicList1[i]; i++)
2864         vaapi_fill_picture(&slice_param->RefPicList1[i], priv->RefPicList1[i], 0);
2865     for (; i <= slice_param->num_ref_idx_l1_active_minus1; i++)
2866         vaapi_init_picture(&slice_param->RefPicList1[i]);
2867     return TRUE;
2868 }
2869
2870 static gboolean
2871 fill_slice(
2872     GstVaapiDecoderH264 *decoder,
2873     GstVaapiSliceH264   *slice,
2874     GstH264NalUnit      *nalu
2875 )
2876 {
2877     GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
2878     VASliceParameterBufferH264 * const slice_param = slice->base.param;
2879
2880     /* Fill in VASliceParameterBufferH264 */
2881     slice_param->slice_data_bit_offset          = get_slice_data_bit_offset(slice_hdr, nalu);
2882     slice_param->first_mb_in_slice              = slice_hdr->first_mb_in_slice;
2883     slice_param->slice_type                     = slice_hdr->type % 5;
2884     slice_param->direct_spatial_mv_pred_flag    = slice_hdr->direct_spatial_mv_pred_flag;
2885     slice_param->cabac_init_idc                 = slice_hdr->cabac_init_idc;
2886     slice_param->slice_qp_delta                 = slice_hdr->slice_qp_delta;
2887     slice_param->disable_deblocking_filter_idc  = slice_hdr->disable_deblocking_filter_idc;
2888     slice_param->slice_alpha_c0_offset_div2     = slice_hdr->slice_alpha_c0_offset_div2;
2889     slice_param->slice_beta_offset_div2         = slice_hdr->slice_beta_offset_div2;
2890
2891     if (!fill_RefPicList(decoder, slice))
2892         return FALSE;
2893     if (!fill_pred_weight_table(decoder, slice))
2894         return FALSE;
2895     return TRUE;
2896 }
2897
2898 static GstVaapiDecoderStatus
2899 decode_slice(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
2900 {
2901     GstVaapiDecoderH264Private * const priv = decoder->priv;
2902     GstVaapiDecoderStatus status;
2903     GstVaapiPictureH264 *picture;
2904     GstVaapiSliceH264 *slice = NULL;
2905     GstH264SliceHdr *slice_hdr;
2906     GstH264ParserResult result;
2907     gboolean is_first_slice = !priv->has_context;
2908
2909     GST_DEBUG("slice (%u bytes)", nalu->size);
2910
2911     if (is_first_slice) {
2912         slice_hdr = &priv->temp_slice_hdr;
2913         memset(slice_hdr, 0, sizeof(*slice_hdr));
2914         result = gst_h264_parser_parse_slice_hdr(priv->parser, nalu,
2915             slice_hdr, TRUE, TRUE);
2916         if (result != GST_H264_PARSER_OK) {
2917             status = get_status(result);
2918             goto error;
2919         }
2920
2921         status = ensure_context(decoder, slice_hdr->pps->sequence);
2922         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2923             return status;
2924     }
2925
2926     slice = gst_vaapi_slice_h264_new(
2927         decoder,
2928         nalu->data + nalu->offset,
2929         nalu->size
2930     );
2931     if (!slice) {
2932         GST_ERROR("failed to allocate slice");
2933         return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
2934     }
2935
2936     slice_hdr = &slice->slice_hdr;
2937     if (is_first_slice)
2938         memcpy(slice_hdr, &priv->temp_slice_hdr, sizeof(*slice_hdr));
2939     else {
2940         memset(slice_hdr, 0, sizeof(*slice_hdr));
2941         result = gst_h264_parser_parse_slice_hdr(priv->parser, nalu,
2942             slice_hdr, TRUE, TRUE);
2943         if (result != GST_H264_PARSER_OK) {
2944             status = get_status(result);
2945             goto error;
2946         }
2947     }
2948
2949     if (is_new_picture(decoder, nalu, slice_hdr)) {
2950         status = decode_picture(decoder, nalu, slice_hdr);
2951         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
2952             goto error;
2953     }
2954     picture = priv->current_picture;
2955
2956     if (!fill_slice(decoder, slice, nalu)) {
2957         status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
2958         goto error;
2959     }
2960     gst_vaapi_picture_add_slice(
2961         GST_VAAPI_PICTURE_CAST(picture),
2962         GST_VAAPI_SLICE_CAST(slice)
2963     );
2964     return GST_VAAPI_DECODER_STATUS_SUCCESS;
2965
2966 error:
2967     if (slice)
2968         gst_mini_object_unref(GST_MINI_OBJECT(slice));
2969     return status;
2970 }
2971
2972 static inline gint
2973 scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
2974 {
2975     return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
2976                                                      0xffffff00, 0x00000100,
2977                                                      ofs, size,
2978                                                      scp);
2979 }
2980
2981 static GstVaapiDecoderStatus
2982 decode_nalu(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
2983 {
2984     GstVaapiDecoderH264Private * const priv = decoder->priv;
2985     GstVaapiDecoderStatus status;
2986
2987     switch (nalu->type) {
2988     case GST_H264_NAL_SLICE_IDR:
2989         /* fall-through. IDR specifics are handled in init_picture() */
2990     case GST_H264_NAL_SLICE:
2991         if (!priv->got_sps || !priv->got_pps)
2992             return GST_VAAPI_DECODER_STATUS_SUCCESS;
2993         status = decode_slice(decoder, nalu);
2994         break;
2995     case GST_H264_NAL_SPS:
2996         status = decode_sps(decoder, nalu);
2997         break;
2998     case GST_H264_NAL_PPS:
2999         status = decode_pps(decoder, nalu);
3000         break;
3001     case GST_H264_NAL_SEI:
3002         status = decode_sei(decoder, nalu);
3003         break;
3004     case GST_H264_NAL_SEQ_END:
3005         status = decode_sequence_end(decoder);
3006         break;
3007     case GST_H264_NAL_AU_DELIMITER:
3008         /* skip all Access Unit NALs */
3009         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3010         break;
3011     case GST_H264_NAL_FILLER_DATA:
3012         /* skip all Filler Data NALs */
3013         status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3014         break;
3015     default:
3016         GST_WARNING("unsupported NAL unit type %d", nalu->type);
3017         status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
3018         break;
3019     }
3020     return status;
3021 }
3022
3023 static GstVaapiDecoderStatus
3024 decode_buffer(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
3025 {
3026     GstVaapiDecoderH264Private * const priv = decoder->priv;
3027     GstVaapiDecoderStatus status;
3028     GstH264ParserResult result;
3029     GstH264NalUnit nalu;
3030     gboolean is_eos;
3031     const guchar *buf;
3032     guint i, buf_size, nalu_size, size;
3033     guint32 start_code;
3034     gint ofs;
3035
3036     buf      = GST_BUFFER_DATA(buffer);
3037     buf_size = GST_BUFFER_SIZE(buffer);
3038     is_eos   = GST_BUFFER_IS_EOS(buffer);
3039     if (buf && buf_size > 0)
3040         gst_adapter_push(priv->adapter, gst_buffer_ref(buffer));
3041
3042     size = gst_adapter_available(priv->adapter);
3043     do {
3044         if (size == 0) {
3045             status = GST_VAAPI_DECODER_STATUS_SUCCESS;
3046             break;
3047         }
3048
3049         status = gst_vaapi_decoder_check_status(GST_VAAPI_DECODER(decoder));
3050         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3051             break;
3052
3053         status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3054         if (priv->is_avc) {
3055             if (size < priv->nal_length_size)
3056                 break;
3057             buf = gst_adapter_peek(priv->adapter, priv->nal_length_size);
3058
3059             nalu_size = 0;
3060             for (i = 0; i < priv->nal_length_size; i++)
3061                 nalu_size = (nalu_size << 8) | buf[i];
3062
3063             buf_size = priv->nal_length_size + nalu_size;
3064             if (size < buf_size)
3065                 break;
3066             buffer = gst_adapter_take_buffer(priv->adapter, buf_size);
3067             size -= buf_size;
3068
3069             buf      = GST_BUFFER_DATA(buffer);
3070             buf_size = GST_BUFFER_SIZE(buffer);
3071
3072             result = gst_h264_parser_identify_nalu_avc(
3073                 priv->parser,
3074                 buf, 0, buf_size, priv->nal_length_size,
3075                 &nalu
3076             );
3077         }
3078         else {
3079             if (size < 4)
3080                 break;
3081             ofs = scan_for_start_code(priv->adapter, 0, size, &start_code);
3082             if (ofs < 0)
3083                 break;
3084             gst_adapter_flush(priv->adapter, ofs);
3085             size -= ofs;
3086
3087             ofs = G_UNLIKELY(size < 8) ? -1 :
3088                 scan_for_start_code(priv->adapter, 4, size - 4, NULL);
3089             if (ofs < 0) {
3090                 // Assume the whole NAL unit is present if end-of-stream
3091                 if (!is_eos)
3092                     break;
3093                 ofs = size;
3094             }
3095             buffer = gst_adapter_take_buffer(priv->adapter, ofs);
3096             size -= ofs;
3097
3098             buf      = GST_BUFFER_DATA(buffer);
3099             buf_size = GST_BUFFER_SIZE(buffer);
3100
3101             result = gst_h264_parser_identify_nalu_unchecked(
3102                 priv->parser,
3103                 buf, 0, buf_size,
3104                 &nalu
3105             );
3106         }
3107         status = get_status(result);
3108         if (status == GST_VAAPI_DECODER_STATUS_SUCCESS)
3109             status = decode_nalu(decoder, &nalu);
3110         gst_buffer_unref(buffer);
3111     } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
3112
3113     if (is_eos && (status == GST_VAAPI_DECODER_STATUS_SUCCESS ||
3114                    status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA))
3115         status = decode_sequence_end(decoder);
3116     return status;
3117 }
3118
3119 static GstVaapiDecoderStatus
3120 decode_codec_data(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
3121 {
3122     GstVaapiDecoderH264Private * const priv = decoder->priv;
3123     GstVaapiDecoderStatus status;
3124     GstH264NalUnit nalu;
3125     GstH264ParserResult result;
3126     guchar *buf;
3127     guint buf_size;
3128     guint i, ofs, num_sps, num_pps;
3129
3130     buf      = GST_BUFFER_DATA(buffer);
3131     buf_size = GST_BUFFER_SIZE(buffer);
3132     if (!buf || buf_size == 0)
3133         return GST_VAAPI_DECODER_STATUS_SUCCESS;
3134
3135     if (buf_size < 8)
3136         return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
3137
3138     if (buf[0] != 1) {
3139         GST_ERROR("failed to decode codec-data, not in avcC format");
3140         return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
3141     }
3142
3143     priv->nal_length_size = (buf[4] & 0x03) + 1;
3144
3145     num_sps = buf[5] & 0x1f;
3146     ofs = 6;
3147
3148     for (i = 0; i < num_sps; i++) {
3149         result = gst_h264_parser_identify_nalu_avc(
3150             priv->parser,
3151             buf, ofs, buf_size, 2,
3152             &nalu
3153         );
3154         if (result != GST_H264_PARSER_OK)
3155             return get_status(result);
3156
3157         status = decode_sps(decoder, &nalu);
3158         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3159             return status;
3160         ofs = nalu.offset + nalu.size;
3161     }
3162
3163     num_pps = buf[ofs];
3164     ofs++;
3165
3166     for (i = 0; i < num_pps; i++) {
3167         result = gst_h264_parser_identify_nalu_avc(
3168             priv->parser,
3169             buf, ofs, buf_size, 2,
3170             &nalu
3171         );
3172         if (result != GST_H264_PARSER_OK)
3173             return get_status(result);
3174
3175         status = decode_pps(decoder, &nalu);
3176         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3177             return status;
3178         ofs = nalu.offset + nalu.size;
3179     }
3180
3181     priv->is_avc = TRUE;
3182     return status;
3183 }
3184
3185 GstVaapiDecoderStatus
3186 gst_vaapi_decoder_h264_decode(GstVaapiDecoder *base, GstBuffer *buffer)
3187 {
3188     GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(base);
3189     GstVaapiDecoderH264Private * const priv = decoder->priv;
3190     GstVaapiDecoderStatus status;
3191     GstBuffer *codec_data;
3192
3193     g_return_val_if_fail(priv->is_constructed,
3194                          GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
3195
3196     if (!priv->is_opened) {
3197         priv->is_opened = gst_vaapi_decoder_h264_open(decoder, buffer);
3198         if (!priv->is_opened)
3199             return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
3200
3201         codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
3202         if (codec_data) {
3203             status = decode_codec_data(decoder, codec_data);
3204             if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
3205                 return status;
3206         }
3207      }
3208      return decode_buffer(decoder, buffer);
3209 }
3210
3211 static void
3212 gst_vaapi_decoder_h264_finalize(GObject *object)
3213 {
3214     GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(object);
3215
3216     gst_vaapi_decoder_h264_destroy(decoder);
3217
3218     G_OBJECT_CLASS(gst_vaapi_decoder_h264_parent_class)->finalize(object);
3219 }
3220
3221 static void
3222 gst_vaapi_decoder_h264_constructed(GObject *object)
3223 {
3224     GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(object);
3225     GstVaapiDecoderH264Private * const priv = decoder->priv;
3226     GObjectClass *parent_class;
3227
3228     parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_h264_parent_class);
3229     if (parent_class->constructed)
3230         parent_class->constructed(object);
3231
3232     priv->is_constructed = gst_vaapi_decoder_h264_create(decoder);
3233 }
3234
3235 static void
3236 gst_vaapi_decoder_h264_class_init(GstVaapiDecoderH264Class *klass)
3237 {
3238     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
3239     GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
3240
3241     g_type_class_add_private(klass, sizeof(GstVaapiDecoderH264Private));
3242
3243     object_class->finalize      = gst_vaapi_decoder_h264_finalize;
3244     object_class->constructed   = gst_vaapi_decoder_h264_constructed;
3245
3246     decoder_class->decode       = gst_vaapi_decoder_h264_decode;
3247     decoder_class->clear_buffer = gst_vaapi_decoder_h264_clear_buffer;
3248 }
3249
3250 static void
3251 gst_vaapi_decoder_h264_init(GstVaapiDecoderH264 *decoder)
3252 {
3253     GstVaapiDecoderH264Private *priv;
3254
3255     priv                        = GST_VAAPI_DECODER_H264_GET_PRIVATE(decoder);
3256     decoder->priv               = priv;
3257     priv->parser                = NULL;
3258     priv->current_picture       = NULL;
3259     priv->dpb_count             = 0;
3260     priv->dpb_size              = 0;
3261     priv->profile               = GST_VAAPI_PROFILE_UNKNOWN;
3262     priv->entrypoint            = GST_VAAPI_ENTRYPOINT_VLD;
3263     priv->chroma_type           = GST_VAAPI_CHROMA_TYPE_YUV420;
3264     priv->short_ref_count       = 0;
3265     priv->long_ref_count        = 0;
3266     priv->RefPicList0_count     = 0;
3267     priv->RefPicList1_count     = 0;
3268     priv->nal_length_size       = 0;
3269     priv->adapter               = NULL;
3270     priv->field_poc[0]          = 0;
3271     priv->field_poc[1]          = 0;
3272     priv->poc_msb               = 0;
3273     priv->poc_lsb               = 0;
3274     priv->prev_poc_msb          = 0;
3275     priv->prev_poc_lsb          = 0;
3276     priv->frame_num_offset      = 0;
3277     priv->frame_num             = 0;
3278     priv->prev_frame_num        = 0;
3279     priv->prev_pic_has_mmco5    = FALSE;
3280     priv->prev_pic_structure    = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
3281     priv->is_constructed        = FALSE;
3282     priv->is_opened             = FALSE;
3283     priv->is_avc                = FALSE;
3284     priv->has_context           = FALSE;
3285     priv->progressive_sequence  = TRUE;
3286
3287     memset(priv->dpb, 0, sizeof(priv->dpb));
3288     memset(priv->short_ref, 0, sizeof(priv->short_ref));
3289     memset(priv->long_ref, 0, sizeof(priv->long_ref));
3290     memset(priv->RefPicList0, 0, sizeof(priv->RefPicList0));
3291     memset(priv->RefPicList1, 0, sizeof(priv->RefPicList1));
3292 }
3293
3294 /**
3295  * gst_vaapi_decoder_h264_new:
3296  * @display: a #GstVaapiDisplay
3297  * @caps: a #GstCaps holding codec information
3298  *
3299  * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
3300  * hold extra information like codec-data and pictured coded size.
3301  *
3302  * Return value: the newly allocated #GstVaapiDecoder object
3303  */
3304 GstVaapiDecoder *
3305 gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps)
3306 {
3307     GstVaapiDecoderH264 *decoder;
3308
3309     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
3310     g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
3311
3312     decoder = g_object_new(
3313         GST_VAAPI_TYPE_DECODER_H264,
3314         "display",      display,
3315         "caps",         caps,
3316         NULL
3317     );
3318     if (!decoder->priv->is_constructed) {
3319         g_object_unref(decoder);
3320         return NULL;
3321     }
3322     return GST_VAAPI_DECODER_CAST(decoder);
3323 }