| |
| /*! |
| ************************************************************************************* |
| * \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); |
| } |