• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include "gsth264picture.h"
25 #include <stdlib.h>
26 
27 GST_DEBUG_CATEGORY_EXTERN (gst_h264_decoder_debug);
28 #define GST_CAT_DEFAULT gst_h264_decoder_debug
29 
30 GST_DEFINE_MINI_OBJECT_TYPE (GstH264Picture, gst_h264_picture);
31 
32 static void
_gst_h264_picture_free(GstH264Picture * picture)33 _gst_h264_picture_free (GstH264Picture * picture)
34 {
35   if (picture->notify)
36     picture->notify (picture->user_data);
37 
38   g_free (picture);
39 }
40 
41 /**
42  * gst_h264_picture_new:
43  *
44  * Create new #GstH264Picture
45  *
46  * Returns: a new #GstH264Picture
47  */
48 GstH264Picture *
gst_h264_picture_new(void)49 gst_h264_picture_new (void)
50 {
51   GstH264Picture *pic;
52 
53   pic = g_new0 (GstH264Picture, 1);
54 
55   pic->top_field_order_cnt = G_MAXINT32;
56   pic->bottom_field_order_cnt = G_MAXINT32;
57   pic->field = GST_H264_PICTURE_FIELD_FRAME;
58 
59   gst_mini_object_init (GST_MINI_OBJECT_CAST (pic), 0,
60       GST_TYPE_H264_PICTURE, NULL, NULL,
61       (GstMiniObjectFreeFunction) _gst_h264_picture_free);
62 
63   return pic;
64 }
65 
66 /**
67  * gst_h264_picture_set_user_data:
68  * @picture: a #GstH264Picture
69  * @user_data: private data
70  * @notify: (closure user_data): a #GDestroyNotify
71  *
72  * Sets @user_data on the picture and the #GDestroyNotify that will be called when
73  * the picture is freed.
74  *
75  * If a @user_data was previously set, then the previous set @notify will be called
76  * before the @user_data is replaced.
77  */
78 void
gst_h264_picture_set_user_data(GstH264Picture * picture,gpointer user_data,GDestroyNotify notify)79 gst_h264_picture_set_user_data (GstH264Picture * picture, gpointer user_data,
80     GDestroyNotify notify)
81 {
82   g_return_if_fail (GST_IS_H264_PICTURE (picture));
83 
84   if (picture->notify)
85     picture->notify (picture->user_data);
86 
87   picture->user_data = user_data;
88   picture->notify = notify;
89 }
90 
91 /**
92  * gst_h264_picture_get_user_data:
93  * @picture: a #GstH264Picture
94  *
95  * Gets private data set on the picture via
96  * gst_h264_picture_set_user_data() previously.
97  *
98  * Returns: (transfer none): The previously set user_data
99  */
100 gpointer
gst_h264_picture_get_user_data(GstH264Picture * picture)101 gst_h264_picture_get_user_data (GstH264Picture * picture)
102 {
103   return picture->user_data;
104 }
105 
106 struct _GstH264Dpb
107 {
108   GArray *pic_list;
109   gint max_num_frames;
110   gint num_output_needed;
111   guint32 max_num_reorder_frames;
112   gint32 last_output_poc;
113   gboolean last_output_non_ref;
114 
115   gboolean interlaced;
116 };
117 
118 static void
gst_h264_dpb_init(GstH264Dpb * dpb)119 gst_h264_dpb_init (GstH264Dpb * dpb)
120 {
121   dpb->num_output_needed = 0;
122   dpb->last_output_poc = G_MININT32;
123   dpb->last_output_non_ref = FALSE;
124 }
125 
126 /**
127  * gst_h264_dpb_new: (skip)
128  *
129  * Create new #GstH264Dpb
130  *
131  * Returns: a new #GstH264Dpb
132  */
133 GstH264Dpb *
gst_h264_dpb_new(void)134 gst_h264_dpb_new (void)
135 {
136   GstH264Dpb *dpb;
137 
138   dpb = g_new0 (GstH264Dpb, 1);
139   gst_h264_dpb_init (dpb);
140 
141   dpb->pic_list =
142       g_array_sized_new (FALSE, TRUE, sizeof (GstH264Picture *),
143       GST_H264_DPB_MAX_SIZE);
144   g_array_set_clear_func (dpb->pic_list,
145       (GDestroyNotify) gst_h264_picture_clear);
146 
147   return dpb;
148 }
149 
150 /**
151  * gst_h264_dpb_set_max_num_frames:
152  * @dpb: a #GstH264Dpb
153  * @max_num_frames: the maximum number of picture
154  *
155  * Set the number of maximum allowed frames to store
156  *
157  * Since: 1.20
158  */
159 void
gst_h264_dpb_set_max_num_frames(GstH264Dpb * dpb,gint max_num_frames)160 gst_h264_dpb_set_max_num_frames (GstH264Dpb * dpb, gint max_num_frames)
161 {
162   g_return_if_fail (dpb != NULL);
163 
164   dpb->max_num_frames = max_num_frames;
165 }
166 
167 /**
168  * gst_h264_dpb_get_max_num_frames:
169  * @dpb: a #GstH264Dpb
170  *
171  * Returns: the number of maximum frames
172  *
173  * Since: 1.20
174  */
175 gint
gst_h264_dpb_get_max_num_frames(GstH264Dpb * dpb)176 gst_h264_dpb_get_max_num_frames (GstH264Dpb * dpb)
177 {
178   g_return_val_if_fail (dpb != NULL, 0);
179 
180   return dpb->max_num_frames;
181 }
182 
183 /**
184  * gst_h264_dpb_set_interlaced:
185  * @dpb: a #GstH264Dpb
186  * @interlaced: %TRUE if interlaced
187  *
188  * Since: 1.20
189  */
190 void
gst_h264_dpb_set_interlaced(GstH264Dpb * dpb,gboolean interlaced)191 gst_h264_dpb_set_interlaced (GstH264Dpb * dpb, gboolean interlaced)
192 {
193   g_return_if_fail (dpb != NULL);
194 
195   dpb->interlaced = interlaced;
196 }
197 
198 /**
199  * gst_h264_dpb_get_interlaced:
200  * @dpb: a #GstH264Dpb
201  *
202  * Returns: %TRUE if @dpb is configured for interlaced stream
203  *
204  * Since: 1.20
205  */
206 gboolean
gst_h264_dpb_get_interlaced(GstH264Dpb * dpb)207 gst_h264_dpb_get_interlaced (GstH264Dpb * dpb)
208 {
209   g_return_val_if_fail (dpb != NULL, FALSE);
210 
211   return dpb->interlaced;
212 }
213 
214 /**
215  * gst_h264_dpb_free:
216  * @dpb: a #GstH264Dpb to free
217  *
218  * Free the @dpb
219  */
220 void
gst_h264_dpb_free(GstH264Dpb * dpb)221 gst_h264_dpb_free (GstH264Dpb * dpb)
222 {
223   g_return_if_fail (dpb != NULL);
224 
225   gst_h264_dpb_clear (dpb);
226   g_array_unref (dpb->pic_list);
227   g_free (dpb);
228 }
229 
230 /**
231  * gst_h264_dpb_clear:
232  * @dpb: a #GstH264Dpb
233  *
234  * Clear all stored #GstH264Picture
235  */
236 void
gst_h264_dpb_clear(GstH264Dpb * dpb)237 gst_h264_dpb_clear (GstH264Dpb * dpb)
238 {
239   g_return_if_fail (dpb != NULL);
240 
241   g_array_set_size (dpb->pic_list, 0);
242   gst_h264_dpb_init (dpb);
243 }
244 
245 /**
246  * gst_h264_dpb_set_max_num_reorder_frames:
247  * @dpb: a #GstH264Dpb
248  * @max_num_reorder_frames: the max number of reorder frames, which
249  * should not exceed the max size of DPB.
250  *
251  * Since: 1.20
252  */
253 void
gst_h264_dpb_set_max_num_reorder_frames(GstH264Dpb * dpb,guint32 max_num_reorder_frames)254 gst_h264_dpb_set_max_num_reorder_frames (GstH264Dpb * dpb,
255     guint32 max_num_reorder_frames)
256 {
257   g_return_if_fail (dpb != NULL);
258   g_return_if_fail (max_num_reorder_frames <= dpb->max_num_frames);
259 
260   dpb->max_num_reorder_frames = max_num_reorder_frames;
261 }
262 
263 /**
264  * gst_h264_dpb_add:
265  * @dpb: a #GstH264Dpb
266  * @picture: (transfer full): a #GstH264Picture
267  *
268  * Store the @picture
269  */
270 void
gst_h264_dpb_add(GstH264Dpb * dpb,GstH264Picture * picture)271 gst_h264_dpb_add (GstH264Dpb * dpb, GstH264Picture * picture)
272 {
273   g_return_if_fail (dpb != NULL);
274   g_return_if_fail (GST_IS_H264_PICTURE (picture));
275 
276   /* C.4.2 Decoding of gaps in frame_num and storage of "non-existing" pictures
277    *
278    * The "non-existing" frame is stored in an empty frame buffer and is marked
279    * as "not needed for output", and the DPB fullness is incremented by one */
280   if (!picture->nonexisting) {
281     picture->needed_for_output = TRUE;
282 
283     if (GST_H264_PICTURE_IS_FRAME (picture)) {
284       dpb->num_output_needed++;
285     } else {
286       /* We can do output only when field pair are complete */
287       if (picture->second_field) {
288         dpb->num_output_needed++;
289       }
290     }
291   } else {
292     picture->needed_for_output = FALSE;
293   }
294 
295   /* Link each field */
296   if (picture->second_field && picture->other_field) {
297     picture->other_field->other_field = picture;
298   }
299 
300   g_array_append_val (dpb->pic_list, picture);
301 
302   if (dpb->pic_list->len > dpb->max_num_frames * (dpb->interlaced + 1))
303     GST_ERROR ("DPB size is %d, exceed the max size %d",
304         dpb->pic_list->len, dpb->max_num_frames * (dpb->interlaced + 1));
305 
306   /* The IDR frame or mem_mgmt_5 */
307   if (picture->pic_order_cnt == 0) {
308     GST_TRACE ("last_output_poc reset because of IDR or mem_mgmt_5");
309     dpb->last_output_poc = G_MININT32;
310     dpb->last_output_non_ref = FALSE;
311   }
312 }
313 
314 /**
315  * gst_h264_dpb_delete_unused:
316  * @dpb: a #GstH264Dpb
317  *
318  * Delete already outputted and not referenced all pictures from dpb
319  */
320 void
gst_h264_dpb_delete_unused(GstH264Dpb * dpb)321 gst_h264_dpb_delete_unused (GstH264Dpb * dpb)
322 {
323   gint i;
324 
325   g_return_if_fail (dpb != NULL);
326 
327   for (i = 0; i < dpb->pic_list->len; i++) {
328     GstH264Picture *picture =
329         g_array_index (dpb->pic_list, GstH264Picture *, i);
330 
331     /* NOTE: don't use g_array_remove_index_fast here since the last picture
332      * need to be referenced for bumping decision */
333     if (!picture->needed_for_output && !GST_H264_PICTURE_IS_REF (picture)) {
334       GST_TRACE
335           ("remove picture %p (frame num: %d, poc: %d, field: %d) from dpb",
336           picture, picture->frame_num, picture->pic_order_cnt, picture->field);
337       g_array_remove_index (dpb->pic_list, i);
338       i--;
339     }
340   }
341 }
342 
343 /**
344  * gst_h264_dpb_num_ref_frames:
345  * @dpb: a #GstH264Dpb
346  *
347  * Returns: The number of referenced frames
348  *
349  * Since: 1.20
350  */
351 gint
gst_h264_dpb_num_ref_frames(GstH264Dpb * dpb)352 gst_h264_dpb_num_ref_frames (GstH264Dpb * dpb)
353 {
354   gint i;
355   gint ret = 0;
356 
357   g_return_val_if_fail (dpb != NULL, -1);
358 
359   for (i = 0; i < dpb->pic_list->len; i++) {
360     GstH264Picture *picture =
361         g_array_index (dpb->pic_list, GstH264Picture *, i);
362 
363     /* Count frame, not field picture */
364     if (picture->second_field)
365       continue;
366 
367     if (GST_H264_PICTURE_IS_REF (picture))
368       ret++;
369   }
370 
371   return ret;
372 }
373 
374 /**
375  * gst_h264_dpb_mark_all_non_ref:
376  * @dpb: a #GstH264Dpb
377  *
378  * Mark all pictures are not referenced
379  */
380 void
gst_h264_dpb_mark_all_non_ref(GstH264Dpb * dpb)381 gst_h264_dpb_mark_all_non_ref (GstH264Dpb * dpb)
382 {
383   gint i;
384 
385   g_return_if_fail (dpb != NULL);
386 
387   for (i = 0; i < dpb->pic_list->len; i++) {
388     GstH264Picture *picture =
389         g_array_index (dpb->pic_list, GstH264Picture *, i);
390 
391     gst_h264_picture_set_reference (picture, GST_H264_PICTURE_REF_NONE, FALSE);
392   }
393 }
394 
395 /**
396  * gst_h264_dpb_get_short_ref_by_pic_num:
397  * @dpb: a #GstH264Dpb
398  * @pic_num: a picture number
399  *
400  * Find a short term reference picture which has matching picture number
401  *
402  * Returns: (nullable) (transfer none): a #GstH264Picture
403  */
404 GstH264Picture *
gst_h264_dpb_get_short_ref_by_pic_num(GstH264Dpb * dpb,gint pic_num)405 gst_h264_dpb_get_short_ref_by_pic_num (GstH264Dpb * dpb, gint pic_num)
406 {
407   gint i;
408 
409   g_return_val_if_fail (dpb != NULL, NULL);
410 
411   for (i = 0; i < dpb->pic_list->len; i++) {
412     GstH264Picture *picture =
413         g_array_index (dpb->pic_list, GstH264Picture *, i);
414 
415     if (GST_H264_PICTURE_IS_SHORT_TERM_REF (picture)
416         && picture->pic_num == pic_num)
417       return picture;
418   }
419 
420   GST_WARNING ("No short term reference picture for %d", pic_num);
421 
422   return NULL;
423 }
424 
425 /**
426  * gst_h264_dpb_get_long_ref_by_long_term_pic_num:
427  * @dpb: a #GstH264Dpb
428  * @long_term_pic_num: a long term picture number
429  *
430  * Find a long term reference picture which has matching long term picture number
431  *
432  * Returns: (nullable) (transfer none): a #GstH264Picture
433  *
434  * Since: 1.20
435  */
436 GstH264Picture *
gst_h264_dpb_get_long_ref_by_long_term_pic_num(GstH264Dpb * dpb,gint long_term_pic_num)437 gst_h264_dpb_get_long_ref_by_long_term_pic_num (GstH264Dpb * dpb,
438     gint long_term_pic_num)
439 {
440   gint i;
441 
442   g_return_val_if_fail (dpb != NULL, NULL);
443 
444   for (i = 0; i < dpb->pic_list->len; i++) {
445     GstH264Picture *picture =
446         g_array_index (dpb->pic_list, GstH264Picture *, i);
447 
448     if (GST_H264_PICTURE_IS_LONG_TERM_REF (picture) &&
449         picture->long_term_pic_num == long_term_pic_num)
450       return picture;
451   }
452 
453   GST_WARNING ("No long term reference picture for %d", long_term_pic_num);
454 
455   return NULL;
456 }
457 
458 /**
459  * gst_h264_dpb_get_lowest_frame_num_short_ref:
460  * @dpb: a #GstH264Dpb
461  *
462  * Find a short term reference picture which has the lowest frame_num_wrap
463  *
464  * Returns: (transfer full): a #GstH264Picture
465  */
466 GstH264Picture *
gst_h264_dpb_get_lowest_frame_num_short_ref(GstH264Dpb * dpb)467 gst_h264_dpb_get_lowest_frame_num_short_ref (GstH264Dpb * dpb)
468 {
469   gint i;
470   GstH264Picture *ret = NULL;
471 
472   g_return_val_if_fail (dpb != NULL, NULL);
473 
474   for (i = 0; i < dpb->pic_list->len; i++) {
475     GstH264Picture *picture =
476         g_array_index (dpb->pic_list, GstH264Picture *, i);
477 
478     if (GST_H264_PICTURE_IS_SHORT_TERM_REF (picture) &&
479         (!ret || picture->frame_num_wrap < ret->frame_num_wrap))
480       ret = picture;
481   }
482 
483   if (ret)
484     gst_h264_picture_ref (ret);
485 
486   return ret;
487 }
488 
489 /**
490  * gst_h264_dpb_get_pictures_short_term_ref:
491  * @dpb: a #GstH264Dpb
492  * @include_non_existing: %TRUE if non-existing pictures need to be included
493  * @include_second_field: %TRUE if the second field pictures need to be included
494  * @out: (out) (element-type GstH264Picture) (transfer full): an array
495  *   of #GstH264Picture pointers
496  *
497  * Retrieve all short-term reference pictures from @dpb. The picture will be
498  * appended to the array.
499  *
500  * Since: 1.20
501  */
502 void
gst_h264_dpb_get_pictures_short_term_ref(GstH264Dpb * dpb,gboolean include_non_existing,gboolean include_second_field,GArray * out)503 gst_h264_dpb_get_pictures_short_term_ref (GstH264Dpb * dpb,
504     gboolean include_non_existing, gboolean include_second_field, GArray * out)
505 {
506   gint i;
507 
508   g_return_if_fail (dpb != NULL);
509   g_return_if_fail (out != NULL);
510 
511   for (i = 0; i < dpb->pic_list->len; i++) {
512     GstH264Picture *picture =
513         g_array_index (dpb->pic_list, GstH264Picture *, i);
514 
515     if (!include_second_field && picture->second_field)
516       continue;
517 
518     if (GST_H264_PICTURE_IS_SHORT_TERM_REF (picture) &&
519         (include_non_existing || (!include_non_existing &&
520                 !picture->nonexisting))) {
521       gst_h264_picture_ref (picture);
522       g_array_append_val (out, picture);
523     }
524   }
525 }
526 
527 /**
528  * gst_h264_dpb_get_pictures_long_term_ref:
529  * @dpb: a #GstH264Dpb
530  * @include_second_field: %TRUE if the second field pictures need to be included
531  * @out: (out) (element-type GstH264Picture) (transfer full): an array
532  *   of #GstH264Picture pointer
533  *
534  * Retrieve all long-term reference pictures from @dpb. The picture will be
535  * appended to the array.
536  *
537  * Since: 1.20
538  */
539 void
gst_h264_dpb_get_pictures_long_term_ref(GstH264Dpb * dpb,gboolean include_second_field,GArray * out)540 gst_h264_dpb_get_pictures_long_term_ref (GstH264Dpb * dpb,
541     gboolean include_second_field, GArray * out)
542 {
543   gint i;
544 
545   g_return_if_fail (dpb != NULL);
546   g_return_if_fail (out != NULL);
547 
548   for (i = 0; i < dpb->pic_list->len; i++) {
549     GstH264Picture *picture =
550         g_array_index (dpb->pic_list, GstH264Picture *, i);
551 
552     if (!include_second_field && picture->second_field)
553       continue;
554 
555     if (GST_H264_PICTURE_IS_LONG_TERM_REF (picture)) {
556       gst_h264_picture_ref (picture);
557       g_array_append_val (out, picture);
558     }
559   }
560 }
561 
562 /**
563  * gst_h264_dpb_get_pictures_all:
564  * @dpb: a #GstH264Dpb
565  *
566  * Return: (element-type GstH264Picture) (transfer full): a #GArray of
567  *   #GstH264Picture stored in @dpb
568  */
569 GArray *
gst_h264_dpb_get_pictures_all(GstH264Dpb * dpb)570 gst_h264_dpb_get_pictures_all (GstH264Dpb * dpb)
571 {
572   g_return_val_if_fail (dpb != NULL, NULL);
573 
574   return g_array_ref (dpb->pic_list);
575 }
576 
577 /**
578  * gst_h264_dpb_get_size:
579  * @dpb: a #GstH264Dpb
580  *
581  * Return: the length of stored dpb array
582  */
583 gint
gst_h264_dpb_get_size(GstH264Dpb * dpb)584 gst_h264_dpb_get_size (GstH264Dpb * dpb)
585 {
586   g_return_val_if_fail (dpb != NULL, -1);
587 
588   return dpb->pic_list->len;
589 }
590 
591 /**
592  * gst_h264_dpb_get_picture:
593  * @dpb: a #GstH264Dpb
594  * @system_frame_number The system frame number
595  *
596  * Returns: (transfer full): the picture identified with the specified
597  * @system_frame_number, or %NULL if DPB does not contain a #GstH264Picture
598  * corresponding to the @system_frame_number
599  *
600  * Since: 1.18
601  */
602 GstH264Picture *
gst_h264_dpb_get_picture(GstH264Dpb * dpb,guint32 system_frame_number)603 gst_h264_dpb_get_picture (GstH264Dpb * dpb, guint32 system_frame_number)
604 {
605   gint i;
606 
607   g_return_val_if_fail (dpb != NULL, NULL);
608 
609   for (i = 0; i < dpb->pic_list->len; i++) {
610     GstH264Picture *picture =
611         g_array_index (dpb->pic_list, GstH264Picture *, i);
612 
613     if (picture->system_frame_number == system_frame_number) {
614       gst_h264_picture_ref (picture);
615       return picture;
616     }
617   }
618 
619   return NULL;
620 }
621 
622 /**
623  * gst_h264_dpb_has_empty_frame_buffer:
624  * @dpb: a #GstH264Dpb
625  *
626  * Returns: %TRUE if @dpb still has empty frame buffers.
627  *
628  * Since: 1.20
629  */
630 gboolean
gst_h264_dpb_has_empty_frame_buffer(GstH264Dpb * dpb)631 gst_h264_dpb_has_empty_frame_buffer (GstH264Dpb * dpb)
632 {
633   if (!dpb->interlaced) {
634     if (dpb->pic_list->len < dpb->max_num_frames)
635       return TRUE;
636   } else {
637     gint i;
638     gint count = 0;
639     /* Count the number of complementary field pairs */
640     for (i = 0; i < dpb->pic_list->len; i++) {
641       GstH264Picture *picture =
642           g_array_index (dpb->pic_list, GstH264Picture *, i);
643 
644       if (picture->second_field)
645         continue;
646 
647       if (GST_H264_PICTURE_IS_FRAME (picture) || picture->other_field)
648         count++;
649     }
650 
651     if (count < dpb->max_num_frames)
652       return TRUE;
653   }
654 
655   return FALSE;
656 }
657 
658 static gint
gst_h264_dpb_get_lowest_output_needed_picture(GstH264Dpb * dpb,GstH264Picture ** picture)659 gst_h264_dpb_get_lowest_output_needed_picture (GstH264Dpb * dpb,
660     GstH264Picture ** picture)
661 {
662   gint i;
663   GstH264Picture *lowest = NULL;
664   gint index = -1;
665 
666   *picture = NULL;
667 
668   for (i = 0; i < dpb->pic_list->len; i++) {
669     GstH264Picture *picture =
670         g_array_index (dpb->pic_list, GstH264Picture *, i);
671 
672     if (!picture->needed_for_output)
673       continue;
674 
675     if (!GST_H264_PICTURE_IS_FRAME (picture) &&
676         (!picture->other_field || picture->second_field))
677       continue;
678 
679     if (!lowest) {
680       lowest = picture;
681       index = i;
682       continue;
683     }
684 
685     if (picture->pic_order_cnt < lowest->pic_order_cnt) {
686       lowest = picture;
687       index = i;
688     }
689   }
690 
691   if (lowest)
692     *picture = gst_h264_picture_ref (lowest);
693 
694   return index;
695 }
696 
697 /**
698  * gst_h264_dpb_needs_bump:
699  * @dpb: a #GstH264Dpb
700  * @to_insert: the current #GstH264Picture to insert to dpb.
701  * @latency_mode: The required #GstH264DpbBumpMode for bumping.
702  *
703  * Returns: %TRUE if bumping is required
704  *
705  * Since: 1.20
706  */
707 gboolean
gst_h264_dpb_needs_bump(GstH264Dpb * dpb,GstH264Picture * to_insert,GstH264DpbBumpMode latency_mode)708 gst_h264_dpb_needs_bump (GstH264Dpb * dpb, GstH264Picture * to_insert,
709     GstH264DpbBumpMode latency_mode)
710 {
711   GstH264Picture *picture = NULL;
712   gint32 lowest_poc;
713   gboolean is_ref_picture;
714   gint lowest_index;
715 
716   g_return_val_if_fail (dpb != NULL, FALSE);
717   g_assert (dpb->num_output_needed >= 0);
718 
719   lowest_poc = G_MAXINT32;
720   is_ref_picture = FALSE;
721   lowest_index = gst_h264_dpb_get_lowest_output_needed_picture (dpb, &picture);
722   if (lowest_index >= 0) {
723     lowest_poc = picture->pic_order_cnt;
724     is_ref_picture = picture->ref_pic;
725     gst_h264_picture_unref (picture);
726   } else {
727     goto normal_bump;
728   }
729 
730   if (latency_mode >= GST_H264_DPB_BUMP_LOW_LATENCY) {
731     /* If low latency, we should not wait for the DPB becoming full.
732        We try to bump the picture as soon as possible without the
733        frames disorder. The policy is from the safe to some risk. */
734 
735     /* Do not support interlaced mode. */
736     if (gst_h264_dpb_get_interlaced (dpb))
737       goto normal_bump;
738 
739     /* Equal to normal bump. */
740     if (!gst_h264_dpb_has_empty_frame_buffer (dpb))
741       goto normal_bump;
742 
743     /* 7.4.1.2.2: The values of picture order count for the coded pictures
744        in consecutive access units in decoding order containing non-reference
745        pictures shall be non-decreasing. Safe. */
746     if (dpb->last_output_non_ref && !is_ref_picture) {
747       g_assert (dpb->last_output_poc < G_MAXINT32);
748       GST_TRACE ("Continuous non-reference frame poc: %d -> %d,"
749           " bumping for low-latency.", dpb->last_output_poc, lowest_poc);
750       return TRUE;
751     }
752 
753     /* num_reorder_frames indicates the maximum number of frames, that
754        precede any frame in the coded video sequence in decoding order
755        and follow it in output order. Safe. */
756     if (lowest_index >= dpb->max_num_reorder_frames) {
757       guint i, need_output;
758 
759       need_output = 0;
760       for (i = 0; i < lowest_index; i++) {
761         GstH264Picture *p = g_array_index (dpb->pic_list, GstH264Picture *, i);
762         if (p->needed_for_output)
763           need_output++;
764       }
765 
766       if (need_output >= dpb->max_num_reorder_frames) {
767         GST_TRACE ("frame with lowest poc %d has %d precede frame, already"
768             " satisfy num_reorder_frames %d, bumping for low-latency.",
769             dpb->last_output_poc, lowest_index, dpb->max_num_reorder_frames);
770         return TRUE;
771       }
772     }
773 
774     /* Bump leading picture with the negative POC if already found positive
775        POC. It's even impossible to insert another negative POC after the
776        positive POCs. Almost safe. */
777     if (to_insert && to_insert->pic_order_cnt > 0 && lowest_poc < 0) {
778       GST_TRACE ("The negative poc %d, bumping for low-latency.", lowest_poc);
779       return TRUE;
780     }
781 
782     /* There may be leading frames with negative POC following the IDR
783        frame in decoder order, so when IDR comes, we need to check the
784        following pictures. In most cases, leading pictures are in increasing
785        POC order. Bump and should be safe. */
786     if (lowest_poc == 0 && gst_h264_dpb_get_size (dpb) <= 1) {
787       if (to_insert && to_insert->pic_order_cnt > lowest_poc) {
788         GST_TRACE ("The IDR or mem_mgmt_5 frame, bumping for low-latency.");
789         return TRUE;
790       }
791 
792       GST_TRACE ("The IDR or mem_mgmt_5 frame is not the first frame.");
793       goto normal_bump;
794     }
795 
796     /* When non-ref frame has the lowest POC, it's unlike to insert another
797        ref frame with very small POC. Bump and should be safe. */
798     if (!is_ref_picture) {
799       GST_TRACE ("non ref with lowest-poc: %d bumping for low-latency",
800           lowest_poc);
801       return TRUE;
802     }
803 
804     /* When insert non-ref frame with bigger POC, it's unlike to insert
805        another ref frame with very small POC. Bump and should be safe. */
806     if (to_insert && !to_insert->ref_pic
807         && lowest_poc < to_insert->pic_order_cnt) {
808       GST_TRACE ("lowest-poc: %d < to insert non ref pic: %d, bumping "
809           "for low-latency", lowest_poc, to_insert->pic_order_cnt);
810       return TRUE;
811     }
812 
813     if (latency_mode >= GST_H264_DPB_BUMP_VERY_LOW_LATENCY) {
814       /* PicOrderCnt increment by <=2. Not all streams meet this, but in
815          practice this condition can be used.
816          For stream with 2 poc increment like:
817          0(IDR), 2(P), 4(P), 6(P), 12(P), 8(B), 10(B)....
818          This can work well, but for streams with 1 poc increment like:
819          0(IDR), 2(P), 4(P), 1(B), 3(B) ...
820          This can cause picture disorder. Most stream in practice has the
821          2 poc increment, but this may have risk and be careful. */
822       if (lowest_poc > dpb->last_output_poc
823           && lowest_poc - dpb->last_output_poc <= 2) {
824         GST_TRACE ("lowest-poc: %d, last-output-poc: %d, diff <= 2, "
825             "bumping for very-low-latency", lowest_poc, dpb->last_output_poc);
826         return TRUE;
827       }
828     }
829   }
830 
831 normal_bump:
832   /* C.4.5.3: The "bumping" process is invoked in the following cases.
833      - There is no empty frame buffer and a empty frame buffer is needed
834      for storage of an inferred "non-existing" frame.
835      - There is no empty frame buffer and an empty frame buffer is needed
836      for storage of a decoded (non-IDR) reference picture.
837      - There is no empty frame buffer and the current picture is a non-
838      reference picture that is not the second field of a complementary
839      non-reference field pair and there are pictures in the DPB that are
840      marked as "needed for output" that precede the current non-reference
841      picture in output order. */
842   if (gst_h264_dpb_has_empty_frame_buffer (dpb)) {
843     GST_TRACE ("DPB has empty frame buffer, no need bumping.");
844     return FALSE;
845   }
846 
847   if (to_insert && to_insert->ref_pic) {
848     GST_TRACE ("No empty frame buffer for ref frame, need bumping.");
849     return TRUE;
850   }
851 
852   if (to_insert && to_insert->pic_order_cnt > lowest_poc) {
853     GST_TRACE ("No empty frame buffer, lowest poc %d < current poc %d,"
854         " need bumping.", lowest_poc, to_insert->pic_order_cnt);
855     return TRUE;
856   }
857 
858   if (to_insert) {
859     GST_TRACE ("No empty frame buffer, but lowest poc %d > current poc %d,"
860         " no need bumping.", lowest_poc, to_insert->pic_order_cnt);
861   }
862 
863   return FALSE;
864 }
865 
866 /**
867  * gst_h264_dpb_bump:
868  * @dpb: a #GstH265Dpb
869  * @drain: whether draining or not
870  *
871  * Perform bumping process as defined in C.4.5.3 "Bumping" process.
872  * If @drain is %TRUE, @dpb will remove a #GstH264Picture from internal array
873  * so that returned #GstH264Picture could hold the last reference of it
874  *
875  * Returns: (nullable) (transfer full): a #GstH264Picture which is needed to be
876  * outputted
877  *
878  * Since: 1.20
879  */
880 GstH264Picture *
gst_h264_dpb_bump(GstH264Dpb * dpb,gboolean drain)881 gst_h264_dpb_bump (GstH264Dpb * dpb, gboolean drain)
882 {
883   GstH264Picture *picture;
884   GstH264Picture *other_picture;
885   gint i;
886   gint index;
887 
888   g_return_val_if_fail (dpb != NULL, NULL);
889 
890   index = gst_h264_dpb_get_lowest_output_needed_picture (dpb, &picture);
891 
892   if (!picture || index < 0)
893     return NULL;
894 
895   picture->needed_for_output = FALSE;
896 
897   dpb->num_output_needed--;
898   g_assert (dpb->num_output_needed >= 0);
899 
900   /* NOTE: don't use g_array_remove_index_fast here since the last picture
901    * need to be referenced for bumping decision */
902   if (!GST_H264_PICTURE_IS_REF (picture) || drain)
903     g_array_remove_index (dpb->pic_list, index);
904 
905   other_picture = picture->other_field;
906   if (other_picture) {
907     other_picture->needed_for_output = FALSE;
908 
909     /* At this moment, this picture should be interlaced */
910     picture->buffer_flags |= GST_VIDEO_BUFFER_FLAG_INTERLACED;
911 
912     /* FIXME: need to check picture timing SEI for the case where top/bottom poc
913      * are identical */
914     if (picture->pic_order_cnt < other_picture->pic_order_cnt)
915       picture->buffer_flags |= GST_VIDEO_BUFFER_FLAG_TFF;
916 
917     if (!other_picture->ref) {
918       for (i = 0; i < dpb->pic_list->len; i++) {
919         GstH264Picture *tmp =
920             g_array_index (dpb->pic_list, GstH264Picture *, i);
921 
922         if (tmp == other_picture) {
923           g_array_remove_index (dpb->pic_list, i);
924           break;
925         }
926       }
927     }
928     /* Now other field may or may not exist */
929   }
930 
931   dpb->last_output_poc = picture->pic_order_cnt;
932   dpb->last_output_non_ref = !picture->ref_pic;
933 
934   return picture;
935 }
936 
937 /**
938  * gst_h264_dpb_set_last_output:
939  * @dpb: a #GstH264Dpb
940  * @picture: a #GstH264Picture of the last output.
941  *
942  * Notify the DPB that @picture is output directly without storing
943  * in the DPB.
944  *
945  * Since: 1.20
946  */
947 void
gst_h264_dpb_set_last_output(GstH264Dpb * dpb,GstH264Picture * picture)948 gst_h264_dpb_set_last_output (GstH264Dpb * dpb, GstH264Picture * picture)
949 {
950   g_return_if_fail (dpb != NULL);
951   g_return_if_fail (GST_IS_H264_PICTURE (picture));
952 
953   dpb->last_output_poc = picture->pic_order_cnt;
954   dpb->last_output_non_ref = !picture->ref_pic;
955 }
956 
957 static gint
get_picNumX(GstH264Picture * picture,GstH264RefPicMarking * ref_pic_marking)958 get_picNumX (GstH264Picture * picture, GstH264RefPicMarking * ref_pic_marking)
959 {
960   return picture->pic_num -
961       (ref_pic_marking->difference_of_pic_nums_minus1 + 1);
962 }
963 
964 /**
965  * gst_h264_dpb_perform_memory_management_control_operation:
966  * @dpb: a #GstH265Dpb
967  * @ref_pic_marking: a #GstH264RefPicMarking
968  * @picture: a #GstH264Picture
969  *
970  * Perform "8.2.5.4 Adaptive memory control decoded reference picture marking process"
971  *
972  * Returns: %TRUE if successful
973  *
974  * Since: 1.20
975  */
976 gboolean
gst_h264_dpb_perform_memory_management_control_operation(GstH264Dpb * dpb,GstH264RefPicMarking * ref_pic_marking,GstH264Picture * picture)977 gst_h264_dpb_perform_memory_management_control_operation (GstH264Dpb * dpb,
978     GstH264RefPicMarking * ref_pic_marking, GstH264Picture * picture)
979 {
980   guint8 type;
981   gint pic_num_x;
982   gint max_long_term_frame_idx;
983   GstH264Picture *other;
984   gint i;
985 
986   g_return_val_if_fail (dpb != NULL, FALSE);
987   g_return_val_if_fail (ref_pic_marking != NULL, FALSE);
988   g_return_val_if_fail (picture != NULL, FALSE);
989 
990   type = ref_pic_marking->memory_management_control_operation;
991 
992   switch (type) {
993     case 0:
994       /* Normal end of operations' specification */
995       break;
996     case 1:
997       /* 8.2.5.4.1 Mark a short term reference picture as unused so it can be
998        * removed if outputted */
999       pic_num_x = get_picNumX (picture, ref_pic_marking);
1000       other = gst_h264_dpb_get_short_ref_by_pic_num (dpb, pic_num_x);
1001       if (other) {
1002         gst_h264_picture_set_reference (other,
1003             GST_H264_PICTURE_REF_NONE, GST_H264_PICTURE_IS_FRAME (picture));
1004         GST_TRACE ("MMCO-1: unmark short-term ref picture %p, (poc %d)",
1005             other, other->pic_order_cnt);
1006       } else {
1007         GST_WARNING ("Invalid picNumX %d for operation type 1", pic_num_x);
1008         return FALSE;
1009       }
1010       break;
1011     case 2:
1012       /* 8.2.5.4.2 Mark a long term reference picture as unused so it can be
1013        * removed if outputted */
1014       other = gst_h264_dpb_get_long_ref_by_long_term_pic_num (dpb,
1015           ref_pic_marking->long_term_pic_num);
1016       if (other) {
1017         gst_h264_picture_set_reference (other,
1018             GST_H264_PICTURE_REF_NONE, FALSE);
1019         GST_TRACE ("MMCO-2: unmark long-term ref picture %p, (poc %d)",
1020             other, other->pic_order_cnt);
1021       } else {
1022         GST_WARNING ("Invalid LongTermPicNum %d for operation type 2",
1023             ref_pic_marking->long_term_pic_num);
1024         return FALSE;
1025       }
1026       break;
1027     case 3:
1028       /* 8.2.5.4.3 Mark a short term reference picture as long term reference */
1029 
1030       pic_num_x = get_picNumX (picture, ref_pic_marking);
1031 
1032       other = gst_h264_dpb_get_short_ref_by_pic_num (dpb, pic_num_x);
1033       if (!other) {
1034         GST_WARNING ("Invalid picNumX %d for operation type 3", pic_num_x);
1035         return FALSE;
1036       }
1037 
1038       /* If we have long-term ref picture for LongTermFrameIdx,
1039        * mark the picture as non-reference */
1040       for (i = 0; i < dpb->pic_list->len; i++) {
1041         GstH264Picture *tmp =
1042             g_array_index (dpb->pic_list, GstH264Picture *, i);
1043 
1044         if (GST_H264_PICTURE_IS_LONG_TERM_REF (tmp)
1045             && tmp->long_term_frame_idx == ref_pic_marking->long_term_frame_idx) {
1046           if (GST_H264_PICTURE_IS_FRAME (tmp)) {
1047             /* When long_term_frame_idx is already assigned to a long-term
1048              * reference frame, that frame is marked as "unused for reference"
1049              */
1050             gst_h264_picture_set_reference (tmp,
1051                 GST_H264_PICTURE_REF_NONE, TRUE);
1052             GST_TRACE ("MMCO-3: unmark old long-term frame %p (poc %d)",
1053                 tmp, tmp->pic_order_cnt);
1054           } else if (tmp->other_field &&
1055               GST_H264_PICTURE_IS_LONG_TERM_REF (tmp->other_field) &&
1056               tmp->other_field->long_term_frame_idx ==
1057               ref_pic_marking->long_term_frame_idx) {
1058             /* When long_term_frame_idx is already assigned to a long-term
1059              * reference field pair, that complementary field pair and both of
1060              * its fields are marked as "unused for reference"
1061              */
1062             gst_h264_picture_set_reference (tmp,
1063                 GST_H264_PICTURE_REF_NONE, TRUE);
1064             GST_TRACE ("MMCO-3: unmark old long-term field-pair %p (poc %d)",
1065                 tmp, tmp->pic_order_cnt);
1066           } else {
1067             /* When long_term_frame_idx is already assigned to a reference field,
1068              * and that reference field is not part of a complementary field
1069              * pair that includes the picture specified by picNumX,
1070              * that field is marked as "unused for reference"
1071              */
1072 
1073             /* Check "tmp" (a long-term ref pic) is part of
1074              * "other" (a picture to be updated from short-term to long-term)
1075              * complementary field pair */
1076 
1077             /* NOTE: "other" here is short-ref, so "other" and "tmp" must not be
1078              * identical picture */
1079             if (!tmp->other_field) {
1080               gst_h264_picture_set_reference (tmp,
1081                   GST_H264_PICTURE_REF_NONE, FALSE);
1082               GST_TRACE ("MMCO-3: unmark old long-term field %p (poc %d)",
1083                   tmp, tmp->pic_order_cnt);
1084             } else if (tmp->other_field != other &&
1085                 (!other->other_field || other->other_field != tmp)) {
1086               gst_h264_picture_set_reference (tmp,
1087                   GST_H264_PICTURE_REF_NONE, FALSE);
1088               GST_TRACE ("MMCO-3: unmark old long-term field %p (poc %d)",
1089                   tmp, tmp->pic_order_cnt);
1090             }
1091           }
1092           break;
1093         }
1094       }
1095 
1096       gst_h264_picture_set_reference (other,
1097           GST_H264_PICTURE_REF_LONG_TERM, GST_H264_PICTURE_IS_FRAME (picture));
1098       other->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
1099 
1100       GST_TRACE ("MMCO-3: mark long-term ref pic %p, index %d, (poc %d)",
1101           other, other->long_term_frame_idx, other->pic_order_cnt);
1102 
1103       if (other->other_field &&
1104           GST_H264_PICTURE_IS_LONG_TERM_REF (other->other_field)) {
1105         other->other_field->long_term_frame_idx =
1106             ref_pic_marking->long_term_frame_idx;
1107       }
1108       break;
1109     case 4:
1110       /* 8.2.5.4.4  All pictures for which LongTermFrameIdx is greater than
1111        * max_long_term_frame_idx_plus1 − 1 and that are marked as
1112        * "used for long-term reference" are marked as "unused for reference */
1113       max_long_term_frame_idx =
1114           ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
1115 
1116       GST_TRACE ("MMCO-4: max_long_term_frame_idx %d", max_long_term_frame_idx);
1117 
1118       for (i = 0; i < dpb->pic_list->len; i++) {
1119         other = g_array_index (dpb->pic_list, GstH264Picture *, i);
1120 
1121         if (GST_H264_PICTURE_IS_LONG_TERM_REF (other) &&
1122             other->long_term_frame_idx > max_long_term_frame_idx) {
1123           gst_h264_picture_set_reference (other,
1124               GST_H264_PICTURE_REF_NONE, FALSE);
1125           GST_TRACE ("MMCO-4: unmark long-term ref pic %p, index %d, (poc %d)",
1126               other, other->long_term_frame_idx, other->pic_order_cnt);
1127         }
1128       }
1129       break;
1130     case 5:
1131       /* 8.2.5.4.5 Unmark all reference pictures */
1132       for (i = 0; i < dpb->pic_list->len; i++) {
1133         other = g_array_index (dpb->pic_list, GstH264Picture *, i);
1134         gst_h264_picture_set_reference (other,
1135             GST_H264_PICTURE_REF_NONE, FALSE);
1136       }
1137       picture->mem_mgmt_5 = TRUE;
1138       picture->frame_num = 0;
1139       /* When the current picture includes a memory management control operation
1140          equal to 5, after the decoding of the current picture, tempPicOrderCnt
1141          is set equal to PicOrderCnt( CurrPic ), TopFieldOrderCnt of the current
1142          picture (if any) is set equal to TopFieldOrderCnt - tempPicOrderCnt,
1143          and BottomFieldOrderCnt of the current picture (if any) is set equal to
1144          BottomFieldOrderCnt - tempPicOrderCnt. */
1145       if (picture->field == GST_H264_PICTURE_FIELD_TOP_FIELD) {
1146         picture->top_field_order_cnt = picture->pic_order_cnt = 0;
1147       } else if (picture->field == GST_H264_PICTURE_FIELD_BOTTOM_FIELD) {
1148         picture->bottom_field_order_cnt = picture->pic_order_cnt = 0;
1149       } else {
1150         picture->top_field_order_cnt -= picture->pic_order_cnt;
1151         picture->bottom_field_order_cnt -= picture->pic_order_cnt;
1152         picture->pic_order_cnt = MIN (picture->top_field_order_cnt,
1153             picture->bottom_field_order_cnt);
1154       }
1155       break;
1156     case 6:
1157       /* 8.2.5.4.6 Replace long term reference pictures with current picture.
1158        * First unmark if any existing with this long_term_frame_idx */
1159 
1160       /* If we have long-term ref picture for LongTermFrameIdx,
1161        * mark the picture as non-reference */
1162       for (i = 0; i < dpb->pic_list->len; i++) {
1163         other = g_array_index (dpb->pic_list, GstH264Picture *, i);
1164 
1165         if (GST_H264_PICTURE_IS_LONG_TERM_REF (other) &&
1166             other->long_term_frame_idx ==
1167             ref_pic_marking->long_term_frame_idx) {
1168           GST_TRACE ("MMCO-6: unmark old long-term ref pic %p (poc %d)",
1169               other, other->pic_order_cnt);
1170           gst_h264_picture_set_reference (other,
1171               GST_H264_PICTURE_REF_NONE, TRUE);
1172           break;
1173         }
1174       }
1175 
1176       gst_h264_picture_set_reference (picture,
1177           GST_H264_PICTURE_REF_LONG_TERM, picture->second_field);
1178       picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
1179       if (picture->other_field &&
1180           GST_H264_PICTURE_IS_LONG_TERM_REF (picture->other_field)) {
1181         picture->other_field->long_term_frame_idx =
1182             ref_pic_marking->long_term_frame_idx;
1183       }
1184       break;
1185     default:
1186       g_assert_not_reached ();
1187       return FALSE;
1188   }
1189 
1190   return TRUE;
1191 }
1192 
1193 /**
1194  * gst_h264_picture_set_reference:
1195  * @picture: a #GstH264Picture
1196  * @reference: a GstH264PictureReference
1197  * @other_field: %TRUE if @reference needs to be applied to the
1198  * other field if any
1199  *
1200  * Update reference picture type of @picture with @reference
1201  *
1202  * Since: 1.20
1203  */
1204 void
gst_h264_picture_set_reference(GstH264Picture * picture,GstH264PictureReference reference,gboolean other_field)1205 gst_h264_picture_set_reference (GstH264Picture * picture,
1206     GstH264PictureReference reference, gboolean other_field)
1207 {
1208   g_return_if_fail (picture != NULL);
1209 
1210   picture->ref = reference;
1211   if (reference > GST_H264_PICTURE_REF_NONE)
1212     picture->ref_pic = TRUE;
1213 
1214   if (other_field && picture->other_field) {
1215     picture->other_field->ref = reference;
1216 
1217     if (reference > GST_H264_PICTURE_REF_NONE)
1218       picture->other_field->ref_pic = TRUE;
1219   }
1220 }
1221