Mercurial > libavcodec.hg
annotate h264_refs.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01: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 } |