/*! ************************************************************************ * \brief * Write out unpaired fields from output buffer. * \param p_out * Output file ************************************************************************ */ void flush_direct_output(FILE *p_out) { write_unpaired_field(out_buffer, p_out); free_storable_picture(out_buffer->frame); out_buffer->frame = NULL; free_storable_picture(out_buffer->top_field); out_buffer->top_field = NULL; free_storable_picture(out_buffer->bottom_field); out_buffer->bottom_field = NULL; out_buffer->is_used = 0; }
/*! ************************************************************************ * \brief * Directly output a picture without storing it in the DPB. Fields * are buffered before they are written to the file. * \param p * Picture for output * \param p_out * Output file ************************************************************************ */ void direct_output(StorablePicture *p, FILE *p_out) { if (p->structure==FRAME) { // we have a frame (or complementary field pair) // so output it directly flush_direct_output(p_out); write_picture (p, p_out, FRAME); if (p_ref) find_snr(snr, p, p_ref); free_storable_picture(p); return; } if (p->structure == TOP_FIELD) { if (out_buffer->is_used &1) flush_direct_output(p_out); out_buffer->top_field = p; out_buffer->is_used |= 1; } if (p->structure == BOTTOM_FIELD) { if (out_buffer->is_used &2) flush_direct_output(p_out); out_buffer->bottom_field = p; out_buffer->is_used |= 2; } if (out_buffer->is_used == 3) { // we have both fields, so output them dpb_combine_field(out_buffer); write_picture (out_buffer->frame, p_out, FRAME); if (p_ref) find_snr(snr, out_buffer->frame, p_ref); free_storable_picture(out_buffer->frame); out_buffer->frame = NULL; free_storable_picture(out_buffer->top_field); out_buffer->top_field = NULL; free_storable_picture(out_buffer->bottom_field); out_buffer->bottom_field = NULL; out_buffer->is_used = 0; } }
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); }