int Write_Filler_Data_NALU( VideoParameters *p_Vid, int num_bytes ) { int RBSPlen = num_bytes - 1; int len, bytes_written = 0; byte rbsp[MAXRBSPSIZE]; byte filler_byte = (byte)0xFF; byte trailing_byte = (byte)0x80; NALU_t *nalu = AllocNALU( MAXNALUSIZE ); num_bytes = iClip3( 1, (MAXRBSPSIZE - 2), num_bytes ); assert( num_bytes > 0 && num_bytes < (MAXRBSPSIZE - 1) ); num_bytes = imax( 2, num_bytes ); // one byte for the NAL header and one for the rbsp trailing byte if ( RBSPlen > 1 ) { while ( bytes_written < (RBSPlen - 1) ) { rbsp[ bytes_written++ ] = filler_byte; } } rbsp[ bytes_written++ ] = trailing_byte; // rbsp_trailing_bits assert( num_bytes == (bytes_written + 1) ); // write RBSP into NALU RBSPtoNALU( rbsp, nalu, RBSPlen, NALU_TYPE_FILL, NALU_PRIORITY_DISPOSABLE, 1 ); // write NALU into bitstream len = p_Vid->WriteNALU( p_Vid, nalu, p_Vid->f_out ); p_Vid->bytes_in_picture += (nalu->len + 1); FreeNALU( nalu ); return len; }
/*! ************************************************************************ * \brief * Interpret GOP struct from input parameters ************************************************************************ */ void interpret_gop_structure() { int nLength = strlen(input->ExplicitHierarchyFormat); int i =0, k, dqp, display_no; int slice_read =0, order_read = 0, stored_read = 0, qp_read =0; int coded_frame = 0; if (nLength > 0) { for (i = 0; i < nLength ; i++) { //! First lets read slice type if (slice_read == 0) { switch (input->ExplicitHierarchyFormat[i]) { case 'P': case 'p': gop_structure[coded_frame].slice_type=P_SLICE; break; case 'B': case 'b': gop_structure[coded_frame].slice_type=B_SLICE; break; case 'I': case 'i': gop_structure[coded_frame].slice_type=I_SLICE; break; default: snprintf(errortext, ET_SIZE, "Slice Type invalid in ExplicitHierarchyFormat param. Please check configuration file."); error (errortext, 400); break; } slice_read = 1; } else { //! Next is Display Order if (order_read == 0) { if (isdigit((int)(*(input->ExplicitHierarchyFormat+i)))) { sscanf(input->ExplicitHierarchyFormat+i,"%d",&display_no); gop_structure[coded_frame].display_no = display_no; order_read = 1; if (display_no<0 || display_no>=input->jumpd) { snprintf(errortext, ET_SIZE, "Invalid Frame Order value. Frame position needs to be in [0,%d] range.",input->jumpd-1); error (errortext, 400); } for (k=0;k<coded_frame;k++) { if (gop_structure[k].display_no == display_no) { snprintf(errortext, ET_SIZE, "Frame Order value %d in frame %d already used for enhancement frame %d.",display_no,coded_frame,k); error (errortext, 400); } } } else { snprintf(errortext, ET_SIZE, "Slice Type needs to be followed by Display Order. Please check configuration file."); error (errortext, 400); } } else if (order_read == 1) { if (stored_read == 0 && !(isdigit((int)(*(input->ExplicitHierarchyFormat+i))))) { switch (input->ExplicitHierarchyFormat[i]) { case 'E': case 'e': gop_structure[coded_frame].reference_idc = NALU_PRIORITY_DISPOSABLE; gop_structure[coded_frame].hierarchy_layer = 0; break; case 'R': case 'r': gop_structure[coded_frame].reference_idc= NALU_PRIORITY_HIGH; gop_structure[coded_frame].hierarchy_layer = 1; img->GopLevels = 2; break; default: snprintf(errortext, ET_SIZE, "Reference_IDC invalid in ExplicitHierarchyFormat param. Please check configuration file."); error (errortext, 400); break; } stored_read = 1; } else if (stored_read == 1 && qp_read == 0) { if (isdigit((int)(*(input->ExplicitHierarchyFormat+i)))) { sscanf(input->ExplicitHierarchyFormat+i,"%d",&dqp); if (gop_structure[coded_frame].slice_type == I_SLICE) gop_structure[coded_frame].slice_qp = input->qp0; else if (gop_structure[coded_frame].slice_type == P_SLICE) gop_structure[coded_frame].slice_qp = input->qpN; else gop_structure[coded_frame].slice_qp = input->qpB; gop_structure[coded_frame].slice_qp = iClip3(-img->bitdepth_luma_qp_scale, 51,gop_structure[coded_frame].slice_qp + dqp); qp_read = 1; } else { snprintf(errortext, ET_SIZE, "Reference_IDC needs to be followed by QP. Please check configuration file."); error (errortext, 400); } } else if (stored_read == 1 && qp_read == 1 && !(isdigit((int)(*(input->ExplicitHierarchyFormat+i)))) && (i < nLength - 2)) { stored_read =0; qp_read=0; order_read=0; slice_read=0; i--; coded_frame ++; if (coded_frame >= input->jumpd ) { snprintf(errortext, ET_SIZE, "Total number of frames in Enhancement GOP need to be fewer or equal to FrameSkip parameter."); error (errortext, 400); } } } } } } else { snprintf(errortext, ET_SIZE, "ExplicitHierarchyFormat is empty. Please check configuration file."); error (errortext, 400); } input->successive_Bframe = coded_frame + 1; }
void frame_picture_mp_b_slice(VideoParameters *p_Vid, InputParameters *p_Inp) { int rd_pass = 0; int rd_qp = p_Vid->p_curr_frm_struct->qp; float rateRatio = 1.0F; int wp_pass = 0; CodingInfo coding_info; FrameCodingMethod best_method = REGULAR; int apply_wp = 0; int selection; Slice *dummy_slice = NULL; #if (DBG_IMAGE_MP) printf("pass0_wp = %d\n", p_Vid->pass0_wp); #endif frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); if(p_Inp->WPIterMC) p_Vid->frameOffsetAvail = 1; rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassBSlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } init_slice_lite(p_Vid, &dummy_slice, 0); #if (DBG_IMAGE_MP) printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, p_Vid->frame_pic[0]->bits_per_picture, p_Vid->frame_pic[0]->distortion.value[0], p_Vid->frame_pic[0]->distortion.value[1], p_Vid->frame_pic[0]->distortion.value[2]); #endif // for B_Slice, consider implicit WP wp_pass = 0; { if (p_Inp->GenerateMultiplePPS) { InitWP(p_Vid, p_Inp, 0); if ( p_Inp->WPMCPrecision ) p_Vid->pWPX->curr_wp_rd_pass = p_Vid->pWPX->wp_rd_passes + 1; if (p_Vid->TestWPBSlice(dummy_slice, 1) == 1) { // regular WP pass p_Vid->active_pps = p_Vid->PicParSet[2]; if(p_Inp->WPMCPrecision) p_Vid->pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR; wp_pass = 1; } } if(wp_pass) { p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("IMP WP, rd_pass = %d, selection = %d\n", rd_pass, selection); printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, p_Vid->frame_pic[rd_pass]->bits_per_picture, p_Vid->frame_pic[rd_pass]->distortion.value[0], p_Vid->frame_pic[rd_pass]->distortion.value[1], p_Vid->frame_pic[rd_pass]->distortion.value[2]); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = IMP_WP; apply_wp = IMP_WP; } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassBSlice) { frame_picture_mp_exit(p_Vid, &coding_info); free_slice(dummy_slice); return; } } // for B_Slice, consider explicit WP wp_pass = 0; if (p_Inp->GenerateMultiplePPS) { InitWP(p_Vid, p_Inp, 0); if( p_Inp->WPMCPrecision ) p_Vid->pWPX->curr_wp_rd_pass = p_Vid->pWPX->wp_rd_passes + 1; if (p_Vid->TestWPBSlice(dummy_slice, 0) == 1) { // regular WP pass p_Vid->active_pps = p_Vid->PicParSet[1]; if( p_Inp->WPMCPrecision ) p_Vid->pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR; wp_pass = 1; } else if ( p_Inp->WPMCPrecision == 2 && (p_Inp->WPMCPrecBSlice == 2 || (p_Inp->WPMCPrecBSlice == 1 && p_Vid->nal_reference_idc) ) ) { p_Vid->active_pps = p_Vid->PicParSet[1]; wp_pass = 1; } } if(wp_pass) { p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("EXP WP, rd_pass = %d, selection = %d\n", rd_pass, selection); printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, p_Vid->frame_pic[rd_pass]->bits_per_picture, p_Vid->frame_pic[rd_pass]->distortion.value[0], p_Vid->frame_pic[rd_pass]->distortion.value[1], p_Vid->frame_pic[rd_pass]->distortion.value[2]); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = EXP_WP; apply_wp = EXP_WP; } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassBSlice) { frame_picture_mp_exit(p_Vid, &coding_info); free_slice(dummy_slice); return; } } } if(p_Inp->RDPictureFrameQPBSlice) { // frame QP pass p_Vid->active_pps = best_method == EXP_WP ? p_Vid->PicParSet[1]:best_method==IMP_WP?p_Vid->PicParSet[2]:p_Vid->PicParSet[0]; //p_Vid->qp = (p_Vid->nal_reference_idc==0 ? rd_qp + 1 : rd_qp - 1); p_Vid->qp = (p_Vid->nal_reference_idc==0 ? rd_qp + 1 : rd_qp ); p_Vid->qp = iClip3( p_Vid->RCMinQP, p_Vid->RCMaxQP, p_Vid->qp ); if ( p_Inp->RCEnable ) { rateRatio = p_Vid->nal_reference_idc ? 1.15F : 0.85F; rc_init_frame_rdpic( p_Vid, p_Inp, rateRatio ); } p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("frame QP, rd_pass = %d, selection = %d \n", rd_pass, selection); printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, p_Vid->frame_pic[rd_pass]->bits_per_picture, p_Vid->frame_pic[rd_pass]->distortion.value[0], p_Vid->frame_pic[rd_pass]->distortion.value[1], p_Vid->frame_pic[rd_pass]->distortion.value[2]); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = FRAME_QP; } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassBSlice) { frame_picture_mp_exit(p_Vid, &coding_info); free_slice(dummy_slice); return; } } // alternative direct mode pass if(p_Inp->RDPictureDirectMode) { // consider using the best coding "method" found so far p_Vid->active_pps = apply_wp == IMP_WP ? p_Vid->PicParSet[1]:apply_wp==EXP_WP?p_Vid->PicParSet[2]:p_Vid->PicParSet[0]; if(best_method == FRAME_QP) p_Vid->qp = (p_Vid->nal_reference_idc==0 ? rd_qp+1:rd_qp-1); else p_Vid->qp = rd_qp; p_Vid->qp = iClip3( p_Vid->RCMinQP, p_Vid->RCMaxQP, p_Vid->qp ); // flip direct mode type p_Vid->direct_spatial_mv_pred_flag = 1-p_Vid->direct_spatial_mv_pred_flag; p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("alternate direct mode, rd_pass = %d, selection = %d\n", rd_pass, selection); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = ALT_DIRECT; } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassBSlice) { frame_picture_mp_exit(p_Vid, &coding_info); free_slice(dummy_slice); return; } } frame_picture_mp_exit(p_Vid, &coding_info); free_slice(dummy_slice); return; }
void frame_picture_mp_i_slice(VideoParameters *p_Vid, InputParameters *p_Inp) { int rd_pass = 0; int qp = p_Vid->qp; float rateRatio = 1.0F; CodingInfo coding_info; int selection; // initial pass encoding frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassISlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } { // try QP-1 qp = p_Vid->qp; p_Vid->qp = qp - 1; p_Vid->qp = iClip3( p_Vid->RCMinQP, p_Vid->RCMaxQP, p_Vid->qp ); if ( p_Inp->RCEnable ) { rateRatio = 1.15F; rc_init_frame_rdpic( p_Vid, p_Inp, rateRatio ); } p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], qp); if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassISlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } // try QP+1 p_Vid->qp = (qp + 1); p_Vid->qp = iClip3( p_Vid->RCMinQP, p_Vid->RCMaxQP, p_Vid->qp ); p_Vid->write_macroblock = FALSE; if ( p_Inp->RCEnable ) { rateRatio = 1.0F; rc_init_frame_rdpic( p_Vid, p_Inp, rateRatio ); } p_Vid->qp = iClip3( p_Vid->RCMinQP, p_Vid->RCMaxQP, p_Vid->qp ); p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], qp); if ( selection ) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassISlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } } frame_picture_mp_exit(p_Vid, &coding_info); }
void frame_picture_mp_p_slice(VideoParameters *p_Vid, InputParameters *p_Inp) { int rd_pass = 0; int rd_qp = p_Vid->p_curr_frm_struct->qp; float rateRatio = 1.0F; int wp_pass=0; int frame_type_pass = 0; CodingInfo coding_info; FrameCodingMethod best_method = REGULAR; int frame_type = P_SLICE; int apply_wp = 0; int selection; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); if(p_Inp->WPIterMC) p_Vid->frameOffsetAvail = 1; #if (DBG_IMAGE_MP) printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, p_Vid->frame_pic[0]->bits_per_picture, p_Vid->frame_pic[0]->distortion.value[0], p_Vid->frame_pic[0]->distortion.value[1], p_Vid->frame_pic[0]->distortion.value[2]); #endif rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassPSlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } // for P_Slice, consider WP wp_pass = 0; if (p_Inp->GenerateMultiplePPS) { Slice *dummy_slice = NULL; InitWP(p_Vid, p_Inp, 0); if ( p_Inp->WPMCPrecision ) p_Vid->pWPX->curr_wp_rd_pass = p_Vid->pWPX->wp_rd_passes + 1; init_slice_lite(p_Vid, &dummy_slice, 0); if (p_Vid->TestWPPSlice(dummy_slice, 0) == 1) { // regular WP pass p_Vid->active_pps = p_Vid->PicParSet[1]; if ( p_Inp->WPMCPrecision ) p_Vid->pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR; wp_pass = 1; } else if ( p_Inp->WPMCPrecision ) { // WPMC pass p_Vid->active_pps = p_Vid->PicParSet[1]; wp_pass = 1; } // The way it is, the code would only reach here if prior conditional using // generatemultiplepps is satisfied if(wp_pass) { p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("rd_pass = %d, selection = %d\n", rd_pass, selection); #endif #if (DBG_IMAGE_MP) printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, p_Vid->frame_pic[rd_pass]->bits_per_picture, p_Vid->frame_pic[rd_pass]->distortion.value[0], p_Vid->frame_pic[rd_pass]->distortion.value[1], p_Vid->frame_pic[rd_pass]->distortion.value[2]); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = EXP_WP; apply_wp = 1; } if(p_Inp->WPMethod == 0 || p_Inp->WPMCPrecision) { wp_pass = 0; if ( p_Inp->WPMCPrecision ) p_Vid->pWPX->curr_wp_rd_pass = p_Vid->pWPX->wp_rd_passes + 2; if (p_Inp->WPMethod == 0 && p_Vid->TestWPPSlice(dummy_slice, 1) == 1) { // regular WP pass p_Vid->active_pps = p_Vid->PicParSet[1]; if ( p_Inp->WPMCPrecision ) p_Vid->pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR; wp_pass = 1; } else if ( p_Inp->WPMCPrecision ) { // WPMC pass p_Vid->active_pps = p_Vid->PicParSet[1]; wp_pass = 1; } if(wp_pass) { p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; free_slice_list(p_Vid->frame_pic[rd_pass]); free_storable_picture(p_Vid, p_Vid->enc_frame_picture[rd_pass]); frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("rd_pass = %d, selection = %d\n", rd_pass, selection); #endif #if (DBG_IMAGE_MP) printf("rd_pass = %d: %d (%.0f, %.0f, %.0f)\n", rd_pass, p_Vid->frame_pic[rd_pass]->bits_per_picture, p_Vid->frame_pic[rd_pass]->distortion.value[0], p_Vid->frame_pic[rd_pass]->distortion.value[1], p_Vid->frame_pic[rd_pass]->distortion.value[2]); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = EXP_WP; apply_wp = 1; } } } rd_pass++; //free_slice(dummy_slice); if(rd_pass >= p_Inp->RDPictureMaxPassPSlice) { frame_picture_mp_exit(p_Vid, &coding_info); free_slice(dummy_slice); return; } } free_slice(dummy_slice); } // code as I? or maybe as B? frame_type_pass = 0; if(p_Inp->RDPSliceITest && (coding_info.intras * 100/p_Vid->FrameSizeInMbs) >= 75) { frame_type = I_SLICE; set_slice_type(p_Vid, p_Inp, I_SLICE); populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, I_SLICE, p_Vid->p_pred->max_num_slices ); p_Vid->active_pps = p_Vid->PicParSet[0]; frame_type_pass = 1; } else if (p_Inp->RDPSliceBTest && p_Vid->active_sps->profile_idc != BASELINE) // later need to add some automatic criterion to see if this (coding P as B) may be beneficial { frame_type = B_SLICE; set_slice_type(p_Vid, p_Inp, B_SLICE ); populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, B_SLICE, p_Vid->p_pred->max_num_slices ); p_Vid->active_pps = p_Vid->PicParSet[0]; frame_type_pass = 1; } if(frame_type_pass) { p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("rd_pass = %d, selection = %d\n", rd_pass, selection); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = FRAME_TYPE; } // reset frame_type else frame_type = P_SLICE; rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassPSlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } } if(p_Vid->EvaluateDBOff) { // Perform DB off coding pass p_Vid->active_pps = (best_method == EXP_WP?p_Vid->PicParSet[1]:p_Vid->PicParSet[0]); if(frame_type != P_SLICE) { set_slice_type(p_Vid, p_Inp, frame_type); populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, frame_type, p_Vid->p_pred->max_num_slices ); } p_Vid->TurnDBOff = 1; p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("DB OFF, rd_pass = %d, selection = %d\n", rd_pass, selection); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = DB_OFF; } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassPSlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } } if(p_Inp->RDPictureFrameQPPSlice) { // frame QP pass p_Vid->active_pps = (apply_wp?p_Vid->PicParSet[1]:p_Vid->PicParSet[0]); if(frame_type != P_SLICE) { set_slice_type(p_Vid, p_Inp, frame_type); populate_frame_slice_type( p_Inp, p_Vid->p_curr_frm_struct, I_SLICE, p_Vid->p_pred->max_num_slices ); } p_Vid->qp = (p_Vid->nal_reference_idc==0 ? rd_qp+1:rd_qp-1); p_Vid->qp = iClip3( p_Vid->RCMinQP, p_Vid->RCMaxQP, p_Vid->qp ); if ( p_Inp->RCEnable ) { rateRatio = p_Vid->nal_reference_idc ? 1.15F : 0.85F; rc_init_frame_rdpic( p_Vid, p_Inp, rateRatio ); } p_Vid->TurnDBOff = 0; p_Vid->write_macroblock = FALSE; p_Vid->p_curr_frm_struct->qp = p_Vid->qp; frame_picture (p_Vid, p_Vid->frame_pic[rd_pass], &p_Vid->imgData, rd_pass); selection = picture_coding_decision(p_Vid, p_Vid->frame_pic[0], p_Vid->frame_pic[rd_pass], rd_qp); #if (DBG_IMAGE_MP) printf("rd_pass = %d, selection = %d\n", rd_pass, selection); #endif if (selection) { swap_frame_buffer(p_Vid, 0, rd_pass); store_coding_and_rc_info(p_Vid, &coding_info); best_method = FRAME_QP; } rd_pass++; if(rd_pass >= p_Inp->RDPictureMaxPassPSlice) { frame_picture_mp_exit(p_Vid, &coding_info); return; } } frame_picture_mp_exit(p_Vid, &coding_info); }
/*! ************************************************************************ * \brief * Interpret GOP struct from input parameters ************************************************************************ */ void interpret_gop_structure(VideoParameters *p_Vid, InputParameters *p_Inp) { int nLength = (int) strlen(p_Inp->ExplicitHierarchyFormat); int i =0, k, dqp, display_no; int slice_read =0, order_read = 0, stored_read = 0, qp_read =0; int coded_frame = 0; int tlyr, temporal_layer_read = 0; if (nLength > 0) { for (i = 0; i < nLength ; i++) { //! First lets read slice type if (slice_read == 0) { switch (p_Inp->ExplicitHierarchyFormat[i]) { case 'P': case 'p': p_Vid->gop_structure[coded_frame].slice_type = P_SLICE; break; case 'B': case 'b': p_Vid->gop_structure[coded_frame].slice_type = B_SLICE; break; case 'I': case 'i': p_Vid->gop_structure[coded_frame].slice_type = I_SLICE; break; default: snprintf(errortext, ET_SIZE, "Slice Type invalid in ExplicitHierarchyFormat param. Please check configuration file."); error (errortext, 400); break; } slice_read = 1; } else { //! Next is Display Order if (order_read == 0) { if (isdigit((int)(*(p_Inp->ExplicitHierarchyFormat+i)))) { sscanf(p_Inp->ExplicitHierarchyFormat+i,"%d",&display_no); p_Vid->gop_structure[coded_frame].display_no = display_no; order_read = 1; if (display_no < 0 || display_no >= p_Inp->NumberBFrames) { snprintf(errortext, ET_SIZE, "Invalid Frame Order value. Frame position needs to be in [0,%d] range.",p_Inp->NumberBFrames - 1); error (errortext, 400); } for (k=0;k<coded_frame;k++) { if (p_Vid->gop_structure[k].display_no == display_no) { snprintf(errortext, ET_SIZE, "Frame Order value %d in frame %d already used for enhancement frame %d.",display_no,coded_frame,k); error (errortext, 400); } } } else { snprintf(errortext, ET_SIZE, "Slice Type needs to be followed by Display Order. Please check configuration file."); error (errortext, 400); } } else if (order_read == 1) { if (stored_read == 0 && !(isdigit((int)(*(p_Inp->ExplicitHierarchyFormat+i))))) { switch (p_Inp->ExplicitHierarchyFormat[i]) { case 'E': case 'e': p_Vid->gop_structure[coded_frame].reference_idc = NALU_PRIORITY_DISPOSABLE; p_Vid->gop_structure[coded_frame].hierarchy_layer = 0; break; case 'R': case 'r': p_Vid->gop_structure[coded_frame].reference_idc= NALU_PRIORITY_LOW; p_Vid->gop_structure[coded_frame].hierarchy_layer = 1; break; default: snprintf(errortext, ET_SIZE, "Reference_IDC invalid in ExplicitHierarchyFormat param. Please check configuration file."); error (errortext, 400); break; } stored_read = 1; } else if (stored_read == 1 && qp_read == 0) { if (isdigit((int)(*(p_Inp->ExplicitHierarchyFormat+i)))) { sscanf(p_Inp->ExplicitHierarchyFormat+i,"%d",&dqp); p_Vid->gop_structure[coded_frame].slice_qp = 0; //p_Inp->qp[ p_Vid->gop_structure[coded_frame].slice_type ]; p_Vid->gop_structure[coded_frame].slice_qp = iClip3(-p_Vid->bitdepth_luma_qp_scale, 51,p_Vid->gop_structure[coded_frame].slice_qp + dqp); qp_read = 1; } else { snprintf(errortext, ET_SIZE, "Reference_IDC needs to be followed by QP. Please check configuration file."); error (errortext, 400); } } else if (stored_read == 1 && qp_read == 1 && temporal_layer_read == 0) { if (!(isdigit((int)(*(p_Inp->ExplicitHierarchyFormat+i))))) { if (p_Inp->ExplicitHierarchyFormat[i] == 't' || p_Inp->ExplicitHierarchyFormat[i] == 'T') { p_Vid->gop_structure[coded_frame].temporal_layer = 0; if (isdigit((int)(*(p_Inp->ExplicitHierarchyFormat+i+1)))) { sscanf(p_Inp->ExplicitHierarchyFormat+i+1,"%d",&tlyr); p_Vid->gop_structure[coded_frame].temporal_layer = tlyr; i++; // temporal layer number is specified } } else { i--; // temporal layer is optional and it is not specified } } temporal_layer_read = 1; } else if (stored_read == 1 && qp_read == 1 && temporal_layer_read == 1 && !(isdigit((int)(*(p_Inp->ExplicitHierarchyFormat+i)))) && (i < nLength - 3)) { stored_read =0; qp_read=0; order_read=0; slice_read=0; temporal_layer_read=0; i--; coded_frame ++; if (coded_frame >= p_Inp->NumberBFrames ) { snprintf(errortext, ET_SIZE, "Total number of frames in Enhancement GOP need to be fewer or equal to NumberBFrames parameter."); error (errortext, 400); } } } } } } else { snprintf(errortext, ET_SIZE, "ExplicitHierarchyFormat is empty. Please check configuration file."); error (errortext, 400); } p_Inp->NumberBFrames = coded_frame + 1; }
int residual_transform_quant_luma_8x8_ls(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra) { VideoParameters *p_Vid = currMB->p_Vid; int i,j,coeff_ctr; int scan_pos = 0,run = -1; int nonzero = FALSE; int block_x = 8*(b8 & 0x01); int block_y = 8*(b8 >> 1); int pl_off = b8 + (pl<<2); Slice *currSlice = currMB->p_Slice; int* ACLevel = currSlice->cofAC[pl_off][0][0]; int* ACRun = currSlice->cofAC[pl_off][0][1]; imgpel **img_enc = p_Vid->enc_picture->p_curr_img; imgpel **mb_pred = currSlice->mb_pred[pl]; int **mb_ores = currSlice->mb_ores[pl]; int **mb_rres = currSlice->mb_rres[pl]; int scan_poss[4] = { 0 }, runs[4] = { -1, -1, -1, -1 }; int MCcoeff = 0; int *m7; int is_cavlc = (currSlice->symbol_mode == CAVLC); const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN8x8 : SNGL_SCAN8x8; int **fadjust8x8 = p_Vid->AdaptiveRounding ? (&p_Vid->ARCofAdj8x8[pl][currMB->ar_mode][block_y]) :NULL; runs[0]=runs[1]=runs[2]=runs[3]=-1; scan_poss[0] = scan_poss[1] = scan_poss[2] = scan_poss[3] = 0; if( (currMB->ipmode_DPCM < 2)&&(intra)) { Residual_DPCM_8x8(currMB->ipmode_DPCM, mb_ores, mb_rres, block_y, block_x); } else { for (j = block_y ; j < block_y + BLOCK_SIZE_8x8 ; j ++) for (i = block_x ; i < block_x + BLOCK_SIZE_8x8 ; i ++) mb_rres[j][i] = mb_ores[j][i] ; } for (coeff_ctr=0; coeff_ctr < 64; coeff_ctr++) { i=pos_scan[coeff_ctr][0]; j=pos_scan[coeff_ctr][1]; run++; if (currMB->luma_transform_size_8x8_flag && is_cavlc) { MCcoeff = (coeff_ctr & 3); runs[MCcoeff]++; } m7 = &mb_rres[block_y + j][block_x + i]; if (p_Vid->AdaptiveRounding) { fadjust8x8[j][block_x+i] = 0; } if (*m7 != 0) { nonzero = TRUE; if (currMB->luma_transform_size_8x8_flag && is_cavlc) { *m7 = iClip3(-CAVLC_LEVEL_LIMIT, CAVLC_LEVEL_LIMIT, *m7); *coeff_cost += MAX_VALUE; currSlice->cofAC[pl_off][MCcoeff][0][scan_poss[MCcoeff] ] = *m7; currSlice->cofAC[pl_off][MCcoeff][1][scan_poss[MCcoeff]++] = runs[MCcoeff]; ++scan_pos; runs[MCcoeff]=-1; } else { *coeff_cost += MAX_VALUE; ACLevel[scan_pos ] = *m7; ACRun [scan_pos++] = run; run=-1; // reset zero level counter } } } if (!currMB->luma_transform_size_8x8_flag || !is_cavlc) ACLevel[scan_pos] = 0; else { for(i=0; i<4; i++) currSlice->cofAC[pl_off][i][0][scan_poss[i]] = 0; } if( (currMB->ipmode_DPCM < 2) && (intra)) { Inv_Residual_DPCM_8x8(currMB, mb_rres, block_y, block_x); } for( j=block_y; j<block_y + BLOCK_SIZE_8x8; j++) { for( i=block_x; i< block_x + BLOCK_SIZE_8x8; i++) { mb_rres[j][i] += (int) mb_pred[j][i]; img_enc[currMB->pix_y + j][currMB->pix_x + i]= (imgpel) mb_rres[j][i]; } } // Decoded block moved to frame memory return nonzero; }