int main(int argc, char** argv) { FILE *infile,*outfile; decoder_info_t decoder_info; stream_t stream; yuv_frame_t rec[MAX_REORDER_BUFFER]; yuv_frame_t ref[MAX_REF_FRAMES]; int rec_available[MAX_REORDER_BUFFER]={0}; int rec_buffer_idx; int op_rec_buffer_idx; int decode_frame_num = 0; int last_frame_output = -1; int done = 0; int width; int height; int r; init_use_simd(); parse_arg(argc, argv, &infile, &outfile); fseek(infile, 0, SEEK_END); int input_file_size = ftell(infile); fseek(infile, 0, SEEK_SET); initbits_dec(infile, &stream); decoder_info.stream = &stream; memset(&decoder_info.bit_count,0,sizeof(bit_count_t)); int bit_start = stream.bitcnt; /* Read sequence header */ width = getbits(&stream,16); height = getbits(&stream,16); decoder_info.width = width; decoder_info.height = height; printf("width=%4d height=%4d\n",width,height); decoder_info.pb_split = getbits(&stream,1); printf("pb_split_enable=%1d\n",decoder_info.pb_split); //TODO: Rename variable to pb_split_enable decoder_info.tb_split_enable = getbits(&stream,1); printf("tb_split_enable=%1d\n",decoder_info.tb_split_enable); decoder_info.max_num_ref = getbits(&stream,2) + 1; fprintf(stderr,"num refs is %d\n",decoder_info.max_num_ref); decoder_info.interp_ref = getbits(&stream,1); decoder_info.max_delta_qp = getbits(&stream, 1); decoder_info.deblocking = getbits(&stream,1); decoder_info.clpf = getbits(&stream,1); decoder_info.use_block_contexts = getbits(&stream,1); decoder_info.bipred = getbits(&stream,1); decoder_info.bit_count.sequence_header += (stream.bitcnt - bit_start); for (r=0;r<MAX_REORDER_BUFFER;r++){ create_yuv_frame(&rec[r],width,height,0,0,0,0); } for (r=0;r<MAX_REF_FRAMES;r++){ create_yuv_frame(&ref[r],width,height,PADDING_Y,PADDING_Y,PADDING_Y/2,PADDING_Y/2); decoder_info.ref[r] = &ref[r]; } if (decoder_info.interp_ref) { for (r=0;r<MAX_SKIP_FRAMES;r++){ decoder_info.interp_frames[r] = malloc(sizeof(yuv_frame_t)); create_yuv_frame(decoder_info.interp_frames[r],width,height,PADDING_Y,PADDING_Y,PADDING_Y/2,PADDING_Y/2); } } decoder_info.deblock_data = (deblock_data_t *)malloc((height/MIN_PB_SIZE) * (width/MIN_PB_SIZE) * sizeof(deblock_data_t)); do { decoder_info.frame_info.decode_order_frame_num = decode_frame_num; decode_frame(&decoder_info,rec); rec_buffer_idx = decoder_info.frame_info.display_frame_num%MAX_REORDER_BUFFER; rec_available[rec_buffer_idx]=1; done = initbits_dec(infile, &stream); op_rec_buffer_idx = (last_frame_output+1)%MAX_REORDER_BUFFER; if (rec_available[op_rec_buffer_idx]) { last_frame_output++; write_yuv_frame(&rec[op_rec_buffer_idx],width,height,outfile); rec_available[op_rec_buffer_idx] = 0; } printf("decode_frame_num=%4d display_frame_num=%4d input_file_size=%12d bitcnt=%12d\n", decode_frame_num,decoder_info.frame_info.display_frame_num,input_file_size,stream.bitcnt); decode_frame_num++; } while (!done); // Output the tail int i,j; for (i=1; i<=MAX_REORDER_BUFFER; ++i) { op_rec_buffer_idx=(last_frame_output+i) % MAX_REORDER_BUFFER; if (rec_available[op_rec_buffer_idx]) write_yuv_frame(&rec[op_rec_buffer_idx],width,height,outfile); else break; } bit_count_t bit_count = decoder_info.bit_count; uint32_t tot_bits[NUM_FRAME_TYPES] = {0}; for (i=0;i<NUM_FRAME_TYPES;i++){ tot_bits[i] = bit_count.frame_header[i] + bit_count.super_mode[i] + bit_count.intra_mode[i] + bit_count.mv[i] + bit_count.skip_idx[i] + bit_count.coeff_y[i] + bit_count.coeff_u[i] + bit_count.coeff_v[i] + bit_count.cbp[i] + bit_count.clpf[i]; } tot_bits[0] += bit_count.sequence_header; int ni = bit_count.frame_type[0]; int np = bit_count.frame_type[1]; int nb = bit_count.frame_type[2]; if (np==0) np = (1<<30); //Hack to avoid division by zero if there are no P frames if (nb==0) nb = (1<<30); //Hack to avoid division by zero if there are no B frames printf("\n\nBIT STATISTICS:\n"); printf("Sequence header: %4d\n",bit_count.sequence_header); printf(" I pictures: P pictures: B pictures:\n"); printf(" total average total average total average\n"); printf("Frame header: %9d %9d %9d %9d %9d %9d\n",bit_count.frame_header[0],bit_count.frame_header[0]/ni,bit_count.frame_header[1],bit_count.frame_header[1]/np,bit_count.frame_header[2],bit_count.frame_header[2]/nb); printf("Super mode: %9d %9d %9d %9d %9d %9d\n",bit_count.super_mode[0],bit_count.super_mode[0]/ni,bit_count.super_mode[1],bit_count.super_mode[1]/np,bit_count.super_mode[2],bit_count.super_mode[2]/nb); printf("Intra mode: %9d %9d %9d %9d %9d %9d\n",bit_count.intra_mode[0],bit_count.intra_mode[0]/ni,bit_count.intra_mode[1],bit_count.intra_mode[1]/np, bit_count.intra_mode[2],bit_count.intra_mode[2]/nb); printf("MV: %9d %9d %9d %9d %9d %9d\n",bit_count.mv[0],bit_count.mv[0],bit_count.mv[1],bit_count.mv[1]/np, bit_count.mv[2],bit_count.mv[2]/nb); printf("Skip idx: %9d %9d %9d %9d %9d %9d\n",bit_count.skip_idx[0],bit_count.skip_idx[0],bit_count.skip_idx[1],bit_count.skip_idx[1]/np,bit_count.skip_idx[2],bit_count.skip_idx[2]/nb); printf("Coeff_y: %9d %9d %9d %9d %9d %9d\n",bit_count.coeff_y[0],bit_count.coeff_y[0]/ni,bit_count.coeff_y[1],bit_count.coeff_y[1]/np,bit_count.coeff_y[2],bit_count.coeff_y[2]/nb); printf("Coeff_u: %9d %9d %9d %9d %9d %9d\n",bit_count.coeff_u[0],bit_count.coeff_u[0]/ni,bit_count.coeff_u[1],bit_count.coeff_u[1]/np,bit_count.coeff_u[2],bit_count.coeff_u[2]/nb); printf("Coeff_v: %9d %9d %9d %9d %9d %9d\n",bit_count.coeff_v[0],bit_count.coeff_v[0]/ni,bit_count.coeff_v[1],bit_count.coeff_v[1]/np,bit_count.coeff_v[2],bit_count.coeff_v[2]/nb); printf("CBP (TU-split): %9d %9d %9d %9d %9d %9d\n",bit_count.cbp[0],bit_count.cbp[0]/ni,bit_count.cbp[1],bit_count.cbp[1]/np,bit_count.cbp[2],bit_count.cbp[2]/nb); printf("CLPF: %9d %9d %9d %9d %9d %9d\n",bit_count.clpf[0],bit_count.clpf[0]/ni,bit_count.clpf[1],bit_count.clpf[1]/np,bit_count.clpf[2],bit_count.clpf[2]/nb); printf("Total: %9d %9d %9d %9d %9d %9d\n",tot_bits[0],tot_bits[0],tot_bits[1],tot_bits[1]/np,tot_bits[2],tot_bits[2]/nb); printf("---------------------------------------------------------------------------------------\n\n"); printf("PARAMETER STATISTICS:\n"); printf(" I pictures: P pictures: B pictures:\n"); printf(" total average total average total average\n"); printf("Skip-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.mode[0][0],bit_count.mode[0][0]/ni,bit_count.mode[1][0],bit_count.mode[1][0]/np,bit_count.mode[2][0],bit_count.mode[2][0]/nb); printf("Intra-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.mode[0][1],bit_count.mode[0][1]/ni,bit_count.mode[1][1],bit_count.mode[1][1]/np,bit_count.mode[2][1],bit_count.mode[2][1]/nb); printf("Inter-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.mode[0][2],bit_count.mode[0][2]/ni,bit_count.mode[1][2],bit_count.mode[1][2]/np,bit_count.mode[2][2],bit_count.mode[2][2]/nb); printf("Bipred-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.mode[0][3],bit_count.mode[0][3]/ni,bit_count.mode[1][3],bit_count.mode[1][3]/np,bit_count.mode[2][3],bit_count.mode[2][3]/nb); printf("Merge-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.mode[0][4],bit_count.mode[0][4]/ni,bit_count.mode[1][4],bit_count.mode[1][4]/np,bit_count.mode[2][4],bit_count.mode[2][4]/nb); printf("\n"); printf("8x8-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.size[0][0],bit_count.size[0][0]/ni,bit_count.size[1][0],bit_count.size[1][0]/np,bit_count.size[2][0],bit_count.size[2][0]/nb); printf("16x16-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.size[0][1],bit_count.size[0][1]/ni,bit_count.size[1][1],bit_count.size[1][1]/np,bit_count.size[2][1],bit_count.size[2][1]/nb); printf("32x32-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.size[0][2],bit_count.size[0][2]/ni,bit_count.size[1][2],bit_count.size[1][2]/np,bit_count.size[2][2],bit_count.size[2][2]/nb); printf("64x64-blocks (8x8): %9d %9d %9d %9d %9d %9d\n",bit_count.size[0][3],bit_count.size[0][3]/ni,bit_count.size[1][3],bit_count.size[1][3]/np,bit_count.size[2][3],bit_count.size[2][3]/nb); printf("\n"); printf("Mode and size distribution for P pictures:\n"); printf(" SKIP INTRA INTER BIPRED MERGE\n"); printf("8x8-blocks (8x8): %9d %9d %9d %9d %9d\n",bit_count.size_and_mode[P_FRAME][0][0],bit_count.size_and_mode[P_FRAME][0][1],bit_count.size_and_mode[P_FRAME][0][2],bit_count.size_and_mode[P_FRAME][0][3],bit_count.size_and_mode[P_FRAME][0][4]); printf("16x16-blocks (8x8): %9d %9d %9d %9d %9d\n",bit_count.size_and_mode[P_FRAME][1][0],bit_count.size_and_mode[P_FRAME][1][1],bit_count.size_and_mode[P_FRAME][1][2],bit_count.size_and_mode[P_FRAME][1][3],bit_count.size_and_mode[P_FRAME][1][4]); printf("32x32-blocks (8x8): %9d %9d %9d %9d %9d\n",bit_count.size_and_mode[P_FRAME][2][0],bit_count.size_and_mode[P_FRAME][2][1],bit_count.size_and_mode[P_FRAME][2][2],bit_count.size_and_mode[P_FRAME][2][3],bit_count.size_and_mode[P_FRAME][2][4]); printf("64x64-blocks (8x8): %9d %9d %9d %9d %9d\n",bit_count.size_and_mode[P_FRAME][3][0],bit_count.size_and_mode[P_FRAME][3][1],bit_count.size_and_mode[P_FRAME][3][2],bit_count.size_and_mode[P_FRAME][3][3],bit_count.size_and_mode[P_FRAME][3][4]); printf("\n"); printf("Mode and size distribution for B pictures:\n"); printf(" SKIP INTRA INTER BIPRED MERGE\n"); printf("8x8-blocks (8x8): %9d %9d %9d %9d %9d\n", bit_count.size_and_mode[B_FRAME][0][0], bit_count.size_and_mode[B_FRAME][0][1], bit_count.size_and_mode[B_FRAME][0][2], bit_count.size_and_mode[B_FRAME][0][3], bit_count.size_and_mode[B_FRAME][0][4]); printf("16x16-blocks (8x8): %9d %9d %9d %9d %9d\n", bit_count.size_and_mode[B_FRAME][1][0], bit_count.size_and_mode[B_FRAME][1][1], bit_count.size_and_mode[B_FRAME][1][2], bit_count.size_and_mode[B_FRAME][1][3], bit_count.size_and_mode[B_FRAME][1][4]); printf("32x32-blocks (8x8): %9d %9d %9d %9d %9d\n", bit_count.size_and_mode[B_FRAME][2][0], bit_count.size_and_mode[B_FRAME][2][1], bit_count.size_and_mode[B_FRAME][2][2], bit_count.size_and_mode[B_FRAME][2][3], bit_count.size_and_mode[B_FRAME][2][4]); printf("64x64-blocks (8x8): %9d %9d %9d %9d %9d\n", bit_count.size_and_mode[B_FRAME][3][0], bit_count.size_and_mode[B_FRAME][3][1], bit_count.size_and_mode[B_FRAME][3][2], bit_count.size_and_mode[B_FRAME][3][3], bit_count.size_and_mode[B_FRAME][3][4]); int idx; int num = 5 + decoder_info.max_num_ref; printf("\nSuper-mode distribution for P pictures:\n"); printf(" SKIP SPLIT INTERr0 MERGE BIPRED INTRA "); for (i = 1; i < decoder_info.max_num_ref; i++) printf("INTERr%1d ", i); printf("\n"); for (idx=0;idx<NUM_BLOCK_SIZES;idx++){ int size = 8<<idx; printf("%2d x %2d-blocks: ",size,size); for (i=0;i<num;i++){ printf("%8d",bit_count.super_mode_stat[P_FRAME][idx][i]); } printf("\n"); } printf("\nSuper-mode distribution for B pictures:\n"); printf(" SKIP SPLIT INTERr0 MERGE BIPRED INTRA "); for (i = 1; i < decoder_info.max_num_ref; i++) printf("INTERr%1d ", i); printf("\n"); for (idx = 0; idx<NUM_BLOCK_SIZES; idx++) { int size = 8 << idx; printf("%2d x %2d-blocks: ", size, size); for (i = 0; i<num; i++) { printf("%8d", bit_count.super_mode_stat[B_FRAME][idx][i]); } printf("\n"); } int size; int max_num_ref = 4; printf("\n"); printf("Ref_idx and size distribution for P pictures:\n"); for (i=0;i<NUM_BLOCK_SIZES;i++){ size = 1<<(i+3); printf("%2d x %2d-blocks: ",size,size); for (j=0;j<decoder_info.max_num_ref;j++){ printf("%6d",bit_count.size_and_ref_idx[P_FRAME][i][j]); } printf("\n"); } printf("\n"); printf("Ref_idx and size distribution for B pictures:\n"); for (i = 0; i<NUM_BLOCK_SIZES; i++) { size = 1 << (i + 3); printf("%2d x %2d-blocks: ", size, size); for (j = 0; j<decoder_info.max_num_ref; j++) { printf("%6d", bit_count.size_and_ref_idx[B_FRAME][i][j]); } printf("\n"); } printf("\n"); printf("bi-ref-P: "); for (j=0;j<max_num_ref*max_num_ref;j++){ printf("%7d",bit_count.bi_ref[P_FRAME][j]); } printf("\n"); printf("bi-ref-B: "); for (j = 0; j<max_num_ref*max_num_ref; j++) { printf("%7d", bit_count.bi_ref[B_FRAME][j]); } printf("\n"); printf("-----------------------------------------------------------------\n"); for (r=0;r<MAX_REORDER_BUFFER;r++){ close_yuv_frame(&rec[r]); } for (r=0;r<MAX_REF_FRAMES;r++){ close_yuv_frame(&ref[r]); } if (decoder_info.interp_ref) { for (r=0;r<MAX_SKIP_FRAMES;r++){ close_yuv_frame(decoder_info.interp_frames[r]); free(decoder_info.interp_frames[r]); } } free(decoder_info.deblock_data); return 0; }
void interpolate_frames(yuv_frame_t* new_frame, yuv_frame_t* ref0, yuv_frame_t* ref1, int ratio, int pos) { int widthin = ref0->width; int heightin = ref0->height; int max_levels=min(MAX_LEVELS, (int) (log10(min(widthin, heightin))/log10(2.0)-4.0)); mv_data_t * mv_data[MAX_LEVELS]; mv_data_t * spatial_mv_data[MAX_LEVELS]; mv_data_t * guide_mv_data[NUM_GUIDES]; yuv_frame_t* in_down[MAX_LEVELS][2]; yuv_frame_t* out_down[MAX_LEVELS]; int interpolate = 1; for (int j=1; j<max_levels; j++) { out_down[j]=malloc(sizeof(yuv_frame_t)); create_yuv_frame(out_down[j],widthin>>j,heightin>>j, 32, 32, 16, 16); } out_down[0]=new_frame; for (int j=0; j<max_levels; j++) { mv_data[j] = alloc_mv_data(widthin>>j, heightin>>j, BLOCK_STEP/2, BLOCK_STEP, ratio, pos, interpolate); mv_data[j]->ratio = ratio; spatial_mv_data[j] = alloc_mv_data(widthin>>j, heightin>>j, BLOCK_STEP/2, BLOCK_STEP, ratio, pos, interpolate); spatial_mv_data[j]->ratio = ratio; } /* Higher levels are down-sampled*/ for (int i=1; i<max_levels; ++i) { in_down[i][0]=malloc(sizeof(yuv_frame_t)); in_down[i][1]=malloc(sizeof(yuv_frame_t)); create_yuv_frame(in_down[i][0],widthin>>i, heightin>>i, 32, 32, 16, 16); create_yuv_frame(in_down[i][1],widthin>>i, heightin>>i, 32, 32, 16, 16); } // Level 0 is just the original pictures in_down[0][0]=ref0; in_down[0][1]=ref1; for (int l=0; l<max_levels-1; ++l) { if (use_simd) { scale_frame_down2x2_simd(in_down[l][0], in_down[l+1][0]); scale_frame_down2x2_simd(in_down[l][1], in_down[l+1][1]); } else { scale_frame_down2x2(in_down[l][0], in_down[l+1][0]); scale_frame_down2x2(in_down[l][1], in_down[l+1][1]); } } for (int lvl=max_levels-1; lvl>=0; --lvl) { int num_guides=0; if (lvl!=max_levels-1) { guide_mv_data[num_guides++]=spatial_mv_data[lvl]; } motion_estimate_bi(mv_data[lvl], guide_mv_data, num_guides, in_down[lvl][0], in_down[lvl][1], pos); if (lvl==0) interpolate_frame(mv_data[lvl], in_down[lvl][0], in_down[lvl][1], out_down[lvl], widthin, heightin, pos, ratio); if (lvl>0) { upscale_mv_data_2x2(mv_data[lvl], spatial_mv_data[lvl-1]); } } for (int j=1; j<max_levels; j++) { close_yuv_frame(out_down[j]); free(out_down[j]); } for (int j=0; j<max_levels; j++) { free_mv_data(mv_data[j]); free_mv_data(spatial_mv_data[j]); } /* Higher levels are down-sampled*/ for (int i=1; i<max_levels; ++i) { close_yuv_frame(in_down[i][0]); close_yuv_frame(in_down[i][1]); free(in_down[i][0]); free(in_down[i][1]); } }