Mercurial > libavcodec.hg
annotate h264_refs.c @ 12463:04e68eb1aab7 libavcodec
Check rc_buffer_size value using integer arithmetic
Using floating-point here can cause erroneous rejection of
parameters due to rounding errors leading to a slightly too
large result.
This fixes the mxf regression test with gcc 4.5 on x86_32.
author | mru |
---|---|
date | Tue, 07 Sep 2010 19:54:48 +0000 |
parents | f7bedc1ce1bc |
children |
rev | line source |
---|---|
10862 | 1 /* |
2 * H.26L/H.264/AVC/JVT/14496-10/... reference picture handling | |
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11558
diff
changeset
|
23 * @file |
10862 | 24 * H.264 / AVC / MPEG4 part10 reference picture handling. |
25 * @author Michael Niedermayer <michaelni@gmx.at> | |
26 */ | |
27 | |
28 #include "internal.h" | |
29 #include "dsputil.h" | |
30 #include "avcodec.h" | |
31 #include "h264.h" | |
32 #include "golomb.h" | |
33 | |
34 //#undef NDEBUG | |
35 #include <assert.h> | |
36 | |
37 | |
38 static void pic_as_field(Picture *pic, const int parity){ | |
39 int i; | |
40 for (i = 0; i < 4; ++i) { | |
41 if (parity == PICT_BOTTOM_FIELD) | |
42 pic->data[i] += pic->linesize[i]; | |
43 pic->reference = parity; | |
44 pic->linesize[i] *= 2; | |
45 } | |
46 pic->poc= pic->field_poc[parity == PICT_BOTTOM_FIELD]; | |
47 } | |
48 | |
49 static int split_field_copy(Picture *dest, Picture *src, | |
50 int parity, int id_add){ | |
51 int match = !!(src->reference & parity); | |
52 | |
53 if (match) { | |
54 *dest = *src; | |
55 if(parity != PICT_FRAME){ | |
56 pic_as_field(dest, parity); | |
57 dest->pic_id *= 2; | |
58 dest->pic_id += id_add; | |
59 } | |
60 } | |
61 | |
62 return match; | |
63 } | |
64 | |
65 static int build_def_list(Picture *def, Picture **in, int len, int is_long, int sel){ | |
66 int i[2]={0}; | |
67 int index=0; | |
68 | |
69 while(i[0]<len || i[1]<len){ | |
70 while(i[0]<len && !(in[ i[0] ] && (in[ i[0] ]->reference & sel))) | |
71 i[0]++; | |
72 while(i[1]<len && !(in[ i[1] ] && (in[ i[1] ]->reference & (sel^3)))) | |
73 i[1]++; | |
74 if(i[0] < len){ | |
75 in[ i[0] ]->pic_id= is_long ? i[0] : in[ i[0] ]->frame_num; | |
76 split_field_copy(&def[index++], in[ i[0]++ ], sel , 1); | |
77 } | |
78 if(i[1] < len){ | |
79 in[ i[1] ]->pic_id= is_long ? i[1] : in[ i[1] ]->frame_num; | |
80 split_field_copy(&def[index++], in[ i[1]++ ], sel^3, 0); | |
81 } | |
82 } | |
83 | |
84 return index; | |
85 } | |
86 | |
87 static int add_sorted(Picture **sorted, Picture **src, int len, int limit, int dir){ | |
88 int i, best_poc; | |
89 int out_i= 0; | |
90 | |
91 for(;;){ | |
92 best_poc= dir ? INT_MIN : INT_MAX; | |
93 | |
94 for(i=0; i<len; i++){ | |
95 const int poc= src[i]->poc; | |
96 if(((poc > limit) ^ dir) && ((poc < best_poc) ^ dir)){ | |
97 best_poc= poc; | |
98 sorted[out_i]= src[i]; | |
99 } | |
100 } | |
101 if(best_poc == (dir ? INT_MIN : INT_MAX)) | |
102 break; | |
103 limit= sorted[out_i++]->poc - dir; | |
104 } | |
105 return out_i; | |
106 } | |
107 | |
108 int ff_h264_fill_default_ref_list(H264Context *h){ | |
109 MpegEncContext * const s = &h->s; | |
110 int i, len; | |
111 | |
112 if(h->slice_type_nos==FF_B_TYPE){ | |
113 Picture *sorted[32]; | |
114 int cur_poc, list; | |
115 int lens[2]; | |
116 | |
117 if(FIELD_PICTURE) | |
118 cur_poc= s->current_picture_ptr->field_poc[ s->picture_structure == PICT_BOTTOM_FIELD ]; | |
119 else | |
120 cur_poc= s->current_picture_ptr->poc; | |
121 | |
122 for(list= 0; list<2; list++){ | |
123 len= add_sorted(sorted , h->short_ref, h->short_ref_count, cur_poc, 1^list); | |
124 len+=add_sorted(sorted+len, h->short_ref, h->short_ref_count, cur_poc, 0^list); | |
125 assert(len<=32); | |
126 len= build_def_list(h->default_ref_list[list] , sorted , len, 0, s->picture_structure); | |
127 len+=build_def_list(h->default_ref_list[list]+len, h->long_ref, 16 , 1, s->picture_structure); | |
128 assert(len<=32); | |
129 | |
130 if(len < h->ref_count[list]) | |
131 memset(&h->default_ref_list[list][len], 0, sizeof(Picture)*(h->ref_count[list] - len)); | |
132 lens[list]= len; | |
133 } | |
134 | |
135 if(lens[0] == lens[1] && lens[1] > 1){ | |
136 for(i=0; h->default_ref_list[0][i].data[0] == h->default_ref_list[1][i].data[0] && i<lens[0]; i++); | |
137 if(i == lens[0]) | |
138 FFSWAP(Picture, h->default_ref_list[1][0], h->default_ref_list[1][1]); | |
139 } | |
140 }else{ | |
141 len = build_def_list(h->default_ref_list[0] , h->short_ref, h->short_ref_count, 0, s->picture_structure); | |
142 len+= build_def_list(h->default_ref_list[0]+len, h-> long_ref, 16 , 1, s->picture_structure); | |
143 assert(len <= 32); | |
144 if(len < h->ref_count[0]) | |
145 memset(&h->default_ref_list[0][len], 0, sizeof(Picture)*(h->ref_count[0] - len)); | |
146 } | |
147 #ifdef TRACE | |
148 for (i=0; i<h->ref_count[0]; i++) { | |
149 tprintf(h->s.avctx, "List0: %s fn:%d 0x%p\n", (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), h->default_ref_list[0][i].pic_id, h->default_ref_list[0][i].data[0]); | |
150 } | |
151 if(h->slice_type_nos==FF_B_TYPE){ | |
152 for (i=0; i<h->ref_count[1]; i++) { | |
153 tprintf(h->s.avctx, "List1: %s fn:%d 0x%p\n", (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), h->default_ref_list[1][i].pic_id, h->default_ref_list[1][i].data[0]); | |
154 } | |
155 } | |
156 #endif | |
157 return 0; | |
158 } | |
159 | |
160 static void print_short_term(H264Context *h); | |
161 static void print_long_term(H264Context *h); | |
162 | |
163 /** | |
164 * Extract structure information about the picture described by pic_num in | |
165 * the current decoding context (frame or field). Note that pic_num is | |
166 * picture number without wrapping (so, 0<=pic_num<max_pic_num). | |
167 * @param pic_num picture number for which to extract structure information | |
168 * @param structure one of PICT_XXX describing structure of picture | |
169 * with pic_num | |
170 * @return frame number (short term) or long term index of picture | |
171 * described by pic_num | |
172 */ | |
173 static int pic_num_extract(H264Context *h, int pic_num, int *structure){ | |
174 MpegEncContext * const s = &h->s; | |
175 | |
176 *structure = s->picture_structure; | |
177 if(FIELD_PICTURE){ | |
178 if (!(pic_num & 1)) | |
179 /* opposite field */ | |
180 *structure ^= PICT_FRAME; | |
181 pic_num >>= 1; | |
182 } | |
183 | |
184 return pic_num; | |
185 } | |
186 | |
187 int ff_h264_decode_ref_pic_list_reordering(H264Context *h){ | |
188 MpegEncContext * const s = &h->s; | |
189 int list, index, pic_structure; | |
190 | |
191 print_short_term(h); | |
192 print_long_term(h); | |
193 | |
194 for(list=0; list<h->list_count; list++){ | |
195 memcpy(h->ref_list[list], h->default_ref_list[list], sizeof(Picture)*h->ref_count[list]); | |
196 | |
197 if(get_bits1(&s->gb)){ | |
198 int pred= h->curr_pic_num; | |
199 | |
200 for(index=0; ; index++){ | |
201 unsigned int reordering_of_pic_nums_idc= get_ue_golomb_31(&s->gb); | |
202 unsigned int pic_id; | |
203 int i; | |
204 Picture *ref = NULL; | |
205 | |
206 if(reordering_of_pic_nums_idc==3) | |
207 break; | |
208 | |
209 if(index >= h->ref_count[list]){ | |
210 av_log(h->s.avctx, AV_LOG_ERROR, "reference count overflow\n"); | |
211 return -1; | |
212 } | |
213 | |
214 if(reordering_of_pic_nums_idc<3){ | |
215 if(reordering_of_pic_nums_idc<2){ | |
216 const unsigned int abs_diff_pic_num= get_ue_golomb(&s->gb) + 1; | |
217 int frame_num; | |
218 | |
219 if(abs_diff_pic_num > h->max_pic_num){ | |
220 av_log(h->s.avctx, AV_LOG_ERROR, "abs_diff_pic_num overflow\n"); | |
221 return -1; | |
222 } | |
223 | |
224 if(reordering_of_pic_nums_idc == 0) pred-= abs_diff_pic_num; | |
225 else pred+= abs_diff_pic_num; | |
226 pred &= h->max_pic_num - 1; | |
227 | |
228 frame_num = pic_num_extract(h, pred, &pic_structure); | |
229 | |
230 for(i= h->short_ref_count-1; i>=0; i--){ | |
231 ref = h->short_ref[i]; | |
232 assert(ref->reference); | |
233 assert(!ref->long_ref); | |
234 if( | |
235 ref->frame_num == frame_num && | |
236 (ref->reference & pic_structure) | |
237 ) | |
238 break; | |
239 } | |
240 if(i>=0) | |
241 ref->pic_id= pred; | |
242 }else{ | |
243 int long_idx; | |
244 pic_id= get_ue_golomb(&s->gb); //long_term_pic_idx | |
245 | |
246 long_idx= pic_num_extract(h, pic_id, &pic_structure); | |
247 | |
248 if(long_idx>31){ | |
249 av_log(h->s.avctx, AV_LOG_ERROR, "long_term_pic_idx overflow\n"); | |
250 return -1; | |
251 } | |
252 ref = h->long_ref[long_idx]; | |
253 assert(!(ref && !ref->reference)); | |
254 if(ref && (ref->reference & pic_structure)){ | |
255 ref->pic_id= pic_id; | |
256 assert(ref->long_ref); | |
257 i=0; | |
258 }else{ | |
259 i=-1; | |
260 } | |
261 } | |
262 | |
263 if (i < 0) { | |
264 av_log(h->s.avctx, AV_LOG_ERROR, "reference picture missing during reorder\n"); | |
265 memset(&h->ref_list[list][index], 0, sizeof(Picture)); //FIXME | |
266 } else { | |
267 for(i=index; i+1<h->ref_count[list]; i++){ | |
268 if(ref->long_ref == h->ref_list[list][i].long_ref && ref->pic_id == h->ref_list[list][i].pic_id) | |
269 break; | |
270 } | |
271 for(; i > index; i--){ | |
272 h->ref_list[list][i]= h->ref_list[list][i-1]; | |
273 } | |
274 h->ref_list[list][index]= *ref; | |
275 if (FIELD_PICTURE){ | |
276 pic_as_field(&h->ref_list[list][index], pic_structure); | |
277 } | |
278 } | |
279 }else{ | |
280 av_log(h->s.avctx, AV_LOG_ERROR, "illegal reordering_of_pic_nums_idc\n"); | |
281 return -1; | |
282 } | |
283 } | |
284 } | |
285 } | |
286 for(list=0; list<h->list_count; list++){ | |
287 for(index= 0; index < h->ref_count[list]; index++){ | |
288 if(!h->ref_list[list][index].data[0]){ | |
289 av_log(h->s.avctx, AV_LOG_ERROR, "Missing reference picture\n"); | |
290 if(h->default_ref_list[list][0].data[0]) | |
291 h->ref_list[list][index]= h->default_ref_list[list][0]; | |
292 else | |
293 return -1; | |
294 } | |
295 } | |
296 } | |
297 | |
298 return 0; | |
299 } | |
300 | |
301 void ff_h264_fill_mbaff_ref_list(H264Context *h){ | |
302 int list, i, j; | |
303 for(list=0; list<2; list++){ //FIXME try list_count | |
304 for(i=0; i<h->ref_count[list]; i++){ | |
305 Picture *frame = &h->ref_list[list][i]; | |
306 Picture *field = &h->ref_list[list][16+2*i]; | |
307 field[0] = *frame; | |
308 for(j=0; j<3; j++) | |
309 field[0].linesize[j] <<= 1; | |
310 field[0].reference = PICT_TOP_FIELD; | |
311 field[0].poc= field[0].field_poc[0]; | |
312 field[1] = field[0]; | |
313 for(j=0; j<3; j++) | |
314 field[1].data[j] += frame->linesize[j]; | |
315 field[1].reference = PICT_BOTTOM_FIELD; | |
316 field[1].poc= field[1].field_poc[1]; | |
317 | |
11349 | 318 h->luma_weight[16+2*i][list][0] = h->luma_weight[16+2*i+1][list][0] = h->luma_weight[i][list][0]; |
319 h->luma_weight[16+2*i][list][1] = h->luma_weight[16+2*i+1][list][1] = h->luma_weight[i][list][1]; | |
10862 | 320 for(j=0; j<2; j++){ |
11349 | 321 h->chroma_weight[16+2*i][list][j][0] = h->chroma_weight[16+2*i+1][list][j][0] = h->chroma_weight[i][list][j][0]; |
322 h->chroma_weight[16+2*i][list][j][1] = h->chroma_weight[16+2*i+1][list][j][1] = h->chroma_weight[i][list][j][1]; | |
10862 | 323 } |
324 } | |
325 } | |
326 } | |
327 | |
328 /** | |
329 * Mark a picture as no longer needed for reference. The refmask | |
330 * argument allows unreferencing of individual fields or the whole frame. | |
331 * If the picture becomes entirely unreferenced, but is being held for | |
332 * display purposes, it is marked as such. | |
333 * @param refmask mask of fields to unreference; the mask is bitwise | |
334 * anded with the reference marking of pic | |
335 * @return non-zero if pic becomes entirely unreferenced (except possibly | |
336 * for display purposes) zero if one of the fields remains in | |
337 * reference | |
338 */ | |
339 static inline int unreference_pic(H264Context *h, Picture *pic, int refmask){ | |
340 int i; | |
341 if (pic->reference &= refmask) { | |
342 return 0; | |
343 } else { | |
344 for(i = 0; h->delayed_pic[i]; i++) | |
345 if(pic == h->delayed_pic[i]){ | |
346 pic->reference=DELAYED_PIC_REF; | |
347 break; | |
348 } | |
349 return 1; | |
350 } | |
351 } | |
352 | |
353 /** | |
354 * Find a Picture in the short term reference list by frame number. | |
355 * @param frame_num frame number to search for | |
356 * @param idx the index into h->short_ref where returned picture is found | |
357 * undefined if no picture found. | |
358 * @return pointer to the found picture, or NULL if no pic with the provided | |
359 * frame number is found | |
360 */ | |
361 static Picture * find_short(H264Context *h, int frame_num, int *idx){ | |
362 MpegEncContext * const s = &h->s; | |
363 int i; | |
364 | |
365 for(i=0; i<h->short_ref_count; i++){ | |
366 Picture *pic= h->short_ref[i]; | |
367 if(s->avctx->debug&FF_DEBUG_MMCO) | |
368 av_log(h->s.avctx, AV_LOG_DEBUG, "%d %d %p\n", i, pic->frame_num, pic); | |
369 if(pic->frame_num == frame_num) { | |
370 *idx = i; | |
371 return pic; | |
372 } | |
373 } | |
374 return NULL; | |
375 } | |
376 | |
377 /** | |
378 * Remove a picture from the short term reference list by its index in | |
379 * that list. This does no checking on the provided index; it is assumed | |
380 * to be valid. Other list entries are shifted down. | |
381 * @param i index into h->short_ref of picture to remove. | |
382 */ | |
383 static void remove_short_at_index(H264Context *h, int i){ | |
384 assert(i >= 0 && i < h->short_ref_count); | |
385 h->short_ref[i]= NULL; | |
386 if (--h->short_ref_count) | |
387 memmove(&h->short_ref[i], &h->short_ref[i+1], (h->short_ref_count - i)*sizeof(Picture*)); | |
388 } | |
389 | |
390 /** | |
391 * | |
392 * @return the removed picture or NULL if an error occurs | |
393 */ | |
394 static Picture * remove_short(H264Context *h, int frame_num, int ref_mask){ | |
395 MpegEncContext * const s = &h->s; | |
396 Picture *pic; | |
397 int i; | |
398 | |
399 if(s->avctx->debug&FF_DEBUG_MMCO) | |
400 av_log(h->s.avctx, AV_LOG_DEBUG, "remove short %d count %d\n", frame_num, h->short_ref_count); | |
401 | |
402 pic = find_short(h, frame_num, &i); | |
403 if (pic){ | |
404 if(unreference_pic(h, pic, ref_mask)) | |
405 remove_short_at_index(h, i); | |
406 } | |
407 | |
408 return pic; | |
409 } | |
410 | |
411 /** | |
412 * Remove a picture from the long term reference list by its index in | |
413 * that list. | |
414 * @return the removed picture or NULL if an error occurs | |
415 */ | |
416 static Picture * remove_long(H264Context *h, int i, int ref_mask){ | |
417 Picture *pic; | |
418 | |
419 pic= h->long_ref[i]; | |
420 if (pic){ | |
421 if(unreference_pic(h, pic, ref_mask)){ | |
422 assert(h->long_ref[i]->long_ref == 1); | |
423 h->long_ref[i]->long_ref= 0; | |
424 h->long_ref[i]= NULL; | |
425 h->long_ref_count--; | |
426 } | |
427 } | |
428 | |
429 return pic; | |
430 } | |
431 | |
432 void ff_h264_remove_all_refs(H264Context *h){ | |
433 int i; | |
434 | |
435 for(i=0; i<16; i++){ | |
436 remove_long(h, i, 0); | |
437 } | |
438 assert(h->long_ref_count==0); | |
439 | |
440 for(i=0; i<h->short_ref_count; i++){ | |
441 unreference_pic(h, h->short_ref[i], 0); | |
442 h->short_ref[i]= NULL; | |
443 } | |
444 h->short_ref_count=0; | |
445 } | |
446 | |
447 /** | |
448 * print short term list | |
449 */ | |
450 static void print_short_term(H264Context *h) { | |
451 uint32_t i; | |
452 if(h->s.avctx->debug&FF_DEBUG_MMCO) { | |
453 av_log(h->s.avctx, AV_LOG_DEBUG, "short term list:\n"); | |
454 for(i=0; i<h->short_ref_count; i++){ | |
455 Picture *pic= h->short_ref[i]; | |
456 av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]); | |
457 } | |
458 } | |
459 } | |
460 | |
461 /** | |
462 * print long term list | |
463 */ | |
464 static void print_long_term(H264Context *h) { | |
465 uint32_t i; | |
466 if(h->s.avctx->debug&FF_DEBUG_MMCO) { | |
467 av_log(h->s.avctx, AV_LOG_DEBUG, "long term list:\n"); | |
468 for(i = 0; i < 16; i++){ | |
469 Picture *pic= h->long_ref[i]; | |
470 if (pic) { | |
471 av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]); | |
472 } | |
473 } | |
474 } | |
475 } | |
476 | |
12093
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
477 void ff_generate_sliding_window_mmcos(H264Context *h) { |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
478 MpegEncContext * const s = &h->s; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
479 assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count); |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
480 |
12094
f7bedc1ce1bc
Perform sliding window operation during frame gap handling.
michael
parents:
12093
diff
changeset
|
481 h->mmco_index= 0; |
12093
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
482 if(h->short_ref_count && h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count && |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
483 !(FIELD_PICTURE && !s->first_field && s->current_picture_ptr->reference)) { |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
484 h->mmco[0].opcode= MMCO_SHORT2UNUSED; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
485 h->mmco[0].short_pic_num= h->short_ref[ h->short_ref_count - 1 ]->frame_num; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
486 h->mmco_index= 1; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
487 if (FIELD_PICTURE) { |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
488 h->mmco[0].short_pic_num *= 2; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
489 h->mmco[1].opcode= MMCO_SHORT2UNUSED; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
490 h->mmco[1].short_pic_num= h->mmco[0].short_pic_num + 1; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
491 h->mmco_index= 2; |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
492 } |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
493 } |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
494 } |
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
495 |
10862 | 496 int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ |
497 MpegEncContext * const s = &h->s; | |
498 int i, av_uninit(j); | |
499 int current_ref_assigned=0; | |
500 Picture *av_uninit(pic); | |
501 | |
502 if((s->avctx->debug&FF_DEBUG_MMCO) && mmco_count==0) | |
503 av_log(h->s.avctx, AV_LOG_DEBUG, "no mmco here\n"); | |
504 | |
505 for(i=0; i<mmco_count; i++){ | |
506 int av_uninit(structure), av_uninit(frame_num); | |
507 if(s->avctx->debug&FF_DEBUG_MMCO) | |
508 av_log(h->s.avctx, AV_LOG_DEBUG, "mmco:%d %d %d\n", h->mmco[i].opcode, h->mmco[i].short_pic_num, h->mmco[i].long_arg); | |
509 | |
510 if( mmco[i].opcode == MMCO_SHORT2UNUSED | |
511 || mmco[i].opcode == MMCO_SHORT2LONG){ | |
512 frame_num = pic_num_extract(h, mmco[i].short_pic_num, &structure); | |
513 pic = find_short(h, frame_num, &j); | |
514 if(!pic){ | |
515 if(mmco[i].opcode != MMCO_SHORT2LONG || !h->long_ref[mmco[i].long_arg] | |
516 || h->long_ref[mmco[i].long_arg]->frame_num != frame_num) | |
517 av_log(h->s.avctx, AV_LOG_ERROR, "mmco: unref short failure\n"); | |
518 continue; | |
519 } | |
520 } | |
521 | |
522 switch(mmco[i].opcode){ | |
523 case MMCO_SHORT2UNUSED: | |
524 if(s->avctx->debug&FF_DEBUG_MMCO) | |
525 av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref short %d count %d\n", h->mmco[i].short_pic_num, h->short_ref_count); | |
526 remove_short(h, frame_num, structure ^ PICT_FRAME); | |
527 break; | |
528 case MMCO_SHORT2LONG: | |
529 if (h->long_ref[mmco[i].long_arg] != pic) | |
530 remove_long(h, mmco[i].long_arg, 0); | |
531 | |
532 remove_short_at_index(h, j); | |
533 h->long_ref[ mmco[i].long_arg ]= pic; | |
534 if (h->long_ref[ mmco[i].long_arg ]){ | |
535 h->long_ref[ mmco[i].long_arg ]->long_ref=1; | |
536 h->long_ref_count++; | |
537 } | |
538 break; | |
539 case MMCO_LONG2UNUSED: | |
540 j = pic_num_extract(h, mmco[i].long_arg, &structure); | |
541 pic = h->long_ref[j]; | |
542 if (pic) { | |
543 remove_long(h, j, structure ^ PICT_FRAME); | |
544 } else if(s->avctx->debug&FF_DEBUG_MMCO) | |
545 av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref long failure\n"); | |
546 break; | |
547 case MMCO_LONG: | |
548 // Comment below left from previous code as it is an interresting note. | |
549 /* First field in pair is in short term list or | |
550 * at a different long term index. | |
551 * This is not allowed; see 7.4.3.3, notes 2 and 3. | |
552 * Report the problem and keep the pair where it is, | |
553 * and mark this field valid. | |
554 */ | |
555 | |
556 if (h->long_ref[mmco[i].long_arg] != s->current_picture_ptr) { | |
557 remove_long(h, mmco[i].long_arg, 0); | |
558 | |
559 h->long_ref[ mmco[i].long_arg ]= s->current_picture_ptr; | |
560 h->long_ref[ mmco[i].long_arg ]->long_ref=1; | |
561 h->long_ref_count++; | |
562 } | |
563 | |
564 s->current_picture_ptr->reference |= s->picture_structure; | |
565 current_ref_assigned=1; | |
566 break; | |
567 case MMCO_SET_MAX_LONG: | |
568 assert(mmco[i].long_arg <= 16); | |
569 // just remove the long term which index is greater than new max | |
570 for(j = mmco[i].long_arg; j<16; j++){ | |
571 remove_long(h, j, 0); | |
572 } | |
573 break; | |
574 case MMCO_RESET: | |
575 while(h->short_ref_count){ | |
576 remove_short(h, h->short_ref[0]->frame_num, 0); | |
577 } | |
578 for(j = 0; j < 16; j++) { | |
579 remove_long(h, j, 0); | |
580 } | |
581 s->current_picture_ptr->poc= | |
582 s->current_picture_ptr->field_poc[0]= | |
583 s->current_picture_ptr->field_poc[1]= | |
584 h->poc_lsb= | |
585 h->poc_msb= | |
586 h->frame_num= | |
587 s->current_picture_ptr->frame_num= 0; | |
588 s->current_picture_ptr->mmco_reset=1; | |
589 break; | |
590 default: assert(0); | |
591 } | |
592 } | |
593 | |
594 if (!current_ref_assigned) { | |
595 /* Second field of complementary field pair; the first field of | |
596 * which is already referenced. If short referenced, it | |
597 * should be first entry in short_ref. If not, it must exist | |
598 * in long_ref; trying to put it on the short list here is an | |
599 * error in the encoded bit stream (ref: 7.4.3.3, NOTE 2 and 3). | |
600 */ | |
601 if (h->short_ref_count && h->short_ref[0] == s->current_picture_ptr) { | |
602 /* Just mark the second field valid */ | |
603 s->current_picture_ptr->reference = PICT_FRAME; | |
604 } else if (s->current_picture_ptr->long_ref) { | |
605 av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term reference " | |
606 "assignment for second field " | |
607 "in complementary field pair " | |
608 "(first field is long term)\n"); | |
609 } else { | |
610 pic= remove_short(h, s->current_picture_ptr->frame_num, 0); | |
611 if(pic){ | |
612 av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term buffer state detected\n"); | |
613 } | |
614 | |
615 if(h->short_ref_count) | |
616 memmove(&h->short_ref[1], &h->short_ref[0], h->short_ref_count*sizeof(Picture*)); | |
617 | |
618 h->short_ref[0]= s->current_picture_ptr; | |
619 h->short_ref_count++; | |
620 s->current_picture_ptr->reference |= s->picture_structure; | |
621 } | |
622 } | |
623 | |
624 if (h->long_ref_count + h->short_ref_count > h->sps.ref_frame_count){ | |
625 | |
626 /* We have too many reference frames, probably due to corrupted | |
627 * stream. Need to discard one frame. Prevents overrun of the | |
628 * short_ref and long_ref buffers. | |
629 */ | |
630 av_log(h->s.avctx, AV_LOG_ERROR, | |
631 "number of reference frames exceeds max (probably " | |
632 "corrupt input), discarding one\n"); | |
633 | |
634 if (h->long_ref_count && !h->short_ref_count) { | |
635 for (i = 0; i < 16; ++i) | |
636 if (h->long_ref[i]) | |
637 break; | |
638 | |
639 assert(i < 16); | |
640 remove_long(h, i, 0); | |
641 } else { | |
642 pic = h->short_ref[h->short_ref_count - 1]; | |
643 remove_short(h, pic->frame_num, 0); | |
644 } | |
645 } | |
646 | |
647 print_short_term(h); | |
648 print_long_term(h); | |
649 return 0; | |
650 } | |
651 | |
652 int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb){ | |
653 MpegEncContext * const s = &h->s; | |
654 int i; | |
655 | |
656 h->mmco_index= 0; | |
657 if(h->nal_unit_type == NAL_IDR_SLICE){ //FIXME fields | |
658 s->broken_link= get_bits1(gb) -1; | |
659 if(get_bits1(gb)){ | |
660 h->mmco[0].opcode= MMCO_LONG; | |
661 h->mmco[0].long_arg= 0; | |
662 h->mmco_index= 1; | |
663 } | |
664 }else{ | |
665 if(get_bits1(gb)){ // adaptive_ref_pic_marking_mode_flag | |
666 for(i= 0; i<MAX_MMCO_COUNT; i++) { | |
667 MMCOOpcode opcode= get_ue_golomb_31(gb); | |
668 | |
669 h->mmco[i].opcode= opcode; | |
670 if(opcode==MMCO_SHORT2UNUSED || opcode==MMCO_SHORT2LONG){ | |
671 h->mmco[i].short_pic_num= (h->curr_pic_num - get_ue_golomb(gb) - 1) & (h->max_pic_num - 1); | |
672 /* if(h->mmco[i].short_pic_num >= h->short_ref_count || h->short_ref[ h->mmco[i].short_pic_num ] == NULL){ | |
673 av_log(s->avctx, AV_LOG_ERROR, "illegal short ref in memory management control operation %d\n", mmco); | |
674 return -1; | |
675 }*/ | |
676 } | |
677 if(opcode==MMCO_SHORT2LONG || opcode==MMCO_LONG2UNUSED || opcode==MMCO_LONG || opcode==MMCO_SET_MAX_LONG){ | |
678 unsigned int long_arg= get_ue_golomb_31(gb); | |
679 if(long_arg >= 32 || (long_arg >= 16 && !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE))){ | |
680 av_log(h->s.avctx, AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode); | |
681 return -1; | |
682 } | |
683 h->mmco[i].long_arg= long_arg; | |
684 } | |
685 | |
686 if(opcode > (unsigned)MMCO_LONG){ | |
687 av_log(h->s.avctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode); | |
688 return -1; | |
689 } | |
690 if(opcode == MMCO_END) | |
691 break; | |
692 } | |
693 h->mmco_index= i; | |
694 }else{ | |
12093
05f91a88f986
Factorize ff_generate_sliding_window_mmcos() out.
michael
parents:
11644
diff
changeset
|
695 ff_generate_sliding_window_mmcos(h); |
10862 | 696 } |
697 } | |
698 | |
699 return 0; | |
700 } |