| /*! | |
| ************************************************************************************* | |
| * \file image.c | |
| * | |
| * \brief | |
| * Code one image/slice | |
| * | |
| * \author | |
| * Main contributors (see contributors.h for copyright, address and affiliation details) | |
| * - Inge Lille-Langoy <inge.lille-langoy@telenor.com> | |
| * - Rickard Sjoberg <rickard.sjoberg@era.ericsson.se> | |
| * - Jani Lainema <jani.lainema@nokia.com> | |
| * - Sebastian Purreiter <sebastian.purreiter@mch.siemens.de> | |
| * - Byeong-Moon Jeon <jeonbm@lge.com> | |
| * - Yoon-Seong Soh <yunsung@lge.com> | |
| * - Thomas Stockhammer <stockhammer@ei.tum.de> | |
| * - Detlev Marpe <marpe@hhi.de> | |
| * - Guido Heising <heising@hhi.de> | |
| * - Thomas Wedi <wedi@tnt.uni-hannover.de> | |
| * - Ragip Kurceren <ragip.kurceren@nokia.com> | |
| * - Antti Hallapuro <antti.hallapuro@nokia.com> | |
| * - Alexis Michael Tourapis <alexismt@ieee.org> | |
| * - Athanasios Leontaris <aleon@dolby.com> | |
| ************************************************************************************* | |
| */ | |
| #include "contributors.h" | |
| #include <stdlib.h> | |
| #include <math.h> | |
| #include <time.h> | |
| #include <sys/timeb.h> | |
| #include <string.h> | |
| #include <memory.h> | |
| #include <assert.h> | |
| #include "global.h" | |
| #include "refbuf.h" | |
| #include "mbuffer.h" | |
| #include "img_luma.h" | |
| #include "img_chroma.h" | |
| #include "intrarefresh.h" | |
| #include "fmo.h" | |
| #include "sei.h" | |
| #include "memalloc.h" | |
| #include "nalu.h" | |
| #include "ratectl.h" | |
| #include "rc_quadratic.h" | |
| #include "mb_access.h" | |
| #include "output.h" | |
| #include "cabac.h" | |
| #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) | |
| #include <sys/time.h> | |
| int ftime(struct timeb *tp) | |
| { | |
| struct timeval tv; | |
| struct timezone tz; | |
| gettimeofday(&tv, &tz); | |
| tp->time = tv.tv_sec; | |
| tp->millitm = tv.tv_usec / 1000; | |
| tp->timezone = tz.tz_minuteswest; | |
| tp->dstflag = tz.tz_dsttime; | |
| } | |
| #endif | |
| extern pic_parameter_set_rbsp_t *PicParSet[MAXPPS]; | |
| void code_a_picture(Picture *pic); | |
| void frame_picture (Picture *frame, int method); | |
| void field_picture(Picture *top, Picture *bottom); | |
| static int writeout_picture(Picture *pic); | |
| static int picture_structure_decision(Picture *frame, Picture *top, Picture *bot); | |
| static void distortion_fld (float *dis_fld_y, float *dis_fld_u, float *dis_fld_v); | |
| static void find_snr(void); | |
| static void find_distortion(void); | |
| static void field_mode_buffer(int bit_field, float snr_field_y, float snr_field_u, float snr_field_v); | |
| static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame_u, float snr_frame_v); | |
| static void init_frame(void); | |
| static void init_field(void); | |
| static void put_buffer_frame(void); | |
| static void put_buffer_top(void); | |
| static void put_buffer_bot(void); | |
| static void copy_motion_vectors_MB(void); | |
| static void PaddAutoCropBorders (int org_size_x, int org_size_y, int img_size_x, int img_size_y, | |
| int org_size_x_cr, int org_size_y_cr, int img_size_x_cr, int img_size_y_cr); | |
| static void ReadOneFrame (int FrameNoInFile, int HeaderSize, int xs, int ys, int xs_cr, int ys_cr); | |
| static void writeUnit(Bitstream* currStream ,int partition); | |
| static void rdPictureCoding(void); | |
| #ifdef _ADAPT_LAST_GROUP_ | |
| int *last_P_no; | |
| int *last_P_no_frm; | |
| int *last_P_no_fld; | |
| #endif | |
| static void ReportFirstframe(time_t tmp_time, time_t me_time); | |
| static void ReportIntra(time_t tmp_time, time_t me_time); | |
| static void ReportSP(time_t tmp_time, time_t me_time); | |
| static void ReportP(time_t tmp_time, time_t me_time); | |
| static void ReportB(time_t tmp_time, time_t me_time); | |
| static void ReportNALNonVLCBits(time_t tmp_time, time_t me_time); | |
| static int CalculateFrameNumber(void); // Calculates the next frame number | |
| StorablePicture *enc_picture; | |
| StorablePicture *enc_frame_picture; | |
| StorablePicture *enc_frame_picture2; | |
| StorablePicture *enc_frame_picture3; | |
| StorablePicture *enc_top_picture; | |
| StorablePicture *enc_bottom_picture; | |
| //Rate control | |
| int QP; | |
| void MbAffPostProc(void) | |
| { | |
| imgpel temp[32][16]; | |
| imgpel ** imgY = enc_picture->imgY; | |
| imgpel ***imgUV = enc_picture->imgUV; | |
| int i, y, x0, y0, uv; | |
| if (img->yuv_format != YUV400) | |
| { | |
| for (i=0; i<(int)img->PicSizeInMbs; i+=2) | |
| { | |
| if (enc_picture->mb_field[i]) | |
| { | |
| get_mb_pos(i, &x0, &y0, IS_LUMA); | |
| for (y=0; y<(2*MB_BLOCK_SIZE);y++) | |
| memcpy(&temp[y],&imgY[y0+y][x0], MB_BLOCK_SIZE * sizeof(imgpel)); | |
| for (y=0; y<MB_BLOCK_SIZE;y++) | |
| { | |
| memcpy(&imgY[y0+(2*y)][x0],temp[y], MB_BLOCK_SIZE * sizeof(imgpel)); | |
| memcpy(&imgY[y0+(2*y + 1)][x0],temp[y+ MB_BLOCK_SIZE], MB_BLOCK_SIZE * sizeof(imgpel)); | |
| } | |
| x0 = x0 / (16/img->mb_cr_size_x); | |
| y0 = y0 / (16/img->mb_cr_size_y); | |
| for (uv=0; uv<2; uv++) | |
| { | |
| for (y=0; y<(2*img->mb_cr_size_y);y++) | |
| memcpy(&temp[y],&imgUV[uv][y0+y][x0], img->mb_cr_size_x * sizeof(imgpel)); | |
| for (y=0; y<img->mb_cr_size_y;y++) | |
| { | |
| memcpy(&imgUV[uv][y0+(2*y)][x0],temp[y], img->mb_cr_size_x * sizeof(imgpel)); | |
| memcpy(&imgUV[uv][y0+(2*y + 1)][x0],temp[y+ img->mb_cr_size_y], img->mb_cr_size_x * sizeof(imgpel)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| for (i=0; i<(int)img->PicSizeInMbs; i+=2) | |
| { | |
| if (enc_picture->mb_field[i]) | |
| { | |
| get_mb_pos(i, &x0, &y0, IS_LUMA); | |
| for (y=0; y<(2*MB_BLOCK_SIZE);y++) | |
| memcpy(&temp[y],&imgY[y0+y][x0], MB_BLOCK_SIZE * sizeof(imgpel)); | |
| for (y=0; y<MB_BLOCK_SIZE;y++) | |
| { | |
| memcpy(&imgY[y0+(2*y)][x0],temp[y], MB_BLOCK_SIZE * sizeof(imgpel)); | |
| memcpy(&imgY[y0+(2*y + 1)][x0],temp[y+ MB_BLOCK_SIZE], MB_BLOCK_SIZE * sizeof(imgpel)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Encodes a picture | |
| * | |
| * This is the main picture coding loop.. It is called by all this | |
| * frame and field coding stuff after the img-> elements have been | |
| * set up. Not sure whether it is useful for MB-adaptive frame/field | |
| * coding | |
| ************************************************************************ | |
| */ | |
| void code_a_picture(Picture *pic) | |
| { | |
| unsigned int NumberOfCodedMBs = 0; | |
| int SliceGroup = 0; | |
| int j; | |
| int intra_refresh = input->intra_period == 0 ? (IMG_NUMBER == 0) : ((IMG_NUMBER%input->intra_period) == 0); | |
| img->currentPicture = pic; | |
| img->currentPicture->idr_flag = ((!IMG_NUMBER) && (!(img->structure==BOTTOM_FIELD))) | |
| || (input->idr_enable && intra_refresh && (img->type == I_SLICE || img->type==SI_SLICE)&& (!(img->structure==BOTTOM_FIELD))); | |
| pic->no_slices = 0; | |
| pic->distortion_u = pic->distortion_v = pic->distortion_y = 0.0; | |
| RandomIntraNewPicture (); //! Allocates forced INTRA MBs (even for fields!) | |
| // The slice_group_change_cycle can be changed here. | |
| // FmoInit() is called before coding each picture, frame or field | |
| img->slice_group_change_cycle=1; | |
| FmoInit(img, active_pps, active_sps); | |
| FmoStartPicture (); //! picture level initialization of FMO | |
| CalculateQuantParam(); | |
| CalculateOffsetParam(); | |
| if(input->Transform8x8Mode) | |
| { | |
| CalculateQuant8Param(); | |
| CalculateOffset8Param(); | |
| } | |
| reset_pic_bin_count(); | |
| img->bytes_in_picture = 0; | |
| while (NumberOfCodedMBs < img->PicSizeInMbs) // loop over slices | |
| { | |
| // Encode one SLice Group | |
| while (!FmoSliceGroupCompletelyCoded (SliceGroup)) | |
| { | |
| // Encode the current slice | |
| NumberOfCodedMBs += encode_one_slice (SliceGroup, pic, NumberOfCodedMBs); | |
| FmoSetLastMacroblockInSlice (img->current_mb_nr); | |
| // Proceed to next slice | |
| img->current_slice_nr++; | |
| stats->bit_slice = 0; | |
| } | |
| // Proceed to next SliceGroup | |
| SliceGroup++; | |
| } | |
| FmoEndPicture (); | |
| // Modified for Fast Mode Decision. Inchoon Choi, SungKyunKwan Univ. | |
| if (input->rdopt == 3 && (img->type != B_SLICE)) | |
| for (j = 0; j < input->NoOfDecoders; j++) | |
| DeblockFrame (img, decs->decY_best[j], NULL); | |
| DeblockFrame (img, enc_picture->imgY, enc_picture->imgUV); //comment out to disable loop filter | |
| if (img->MbaffFrameFlag) | |
| MbAffPostProc(); | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Encodes one frame | |
| ************************************************************************ | |
| */ | |
| int encode_one_frame (void) | |
| { | |
| static int prev_frame_no = 0; // POC200301 | |
| static int consecutive_non_reference_pictures = 0; // POC200301 | |
| int FrameNumberInFile; | |
| int i, j; | |
| #ifdef _LEAKYBUCKET_ | |
| //extern long Bit_Buffer[20000]; | |
| extern unsigned long total_frame_buffer; | |
| #endif | |
| time_t ltime1; | |
| time_t ltime2; | |
| struct TIMEB tstruct1; | |
| struct TIMEB tstruct2; | |
| time_t tmp_time; | |
| int bits_frm = 0, bits_fld = 0; | |
| float dis_frm = 0.0, dis_frm_y = 0.0, dis_frm_u = 0.0, dis_frm_v = 0.0; | |
| float dis_fld = 0.0, dis_fld_y = 0.0, dis_fld_u = 0.0, dis_fld_v = 0.0; | |
| //Rate control | |
| int pic_type, bits = 0; | |
| me_time=0; | |
| img->rd_pass = 0; | |
| enc_frame_picture = NULL; | |
| enc_frame_picture2 = NULL; | |
| enc_frame_picture3 = NULL; | |
| ftime (&tstruct1); // start time ms | |
| time (<ime1); // start time s | |
| //Rate control | |
| img->write_macroblock = 0; | |
| /* | |
| //Shankar Regunathan (Oct 2002) | |
| //Prepare Panscanrect SEI payload | |
| UpdatePanScanRectInfo (); | |
| //Prepare Arbitrarydata SEI Payload | |
| UpdateUser_data_unregistered (); | |
| //Prepare Registered data SEI Payload | |
| UpdateUser_data_registered_itu_t_t35 (); | |
| //Prepare RandomAccess SEI Payload | |
| UpdateRandomAccess (); | |
| */ | |
| if (input->ResendPPS && img->number !=0) | |
| { | |
| stats->bit_ctr_parametersets_n=write_PPS(0, 0); | |
| stats->bit_ctr_parametersets += stats->bit_ctr_parametersets_n; | |
| } | |
| put_buffer_frame (); // sets the pointers to the frame structures | |
| // (and not to one of the field structures) | |
| init_frame (); | |
| FrameNumberInFile = CalculateFrameNumber(); | |
| ReadOneFrame (FrameNumberInFile, input->infile_header, | |
| input->img_width, input->img_height, input->img_width_cr, input->img_height_cr); | |
| PaddAutoCropBorders (input->img_width, input->img_height, img->width, img->height, | |
| input->img_width_cr, input->img_height_cr, img->width_cr, img->height_cr); | |
| // set parameters for direct mode and deblocking filter | |
| img->direct_spatial_mv_pred_flag = input->direct_spatial_mv_pred_flag; | |
| img->LFDisableIdc = input->LFDisableIdc; | |
| img->LFAlphaC0Offset = input->LFAlphaC0Offset; | |
| img->LFBetaOffset = input->LFBetaOffset; | |
| img->AdaptiveRounding = input->AdaptiveRounding; | |
| // Following code should consider optimal coding mode. Currently also does not support | |
| // multiple slices per frame. | |
| frame_ctr[img->type]++; | |
| snr->frame_ctr++; | |
| if(img->type == SP_SLICE) | |
| { | |
| if(input->sp2_frame_indicator) | |
| { // switching SP frame encoding | |
| sp2_frame_indicator=1; | |
| read_SP_coefficients(); | |
| } | |
| } | |
| else | |
| { | |
| sp2_frame_indicator=0; | |
| } | |
| if (input->PicInterlace == FIELD_CODING) | |
| { | |
| //Rate control | |
| if ( input->RCEnable ) | |
| generic_RC->FieldControl=1; | |
| img->field_picture = 1; // we encode fields | |
| field_picture (top_pic, bottom_pic); | |
| img->fld_flag = 1; | |
| } | |
| else | |
| { | |
| int tmpFrameQP; | |
| //Rate control | |
| if ( input->RCEnable ) | |
| generic_RC->FieldControl=0; | |
| // For frame coding, turn MB level field/frame coding flag on | |
| if (input->MbInterlace) | |
| mb_adaptive = 1; | |
| img->field_picture = 0; // we encode a frame | |
| //Rate control | |
| if(input->RCEnable) | |
| { | |
| /*update the number of MBs in the basic unit for MB adaptive | |
| f/f coding*/ | |
| if( (input->MbInterlace) && (input->basicunit < img->FrameSizeInMbs) && (img->type == P_SLICE || input->RCUpdateMode == RC_MODE_1) && (IMG_NUMBER) ) | |
| img->BasicUnit = input->basicunit << 1; | |
| else | |
| img->BasicUnit = input->basicunit; | |
| if ( input->RDPictureDecision ) | |
| { | |
| // store rate allocation quadratic... | |
| copy_rc_jvt( quadratic_RC_init, quadratic_RC ); | |
| // ...and generic model | |
| copy_rc_generic( generic_RC_init, generic_RC ); | |
| } | |
| rc_init_pict(quadratic_RC, 1,0,1, 1.0F); | |
| img->qp = updateQP(quadratic_RC, 0); | |
| pic_type = img->type; | |
| QP =0; | |
| if( active_sps->frame_mbs_only_flag) | |
| generic_RC->TopFieldFlag=0; | |
| } | |
| if (input->GenerateMultiplePPS) | |
| active_pps = PicParSet[0]; | |
| frame_picture (frame_pic_1, 0); | |
| if ((input->RDPictureIntra || img->type!=I_SLICE) && input->RDPictureDecision) | |
| { | |
| rdPictureCoding(); | |
| } | |
| tmpFrameQP = img->SumFrameQP; // call it here since rdPictureCoding buffers it and may modify it | |
| if(img->type==SP_SLICE && si_frame_indicator==0 && input->si_frame_indicator) | |
| { | |
| // once the picture has been encoded as a primary SP frame encode as an SI frame | |
| si_frame_indicator=1; | |
| frame_picture (frame_pic_si, 0); | |
| } | |
| if(img->type==SP_SLICE && input->sp_output_indicator) | |
| { | |
| // output the transformed and quantized coefficients (useful for switching SP frames) | |
| output_SP_coefficients(); | |
| } | |
| // For field coding, turn MB level field/frame coding flag off | |
| if (input->MbInterlace) | |
| mb_adaptive = 0; | |
| if (input->PicInterlace == ADAPTIVE_CODING) | |
| { | |
| //Rate control | |
| if ( input->RCEnable ) | |
| generic_RC->FieldControl=1; | |
| img->write_macroblock = 0; | |
| img->bot_MB = 0; | |
| img->field_picture = 1; // we encode fields | |
| field_picture (top_pic, bottom_pic); | |
| //! Note: the distortion for a field coded picture is stored in the top field | |
| //! the distortion values in the bottom field are dummies | |
| dis_fld = top_pic->distortion_y + top_pic->distortion_u + top_pic->distortion_v; | |
| dis_frm = frame_pic_1->distortion_y + frame_pic_1->distortion_u + frame_pic_1->distortion_v; | |
| if(img->rd_pass==0) | |
| img->fld_flag = picture_structure_decision (frame_pic_1, top_pic, bottom_pic); | |
| else if(img->rd_pass==1) | |
| img->fld_flag = picture_structure_decision (frame_pic_2, top_pic, bottom_pic); | |
| else | |
| img->fld_flag = picture_structure_decision (frame_pic_3, top_pic, bottom_pic); | |
| if ( img->fld_flag ) | |
| tmpFrameQP = img->SumFrameQP; | |
| update_field_frame_contexts (img->fld_flag); | |
| //Rate control | |
| if ( input->RCEnable ) | |
| { | |
| generic_RC->FieldFrame = !(img->fld_flag) ? 1 : 0; | |
| } | |
| } | |
| else | |
| img->fld_flag = 0; | |
| img->SumFrameQP = tmpFrameQP; | |
| } | |
| if (img->fld_flag) | |
| stats->bit_ctr_emulationprevention += stats->em_prev_bits_fld; | |
| else | |
| stats->bit_ctr_emulationprevention += stats->em_prev_bits_frm; | |
| if (img->type != B_SLICE) | |
| { | |
| img->pstruct_next_P = img->fld_flag; | |
| } | |
| // Here, img->structure may be either FRAME or BOTTOM FIELD depending on whether AFF coding is used | |
| // The picture structure decision changes really only the fld_flag | |
| if (img->fld_flag) // field mode (use field when fld_flag=1 only) | |
| { | |
| field_mode_buffer (bits_fld, dis_fld_y, dis_fld_u, dis_fld_v); | |
| writeout_picture (top_pic); | |
| writeout_picture (bottom_pic); | |
| } | |
| else //frame mode | |
| { | |
| frame_mode_buffer (bits_frm, dis_frm_y, dis_frm_u, dis_frm_v); | |
| if (input->RDPictureDecision && img->rd_pass == 2) | |
| writeout_picture (frame_pic_3); | |
| else if (input->RDPictureDecision && img->rd_pass == 1) | |
| writeout_picture (frame_pic_2); | |
| else | |
| if(img->type==SP_SLICE && si_frame_indicator==1) | |
| { | |
| writeout_picture (frame_pic_si); | |
| si_frame_indicator=0; | |
| } | |
| else | |
| writeout_picture (frame_pic_1); | |
| } | |
| if (frame_pic_si) | |
| free_slice_list(frame_pic_si); | |
| if (frame_pic_3) | |
| free_slice_list(frame_pic_3); | |
| if (frame_pic_2) | |
| free_slice_list(frame_pic_2); | |
| if (frame_pic_1) | |
| free_slice_list(frame_pic_1); | |
| if (top_pic) | |
| free_slice_list(top_pic); | |
| if (bottom_pic) | |
| free_slice_list(bottom_pic); | |
| /* | |
| // Tian Dong (Sept 2002) | |
| // in frame mode, the newly reconstructed frame has been inserted to the mem buffer | |
| // and it is time to prepare the spare picture SEI payload. | |
| if (input->InterlaceCodingOption == FRAME_CODING | |
| && input->SparePictureOption && img->type != B_SLICE) | |
| CalculateSparePicture (); | |
| */ | |
| //Rate control | |
| if(input->RCEnable) | |
| { | |
| bits = (int) (stats->bit_ctr - stats->bit_ctr_n); | |
| rc_update_pict_frame(quadratic_RC, bits); | |
| } | |
| if (input->PicInterlace == FRAME_CODING) | |
| { | |
| if (input->rdopt == 3 && img->type != B_SLICE) | |
| UpdateDecoders (); // simulate packet losses and move decoded image to reference buffers | |
| if (input->RestrictRef) | |
| UpdatePixelMap (); | |
| } | |
| if (input->Verbose != 0) | |
| find_snr (); | |
| else | |
| { | |
| snr->snr_y = 0.0; | |
| snr->snr_u = 0.0; | |
| snr->snr_v = 0.0; | |
| snr->sse_y = 0.0; | |
| snr->sse_u = 0.0; | |
| snr->sse_v = 0.0; | |
| } | |
| // redundant pictures: save reconstruction to calculate SNR and replace reference picture | |
| if(input->redundant_pic_flag && key_frame) | |
| { | |
| for(i=0; i<img->width; i++) | |
| { | |
| for(j=0; j<img->height; j++) | |
| { | |
| imgY_tmp[j][i] = enc_frame_picture->imgY[j][i]; | |
| } | |
| } | |
| for(i=0; i<img->width_cr; i++) | |
| { | |
| for(j=0; j<img->height_cr; j++) | |
| { | |
| imgUV_tmp[0][j][i] = enc_frame_picture->imgUV[0][j][i]; | |
| imgUV_tmp[1][j][i] = enc_frame_picture->imgUV[1][j][i]; | |
| } | |
| } | |
| } | |
| if(input->redundant_pic_flag && redundant_coding) | |
| { | |
| for(i=0; i<img->width; i++) | |
| { | |
| for(j=0; j<img->height; j++) | |
| { | |
| enc_frame_picture->imgY[j][i] = imgY_tmp[j][i]; | |
| } | |
| } | |
| for(i=0; i<img->width_cr; i++) | |
| { | |
| for(j=0; j<img->height_cr; j++) | |
| { | |
| enc_frame_picture->imgUV[0][j][i] = imgUV_tmp[0][j][i]; | |
| enc_frame_picture->imgUV[1][j][i] = imgUV_tmp[1][j][i]; | |
| } | |
| } | |
| } | |
| time (<ime2); // end time sec | |
| ftime (&tstruct2); // end time ms | |
| tmp_time = (ltime2 * 1000 + tstruct2.millitm) - (ltime1 * 1000 + tstruct1.millitm); | |
| tot_time = tot_time + tmp_time; | |
| if (input->PicInterlace == ADAPTIVE_CODING) | |
| { | |
| if (img->fld_flag) | |
| { | |
| // store bottom field | |
| store_picture_in_dpb(enc_bottom_picture); | |
| free_storable_picture(enc_frame_picture); | |
| } | |
| else | |
| { | |
| // replace top with frame | |
| replace_top_pic_with_frame(enc_frame_picture); | |
| free_storable_picture(enc_bottom_picture); | |
| } | |
| } | |
| else | |
| { | |
| if (img->fld_flag) | |
| { | |
| store_picture_in_dpb(enc_bottom_picture); | |
| } | |
| else | |
| { | |
| if (img->rd_pass==2) | |
| { | |
| store_picture_in_dpb(enc_frame_picture3); | |
| free_storable_picture(enc_frame_picture); | |
| free_storable_picture(enc_frame_picture2); | |
| } | |
| else if (img->rd_pass==1) | |
| { | |
| store_picture_in_dpb(enc_frame_picture2); | |
| free_storable_picture(enc_frame_picture); | |
| free_storable_picture(enc_frame_picture3); | |
| } | |
| else | |
| { | |
| if(input->redundant_pic_flag==0) | |
| { | |
| store_picture_in_dpb(enc_frame_picture); | |
| free_storable_picture(enc_frame_picture2); | |
| free_storable_picture(enc_frame_picture3); | |
| } | |
| else | |
| { | |
| // key picture will be stored in dpb after redundant picture is coded | |
| if(key_frame==0) | |
| { | |
| store_picture_in_dpb(enc_frame_picture); | |
| free_storable_picture(enc_frame_picture2); | |
| free_storable_picture(enc_frame_picture3); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| img->AverageFrameQP = (img->SumFrameQP + (img->FrameSizeInMbs >> 1))/img->FrameSizeInMbs; | |
| if ( input->RCEnable && img->type != B_SLICE && input->basicunit < img->FrameSizeInMbs ) | |
| quadratic_RC->CurrLastQP = img->AverageFrameQP; | |
| #ifdef _LEAKYBUCKET_ | |
| // Store bits used for this frame and increment counter of no. of coded frames | |
| Bit_Buffer[total_frame_buffer] = (int) (stats->bit_ctr - stats->bit_ctr_n); | |
| total_frame_buffer++; | |
| #endif | |
| // POC200301: Verify that POC coding type 2 is not used if more than one consecutive | |
| // non-reference frame is requested or if decoding order is different from output order | |
| if (img->pic_order_cnt_type == 2) | |
| { | |
| if (!img->nal_reference_idc) consecutive_non_reference_pictures++; | |
| else consecutive_non_reference_pictures = 0; | |
| if (frame_no < prev_frame_no || consecutive_non_reference_pictures>1) | |
| error("POC type 2 cannot be applied for the coding pattern where the encoding /decoding order of pictures are different from the output order.\n", -1); | |
| prev_frame_no = frame_no; | |
| } | |
| if (stats->bit_ctr_parametersets_n!=0) | |
| ReportNALNonVLCBits(tmp_time, me_time); | |
| if (IMG_NUMBER == 0) | |
| ReportFirstframe(tmp_time,me_time); | |
| else | |
| { | |
| //Rate control | |
| if(input->RCEnable) | |
| { | |
| if((!input->PicInterlace)&&(!input->MbInterlace)) | |
| bits=(int) (stats->bit_ctr - stats->bit_ctr_n); | |
| else | |
| { | |
| bits = (int)(stats->bit_ctr - (quadratic_RC->Pprev_bits)); // used for rate control update | |
| quadratic_RC->Pprev_bits = stats->bit_ctr; | |
| } | |
| } | |
| switch (img->type) | |
| { | |
| case I_SLICE: | |
| stats->bit_ctr_I += stats->bit_ctr - stats->bit_ctr_n; | |
| ReportIntra(tmp_time,me_time); | |
| break; | |
| case SP_SLICE: | |
| stats->bit_ctr_P += stats->bit_ctr - stats->bit_ctr_n; | |
| ReportSP(tmp_time,me_time); | |
| break; | |
| case B_SLICE: | |
| stats->bit_ctr_B += stats->bit_ctr - stats->bit_ctr_n; | |
| ReportB(tmp_time,me_time); | |
| break; | |
| default: // P | |
| stats->bit_ctr_P += stats->bit_ctr - stats->bit_ctr_n; | |
| ReportP(tmp_time,me_time); | |
| } | |
| } | |
| if (input->Verbose == 0) | |
| { | |
| //for (i = 0; i <= (img->number & 0x0F); i++) | |
| //printf("."); | |
| //printf(" \r"); | |
| printf("Completed Encoding Frame %05d.\r",frame_no); | |
| } | |
| // Flush output statistics | |
| fflush(stdout); | |
| stats->bit_ctr_n = stats->bit_ctr; | |
| //Rate control | |
| if(input->RCEnable) | |
| { | |
| rc_update_pict(quadratic_RC, bits); | |
| // update the parameters of quadratic R-D model | |
| if( (img->type==P_SLICE || input->RCUpdateMode == RC_MODE_1) && (IMG_NUMBER) ) | |
| { | |
| updateRCModel(quadratic_RC); | |
| if ( input->RCUpdateMode == RC_MODE_3 ) | |
| quadratic_RC->PreviousWholeFrameMAD = ComputeFrameMAD(); | |
| } | |
| } | |
| stats->bit_ctr_parametersets_n=0; | |
| if (IMG_NUMBER == 0) | |
| return 0; | |
| else | |
| return 1; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * This function write out a picture | |
| * \return | |
| * 0 if OK, \n | |
| * 1 in case of error | |
| * | |
| ************************************************************************ | |
| */ | |
| static int writeout_picture(Picture *pic) | |
| { | |
| Bitstream *currStream; | |
| int partition, slice; | |
| Slice *currSlice; | |
| img->currentPicture=pic; | |
| for (slice=0; slice<pic->no_slices; slice++) | |
| { | |
| currSlice = pic->slices[slice]; | |
| img->current_mb_nr = currSlice->start_mb_nr; | |
| for (partition=0; partition<currSlice->max_part_nr; partition++) | |
| { | |
| currStream = (currSlice->partArr[partition]).bitstream; | |
| assert (currStream->bits_to_go == 8); //! should always be the case, the | |
| //! byte alignment is done in terminate_slice | |
| // write only if the partition has content | |
| if (currSlice->partArr[partition].bitstream->write_flag ) | |
| writeUnit (currStream,partition); | |
| } // partition loop | |
| } // slice loop | |
| return 0; | |
| } | |
| void copy_params(void) | |
| { | |
| enc_picture->frame_mbs_only_flag = active_sps->frame_mbs_only_flag; | |
| enc_picture->frame_cropping_flag = active_sps->frame_cropping_flag; | |
| enc_picture->chroma_format_idc = active_sps->chroma_format_idc; | |
| if (active_sps->frame_cropping_flag) | |
| { | |
| enc_picture->frame_cropping_rect_left_offset=active_sps->frame_cropping_rect_left_offset; | |
| enc_picture->frame_cropping_rect_right_offset=active_sps->frame_cropping_rect_right_offset; | |
| enc_picture->frame_cropping_rect_top_offset=active_sps->frame_cropping_rect_top_offset; | |
| enc_picture->frame_cropping_rect_bottom_offset=active_sps->frame_cropping_rect_bottom_offset; | |
| } | |
| else | |
| { | |
| enc_picture->frame_cropping_rect_left_offset=0; | |
| enc_picture->frame_cropping_rect_right_offset=0; | |
| enc_picture->frame_cropping_rect_top_offset=0; | |
| enc_picture->frame_cropping_rect_bottom_offset=0; | |
| } | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Encodes a frame picture | |
| ************************************************************************ | |
| */ | |
| void frame_picture (Picture *frame, int rd_pass) | |
| { | |
| img->SumFrameQP = 0; | |
| img->structure = FRAME; | |
| img->PicSizeInMbs = img->FrameSizeInMbs; | |
| if (rd_pass == 2) | |
| { | |
| enc_frame_picture3 = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr); | |
| img->ThisPOC=enc_frame_picture3->poc=img->framepoc; | |
| enc_frame_picture3->top_poc = img->toppoc; | |
| enc_frame_picture3->bottom_poc = img->bottompoc; | |
| enc_frame_picture3->frame_poc = img->framepoc; | |
| enc_frame_picture3->pic_num = img->frame_num; | |
| enc_frame_picture3->frame_num = img->frame_num; | |
| enc_frame_picture3->coded_frame = 1; | |
| enc_frame_picture3->MbaffFrameFlag = img->MbaffFrameFlag = (input->MbInterlace != FRAME_CODING); | |
| get_mb_block_pos = img->MbaffFrameFlag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal; | |
| getNeighbour = img->MbaffFrameFlag ? getAffNeighbour : getNonAffNeighbour; | |
| enc_picture=enc_frame_picture3; | |
| copy_params(); | |
| } | |
| else if (rd_pass == 1) | |
| { | |
| enc_frame_picture2 = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr); | |
| img->ThisPOC=enc_frame_picture2->poc=img->framepoc; | |
| enc_frame_picture2->top_poc = img->toppoc; | |
| enc_frame_picture2->bottom_poc = img->bottompoc; | |
| enc_frame_picture2->frame_poc = img->framepoc; | |
| enc_frame_picture2->pic_num = img->frame_num; | |
| enc_frame_picture2->frame_num = img->frame_num; | |
| enc_frame_picture2->coded_frame = 1; | |
| enc_frame_picture2->MbaffFrameFlag = img->MbaffFrameFlag = (input->MbInterlace != FRAME_CODING); | |
| get_mb_block_pos = img->MbaffFrameFlag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal; | |
| getNeighbour = img->MbaffFrameFlag ? getAffNeighbour : getNonAffNeighbour; | |
| enc_picture=enc_frame_picture2; | |
| copy_params(); | |
| } | |
| else | |
| { | |
| enc_frame_picture = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr); | |
| img->ThisPOC=enc_frame_picture->poc=img->framepoc; | |
| enc_frame_picture->top_poc = img->toppoc; | |
| enc_frame_picture->bottom_poc = img->bottompoc; | |
| enc_frame_picture->frame_poc = img->framepoc; | |
| enc_frame_picture->pic_num = img->frame_num; | |
| enc_frame_picture->frame_num = img->frame_num; | |
| enc_frame_picture->coded_frame = 1; | |
| enc_frame_picture->MbaffFrameFlag = img->MbaffFrameFlag = (input->MbInterlace != FRAME_CODING); | |
| get_mb_block_pos = img->MbaffFrameFlag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal; | |
| getNeighbour = img->MbaffFrameFlag ? getAffNeighbour : getNonAffNeighbour; | |
| enc_picture=enc_frame_picture; | |
| copy_params(); | |
| } | |
| stats->em_prev_bits_frm = 0; | |
| stats->em_prev_bits = &stats->em_prev_bits_frm; | |
| img->fld_flag = 0; | |
| code_a_picture(frame); | |
| frame->bits_per_picture = 8 * ((((img->currentSlice)->partArr[0]).bitstream)->byte_pos); | |
| if (img->structure==FRAME) | |
| { | |
| find_distortion (); | |
| frame->distortion_y = snr->snr_y; | |
| frame->distortion_u = snr->snr_u; | |
| frame->distortion_v = snr->snr_v; | |
| } | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Encodes a field picture, consisting of top and bottom field | |
| ************************************************************************ | |
| */ | |
| void field_picture (Picture *top, Picture *bottom) | |
| { | |
| //Rate control | |
| int old_pic_type; // picture type of top field used for rate control | |
| int TopFieldBits; | |
| img->SumFrameQP = 0; | |
| //Rate control | |
| old_pic_type = img->type; | |
| stats->em_prev_bits_fld = 0; | |
| stats->em_prev_bits = &stats->em_prev_bits_fld; | |
| img->number *= 2; | |
| img->buf_cycle *= 2; | |
| img->height = (input->img_height+img->auto_crop_bottom) / 2; | |
| img->height_cr = img->height_cr_frame / 2; | |
| img->fld_flag = 1; | |
| img->PicSizeInMbs = img->FrameSizeInMbs/2; | |
| // Top field | |
| enc_top_picture = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr); | |
| enc_top_picture->poc=img->toppoc; | |
| enc_top_picture->frame_poc = img->toppoc; | |
| enc_top_picture->pic_num = img->frame_num; | |
| enc_top_picture->frame_num = img->frame_num; | |
| enc_top_picture->coded_frame = 0; | |
| enc_top_picture->MbaffFrameFlag = img->MbaffFrameFlag = FALSE; | |
| get_mb_block_pos = get_mb_block_pos_normal; | |
| getNeighbour = getNonAffNeighbour; | |
| img->ThisPOC = img->toppoc; | |
| img->structure = TOP_FIELD; | |
| enc_picture = enc_top_picture; | |
| copy_params(); | |
| put_buffer_top (); | |
| init_field (); | |
| if (img->type == B_SLICE) //all I- and P-frames | |
| nextP_tr_fld--; | |
| img->fld_flag = 1; | |
| //Rate control | |
| if(input->RCEnable) | |
| { | |
| img->BasicUnit=input->basicunit; | |
| if(input->PicInterlace==FIELD_CODING) | |
| rc_init_pict(quadratic_RC, 0,1,1, 1.0F); | |
| else | |
| rc_init_pict(quadratic_RC, 0,1,0, 1.0F); | |
| img->qp = updateQP(quadratic_RC, 1); | |
| generic_RC->TopFieldFlag=1; | |
| } | |
| code_a_picture(top_pic); | |
| enc_picture->structure = (PictureStructure) 1; | |
| store_picture_in_dpb(enc_top_picture); | |
| top->bits_per_picture = 8 * ((((img->currentSlice)->partArr[0]).bitstream)->byte_pos); | |
| //Rate control | |
| TopFieldBits=top->bits_per_picture; | |
| // Bottom field | |
| enc_bottom_picture = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr); | |
| enc_bottom_picture->poc=img->bottompoc; | |
| enc_bottom_picture->frame_poc = img->bottompoc; | |
| enc_bottom_picture->pic_num = img->frame_num; | |
| enc_bottom_picture->frame_num = img->frame_num; | |
| enc_bottom_picture->coded_frame = 0; | |
| enc_bottom_picture->MbaffFrameFlag = img->MbaffFrameFlag = FALSE; | |
| get_mb_block_pos = get_mb_block_pos_normal; | |
| getNeighbour = getNonAffNeighbour; | |
| img->ThisPOC = img->bottompoc; | |
| img->structure = BOTTOM_FIELD; | |
| enc_picture = enc_bottom_picture; | |
| copy_params(); | |
| put_buffer_bot (); | |
| img->number++; | |
| init_field (); | |
| if (img->type == B_SLICE) //all I- and P-frames | |
| nextP_tr_fld++; //check once coding B field | |
| if (img->type == I_SLICE && input->IntraBottom!=1) | |
| img->type = (input->BRefPictures == 2) ? B_SLICE : P_SLICE; | |
| img->fld_flag = 1; | |
| //Rate control | |
| if(input->RCEnable) | |
| { | |
| quadratic_RC->bits_topfield = TopFieldBits; | |
| rc_init_pict(quadratic_RC, 0,0,0, 1.0F); | |
| img->qp = updateQP(quadratic_RC, 0); | |
| generic_RC->TopFieldFlag = 0; | |
| } | |
| enc_picture->structure = (PictureStructure) 2; | |
| code_a_picture(bottom_pic); | |
| bottom->bits_per_picture = 8 * ((((img->currentSlice)->partArr[0]).bitstream)->byte_pos); | |
| // the distortion for a field coded frame (consisting of top and bottom field) | |
| // lives in the top->distortion variables, the bottom-> are dummies | |
| distortion_fld (&top->distortion_y, &top->distortion_u, &top->distortion_v); | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Distortion Field | |
| ************************************************************************ | |
| */ | |
| static void distortion_fld (float *dis_fld_y, float *dis_fld_u, float *dis_fld_v) | |
| { | |
| img->number /= 2; | |
| img->buf_cycle /= 2; | |
| img->height = (input->img_height+img->auto_crop_bottom); | |
| img->height_cr = img->height_cr_frame; | |
| combine_field (); | |
| imgY_org = imgY_org_frm; | |
| imgUV_org = imgUV_org_frm; | |
| find_distortion (); // find snr from original frame picture | |
| *dis_fld_y = snr->snr_y; | |
| *dis_fld_u = snr->snr_u; | |
| *dis_fld_v = snr->snr_v; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Picture Structure Decision | |
| ************************************************************************ | |
| */ | |
| static int picture_structure_decision (Picture *frame, Picture *top, Picture *bot) | |
| { | |
| double lambda_picture; | |
| int bframe = (img->type == B_SLICE); | |
| float snr_frame, snr_field; | |
| int bit_frame, bit_field; | |
| lambda_picture = 0.68 * pow (2, img->bitdepth_lambda_scale + ((img->qp - SHIFT_QP) / 3.0)) * (bframe ? 1 : 1); | |
| snr_frame = frame->distortion_y + frame->distortion_u + frame->distortion_v; | |
| //! all distrortions of a field picture are accumulated in the top field | |
| snr_field = top->distortion_y + top->distortion_u + top->distortion_v; | |
| bit_field = top->bits_per_picture + bot->bits_per_picture; | |
| bit_frame = frame->bits_per_picture; | |
| return decide_fld_frame (snr_frame, snr_field, bit_field, bit_frame, lambda_picture); | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Field Mode Buffer | |
| ************************************************************************ | |
| */ | |
| static void field_mode_buffer (int bit_field, float snr_field_y, float snr_field_u, float snr_field_v) | |
| { | |
| put_buffer_frame (); | |
| snr->snr_y = snr_field_y; | |
| snr->snr_u = snr_field_u; | |
| snr->snr_v = snr_field_v; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Frame Mode Buffer | |
| ************************************************************************ | |
| */ | |
| static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame_u, float snr_frame_v) | |
| { | |
| put_buffer_frame (); | |
| if ((input->PicInterlace != FRAME_CODING)||(input->MbInterlace != FRAME_CODING)) | |
| { | |
| img->height = img->height / 2; | |
| img->height_cr = img->height_cr / 2; | |
| img->number *= 2; | |
| put_buffer_top (); | |
| img->number++; | |
| put_buffer_bot (); | |
| img->number /= 2; // reset the img->number to field | |
| img->height = (input->img_height+img->auto_crop_bottom); | |
| img->height_cr = img->height_cr_frame; | |
| snr->snr_y = snr_frame_y; | |
| snr->snr_u = snr_frame_u; | |
| snr->snr_v = snr_frame_v; | |
| put_buffer_frame (); | |
| } | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * mmco initializations should go here | |
| ************************************************************************ | |
| */ | |
| static void init_dec_ref_pic_marking_buffer(void) | |
| { | |
| img->dec_ref_pic_marking_buffer=NULL; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Initializes the parameters for a new frame | |
| ************************************************************************ | |
| */ | |
| static void init_frame (void) | |
| { | |
| int i; | |
| int prevP_no, nextP_no; | |
| last_P_no = last_P_no_frm; | |
| img->current_mb_nr = 0; | |
| img->current_slice_nr = 0; | |
| stats->bit_slice = 0; | |
| img->mb_y = img->mb_x = 0; | |
| img->block_y = img->pix_y = img->pix_c_y = 0; | |
| img->block_x = img->pix_x = img->block_c_x = img->pix_c_x = 0; | |
| // The 'slice_nr' of each macroblock is set to -1 here, to guarantee the correct encoding | |
| // with FMO (if no FMO, encoding is correct without following assignment), | |
| // for which MBs may not be encoded with scan order | |
| for(i=0;i< ((int) (img->FrameSizeInMbs));i++) | |
| img->mb_data[i].slice_nr=-1; | |
| if (img->b_frame_to_code == 0) | |
| { | |
| img->tr = start_tr_in_this_IGOP + IMG_NUMBER * (input->jumpd + 1); | |
| img->imgtr_last_P_frm = img->imgtr_next_P_frm; | |
| img->imgtr_next_P_frm = img->tr; | |
| #ifdef _ADAPT_LAST_GROUP_ | |
| if (input->last_frame && img->number + 1 == input->no_frames) | |
| img->tr = input->last_frame; | |
| #endif | |
| if (IMG_NUMBER != 0 && input->successive_Bframe != 0) // B pictures to encode | |
| nextP_tr_frm = img->tr; | |
| //Rate control | |
| if(!input->RCEnable) // without using rate control | |
| { | |
| if (img->type == I_SLICE) | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| img->qp = input->qp02; | |
| else | |
| #endif | |
| img->qp = input->qp0; // set quant. parameter for I-frame | |
| } | |
| else | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| img->qp = input->qpN2 + (img->nal_reference_idc ? 0 : input->DispPQPOffset); | |
| else | |
| #endif | |
| img->qp = input->qpN + (img->nal_reference_idc ? 0 : input->DispPQPOffset); | |
| if (img->type == SP_SLICE) | |
| { | |
| if ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start )) | |
| { | |
| img->qp = input->qpN2-(input->qpN-input->qpsp); | |
| img->qpsp = input->qpN2-(input->qpN-input->qpsp_pred); | |
| } | |
| else | |
| { | |
| img->qp = input->qpsp; | |
| img->qpsp = input->qpsp_pred; | |
| } | |
| } | |
| } | |
| } | |
| img->mb_y_intra = img->mb_y_upd; // img->mb_y_intra indicates which GOB to intra code for this frame | |
| if (input->intra_upd > 0) // if error robustness, find next GOB to update | |
| { | |
| img->mb_y_upd = (IMG_NUMBER / input->intra_upd) % (img->height / MB_BLOCK_SIZE); | |
| } | |
| } | |
| else | |
| { | |
| img->p_interval = input->jumpd + 1; | |
| prevP_no = start_tr_in_this_IGOP + (IMG_NUMBER - 1) * img->p_interval; | |
| nextP_no = start_tr_in_this_IGOP + (IMG_NUMBER) * img->p_interval; | |
| #ifdef _ADAPT_LAST_GROUP_ | |
| last_P_no[0] = prevP_no; | |
| for (i = 1; i < img->buf_cycle; i++) | |
| last_P_no[i] = last_P_no[i - 1] - img->p_interval; | |
| if (input->last_frame && img->number + 1 == input->no_frames) | |
| { | |
| nextP_no = input->last_frame; | |
| img->p_interval = nextP_no - prevP_no; | |
| } | |
| #endif | |
| img->b_interval = | |
| ((double) (input->jumpd + 1) / (input->successive_Bframe + 1.0) ); | |
| if (input->HierarchicalCoding == 3) | |
| img->b_interval = 1.0; | |
| if (input->HierarchicalCoding) | |
| img->tr = prevP_no + (int) (img->b_interval * (double) (1 + gop_structure[img->b_frame_to_code - 1].display_no)); // from prev_P | |
| else | |
| img->tr = prevP_no + (int) (img->b_interval * (double) img->b_frame_to_code); // from prev_P | |
| if (img->tr >= nextP_no) | |
| img->tr = nextP_no - 1; | |
| //Rate control | |
| if(!input->RCEnable && input->HierarchicalCoding == 0) // without using rate control | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| { | |
| img->qp = input->qpB2; | |
| } | |
| else | |
| #endif | |
| { | |
| img->qp = input->qpB; | |
| } | |
| if (img->nal_reference_idc) | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| { | |
| img->qp = iClip3(-img->bitdepth_luma_qp_scale,51,input->qpB2 + input->qpBRS2Offset); | |
| } | |
| else | |
| #endif | |
| { | |
| img->qp = iClip3(-img->bitdepth_luma_qp_scale,51,input->qpB + input->qpBRSOffset); | |
| } | |
| } | |
| } | |
| else if (!input->RCEnable && input->HierarchicalCoding !=0) | |
| { | |
| // Note that _CHANGE_QP_ does not anymore work for gop_structure. Needs to be fixed | |
| img->qp = gop_structure[img->b_frame_to_code - 1].slice_qp; | |
| } | |
| } | |
| img->qp_scaled = img->qp + img->bitdepth_luma_qp_scale; | |
| UpdateSubseqInfo (img->layer); // Tian Dong (Sept 2002) | |
| UpdateSceneInformation (FALSE, 0, 0, -1); // JVT-D099, scene information SEI, nothing included by default | |
| //! Commented out by StW, needs fixing in SEI.h to keep the trace file clean | |
| // PrepareAggregationSEIMessage (); | |
| img->no_output_of_prior_pics_flag = 0; | |
| img->long_term_reference_flag = 0; | |
| init_dec_ref_pic_marking_buffer(); | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Initializes the parameters for a new field | |
| ************************************************************************ | |
| */ | |
| static void init_field (void) | |
| { | |
| int i; | |
| int prevP_no, nextP_no; | |
| last_P_no = last_P_no_fld; | |
| img->current_mb_nr = 0; | |
| img->current_slice_nr = 0; | |
| stats->bit_slice = 0; | |
| input->jumpd *= 2; | |
| input->successive_Bframe *= 2; | |
| img->number /= 2; | |
| img->buf_cycle /= 2; | |
| img->mb_y = img->mb_x = 0; | |
| img->block_y = img->pix_y = img->pix_c_y = 0; // define vertical positions | |
| img->block_x = img->pix_x = img->block_c_x = img->pix_c_x = 0; // define horizontal positions | |
| if (!img->b_frame_to_code) | |
| { | |
| img->tr = img->number * (input->jumpd + 2) + img->fld_type; | |
| if (!img->fld_type) | |
| { | |
| img->imgtr_last_P_fld = img->imgtr_next_P_fld; | |
| img->imgtr_next_P_fld = img->tr; | |
| } | |
| #ifdef _ADAPT_LAST_GROUP_ | |
| if (input->last_frame && img->number + 1 == input->no_frames) | |
| img->tr = input->last_frame; | |
| #endif | |
| if (img->number != 0 && input->successive_Bframe != 0) // B pictures to encode | |
| nextP_tr_fld = img->tr; | |
| //Rate control | |
| if(!input->RCEnable) // without using rate control | |
| { | |
| if (img->type == I_SLICE) | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| img->qp = input->qp02; | |
| else | |
| #endif | |
| img->qp = input->qp0; // set quant. parameter for I-frame | |
| } | |
| else | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| img->qp = input->qpN2 + (img->nal_reference_idc ? 0 : input->DispPQPOffset); | |
| else | |
| #endif | |
| img->qp = input->qpN + (img->nal_reference_idc ? 0 : input->DispPQPOffset); | |
| if (img->type == SP_SLICE) | |
| { | |
| if ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start )) | |
| { | |
| img->qp = input->qpN2-(input->qpN-input->qpsp); | |
| img->qpsp = input->qpN2-(input->qpN-input->qpsp_pred); | |
| } | |
| else | |
| { | |
| img->qp = input->qpsp; | |
| img->qpsp = input->qpsp_pred; | |
| } | |
| } | |
| } | |
| } | |
| img->mb_y_intra = img->mb_y_upd; // img->mb_y_intra indicates which GOB to intra code for this frame | |
| if (input->intra_upd > 0) // if error robustness, find next GOB to update | |
| { | |
| img->mb_y_upd = | |
| (img->number / input->intra_upd) % (img->width / MB_BLOCK_SIZE); | |
| } | |
| } | |
| else | |
| { | |
| img->p_interval = input->jumpd + 2; | |
| prevP_no = (img->number - 1) * img->p_interval + img->fld_type; | |
| nextP_no = img->number * img->p_interval + img->fld_type; | |
| #ifdef _ADAPT_LAST_GROUP_ | |
| if (!img->fld_type) // top field | |
| { | |
| last_P_no[0] = prevP_no + 1; | |
| last_P_no[1] = prevP_no; | |
| for (i = 1; i <= img->buf_cycle; i++) | |
| { | |
| last_P_no[2 * i] = last_P_no[2 * i - 2] - img->p_interval; | |
| last_P_no[2 * i + 1] = last_P_no[2 * i - 1] - img->p_interval; | |
| } | |
| } | |
| else // bottom field | |
| { | |
| last_P_no[0] = nextP_no - 1; | |
| last_P_no[1] = prevP_no; | |
| for (i = 1; i <= img->buf_cycle; i++) | |
| { | |
| last_P_no[2 * i] = last_P_no[2 * i - 2] - img->p_interval; | |
| last_P_no[2 * i + 1] = last_P_no[2 * i - 1] - img->p_interval; | |
| } | |
| } | |
| if (input->last_frame && img->number + 1 == input->no_frames) | |
| { | |
| nextP_no = input->last_frame; | |
| img->p_interval = nextP_no - prevP_no; | |
| } | |
| #endif | |
| img->b_interval = | |
| ((double) (input->jumpd + 1) / (input->successive_Bframe + 1.0) ); | |
| if (input->HierarchicalCoding == 3) | |
| img->b_interval = 1.0; | |
| if (input->HierarchicalCoding) | |
| img->tr = prevP_no + (int) ((img->b_interval + 1.0) * (double) (1 + gop_structure[img->b_frame_to_code - 1].display_no)); // from prev_P | |
| else | |
| img->tr = prevP_no + (int) ((img->b_interval + 1.0) * (double) img->b_frame_to_code); // from prev_P | |
| if (img->tr >= nextP_no) | |
| img->tr = nextP_no - 1; // ????? | |
| //Rate control | |
| if(!input->RCEnable && input->HierarchicalCoding == 0) // without using rate control | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| { | |
| img->qp = input->qpB2; | |
| } | |
| else | |
| #endif | |
| img->qp = input->qpB; | |
| if (img->nal_reference_idc) | |
| { | |
| #ifdef _CHANGE_QP_ | |
| //QP oscillation for secondary SP frames | |
| if ((input->qp2start > 0 && img->tr >= input->qp2start && input->sp2_frame_indicator==0)|| | |
| ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start ) && (input->sp2_frame_indicator==1))) | |
| { | |
| img->qp = iClip3(-img->bitdepth_luma_qp_scale,51,input->qpB2 + input->qpBRS2Offset); | |
| } | |
| else | |
| #endif | |
| img->qp = iClip3(-img->bitdepth_luma_qp_scale,51,input->qpB + input->qpBRSOffset); | |
| } | |
| } | |
| else if (!input->RCEnable && input->HierarchicalCoding != 0) | |
| { | |
| img->qp = gop_structure[img->b_frame_to_code - 1].slice_qp; | |
| } | |
| } | |
| img->qp_scaled = img->qp + img->bitdepth_luma_qp_scale; | |
| input->jumpd /= 2; | |
| input->successive_Bframe /= 2; | |
| img->buf_cycle *= 2; | |
| img->number = 2 * img->number + img->fld_type; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Upsample 4 times, store them in out4x. Color is simply copied | |
| * | |
| * \par Input: | |
| * srcy, srcu, srcv, out4y, out4u, out4v | |
| * | |
| * \par Side Effects_ | |
| * Uses (writes) img4Y_tmp. This should be moved to a static variable | |
| * in this module | |
| ************************************************************************/ | |
| void UnifiedOneForthPix (StorablePicture *s) | |
| { | |
| int ypadded_size = s->size_y + 2 * IMG_PAD_SIZE; | |
| int xpadded_size = s->size_x + 2 * IMG_PAD_SIZE; | |
| // don't upsample twice | |
| if (s->imgY_sub) | |
| return; | |
| // Y component | |
| get_mem4Dpel (&(s->imgY_sub), 4, 4, ypadded_size, xpadded_size); | |
| if (NULL == s->imgY_sub) | |
| no_mem_exit("alloc_storable_picture: s->imgY_sub"); | |
| if ( input->ChromaMCBuffer ) | |
| { | |
| // UV components | |
| if ( img->yuv_format != YUV400 ) | |
| { | |
| if ( img->yuv_format == YUV420 ) | |
| { | |
| get_mem5Dpel (&(s->imgUV_sub), 2, 8, 8, ypadded_size/2, xpadded_size/2); | |
| } | |
| else if ( img->yuv_format == YUV422 ) | |
| { | |
| get_mem5Dpel (&(s->imgUV_sub), 2, 4, 8, ypadded_size, xpadded_size/2); | |
| } | |
| else | |
| { // YUV444 | |
| get_mem5Dpel (&(s->imgUV_sub), 2, 4, 4, ypadded_size, xpadded_size); | |
| } | |
| } | |
| } | |
| // derive the subpixel images for first component | |
| getSubImagesLuma ( s ); | |
| // and the sub-images for U and V | |
| if ( img->yuv_format != YUV400 && input->ChromaMCBuffer ) | |
| getSubImagesChroma( s ); | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Find SNR for all three components | |
| ************************************************************************ | |
| */ | |
| static void find_snr (void) | |
| { | |
| int i, j; | |
| int64 diff_y=0, diff_u=0, diff_v=0; | |
| int impix; | |
| int impix_cr; | |
| unsigned int max_pix_value_sqd = img->max_imgpel_value * img->max_imgpel_value; | |
| unsigned int max_pix_value_sqd_uv = img->max_imgpel_value_uv * img->max_imgpel_value_uv; | |
| // Calculate PSNR for Y, U and V. | |
| // Luma. | |
| impix = input->img_height * input->img_width; | |
| impix_cr = input->img_height_cr * input->img_width_cr; | |
| if (img->fld_flag != 0) | |
| { | |
| diff_y = 0; | |
| for (i = 0; i < input->img_width; ++i) | |
| { | |
| for (j = 0; j < input->img_height; ++j) | |
| { | |
| diff_y += img->quad[imgY_org[j][i] - imgY_com[j][i]]; | |
| } | |
| } | |
| if (img->yuv_format != YUV400) | |
| { | |
| // Chroma. | |
| diff_u = 0; | |
| diff_v = 0; | |
| for (i = 0; i < input->img_width_cr; i++) | |
| { | |
| for (j = 0; j < input->img_height_cr; j++) | |
| { | |
| diff_u += img->quad[imgUV_org[0][j][i] - imgUV_com[0][j][i]]; | |
| diff_v += img->quad[imgUV_org[1][j][i] - imgUV_com[1][j][i]]; | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| imgY_org = imgY_org_frm; | |
| imgUV_org = imgUV_org_frm; | |
| if(input->PicInterlace==ADAPTIVE_CODING) | |
| { | |
| enc_picture = enc_frame_picture; | |
| } | |
| diff_y = 0; | |
| for (i = 0; i < input->img_width; ++i) | |
| { | |
| for (j = 0; j < input->img_height; ++j) | |
| { | |
| diff_y += img->quad[imgY_org[j][i] - enc_picture->imgY[j][i]]; | |
| } | |
| } | |
| if (img->yuv_format != YUV400) | |
| { | |
| // Chroma. | |
| diff_u = 0; | |
| diff_v = 0; | |
| for (i = 0; i < input->img_width_cr; i++) | |
| { | |
| for (j = 0; j < input->img_height_cr; j++) | |
| { | |
| diff_u += img->quad[imgUV_org[0][j][i] - enc_picture->imgUV[0][j][i]]; | |
| diff_v += img->quad[imgUV_org[1][j][i] - enc_picture->imgUV[1][j][i]]; | |
| } | |
| } | |
| } | |
| } | |
| snr->sse_y = (float)diff_y; | |
| snr->sse_u = (float)diff_u; | |
| snr->sse_v = (float)diff_v; | |
| #if ZEROSNR | |
| if (diff_y == 0) | |
| diff_y = 1; | |
| if (diff_u == 0) | |
| diff_u = 1; | |
| if (diff_v == 0) | |
| diff_v = 1; | |
| #endif | |
| // Collecting SNR statistics | |
| if (diff_y != 0) | |
| { | |
| snr->snr_y = (float) (10 * log10 (max_pix_value_sqd * (double)((double) impix / diff_y))); // luma snr for current frame | |
| if (img->yuv_format != YUV400) | |
| { | |
| snr->snr_u = (float) (10 * log10 (max_pix_value_sqd_uv * (double)((double) impix_cr / diff_u))); // u croma snr for current frame, 1/4 of luma samples | |
| snr->snr_v = (float) (10 * log10 (max_pix_value_sqd_uv * (double)((double) impix_cr / diff_v))); // v croma snr for current frame, 1/4 of luma samples | |
| } | |
| else | |
| { | |
| snr->snr_u = 0.0; | |
| snr->snr_v = 0.0; | |
| } | |
| } | |
| if (img->number == 0) | |
| { | |
| snr->snr_y1 = snr->snr_y; // keep luma snr for first frame | |
| snr->snr_u1 = snr->snr_u; // keep croma u snr for first frame | |
| snr->snr_v1 = snr->snr_v; // keep croma v snr for first frame | |
| snr->snr_ya = snr->snr_y1; | |
| snr->snr_ua = snr->snr_u1; | |
| snr->snr_va = snr->snr_v1; | |
| // sse stats | |
| snr->msse_y = snr->sse_y; | |
| snr->msse_u = snr->sse_u; | |
| snr->msse_v = snr->sse_v; | |
| for (i=0; i<5; i++) | |
| { | |
| snr->snr_yt[i] = 0.0; | |
| snr->snr_ut[i] = 0.0; | |
| snr->snr_vt[i] = 0.0; | |
| } | |
| } | |
| else | |
| { | |
| //int total_frames = img->number + frame_ctr[B_SLICE]; | |
| int total_frames = snr->frame_ctr - 1; | |
| snr->snr_ya = (float) (snr->snr_ya * total_frames + snr->snr_y) / (total_frames + 1); // average snr luma for all frames inc. first | |
| snr->snr_ua = (float) (snr->snr_ua * total_frames + snr->snr_u) / (total_frames + 1); // average snr u croma for all frames inc. first | |
| snr->snr_va = (float) (snr->snr_va * total_frames + snr->snr_v) / (total_frames + 1); // average snr v croma for all frames inc. first | |
| snr->msse_y = (float) (snr->msse_y * total_frames + snr->sse_y) / (total_frames + 1); // average sse luma for all frames inc. first | |
| snr->msse_u = (float) (snr->msse_u * total_frames + snr->sse_u) / (total_frames + 1); // average sse u croma for all frames inc. first | |
| snr->msse_v = (float) (snr->msse_v * total_frames + snr->sse_v) / (total_frames + 1); // average sse v croma for all frames inc. first | |
| } | |
| snr->snr_yt[img->type] = (float) (snr->snr_yt[img->type] * (frame_ctr[img->type] - 1) + snr->snr_y) / ( frame_ctr[img->type] ); // average luma snr for img->type coded frames | |
| snr->snr_ut[img->type] = (float) (snr->snr_ut[img->type] * (frame_ctr[img->type] - 1) + snr->snr_u) / ( frame_ctr[img->type] ); // average chroma u snr for img->type coded frames | |
| snr->snr_vt[img->type] = (float) (snr->snr_vt[img->type] * (frame_ctr[img->type] - 1) + snr->snr_v) / ( frame_ctr[img->type] ); // average chroma v snr for img->type coded frames | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Find distortion for all three components | |
| ************************************************************************ | |
| */ | |
| static void find_distortion (void) | |
| { | |
| int i, j; | |
| int64 diff_y, diff_u, diff_v; | |
| int impix; | |
| // Calculate PSNR for Y, U and V. | |
| // Luma. | |
| impix = input->img_height * input->img_width; | |
| if (img->structure!=FRAME) | |
| { | |
| diff_y = 0; | |
| for (i = 0; i < input->img_width; ++i) | |
| { | |
| for (j = 0; j < input->img_height; ++j) | |
| { | |
| diff_y += img->quad[imgY_org[j][i] - imgY_com[j][i]]; | |
| } | |
| } | |
| diff_u = 0; | |
| diff_v = 0; | |
| if (img->yuv_format != YUV400) | |
| { | |
| // Chroma. | |
| for (i = 0; i < input->img_width_cr; i++) | |
| { | |
| for (j = 0; j < input->img_height_cr; j++) | |
| { | |
| diff_u += img->quad[imgUV_org[0][j][i] - imgUV_com[0][j][i]]; | |
| diff_v += img->quad[imgUV_org[1][j][i] - imgUV_com[1][j][i]]; | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| imgY_org = imgY_org_frm; | |
| imgUV_org = imgUV_org_frm; | |
| diff_y = 0; | |
| for (i = 0; i < input->img_width; ++i) | |
| { | |
| for (j = 0; j < input->img_height; ++j) | |
| { | |
| diff_y += img->quad[imgY_org[j][i] - enc_picture->imgY[j][i]]; | |
| } | |
| } | |
| diff_u = 0; | |
| diff_v = 0; | |
| if (img->yuv_format != YUV400) | |
| { | |
| // Chroma. | |
| for (i = 0; i < input->img_width_cr; i++) | |
| { | |
| for (j = 0; j < input->img_height_cr; j++) | |
| { | |
| diff_u += img->quad[imgUV_org[0][j][i] - enc_picture->imgUV[0][j][i]]; | |
| diff_v += img->quad[imgUV_org[1][j][i] - enc_picture->imgUV[1][j][i]]; | |
| } | |
| } | |
| } | |
| } | |
| // Calculate real PSNR at find_snr_avg() | |
| snr->snr_y = (float) diff_y; | |
| snr->snr_u = (float) diff_u; | |
| snr->snr_v = (float) diff_v; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Just a placebo | |
| ************************************************************************ | |
| */ | |
| Boolean dummy_slice_too_big (int bits_slice) | |
| { | |
| return FALSE; | |
| } | |
| /*! | |
| *************************************************************************** | |
| // For MB level field/frame coding | |
| *************************************************************************** | |
| */ | |
| void copy_rdopt_data (int bot_block) | |
| { | |
| int mb_nr = img->current_mb_nr; | |
| Macroblock *currMB = &img->mb_data[mb_nr]; | |
| int i, j, k; | |
| int bframe = (img->type == B_SLICE); | |
| int mode; | |
| int b8mode, b8pdir; | |
| int block_y; | |
| int list_offset = currMB->list_offset; | |
| mode = rdopt->mode; | |
| currMB->mb_type = rdopt->mb_type; // copy mb_type | |
| currMB->cbp = rdopt->cbp; // copy cbp | |
| currMB->cbp_blk = rdopt->cbp_blk; // copy cbp_blk | |
| currMB->bi_pred_me = rdopt->bi_pred_me; // copy biprediction | |
| img->i16offset = rdopt->i16offset; | |
| currMB->prev_qp=rdopt->prev_qp; | |
| currMB->prev_delta_qp=rdopt->prev_delta_qp; | |
| currMB->prev_cbp = rdopt->prev_cbp; | |
| currMB->delta_qp = rdopt->delta_qp; | |
| currMB->qp = rdopt->qp; | |
| set_chroma_qp(currMB); | |
| currMB->c_ipred_mode = rdopt->c_ipred_mode; | |
| for (i = 0; i < 4+img->num_blk8x8_uv; i++) | |
| { | |
| for (j = 0; j < 4; j++) | |
| for (k = 0; k < 2; k++) | |
| memcpy(img->cofAC[i][j][k],rdopt->cofAC[i][j][k], 65 * sizeof(int)); | |
| } | |
| for (i = 0; i < 3; i++) | |
| { | |
| for (k = 0; k < 2; k++) | |
| memcpy(img->cofDC[i][k],rdopt->cofDC[i][k], 18 * sizeof(int)); | |
| } | |
| for (j = 0; j < BLOCK_MULTIPLE; j++) | |
| { | |
| block_y = img->block_y + j; | |
| memcpy(&enc_picture->ref_idx[LIST_0][block_y][img->block_x], rdopt->refar[LIST_0][j], BLOCK_MULTIPLE * sizeof(char)); | |
| for (i = 0; i < BLOCK_MULTIPLE; i++) | |
| enc_picture->ref_pic_id [LIST_0][block_y][img->block_x + i] = | |
| enc_picture->ref_pic_num[LIST_0 + list_offset][(short)enc_picture->ref_idx[LIST_0][block_y][img->block_x+i]]; | |
| } | |
| if (bframe) | |
| { | |
| for (j = 0; j < BLOCK_MULTIPLE; j++) | |
| { | |
| block_y = img->block_y + j; | |
| memcpy(&enc_picture->ref_idx[LIST_1][block_y][img->block_x], rdopt->refar[LIST_1][j], BLOCK_MULTIPLE * sizeof(char)); | |
| for (i = 0; i < BLOCK_MULTIPLE; i++) | |
| enc_picture->ref_pic_id [LIST_1][block_y][img->block_x + i] = | |
| enc_picture->ref_pic_num[LIST_1 + list_offset][(short)enc_picture->ref_idx[LIST_1][block_y][img->block_x+i]]; | |
| } | |
| } | |
| //===== reconstruction values ===== | |
| for (j = 0; j < MB_BLOCK_SIZE; j++) | |
| memcpy(&enc_picture->imgY[img->pix_y + j][img->pix_x],rdopt->rec_mbY[j], MB_BLOCK_SIZE * sizeof(imgpel)); | |
| if (img->yuv_format != YUV400) | |
| { | |
| for (j = 0; j < img->mb_cr_size_y; j++) | |
| { | |
| memcpy(&enc_picture->imgUV[0][img->pix_c_y + j][img->pix_c_x],rdopt->rec_mbU[j], img->mb_cr_size_x * sizeof(imgpel)); | |
| memcpy(&enc_picture->imgUV[1][img->pix_c_y + j][img->pix_c_x],rdopt->rec_mbV[j], img->mb_cr_size_x * sizeof(imgpel)); | |
| } | |
| } | |
| memcpy(currMB->b8mode,rdopt->b8mode, 4 * sizeof(int)); | |
| memcpy(currMB->b8pdir,rdopt->b8pdir, 4 * sizeof(int)); | |
| currMB->luma_transform_size_8x8_flag = rdopt->luma_transform_size_8x8_flag; | |
| //==== intra prediction modes ==== | |
| if (mode == P8x8) | |
| { | |
| memcpy(currMB->intra_pred_modes,rdopt->intra_pred_modes, MB_BLOCK_PARTITIONS * sizeof(char)); | |
| for (j = img->block_y; j < img->block_y + BLOCK_MULTIPLE; j++) | |
| memcpy(&img->ipredmode[j][img->block_x],&rdopt->ipredmode[j][img->block_x], BLOCK_MULTIPLE * sizeof(char)); | |
| } | |
| else if (mode != I4MB && mode != I8MB) | |
| { | |
| memset(currMB->intra_pred_modes,DC_PRED, MB_BLOCK_PARTITIONS * sizeof(char)); | |
| for (j = img->block_y; j < img->block_y + BLOCK_MULTIPLE; j++) | |
| memset(&img->ipredmode[j][img->block_x],DC_PRED, BLOCK_MULTIPLE * sizeof(char)); | |
| } | |
| else if (mode == I4MB || mode == I8MB) | |
| { | |
| memcpy(currMB->intra_pred_modes,rdopt->intra_pred_modes, MB_BLOCK_PARTITIONS * sizeof(char)); | |
| memcpy(currMB->intra_pred_modes8x8,rdopt->intra_pred_modes8x8, MB_BLOCK_PARTITIONS * sizeof(char)); | |
| for (j = img->block_y; j < img->block_y + BLOCK_MULTIPLE; j++) { | |
| memcpy(&img->ipredmode[j][img->block_x],&rdopt->ipredmode[j][img->block_x], BLOCK_MULTIPLE * sizeof(char)); | |
| } | |
| } | |
| if (img->MbaffFrameFlag) | |
| { | |
| // motion vectors | |
| copy_motion_vectors_MB (); | |
| if (!IS_INTRA(currMB)) | |
| { | |
| for (j = 0; j < 4; j++) | |
| for (i = 0; i < 4; i++) | |
| { | |
| b8mode = currMB->b8mode[i/2+2*(j/2)]; | |
| b8pdir = currMB->b8pdir[i/2+2*(j/2)]; | |
| if (b8pdir!=1) | |
| { | |
| enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][0] = rdopt->all_mv[j][i][LIST_0][(short)rdopt->refar[LIST_0][j][i]][b8mode][0]; | |
| enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][1] = rdopt->all_mv[j][i][LIST_0][(short)rdopt->refar[LIST_0][j][i]][b8mode][1]; | |
| } | |
| else | |
| { | |
| enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][0] = 0; | |
| enc_picture->mv[LIST_0][j+img->block_y][i+img->block_x][1] = 0; | |
| } | |
| if (bframe) | |
| { | |
| if (b8pdir!=0) | |
| { | |
| enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][0] = rdopt->all_mv[j][i][LIST_1][(short)rdopt->refar[LIST_1][j][i]][b8mode][0]; | |
| enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][1] = rdopt->all_mv[j][i][LIST_1][(short)rdopt->refar[LIST_1][j][i]][b8mode][1]; | |
| } | |
| else | |
| { | |
| enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][0] = 0; | |
| enc_picture->mv[LIST_1][j+img->block_y][i+img->block_x][1] = 0; | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| for (j = 0; j < 4; j++) | |
| memset(enc_picture->mv[LIST_0][j+img->block_y][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short)); | |
| if (bframe) | |
| { | |
| for (j = 0; j < 4; j++) | |
| memset(enc_picture->mv[LIST_1][j+img->block_y][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short)); | |
| } | |
| } | |
| } | |
| } // end of copy_rdopt_data | |
| static void copy_motion_vectors_MB (void) | |
| { | |
| int i,j,k,l; | |
| for (i = 0; i < 4; i++) | |
| { | |
| for (j = 0; j < 4; j++) | |
| { | |
| for (k = 0; k < img->max_num_references; k++) | |
| { | |
| for (l = 0; l < 9; l++) | |
| { | |
| img->all_mv[j][i][LIST_0][k][l][0] = rdopt->all_mv[j][i][LIST_0][k][l][0]; | |
| img->all_mv[j][i][LIST_0][k][l][1] = rdopt->all_mv[j][i][LIST_0][k][l][1]; | |
| img->all_mv[j][i][LIST_1][k][l][0] = rdopt->all_mv[j][i][LIST_1][k][l][0]; | |
| img->all_mv[j][i][LIST_1][k][l][1] = rdopt->all_mv[j][i][LIST_1][k][l][1]; | |
| img->pred_mv[j][i][LIST_0][k][l][0] = rdopt->pred_mv[j][i][LIST_0][k][l][0]; | |
| img->pred_mv[j][i][LIST_0][k][l][1] = rdopt->pred_mv[j][i][LIST_0][k][l][1]; | |
| img->pred_mv[j][i][LIST_1][k][l][0] = rdopt->pred_mv[j][i][LIST_1][k][l][0]; | |
| img->pred_mv[j][i][LIST_1][k][l][1] = rdopt->pred_mv[j][i][LIST_1][k][l][1]; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| static void ReportNALNonVLCBits(time_t tmp_time, time_t me_time) | |
| { | |
| //! Need to add type (i.e. SPS, PPS, SEI etc). | |
| if (input->Verbose != 0) | |
| printf ("%04d(NVB)%8d \n", frame_no, 0); | |
| } | |
| static void ReportFirstframe(time_t tmp_time, time_t me_time) | |
| { | |
| //Rate control | |
| int bits; | |
| if (input->Verbose == 1) | |
| { | |
| printf ("%04d(IDR)%8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| frame_no, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| } | |
| else if (input->Verbose == 2) | |
| { | |
| printf ("%04d(IDR)%8d %1d %2d %7.3f %7.3f %7.3f %9d %7d %3s %5d %2d %2d %d %d\n", | |
| frame_no,0,0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc); | |
| } | |
| //Rate control | |
| if(input->RCEnable) | |
| { | |
| if((!input->PicInterlace) && (!input->MbInterlace)) | |
| bits = (int) (stats->bit_ctr - stats->bit_ctr_n); // used for rate control update | |
| else | |
| { | |
| bits = (int)(stats->bit_ctr - quadratic_RC->Iprev_bits); // used for rate control update | |
| quadratic_RC->Iprev_bits = stats->bit_ctr; | |
| } | |
| } | |
| stats->bit_ctr_I = stats->bit_ctr; | |
| stats->bit_ctr = 0; | |
| } | |
| static void ReportIntra(time_t tmp_time, time_t me_time) | |
| { | |
| if (input->Verbose == 1) | |
| { | |
| if (img->currentPicture->idr_flag == 1) | |
| printf ("%04d(IDR)%8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| frame_no, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| else | |
| printf ("%04d(I) %8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| frame_no, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| } | |
| else if (input->Verbose == 2) | |
| { | |
| if (img->currentPicture->idr_flag == 1) | |
| printf ("%04d(IDR)%8d %1d %2d %7.3f %7.3f %7.3f %9d %7d %3s %5d %2d %2d %d %d\n", | |
| frame_no, 0, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc); | |
| else | |
| printf ("%04d(I) %8d %1d %2d %7.3f %7.3f %7.3f %9d %7d %3s %5d %2d %2d %d %d\n", | |
| frame_no, 0, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc); | |
| } | |
| } | |
| static void ReportSP(time_t tmp_time, time_t me_time) | |
| { | |
| if (input->Verbose == 1) | |
| { | |
| printf ("%04d(SP) %8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| frame_no, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| } | |
| else if (input->Verbose == 2) | |
| { | |
| printf ("%04d(SP) %8d %1d %2d %7.3f %7.3f %7.3f %9d %7d %3s %5d %2d %2d %d %d\n", | |
| frame_no, 0, active_pps->weighted_pred_flag, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc); | |
| } | |
| } | |
| static void ReportB(time_t tmp_time, time_t me_time) | |
| { | |
| if (input->Verbose == 1) | |
| { | |
| printf ("%04d(B) %8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| frame_no, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| } | |
| else if (input->Verbose == 2) | |
| { | |
| printf ("%04d(B) %8d %1d %2d %7.3f %7.3f %7.3f %9d %7d %3s %5d %1d %2d %2d %d %d\n", | |
| frame_no, 0, active_pps->weighted_bipred_idc, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM",intras,img->direct_spatial_mv_pred_flag, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active,img->rd_pass, img->nal_reference_idc); | |
| } | |
| } | |
| static void ReportP(time_t tmp_time, time_t me_time) | |
| { | |
| if (input->Verbose == 1) | |
| { | |
| if(input->redundant_pic_flag==0) | |
| { | |
| printf ("%04d(P) %8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| frame_no, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| } | |
| else | |
| { | |
| if(!redundant_coding) | |
| { | |
| printf ("%04d(P) %8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| frame_no, 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| } | |
| else | |
| { // report a redundant picture. | |
| printf (" (R) %8d %2d %7.3f %7.3f %7.3f %9d %7d %3s %d\n", | |
| 0, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", img->nal_reference_idc); | |
| } | |
| } | |
| } | |
| else if (input->Verbose == 2) | |
| { | |
| printf ("%04d(P) %8d %1d %2d %7.3f %7.3f %7.3f %9d %7d %3s %5d %2d %2d %d %d\n", | |
| frame_no, 0, active_pps->weighted_pred_flag, | |
| img->AverageFrameQP, snr->snr_y, snr->snr_u, snr->snr_v, 0, 0, | |
| img->fld_flag ? "FLD" : "FRM", intras, img->num_ref_idx_l0_active, img->num_ref_idx_l1_active, img->rd_pass, img->nal_reference_idc); | |
| } | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Padding of automatically added border for picture sizes that are not | |
| * multiples of macroblock/macroblock pair size | |
| * | |
| * \param org_size_x | |
| * original image horizontal size (luma) | |
| * \param org_size_y | |
| * original image vertical size (luma) | |
| * \param img_size_x | |
| * coded image horizontal size (luma) | |
| * \param img_size_y | |
| * code image vertical size (luma) | |
| * \param org_size_x_cr | |
| * original image horizontal size (chroma) | |
| * \param org_size_y_cr | |
| * original image vertical size (chroma) | |
| * \param img_size_x_cr | |
| * coded image horizontal size (chroma) | |
| * \param img_size_y_cr | |
| * code image vertical size (chroma) | |
| ************************************************************************ | |
| */ | |
| static void PaddAutoCropBorders (int org_size_x, int org_size_y, int img_size_x, int img_size_y, | |
| int org_size_x_cr, int org_size_y_cr, int img_size_x_cr, int img_size_y_cr) | |
| { | |
| int x, y; | |
| //padding right border | |
| for (y=0; y<org_size_y; y++) | |
| for (x=org_size_x; x<img_size_x; x++) | |
| imgY_org_frm [y][x] = imgY_org_frm [y][x-1]; | |
| //padding bottom border | |
| for (y=org_size_y; y<img_size_y; y++) | |
| for (x=0; x<img_size_x; x++) | |
| imgY_org_frm [y][x] = imgY_org_frm [y-1][x]; | |
| if (img->yuv_format != YUV400) | |
| { | |
| //padding right border | |
| for (y=0; y<org_size_y_cr; y++) | |
| for (x=org_size_x_cr; x<img_size_x_cr; x++) | |
| { | |
| imgUV_org_frm [0][y][x] = imgUV_org_frm [0][y][x-1]; | |
| imgUV_org_frm [1][y][x] = imgUV_org_frm [1][y][x-1]; | |
| } | |
| //padding bottom border | |
| for (y=org_size_y_cr; y<img_size_y_cr; y++) | |
| for (x=0; x<img_size_x_cr; x++) | |
| { | |
| imgUV_org_frm [0][y][x] = imgUV_org_frm [0][y-1][x]; | |
| imgUV_org_frm [1][y][x] = imgUV_org_frm [1][y-1][x]; | |
| } | |
| } | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Calculates the absolute frame number in the source file out | |
| * of various variables in img-> and input-> | |
| * \return | |
| * frame number in the file to be read | |
| * \par side effects | |
| * global variable frame_no updated -- dunno, for what this one is necessary | |
| ************************************************************************ | |
| */ | |
| static int CalculateFrameNumber(void) | |
| { | |
| if (img->b_frame_to_code) | |
| { | |
| if (input->HierarchicalCoding) | |
| frame_no = start_tr_in_this_IGOP + (IMG_NUMBER - 1) * (input->jumpd + 1) + (int) (img->b_interval * (double) (1 + gop_structure[img->b_frame_to_code - 1].display_no)); | |
| else | |
| frame_no = start_tr_in_this_IGOP + (IMG_NUMBER - 1) * (input->jumpd + 1) + (int) (img->b_interval * (double) img->b_frame_to_code); | |
| } | |
| else | |
| { | |
| frame_no = start_tr_in_this_IGOP + IMG_NUMBER * (input->jumpd + 1); | |
| #ifdef _ADAPT_LAST_GROUP_ | |
| if (input->last_frame && img->number + 1 == input->no_frames) | |
| frame_no = input->last_frame; | |
| #endif | |
| } | |
| return frame_no; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Convert file read buffer to source picture structure | |
| ************************************************************************ | |
| */ | |
| void buf2img ( imgpel** imgX, //!< Pointer to image plane | |
| unsigned char* buf, //!< Buffer for file output | |
| int size_x, //!< horizontal size of picture | |
| int size_y, //!< vertical size of picture | |
| int symbol_size_in_bytes //!< number of bytes in file used for one pixel | |
| ) | |
| { | |
| int i,j; | |
| unsigned short tmp16, ui16; | |
| unsigned long tmp32, ui32; | |
| if (symbol_size_in_bytes> sizeof(imgpel)) | |
| { | |
| error ("Source picture has higher bit depth than imgpel data type. Please recompile with larger data type for imgpel.", 500); | |
| } | |
| if (( sizeof(char) == sizeof (imgpel)) && ( sizeof(char) == symbol_size_in_bytes)) | |
| { | |
| // imgpel == pixel_in_file == 1 byte -> simple copy | |
| for(j=0;j<size_y;j++) | |
| memcpy(imgX[j], buf+j*size_x, size_x); | |
| } | |
| else | |
| { | |
| // sizeof (imgpel) > sizeof(char) | |
| if (testEndian()) | |
| { | |
| // big endian | |
| switch (symbol_size_in_bytes) | |
| { | |
| case 1: | |
| { | |
| for(j=0;j<size_y;j++) | |
| for(i=0;i<size_x;i++) | |
| { | |
| imgX[j][i]= buf[i+j*size_x]; | |
| } | |
| break; | |
| } | |
| case 2: | |
| { | |
| for(j=0;j<size_y;j++) | |
| for(i=0;i<size_x;i++) | |
| { | |
| memcpy(&tmp16, buf+((i+j*size_x)*2), 2); | |
| ui16 = (tmp16 >> 8) | ((tmp16&0xFF)<<8); | |
| imgX[j][i] = (imgpel) ui16; | |
| } | |
| break; | |
| } | |
| case 4: | |
| { | |
| for(j=0;j<size_y;j++) | |
| for(i=0;i<size_x;i++) | |
| { | |
| memcpy(&tmp32, buf+((i+j*size_x)*4), 4); | |
| ui32 = ((tmp32&0xFF00)<<8) | ((tmp32&0xFF)<<24) | ((tmp32&0xFF0000)>>8) | ((tmp32&0xFF000000)>>24); | |
| imgX[j][i] = (imgpel) ui32; | |
| } | |
| } | |
| default: | |
| { | |
| error ("reading only from formats of 8, 16 or 32 bit allowed on big endian architecture", 500); | |
| break; | |
| } | |
| } | |
| } | |
| else | |
| { | |
| // little endian | |
| for (j=0; j < size_y; j++) | |
| for (i=0; i < size_x; i++) | |
| { | |
| imgX[j][i]=0; | |
| memcpy(&(imgX[j][i]), buf +((i+j*size_x)*symbol_size_in_bytes), symbol_size_in_bytes); | |
| } | |
| } | |
| } | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Reads one new frame from file | |
| * | |
| * \param FrameNoInFile | |
| * Frame number in the source file | |
| * \param HeaderSize | |
| * Number of bytes in the source file to be skipped | |
| * \param xs | |
| * horizontal size of frame in pixels | |
| * \param ys | |
| * vertical size of frame in pixels | |
| * \param xs_cr | |
| * horizontal chroma size of frame in pixels | |
| * \param ys_cr | |
| * vertical chroma size of frame in pixels | |
| ************************************************************************ | |
| */ | |
| static void ReadOneFrame (int FrameNoInFile, int HeaderSize, int xs, int ys, int xs_cr, int ys_cr) | |
| { | |
| unsigned int symbol_size_in_bytes = img->pic_unit_size_on_disk/8; | |
| const int imgsize_y = xs*ys; | |
| const int imgsize_uv = xs_cr*ys_cr; | |
| const int bytes_y = imgsize_y * symbol_size_in_bytes; | |
| const int bytes_uv = imgsize_uv * symbol_size_in_bytes; | |
| const int64 framesize_in_bytes = bytes_y + 2*bytes_uv; | |
| unsigned char *buf; | |
| Boolean rgb_input = (Boolean) (input->rgb_input_flag==1 && input->yuv_format==3); | |
| assert (p_in != -1); | |
| // KS: this buffer should actually be allocated only once, but this is still much faster than the previous version | |
| if (NULL==(buf = malloc (xs*ys * symbol_size_in_bytes))) no_mem_exit("ReadOneFrame: buf"); | |
| // skip Header | |
| if (lseek (p_in, HeaderSize, SEEK_SET) != HeaderSize) | |
| { | |
| error ("ReadOneFrame: cannot fseek to (Header size) in p_in", -1); | |
| } | |
| // skip starting frames | |
| if (lseek (p_in, framesize_in_bytes * input->start_frame, SEEK_CUR) == -1) | |
| { | |
| snprintf(errortext, ET_SIZE, "ReadOneFrame: cannot advance file pointer in p_in beyond frame %d\n", input->start_frame); | |
| error (errortext,-1); | |
| } | |
| // seek to current frame | |
| if (lseek (p_in, framesize_in_bytes * FrameNoInFile, SEEK_CUR) == -1) | |
| { | |
| snprintf(errortext, ET_SIZE, "ReadOneFrame: cannot advance file pointer in p_in beyond frame %d\n", input->start_frame + FrameNoInFile); | |
| error (errortext,-1); | |
| } | |
| // Here we are at the correct position for the source frame in the file. Now | |
| // read it. | |
| if (img->pic_unit_size_on_disk%8 == 0) | |
| { | |
| if(rgb_input) | |
| lseek (p_in, framesize_in_bytes/3, SEEK_CUR); | |
| if (read(p_in, buf, bytes_y) != bytes_y) | |
| { | |
| printf ("ReadOneFrame: cannot read %d bytes from input file, unexpected EOF?, exiting", bytes_y); | |
| report_stats_on_error(); | |
| exit (-1); | |
| } | |
| buf2img(imgY_org_frm, buf, xs, ys, symbol_size_in_bytes); | |
| //#define _DEBUG_BITDEPTH_ | |
| #ifdef _DEBUG_BITDEPTH_ | |
| { | |
| int i,j; | |
| for (j=0; j < ys; j++) | |
| { | |
| for (i=0; i < xs; i++) | |
| { | |
| imgY_org_frm[j][i]= (imgpel) (imgY_org_frm[j][i] & ((1<<img->bitdepth_luma ) - 1)); | |
| } | |
| } | |
| } | |
| #endif | |
| if (img->yuv_format != YUV400) | |
| { | |
| if (read(p_in, buf, bytes_uv) != bytes_uv) | |
| { | |
| printf ("ReadOneFrame: cannot read %d bytes from input file, unexpected EOF?, exiting", bytes_y); | |
| report_stats_on_error(); | |
| exit (-1); | |
| } | |
| buf2img(imgUV_org_frm[0], buf, xs_cr, ys_cr, symbol_size_in_bytes); | |
| if(rgb_input) | |
| lseek (p_in, -framesize_in_bytes, SEEK_CUR); | |
| if (read(p_in, buf, bytes_uv) != bytes_uv) | |
| { | |
| printf ("ReadOneFrame: cannot read %d bytes from input file, unexpected EOF?, exiting", bytes_y); | |
| report_stats_on_error(); | |
| exit (-1); | |
| } | |
| buf2img(imgUV_org_frm[1], buf, xs_cr, ys_cr, symbol_size_in_bytes); | |
| #ifdef _DEBUG_BITDEPTH_ | |
| { | |
| int i,j; | |
| for (j=0; j < ys_cr; j++) | |
| { | |
| for (i=0; i < xs_cr; i++) | |
| { | |
| imgUV_org_frm[0][j][i]=(imgpel) (imgUV_org_frm[0][j][i] & ((1<<img->bitdepth_chroma ) - 1)); | |
| imgUV_org_frm[1][j][i]=(imgpel) (imgUV_org_frm[1][j][i] & ((1<<img->bitdepth_chroma ) - 1)); | |
| } | |
| } | |
| } | |
| #endif | |
| if(rgb_input) | |
| lseek (p_in, framesize_in_bytes*2/3, SEEK_CUR); | |
| } | |
| } | |
| else | |
| { | |
| printf ("ReadOneFrame (NOT IMPLEMENTED): pic unit size on disk must be divided by 8"); | |
| exit (-1); | |
| } | |
| free (buf); | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * point to frame coding variables | |
| ************************************************************************ | |
| */ | |
| static void put_buffer_frame(void) | |
| { | |
| imgY_org = imgY_org_frm; | |
| imgUV_org = imgUV_org_frm; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * point to top field coding variables | |
| ************************************************************************ | |
| */ | |
| static void put_buffer_top(void) | |
| { | |
| img->fld_type = 0; | |
| imgY_org = imgY_org_top; | |
| imgUV_org = imgUV_org_top; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * point to bottom field coding variables | |
| ************************************************************************ | |
| */ | |
| static void put_buffer_bot(void) | |
| { | |
| img->fld_type = 1; | |
| imgY_org = imgY_org_bot; | |
| imgUV_org = imgUV_org_bot; | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * Writes a NAL unit of a partition or slice | |
| ************************************************************************ | |
| */ | |
| static void writeUnit(Bitstream* currStream, int partition) | |
| { | |
| const int buffer_size = 500 + img->FrameSizeInMbs * (128 + 256 * img->bitdepth_luma + 512 * img->bitdepth_chroma); | |
| // KS: this is approx. max. allowed code picture size | |
| NALU_t *nalu; | |
| assert (currStream->bits_to_go == 8); | |
| nalu = AllocNALU(buffer_size); | |
| nalu->startcodeprefix_len = 1+ (img->current_mb_nr == 0 && partition == 0 ?ZEROBYTES_SHORTSTARTCODE+1:ZEROBYTES_SHORTSTARTCODE); | |
| //printf ("nalu->startcodeprefix_len %d\n", nalu->startcodeprefix_len); | |
| nalu->len = currStream->byte_pos +1; // add one for the first byte of the NALU | |
| //printf ("nalu->len %d\n", nalu->len); | |
| memcpy (&nalu->buf[1], currStream->streamBuffer, nalu->len-1); | |
| if (img->currentPicture->idr_flag) | |
| { | |
| nalu->nal_unit_type = NALU_TYPE_IDR; | |
| nalu->nal_reference_idc = NALU_PRIORITY_HIGHEST; | |
| } | |
| else if (img->type == B_SLICE) | |
| { | |
| //different nal header for different partitions | |
| if(input->partition_mode == 0) | |
| { | |
| nalu->nal_unit_type = NALU_TYPE_SLICE; | |
| } | |
| else | |
| { | |
| nalu->nal_unit_type = NALU_TYPE_DPA + partition; | |
| } | |
| if (img->nal_reference_idc !=0) | |
| { | |
| nalu->nal_reference_idc = NALU_PRIORITY_HIGH; | |
| } | |
| else | |
| { | |
| nalu->nal_reference_idc = NALU_PRIORITY_DISPOSABLE; | |
| } | |
| } | |
| else // non-b frame, non IDR slice | |
| { | |
| //different nal header for different partitions | |
| if(input->partition_mode == 0) | |
| { | |
| nalu->nal_unit_type = NALU_TYPE_SLICE; | |
| } | |
| else | |
| { | |
| nalu->nal_unit_type = NALU_TYPE_DPA + partition; | |
| } | |
| if (img->nal_reference_idc !=0) | |
| { | |
| nalu->nal_reference_idc = NALU_PRIORITY_HIGH; | |
| } | |
| else | |
| { | |
| nalu->nal_reference_idc = NALU_PRIORITY_DISPOSABLE; | |
| } | |
| } | |
| nalu->forbidden_bit = 0; | |
| stats->bit_ctr += WriteNALU (nalu); | |
| FreeNALU(nalu); | |
| } | |
| /*! | |
| ************************************************************************ | |
| * \brief | |
| * performs multi-pass encoding of same picture using different | |
| * coding conditions | |
| ************************************************************************ | |
| */ | |
| static void rdPictureCoding(void) | |
| { | |
| int second_qp = img->qp, rd_qp = img->qp; | |
| int previntras = intras; | |
| int prevtype = img->type; | |
| int skip_encode = 0; | |
| pic_parameter_set_rbsp_t *sec_pps; | |
| int tmpFrameQP = img->SumFrameQP; | |
| if ( input->RCEnable ) | |
| { | |
| // save the current RC model as preliminary best | |
| copy_rc_jvt( quadratic_RC_best, quadratic_RC ); | |
| copy_rc_generic( generic_RC_best, generic_RC ); | |
| } | |
| if (img->type!=I_SLICE && input->GenerateMultiplePPS) | |
| { | |
| if (img->type==P_SLICE) | |
| { | |
| if (test_wp_P_slice(0) == 1) | |
| { | |
| active_pps = PicParSet[1]; | |
| } | |
| else | |
| { | |
| skip_encode = input->RDPSliceWeightOnly; | |
| active_pps = PicParSet[0]; | |
| if (!img->AdaptiveRounding) | |
| img->qp-=1; | |
| } | |
| } | |
| else | |
| { | |
| active_pps = PicParSet[2]; | |
| } | |
| } | |
| else | |
| { | |
| if (!img->AdaptiveRounding) | |
| img->qp-=1; | |
| } | |
| sec_pps = active_pps; | |
| second_qp = img->qp; | |
| img->write_macroblock = 0; | |
| if (skip_encode) | |
| { | |
| img->rd_pass = 0; | |
| enc_frame_picture2 = NULL; | |
| } | |
| else | |
| { | |
| if(input->RCEnable) | |
| { | |
| // re-store the initial RC model | |
| copy_rc_jvt( quadratic_RC, quadratic_RC_init ); | |
| copy_rc_generic( generic_RC, generic_RC_init ); | |
| rc_init_pict(quadratic_RC, 1,0,1, input->GenerateMultiplePPS ? 1.0F : 0.85F ); | |
| img->qp = updateQP(quadratic_RC, 0); | |
| } | |
| frame_picture (frame_pic_2,1); | |
| img->rd_pass=picture_coding_decision(frame_pic_1, frame_pic_2, rd_qp); | |
| } | |
| // update_rd_picture_contexts (img->rd_pass); | |
| if (img->rd_pass==0) | |
| { | |
| enc_picture=enc_frame_picture; | |
| if (img->type!=I_SLICE && input->GenerateMultiplePPS) | |
| { | |
| img->qp=rd_qp; | |
| active_pps = PicParSet[0]; | |
| } | |
| else | |
| { | |
| img->qp=rd_qp; | |
| } | |
| intras = previntras; | |
| frame_pic = frame_pic_1; | |
| } | |
| else | |
| { | |
| previntras = intras; | |
| frame_pic = frame_pic_2; | |
| tmpFrameQP = img->SumFrameQP; | |
| if(input->RCEnable) | |
| { | |
| copy_rc_jvt( quadratic_RC_best, quadratic_RC ); | |
| copy_rc_generic( generic_RC_best, generic_RC ); | |
| } | |
| } | |
| // Final Encoding pass - note that we should | |
| // make this more flexible in a later version. | |
| if (img->type!=I_SLICE ) | |
| { | |
| skip_encode = 0; | |
| img->qp = rd_qp; | |
| if (img->type == P_SLICE && (intras * 100 )/img->FrameSizeInMbs >=75) | |
| { | |
| img->type=I_SLICE; | |
| active_pps = PicParSet[0]; | |
| } | |
| else if (img->type==P_SLICE) | |
| { | |
| if (input->GenerateMultiplePPS) | |
| { | |
| if (test_wp_P_slice(1) == 1) | |
| { | |
| active_pps = PicParSet[1]; | |
| } | |
| else if (input->RDPSliceBTest && active_sps->profile_idc != 66) | |
| { | |
| img->type = B_SLICE; | |
| active_pps = PicParSet[0]; | |
| } | |
| else | |
| { | |
| skip_encode = input->RDPSliceWeightOnly; | |
| active_pps = PicParSet[0]; | |
| if (!img->AdaptiveRounding) | |
| img->qp+=1; | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if (input->GenerateMultiplePPS && test_wp_B_slice(0) == 1) | |
| { | |
| active_pps = PicParSet[1]; | |
| } | |
| else | |
| { | |
| skip_encode = input->RDBSliceWeightOnly; | |
| img->qp = rd_qp + (img->nal_reference_idc ? - 1 : 1); | |
| } | |
| } | |
| } | |
| else | |
| { | |
| active_pps = PicParSet[0]; | |
| if (!img->AdaptiveRounding) | |
| img->qp = (rd_qp + 1); | |
| } | |
| img->write_macroblock = 0; | |
| if (skip_encode) | |
| { | |
| enc_frame_picture3 = NULL; | |
| img->qp = rd_qp; | |
| } | |
| else | |
| { | |
| if(input->RCEnable) | |
| { | |
| // re-store the initial RC model | |
| copy_rc_jvt( quadratic_RC, quadratic_RC_init ); | |
| copy_rc_generic( generic_RC, generic_RC_init ); | |
| rc_init_pict(quadratic_RC, 1,0,1, input->GenerateMultiplePPS ? 1.0F : 1.15F ); | |
| img->qp = updateQP(quadratic_RC, 0); | |
| } | |
| frame_picture (frame_pic_3,2); | |
| if (img->rd_pass==0) | |
| img->rd_pass = 2*picture_coding_decision(frame_pic_1, frame_pic_3, rd_qp); | |
| else | |
| img->rd_pass += picture_coding_decision(frame_pic_2, frame_pic_3, rd_qp); | |
| if ( input->RCEnable && img->rd_pass == 2 ) | |
| { | |
| copy_rc_jvt( quadratic_RC_best, quadratic_RC ); | |
| copy_rc_generic( generic_RC_best, generic_RC ); | |
| } | |
| if ( img->rd_pass == 2 ) | |
| tmpFrameQP = img->SumFrameQP; | |
| } | |
| //update_rd_picture_contexts (img->rd_pass); | |
| if (img->rd_pass==0) | |
| { | |
| enc_picture = enc_frame_picture; | |
| img->type = prevtype; | |
| active_pps = PicParSet[0]; | |
| img->qp = rd_qp; | |
| intras = previntras; | |
| } | |
| else if (img->rd_pass==1) | |
| { | |
| enc_picture = enc_frame_picture2; | |
| img->type = prevtype; | |
| active_pps = sec_pps; | |
| img->qp = second_qp; | |
| intras = previntras; | |
| } | |
| if ( input->RCEnable ) | |
| { | |
| copy_rc_jvt( quadratic_RC, quadratic_RC_best ); | |
| copy_rc_generic( generic_RC, generic_RC_best ); | |
| } | |
| img->SumFrameQP = tmpFrameQP; | |
| } | |
| /*! | |
| ************************************************************************************* | |
| * Brief | |
| * Output SP frames coefficients | |
| ************************************************************************************* | |
| */ | |
| void output_SP_coefficients() | |
| { | |
| int i,k; | |
| FILE *SP_coeff_file; | |
| if(number_sp2_frames==0) | |
| { | |
| if ((SP_coeff_file = fopen(input->sp_output_filename,"wb")) == NULL) | |
| { | |
| printf ("Fatal: cannot open SP output file '%s', exit (-1)\n", input->sp_output_filename); | |
| exit (-1); | |
| } | |
| number_sp2_frames++; | |
| } | |
| else | |
| { | |
| if ((SP_coeff_file = fopen(input->sp_output_filename,"ab")) == NULL) | |
| { | |
| printf ("Fatal: cannot open SP output file '%s', exit (-1)\n", input->sp_output_filename); | |
| exit (-1); | |
| } | |
| } | |
| for(i=0;i<img->height;i++) | |
| { | |
| fwrite(lrec[i],sizeof(int),img->width,SP_coeff_file); | |
| } | |
| for(k=0;k<2;k++) | |
| { | |
| for(i=0;i<img->height_cr;i++) | |
| { | |
| fwrite(lrec_uv[k][i],sizeof(int),img->width_cr,SP_coeff_file); | |
| } | |
| } | |
| fclose(SP_coeff_file); | |
| } | |
| /*! | |
| ************************************************************************************* | |
| * Brief | |
| * Read SP frames coefficients | |
| ************************************************************************************* | |
| */ | |
| void read_SP_coefficients() | |
| { | |
| int i,k; | |
| FILE *SP_coeff_file; | |
| if ( (input->qp2start > 0) && ( ( (img->tr ) % (2*input->qp2start) ) >=input->qp2start )) | |
| { | |
| if ((SP_coeff_file = fopen(input->sp2_input_filename1,"rb")) == NULL) | |
| { | |
| printf ("Fatal: cannot open SP input file '%s', exit (-1)\n", input->sp2_input_filename2); | |
| exit (-1); | |
| } | |
| } | |
| else | |
| { | |
| if ((SP_coeff_file = fopen(input->sp2_input_filename2,"rb")) == NULL) | |
| { | |
| printf ("Fatal: cannot open SP input file '%s', exit (-1)\n", input->sp2_input_filename1); | |
| exit (-1); | |
| } | |
| } | |
| if (0 != fseek (SP_coeff_file, img->size * 3/2*number_sp2_frames*sizeof(int), SEEK_SET)) | |
| { | |
| printf ("Fatal: cannot seek in SP input file, exit (-1)\n"); | |
| exit (-1); | |
| } | |
| number_sp2_frames++; | |
| for(i=0;i<img->height;i++) | |
| { | |
| if(img->width!=(int)fread(lrec[i],sizeof(int),img->width,SP_coeff_file)) | |
| { | |
| printf ("Fatal: cannot read in SP input file, exit (-1)\n"); | |
| exit (-1); | |
| } | |
| } | |
| for(k=0;k<2;k++) | |
| { | |
| for(i=0;i<img->height_cr;i++) | |
| { | |
| if(img->width_cr!=(int)fread(lrec_uv[k][i],sizeof(int),img->width_cr,SP_coeff_file)) | |
| { | |
| printf ("Fatal: cannot read in SP input file, exit (-1)\n"); | |
| exit (-1); | |
| } | |
| } | |
| } | |
| fclose(SP_coeff_file); | |
| } |