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