1 /*!
2 *************************************************************************************
3 * \file mmco.c
4 *
5 * \brief
6 * MMCO example operations.
7 *
8 * \author
9 * Main contributors (see contributors.h for copyright, address and affiliation details)
10 * - Alexis Michael Tourapis <alexismt@ieee.org>
11 * - Athanasios Leontaris <aleon@dolby.com>
12 *************************************************************************************
13 */
14
15 #include "contributors.h"
16
17 #include <ctype.h>
18 #include <limits.h>
19 #include "global.h"
20
21 #include "image.h"
22 #include "nalucommon.h"
23 #include "report.h"
24
25
mmco_long_term(VideoParameters * p_Vid,int current_pic_num)26 void mmco_long_term(VideoParameters *p_Vid, int current_pic_num)
27 {
28 DecRefPicMarking_t *tmp_drpm,*tmp_drpm2;
29
30 if ( !p_Vid->currentPicture->idr_flag )
31 {
32 if (p_Vid->dec_ref_pic_marking_buffer!=NULL)
33 return;
34
35 if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
36 no_mem_exit("poc_based_ref_management: tmp_drpm");
37
38 tmp_drpm->Next=NULL;
39
40 tmp_drpm->memory_management_control_operation = 0;
41
42 if (NULL==(tmp_drpm2=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
43 no_mem_exit("poc_based_ref_management: tmp_drpm2");
44 tmp_drpm2->Next=tmp_drpm;
45
46 tmp_drpm2->memory_management_control_operation = 3;
47 tmp_drpm2->long_term_frame_idx = current_pic_num;
48 p_Vid->dec_ref_pic_marking_buffer = tmp_drpm2;
49 }
50 else
51 {
52 p_Vid->long_term_reference_flag = TRUE;
53 }
54 }
55
56 #if HM50_LIKE_MMCO
hm50_ref_management_frame_pic(DecodedPictureBuffer * p_Dpb,int current_pic_num)57 void hm50_ref_management_frame_pic(DecodedPictureBuffer *p_Dpb, int current_pic_num)
58 {
59 VideoParameters *p_Vid = p_Dpb->p_Vid;
60 unsigned i;
61 int pic_num = 0;
62
63 int target_poc=-1;
64 DecRefPicMarking_t *tmp_drpm,*tmp_drpm2;
65
66 // only support GOP Size = 8, 4 reference frames, 2 in list0 and 2 in list1
67 if ( p_Vid->p_Inp->NumberBFrames != 7 ||
68 p_Vid->p_Inp->num_ref_frames != 4 ||
69 p_Vid->p_Inp->B_List0_refs[0] != 2 ||
70 p_Vid->p_Inp->B_List1_refs[0] != 2 )
71 {
72 return;
73 }
74
75 #if CRA
76 // for CRA pictures, we have MMCO already
77 if ( p_Vid->p_Inp->useCRA )
78 {
79 if ( ( p_Vid->currentSlice->slice_type == B_SLICE || p_Vid->currentSlice->slice_type == P_SLICE ) && p_Vid->currentSlice->p_Dpb->ref_frames_in_buffer >= 2 )
80 {
81 if ( ( (p_Vid->currentSlice->ThisPOC/2) - (p_Vid->p_Inp->NumberBFrames+1) ) % p_Vid->p_Inp->intra_period == 0 )
82 {
83 return;
84 }
85 }
86 }
87 #endif
88
89 if (p_Vid->dec_ref_pic_marking_buffer!=NULL)
90 return;
91
92 if ( p_Vid->currentPicture->idr_flag )
93 return;
94
95 if ((p_Dpb->ref_frames_in_buffer + p_Dpb->ltref_frames_in_buffer)==0)
96 return;
97
98 switch ( p_Vid->currentSlice->ThisPOC / 2 % 8 )
99 {
100 case 0:
101 target_poc = p_Vid->currentSlice->ThisPOC - 32;
102 break;
103 case 4:
104 target_poc = p_Vid->currentSlice->ThisPOC - 16;
105 break;
106 case 2:
107 target_poc = p_Vid->currentSlice->ThisPOC - 8;
108 break;
109 case 6:
110 target_poc = p_Vid->currentSlice->ThisPOC - 8;
111 break;
112 default:
113 target_poc = -1;
114 break;
115 }
116
117 if ( target_poc < 0 )
118 return;
119
120
121 for (i = 0; i < p_Dpb->used_size; i++)
122 {
123 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->poc == target_poc)
124 {
125 pic_num = p_Dpb->fs[i]->frame->pic_num;
126 }
127 }
128
129 if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
130 no_mem_exit("poc_based_ref_management: tmp_drpm");
131 tmp_drpm->Next=NULL;
132
133 tmp_drpm->memory_management_control_operation = 0;
134
135 if (NULL==(tmp_drpm2=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
136 no_mem_exit("poc_based_ref_management: tmp_drpm2");
137 tmp_drpm2->Next=tmp_drpm;
138
139 tmp_drpm2->memory_management_control_operation = 1;
140
141 if ( p_Vid->num_of_layers == 1 )
142 tmp_drpm2->difference_of_pic_nums_minus1 = current_pic_num - pic_num - 1;
143 else
144 tmp_drpm2->difference_of_pic_nums_minus1 = (current_pic_num - pic_num)/2 - 1;
145
146 p_Vid->dec_ref_pic_marking_buffer = tmp_drpm2;
147 }
148 #endif
149
150 #if CRA
cra_ref_management_frame_pic(DecodedPictureBuffer * p_Dpb,int current_pic_num)151 void cra_ref_management_frame_pic(DecodedPictureBuffer *p_Dpb, int current_pic_num)
152 {
153 VideoParameters *p_Vid = p_Dpb->p_Vid;
154 unsigned i;
155 int pic_num = 0;
156
157 //int min_poc=INT_MAX;
158 DecRefPicMarking_t *tmp_drpm,*tmp_drpm2;
159
160 int last_intra_poc = p_Vid->currentSlice->ThisPOC / 2 / p_Vid->p_Inp->intra_period * p_Vid->p_Inp->intra_period * 2;
161
162 if (p_Vid->dec_ref_pic_marking_buffer!=NULL)
163 return;
164
165 if ( p_Vid->currentPicture->idr_flag )
166 return;
167
168 if ((p_Dpb->ref_frames_in_buffer + p_Dpb->ltref_frames_in_buffer)==0)
169 return;
170
171 if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
172 no_mem_exit("poc_based_ref_management: tmp_drpm");
173 tmp_drpm->Next=NULL;
174
175 tmp_drpm->memory_management_control_operation = 0;
176
177 for (i = 0; i < p_Dpb->used_size; i++)
178 {
179 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->poc < last_intra_poc)
180 {
181 if (NULL==(tmp_drpm2=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
182 no_mem_exit("poc_based_ref_management: tmp_drpm2");
183 tmp_drpm2->Next=tmp_drpm;
184 tmp_drpm2->memory_management_control_operation = 1;
185
186 pic_num = p_Dpb->fs[i]->frame->pic_num;
187
188 if ( p_Vid->num_of_layers == 1 )
189 tmp_drpm2->difference_of_pic_nums_minus1 = current_pic_num - pic_num - 1;
190 else
191 tmp_drpm2->difference_of_pic_nums_minus1 = (current_pic_num - pic_num)/2 - 1;
192
193 if ( tmp_drpm2->difference_of_pic_nums_minus1 < 0 )
194 {
195 tmp_drpm2->difference_of_pic_nums_minus1 += p_Vid->currentSlice->max_frame_num;
196 }
197 if ( tmp_drpm2->difference_of_pic_nums_minus1 >= (int) p_Vid->currentSlice->max_frame_num )
198 {
199 tmp_drpm2->difference_of_pic_nums_minus1 -= p_Vid->currentSlice->max_frame_num;
200 }
201
202 tmp_drpm = tmp_drpm2;
203 }
204 }
205
206 p_Vid->dec_ref_pic_marking_buffer = tmp_drpm;
207 }
208 #endif
209
210 #if LD_REF_SETTING
low_delay_ref_management_frame_pic(DecodedPictureBuffer * p_Dpb,int current_pic_num)211 void low_delay_ref_management_frame_pic(DecodedPictureBuffer *p_Dpb, int current_pic_num)
212 {
213 VideoParameters *p_Vid = p_Dpb->p_Vid;
214 unsigned i;
215 int pic_num = 0;
216
217 int min_poc=INT_MAX;
218 int min_poc_not_4x = INT_MAX;
219 DecRefPicMarking_t *tmp_drpm,*tmp_drpm2;
220
221 #if CRA
222 // for CRA pictures, we have MMCO already
223 if ( p_Vid->p_Inp->useCRA )
224 {
225 if ( ( p_Vid->currentSlice->slice_type == B_SLICE || p_Vid->currentSlice->slice_type == P_SLICE ) && p_Vid->currentSlice->p_Dpb->ref_frames_in_buffer >= 2 )
226 {
227 if ( ( (p_Vid->currentSlice->ThisPOC/2) - (p_Vid->p_Inp->NumberBFrames+1) ) % p_Vid->p_Inp->intra_period == 0 )
228 {
229 return;
230 }
231 }
232 }
233 #endif
234
235 if (p_Vid->dec_ref_pic_marking_buffer!=NULL)
236 return;
237
238 if ( p_Vid->currentPicture->idr_flag )
239 return;
240
241 if ((p_Dpb->ref_frames_in_buffer + p_Dpb->ltref_frames_in_buffer)==0)
242 return;
243
244 for (i = 0; i < p_Dpb->used_size; i++)
245 {
246 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->poc < min_poc)
247 {
248 min_poc = p_Dpb->fs[i]->frame->poc ;
249 pic_num = p_Dpb->fs[i]->frame->pic_num;
250 }
251 }
252 for (i = 0; i < p_Dpb->used_size; i++)
253 {
254 if((p_Vid->currentSlice->ThisPOC/2-p_Dpb->fs[i]->poc/2)>4)
255 {
256 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->poc < min_poc_not_4x && (p_Dpb->fs[i]->poc/2)%(p_Vid->p_Inp->NumberBFrames+1)!=0 )
257 {
258 min_poc_not_4x = p_Dpb->fs[i]->frame->poc ;
259 pic_num = p_Dpb->fs[i]->frame->pic_num;
260 }
261 }
262 else
263 {
264 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->poc < min_poc_not_4x && (p_Dpb->fs[i]->poc/2)%((p_Vid->p_Inp->NumberBFrames+1)/2)!=0 )
265 {
266 min_poc_not_4x = p_Dpb->fs[i]->frame->poc ;
267 pic_num = p_Dpb->fs[i]->frame->pic_num;
268 }
269 }
270 }
271
272 if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
273 no_mem_exit("poc_based_ref_management: tmp_drpm");
274 tmp_drpm->Next=NULL;
275
276 tmp_drpm->memory_management_control_operation = 0;
277
278 if (NULL==(tmp_drpm2=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
279 no_mem_exit("poc_based_ref_management: tmp_drpm2");
280 tmp_drpm2->Next=tmp_drpm;
281
282 tmp_drpm2->memory_management_control_operation = 1;
283
284 if ( p_Vid->num_of_layers == 1 )
285 tmp_drpm2->difference_of_pic_nums_minus1 = current_pic_num - pic_num - 1;
286 else
287 tmp_drpm2->difference_of_pic_nums_minus1 = (current_pic_num - pic_num)/2 - 1;
288
289 p_Vid->dec_ref_pic_marking_buffer = tmp_drpm2;
290 }
291 #endif
292
293 /*!
294 ************************************************************************
295 * \brief
296 * POC-based reference management (FRAME)
297 ************************************************************************
298 */
299
poc_based_ref_management_frame_pic(DecodedPictureBuffer * p_Dpb,int current_pic_num)300 void poc_based_ref_management_frame_pic(DecodedPictureBuffer *p_Dpb, int current_pic_num)
301 {
302 VideoParameters *p_Vid = p_Dpb->p_Vid;
303 unsigned i;
304 int pic_num = 0;
305
306 int min_poc=INT_MAX;
307 DecRefPicMarking_t *tmp_drpm,*tmp_drpm2;
308
309 #if CRA
310 // for CRA pictures, we have MMCO already
311 if ( p_Vid->p_Inp->useCRA )
312 {
313 if ( ( p_Vid->currentSlice->slice_type == B_SLICE || p_Vid->currentSlice->slice_type == P_SLICE ) && p_Vid->currentSlice->p_Dpb->ref_frames_in_buffer >= 2 )
314 {
315 if ( ( (p_Vid->currentSlice->ThisPOC/2) - (p_Vid->p_Inp->NumberBFrames+1) ) % p_Vid->p_Inp->intra_period == 0 )
316 {
317 return;
318 }
319 }
320 }
321 #endif
322
323 #if HM50_LIKE_MMCO
324 if ( p_Vid->p_Inp->HM50RefStructure )
325 {
326 // for the case that we already have MMCO, just return
327 if ( p_Vid->p_Inp->NumberBFrames != 7 ||
328 p_Vid->p_Inp->num_ref_frames != 4 ||
329 p_Vid->p_Inp->B_List0_refs[0] != 2 ||
330 p_Vid->p_Inp->B_List1_refs[0] != 2 )
331 {
332 return;
333 }
334 }
335 #endif
336
337 if (p_Vid->dec_ref_pic_marking_buffer!=NULL)
338 return;
339
340 if ( p_Vid->currentPicture->idr_flag )
341 return;
342
343 if ((p_Dpb->ref_frames_in_buffer + p_Dpb->ltref_frames_in_buffer)==0)
344 return;
345
346 for (i = 0; i < p_Dpb->used_size; i++)
347 {
348 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->poc < min_poc)
349 {
350 min_poc = p_Dpb->fs[i]->frame->poc ;
351 pic_num = p_Dpb->fs[i]->frame->pic_num;
352 }
353 }
354
355 if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
356 no_mem_exit("poc_based_ref_management: tmp_drpm");
357 tmp_drpm->Next=NULL;
358
359 tmp_drpm->memory_management_control_operation = 0;
360
361 if (NULL==(tmp_drpm2=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
362 no_mem_exit("poc_based_ref_management: tmp_drpm2");
363 tmp_drpm2->Next=tmp_drpm;
364
365 tmp_drpm2->memory_management_control_operation = 1;
366 tmp_drpm2->difference_of_pic_nums_minus1 = current_pic_num - pic_num - 1;
367
368 p_Vid->dec_ref_pic_marking_buffer = tmp_drpm2;
369 }
370
371 /*!
372 ************************************************************************
373 * \brief
374 * POC-based reference management (FIELD)
375 ************************************************************************
376 */
377
poc_based_ref_management_field_pic(DecodedPictureBuffer * p_Dpb,int current_pic_num)378 void poc_based_ref_management_field_pic(DecodedPictureBuffer *p_Dpb, int current_pic_num)
379 {
380 VideoParameters *p_Vid = p_Dpb->p_Vid;
381 unsigned int i;
382 int pic_num1 = 0, pic_num2 = 0;
383
384 int min_poc=INT_MAX;
385 DecRefPicMarking_t *tmp_drpm,*tmp_drpm2, *tmp_drpm3;
386
387 if (p_Vid->dec_ref_pic_marking_buffer!=NULL)
388 return;
389
390 if ( p_Vid->currentPicture->idr_flag )
391 return;
392
393 if ((p_Dpb->ref_frames_in_buffer + p_Dpb->ltref_frames_in_buffer)==0)
394 return;
395
396 if ( p_Vid->structure == TOP_FIELD )
397 {
398 for (i=0; i<p_Dpb->used_size;i++)
399 {
400 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->poc < min_poc)
401 {
402 min_poc = p_Dpb->fs[i]->poc;
403 pic_num1 = p_Dpb->fs[i]->top_field->pic_num;
404 pic_num2 = p_Dpb->fs[i]->bottom_field->pic_num;
405 }
406 }
407 }
408
409 if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t)))) no_mem_exit("poc_based_ref_management_field_pic: tmp_drpm");
410 tmp_drpm->Next=NULL;
411 tmp_drpm->memory_management_control_operation = 0;
412
413 if ( p_Vid->structure == BOTTOM_FIELD )
414 {
415 p_Vid->dec_ref_pic_marking_buffer = tmp_drpm;
416 return;
417 }
418
419 if (NULL==(tmp_drpm2=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t)))) no_mem_exit("poc_based_ref_management_field_pic: tmp_drpm2");
420 tmp_drpm2->Next=tmp_drpm;
421 tmp_drpm2->memory_management_control_operation = 1;
422 tmp_drpm2->difference_of_pic_nums_minus1 = current_pic_num - pic_num1 - 1;
423
424 if (NULL==(tmp_drpm3=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t)))) no_mem_exit("poc_based_ref_management_field_pic: tmp_drpm3");
425 tmp_drpm3->Next=tmp_drpm2;
426 tmp_drpm3->memory_management_control_operation = 1;
427 tmp_drpm3->difference_of_pic_nums_minus1 = current_pic_num - pic_num2 - 1;
428
429 p_Vid->dec_ref_pic_marking_buffer = tmp_drpm3;
430 }
431
432
433 /*!
434 ************************************************************************
435 * \brief
436 * Temporal layer-based reference management (FRAME)
437 ************************************************************************
438 */
439
tlyr_based_ref_management_frame_pic(VideoParameters * p_Vid,int current_pic_num)440 void tlyr_based_ref_management_frame_pic(VideoParameters *p_Vid, int current_pic_num)
441 {
442 unsigned i, first = 1;
443 DecRefPicMarking_t *drpm = NULL, *current_drpm = NULL, *tmp_drpm = NULL;
444 struct decoded_picture_buffer *p_Dpb = p_Vid->p_Dpb_layer[0];
445
446 if (p_Vid->dec_ref_pic_marking_buffer!=NULL)
447 return;
448
449 if ( p_Vid->currentPicture->idr_flag )
450 return;
451
452 if ((p_Dpb->ref_frames_in_buffer + p_Dpb->ltref_frames_in_buffer)==0)
453 return;
454
455 for (i = 0; i < p_Dpb->used_size; i++)
456 {
457 if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term)) && p_Dpb->fs[i]->frame->temporal_layer > p_Vid->enc_picture->temporal_layer)
458 {
459 if (NULL == (tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
460 no_mem_exit("poc_based_ref_management: tmp_drpm2");
461 tmp_drpm->memory_management_control_operation = 1;
462 tmp_drpm->difference_of_pic_nums_minus1 = current_pic_num - p_Dpb->fs[i]->frame->pic_num - 1;
463
464 if (first)
465 {
466 drpm = current_drpm = tmp_drpm;
467 first = 0;
468 }
469 else
470 {
471 current_drpm->Next = tmp_drpm;
472 current_drpm = current_drpm->Next;
473 }
474 }
475 }
476
477 if (first)
478 return;
479
480 if (NULL==(tmp_drpm=(DecRefPicMarking_t*)calloc (1,sizeof (DecRefPicMarking_t))))
481 no_mem_exit("poc_based_ref_management: tmp_drpm");
482 tmp_drpm->Next=NULL;
483
484 tmp_drpm->memory_management_control_operation = 0;
485
486 current_drpm->Next=tmp_drpm;
487
488 p_Vid->dec_ref_pic_marking_buffer = drpm;
489 }
490
491