Mercurial > cgi-bin > hgwebdir.cgi > PR > Applications > VSs > VSs__H264__App
diff libavcodec/h264_refs.c @ 2:897f711a7157
rearrange to work with autoconf
| author | Nina Engelhardt <nengel@mailbox.tu-berlin.de> |
|---|---|
| date | Tue, 25 Sep 2012 15:55:33 +0200 |
| parents | |
| children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libavcodec/h264_refs.c Tue Sep 25 15:55:33 2012 +0200 1.3 @@ -0,0 +1,461 @@ 1.4 +/* 1.5 + * H.26L/H.264/AVC/JVT/14496-10/... reference picture handling 1.6 + * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> 1.7 + * 1.8 + * This file is part of FFmpeg. 1.9 + * 1.10 + * FFmpeg is free software; you can redistribute it and/or 1.11 + * modify it under the terms of the GNU Lesser General Public 1.12 + * License as published by the Free Software Foundation; either 1.13 + * version 2.1 of the License, or (at your option) any later version. 1.14 + * 1.15 + * FFmpeg is distributed in the hope that it will be useful, 1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.18 + * Lesser General Public License for more details. 1.19 + * 1.20 + * You should have received a copy of the GNU Lesser General Public 1.21 + * License along with FFmpeg; if not, write to the Free Software 1.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 1.23 + */ 1.24 + 1.25 +/** 1.26 + * @file 1.27 + * H.264 / AVC / MPEG4 part10 reference picture handling. 1.28 + * @author Michael Niedermayer <michaelni@gmx.at> 1.29 + */ 1.30 + 1.31 +#include "dsputil.h" 1.32 +#include "h264_types.h" 1.33 +#include "golomb.h" 1.34 + 1.35 +//#undef NDEBUG 1.36 +#include <assert.h> 1.37 + 1.38 +static int build_def_list(PictureInfo **def, PictureInfo **in, int len, int is_long){ 1.39 + int i[2]={0}; 1.40 + int index=0; 1.41 + 1.42 + while(i[0]<len || i[1]<len){ 1.43 + while(i[0]<len && !(in[ i[0] ] && (in[ i[0] ]->reference))) 1.44 + i[0]++; 1.45 + while(i[1]<len && !(in[ i[1] ] && (in[ i[1] ]->reference & 0))) 1.46 + i[1]++; 1.47 + if(i[0] < len){ 1.48 + in[ i[0] ]->pic_id= is_long ? i[0] : in[ i[0] ]->frame_num; 1.49 + def[index++]= in[ i[0]++ ]; 1.50 + } 1.51 + if(i[1] < len){ 1.52 + in[ i[1] ]->pic_id= is_long ? i[1] : in[ i[1] ]->frame_num; 1.53 + def[index++]= in[ i[1]++ ]; 1.54 + } 1.55 + } 1.56 + 1.57 + return index; 1.58 +} 1.59 + 1.60 +static int add_sorted(PictureInfo **sorted, PictureInfo **src, int len, int limit, int dir){ 1.61 + int i, best_poc; 1.62 + int out_i= 0; 1.63 + 1.64 + for(;;){ 1.65 + best_poc= dir ? INT_MIN : INT_MAX; 1.66 + 1.67 + for(i=0; i<len; i++){ 1.68 + const int poc= src[i]->poc; 1.69 + if(((poc > limit) ^ dir) && ((poc < best_poc) ^ dir)){ 1.70 + best_poc= poc; 1.71 + sorted[out_i]= src[i]; 1.72 + } 1.73 + } 1.74 + if(best_poc == (dir ? INT_MIN : INT_MAX)) 1.75 + break; 1.76 + limit= sorted[out_i++]->poc - dir; 1.77 + } 1.78 + return out_i; 1.79 +} 1.80 + 1.81 +int ff_h264_fill_default_ref_list(NalContext *n, H264Slice *s){ 1.82 + int i,len; 1.83 + 1.84 + if(s->slice_type_nos==FF_B_TYPE){ 1.85 + PictureInfo *sorted[32]; 1.86 + int cur_poc, list; 1.87 + int lens[2]; 1.88 + 1.89 + cur_poc= s->poc; 1.90 + 1.91 + for(list= 0; list<2; list++){ 1.92 + len= add_sorted(sorted, n->short_ref, n->short_ref_count, cur_poc, !list); 1.93 + len+=add_sorted(sorted+len, n->short_ref, n->short_ref_count, cur_poc, list); 1.94 + assert(len<=32); 1.95 + len= build_def_list(s->ref_list[list], sorted, len, 0); 1.96 + len+=build_def_list(s->ref_list[list] +len, n->long_ref, 16 , 1); 1.97 + assert(len<=32); 1.98 + 1.99 + for(int i=len; i<s->ref_count[list]; i++) 1.100 + s->ref_list[list][i] = NULL; 1.101 + 1.102 + lens[list]= len; 1.103 + } 1.104 + 1.105 + if(lens[0] == lens[1] && lens[1] > 1){ 1.106 + for(i=0; s->ref_list[0][i]->poc == s->ref_list[1][i]->poc && i<lens[0]; i++); 1.107 + 1.108 + if(i == lens[0]) 1.109 + FFSWAP(PictureInfo *, s->ref_list[1][0], s->ref_list[1][1]); 1.110 + } 1.111 + }else{ 1.112 + len = build_def_list(s->ref_list[0], n->short_ref, n->short_ref_count, 0); 1.113 + len+= build_def_list(s->ref_list[0] +len, n->long_ref, 16, 1); 1.114 + assert(len <= 32); 1.115 + for(i=len; i<s->ref_count[0]; i++) 1.116 + s->ref_list[0][i] = NULL; 1.117 + } 1.118 + 1.119 + return 0; 1.120 +} 1.121 + 1.122 +/** 1.123 +* print short term list 1.124 +*/ 1.125 +static void print_short_term(NalContext *n) { 1.126 + av_log(AV_LOG_DEBUG, "short term list:\n"); 1.127 + for(int i=0; i<n->short_ref_count; i++){ 1.128 + PictureInfo *pic= n->short_ref[i]; 1.129 + av_log(AV_LOG_DEBUG, "%d fn:%d poc:%d ref:%d \n", i, pic->frame_num, pic->poc, pic->reference); 1.130 + } 1.131 +} 1.132 + 1.133 +/** 1.134 +* print long term list 1.135 +*/ 1.136 +static void print_long_term(NalContext *n) { 1.137 + uint32_t i; 1.138 + 1.139 + av_log(AV_LOG_DEBUG, "long term list:\n"); 1.140 + for(i = 0; i < 16; i++){ 1.141 + PictureInfo *pic= n->long_ref[i]; 1.142 + if (pic) { 1.143 + av_log(AV_LOG_DEBUG, "%d fn:%d poc:%d\n", i, pic->frame_num, pic->poc); 1.144 + } 1.145 + } 1.146 +} 1.147 + 1.148 +int ff_h264_decode_ref_pic_list_reordering(NalContext *n, H264Slice *s, GetBitContext *gb){ 1.149 + int list, index; 1.150 + 1.151 + print_short_term(n); 1.152 + print_long_term(n); 1.153 + 1.154 + for(list=0; list<s->list_count; list++){ 1.155 + 1.156 + if(get_bits1(gb)){ 1.157 + int frame_num = n->frame_num; 1.158 + unsigned int abs_diff_pic_num; 1.159 + for(index=0; ; index++){ 1.160 + unsigned int reordering_of_pic_nums_idc= get_ue_golomb_31(gb); 1.161 + int i=0; 1.162 + PictureInfo *ref = NULL; 1.163 + 1.164 + if(reordering_of_pic_nums_idc==3){ 1.165 + break; 1.166 + } 1.167 + if(index >= s->ref_count[list]){ 1.168 + av_log(AV_LOG_ERROR, "reference count overflow\n"); 1.169 + return -1; 1.170 + } 1.171 + 1.172 + if (reordering_of_pic_nums_idc>2){ 1.173 + av_log(AV_LOG_ERROR, "illegal reordering_of_pic_nums_idc\n"); 1.174 + return -1; 1.175 + } 1.176 + 1.177 + if (reordering_of_pic_nums_idc<2){ 1.178 + //av_log(AV_LOG_ERROR, "long term pic not supported\n"); 1.179 + 1.180 + abs_diff_pic_num= get_ue_golomb(gb) + 1; 1.181 + if(abs_diff_pic_num > (unsigned) n->max_pic_num){ 1.182 + av_log(AV_LOG_ERROR, "abs_diff_pic_num overflow\n"); 1.183 + return -1; 1.184 + } 1.185 + 1.186 + if(reordering_of_pic_nums_idc == 0) 1.187 + frame_num-= abs_diff_pic_num; 1.188 + else 1.189 + frame_num+= abs_diff_pic_num; 1.190 + frame_num &= n->max_pic_num - 1; 1.191 + 1.192 + for(i= 0 ; i<n->short_ref_count; i++){ 1.193 + ref = n->short_ref[i]; 1.194 + if(ref->frame_num == frame_num && ref->reference){ 1.195 + break; 1.196 + } 1.197 + } 1.198 + ref->pic_id= frame_num; 1.199 + }else{ 1.200 + int long_idx; 1.201 + long_idx= get_ue_golomb(gb); //long_term_pic_idx 1.202 + 1.203 + if(long_idx>31){ 1.204 + av_log(AV_LOG_ERROR, "long_term_pic_idx overflow\n"); 1.205 + return -1; 1.206 + } 1.207 + ref = n->long_ref[long_idx]; 1.208 + assert(!(ref && !ref->reference)); 1.209 + if(ref && (ref->reference)){ 1.210 + ref->pic_id= long_idx; 1.211 + assert(ref->long_ref); 1.212 + }else{ 1.213 + av_log(AV_LOG_ERROR, "reference picture missing during reorder\n"); 1.214 + } 1.215 + } 1.216 + 1.217 + if (i >= n->short_ref_count) { 1.218 + av_log(AV_LOG_ERROR, "reference picture missing during reorder\n"); 1.219 + return -1; 1.220 + } else { 1.221 + for(i=index; i+1 <s->ref_count[list]; i++){ 1.222 + 1.223 +// if(ref->frame_num == s->ref_list[list][i]->frame_num) 1.224 +// break; 1.225 + ///there is probably no need for a separate pic_id and frame_num 1.226 + if (s->ref_list[list][i]){ 1.227 + 1.228 + if(ref->long_ref == s->ref_list[list][i]->long_ref && ref->pic_id == s->ref_list[list][i]->pic_id) 1.229 + break; 1.230 + } 1.231 + } 1.232 + for(; i > index; i--){ 1.233 + s->ref_list[list][i]= s->ref_list[list][i-1]; 1.234 + } 1.235 + s->ref_list[list][index]= ref; 1.236 + } 1.237 + } 1.238 + } 1.239 + } 1.240 + 1.241 +// //Check if everything went well 1.242 +// for(list=0; list<s->list_count; list++){ 1.243 +// //printf("ref_count %d list %d\n", s->ref_count[list], list); 1.244 +// for(index= 0; index < s->ref_count[list]; index++){ 1.245 +// //printf("%d\n", s->ref_list[list][index]->pic_id); 1.246 +// if(!s->ref_list[list][index]->data[0]){ 1.247 +// av_log(AV_LOG_ERROR, "Missing reference picture\n"); 1.248 +// return -1; 1.249 +// } 1.250 +// } 1.251 +// } 1.252 + 1.253 + return 0; 1.254 +} 1.255 + 1.256 +static PictureInfo *find_short(NalContext *n, int frame_num){ 1.257 + int i; 1.258 + for(i=0; i<n->short_ref_count; i++){ 1.259 + if(n->short_ref[i]->frame_num == frame_num) { 1.260 + return n->short_ref[i]; 1.261 + } 1.262 + } 1.263 + return NULL; 1.264 +} 1.265 + 1.266 +static int remove_short(NalContext *n, H264Slice *s, int frame_num, int release){ 1.267 + int i; 1.268 + 1.269 + for (i=0; i<n->short_ref_count; i++){ 1.270 + if (n->short_ref[i]->frame_num == frame_num){ 1.271 + if (release){ 1.272 + s->release_ref_cpn[s->release_cnt++] = n->short_ref[i]->cpn; 1.273 + n->short_ref[i]->reference &= ~2; 1.274 + } 1.275 + n->short_ref[i] = NULL; 1.276 + if (--n->short_ref_count) 1.277 + memmove(&n->short_ref[i], &n->short_ref[i+1], (n->short_ref_count - i)*sizeof(PictureInfo *)); 1.278 + return 0; 1.279 + } 1.280 + } 1.281 + return -1; 1.282 +} 1.283 + 1.284 +static void remove_long(NalContext *n, H264Slice *s, int i){ 1.285 + 1.286 + if (n->long_ref[i]){ 1.287 + s->release_ref_cpn[s->release_cnt++] = n->long_ref[i]->cpn; 1.288 + n->long_ref[i]->reference &= ~2; 1.289 + n->long_ref[i]->long_ref = 0; 1.290 + n->long_ref_count--; 1.291 + n->long_ref[i] = NULL; 1.292 + } 1.293 +} 1.294 + 1.295 +void ff_h264_remove_all_refs(NalContext *n, H264Slice *s){ 1.296 + int i; 1.297 + 1.298 + while (n->short_ref[0]) 1.299 + remove_short(n, s, n->short_ref[0]->frame_num, 1); 1.300 + 1.301 + for(i=0; i<16; i++){ 1.302 + remove_long(n, s, i); 1.303 + } 1.304 + assert(n->short_ref_count==0); 1.305 + assert(n->long_ref_count==0); 1.306 +} 1.307 + 1.308 +int ff_h264_ref_pic_marking(NalContext *n, H264Slice *s, GetBitContext *gb){ 1.309 + 1.310 + if(s->nal_unit_type == NAL_IDR_SLICE){ //FIXME fields 1.311 + get_bits1(gb); //get_bits1(gb) -1; //broken link 1.312 + if(get_bits1(gb)){ 1.313 + av_log(AV_LOG_ERROR, "MMCO_LONG reference management not supported\n"); 1.314 + } 1.315 + }else{ 1.316 + if(get_bits1(gb)){ // adaptive_ref_pic_marking_mode_flag 1.317 + int i,j; 1.318 + for(i= 0; i<MAX_MMCO_COUNT; i++) { 1.319 + PictureInfo *pic; 1.320 + int short_pic_num=0; 1.321 + unsigned int long_arg=0; 1.322 + MMCOOpcode opcode= get_ue_golomb_31(gb); 1.323 + 1.324 + if(opcode==MMCO_SHORT2UNUSED || opcode==MMCO_SHORT2LONG){ 1.325 + short_pic_num= (n->frame_num - get_ue_golomb(gb) - 1) & (n->max_pic_num - 1); 1.326 + } 1.327 + if(opcode==MMCO_SHORT2LONG || opcode==MMCO_LONG2UNUSED || opcode==MMCO_LONG || opcode==MMCO_SET_MAX_LONG){ 1.328 + long_arg= get_ue_golomb_31(gb); 1.329 + if(long_arg >= 16){ 1.330 + av_log(AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode); 1.331 + return -1; 1.332 + } 1.333 + } 1.334 + 1.335 + if(opcode > (unsigned)MMCO_LONG){ 1.336 + av_log(AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode); 1.337 + return -1; 1.338 + } 1.339 + if(opcode == MMCO_END) 1.340 + break; 1.341 + 1.342 + switch (opcode){ 1.343 + case MMCO_SHORT2UNUSED: 1.344 + remove_short(n, s, short_pic_num, 1); 1.345 + break; 1.346 + case MMCO_SHORT2LONG: 1.347 + pic = find_short(n, short_pic_num); 1.348 + if (n->long_ref[long_arg] != pic) 1.349 + remove_long(n, s, long_arg); 1.350 + remove_short(n, s, short_pic_num, 0); 1.351 + n->long_ref[long_arg]= pic; 1.352 + if (pic){ 1.353 + pic->long_ref=1; 1.354 + n->long_ref[long_arg]= pic; 1.355 + n->long_ref_count++; 1.356 + } 1.357 + break; 1.358 + case MMCO_LONG2UNUSED: 1.359 + assert(n->long_ref[long_arg]); 1.360 + remove_long(n, s, long_arg); 1.361 + break; 1.362 + case MMCO_SET_MAX_LONG: 1.363 + for(j=long_arg; j<16; j++) 1.364 + remove_long(n, s, j); 1.365 + break; 1.366 + case MMCO_RESET: 1.367 + while(n->short_ref_count) 1.368 + remove_short(n, s, n->short_ref[0]->frame_num, 1); 1.369 + 1.370 + for(j=0; j < 16; j++) 1.371 + remove_long(n, s, j); 1.372 + 1.373 + s->current_picture_info->poc= 1.374 + s->poc = 1.375 + n->poc_lsb= 1.376 + n->poc_msb= 1.377 + n->frame_num= 1.378 + s->current_picture_info->frame_num= 0; 1.379 + break; 1.380 + case MMCO_END: 1.381 + case MMCO_LONG: 1.382 + break; 1.383 + } 1.384 + } 1.385 + }else{// sliding window ref picture marking 1.386 + if(n->short_ref_count == n->sps.ref_frame_count) { 1.387 + s->release_ref_cpn[s->release_cnt++] = n->short_ref[n->short_ref_count - 1]->cpn; 1.388 + n->short_ref[n->short_ref_count - 1]->reference &= ~2; 1.389 + n->short_ref[ n->short_ref_count - 1 ] =NULL; 1.390 + n->short_ref_count--; 1.391 + } 1.392 + } 1.393 + } 1.394 + 1.395 + if(n->short_ref_count) 1.396 + memmove(&n->short_ref[1], &n->short_ref[0], n->short_ref_count*sizeof(PictureInfo *)); 1.397 + 1.398 + n->short_ref[0]= s->current_picture_info; 1.399 + n->short_ref_count++; 1.400 + 1.401 + return 0; 1.402 +} 1.403 + 1.404 +static int get_scale_factor(H264Slice *s, int poc, int poc1, int i){ 1.405 + int poc0 = s->ref_list[0][i]->poc; 1.406 + int td = av_clip(poc1 - poc0, -128, 127); 1.407 + if(td == 0 || s->ref_list[0][i]->long_ref){ 1.408 + return 256; 1.409 + }else{ 1.410 + int tb = av_clip(poc - poc0, -128, 127); 1.411 + int tx = (16384 + (FFABS(td) >> 1)) / td; 1.412 + return av_clip((tb*tx + 32) >> 6, -1024, 1023); 1.413 + } 1.414 +} 1.415 + 1.416 +void ff_h264_direct_dist_scale_factor(H264Slice *s){ 1.417 + const int poc = s->current_picture_info->poc; 1.418 + const int poc1 = s->ref_list[1][0]->poc; 1.419 + 1.420 + for(int i=0; i<s->ref_count[0]; i++){ 1.421 + s->dist_scale_factor[i] = get_scale_factor(s, poc, poc1, i); 1.422 + } 1.423 +} 1.424 + 1.425 +static void fill_colmap(H264Slice *s, int map[2][16], int list){ 1.426 + PictureInfo * const ref1 = s->ref_list[1][0]; 1.427 + int old_ref, rfield; 1.428 + 1.429 + /* bogus; fills in for missing frames */ 1.430 + memset(map[list], 0, sizeof(map[list])); 1.431 + 1.432 + for(rfield=0; rfield<2; rfield++){ 1.433 + for(old_ref=0; old_ref < ref1->ref_count[list]; old_ref++){ 1.434 + int poc = ref1->ref_poc[list][old_ref]; 1.435 + 1.436 + for(int j=0; j<s->ref_count[0]; j++){ 1.437 + if(s->ref_list[0][j]->poc == poc){ 1.438 + map[list][old_ref] = j; 1.439 + break; 1.440 + } 1.441 + } 1.442 + } 1.443 + } 1.444 +} 1.445 + 1.446 +void ff_h264_direct_ref_list_init(H264Slice *s){ 1.447 + PictureInfo * const cur = s->current_picture_info; 1.448 + int list; 1.449 + 1.450 + for(list=0; list<2; list++){ 1.451 + cur->ref_count[list] = s->ref_count[list]; 1.452 + for(int j=0; j<s->ref_count[list]; j++){ 1.453 + cur->ref_poc[list][j] = s->ref_list[list][j] ? s->ref_list[list][j]->poc : 0; 1.454 + } 1.455 + } 1.456 + 1.457 + if(s->slice_type_nos != FF_B_TYPE || s->direct_spatial_mv_pred) 1.458 + return; 1.459 + 1.460 + for(list=0; list<2; list++){ 1.461 + fill_colmap(s, s->map_col_to_list0, list); 1.462 + } 1.463 +} 1.464 +
