Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #include "avcenc_lib.h"
     19 #include "avcenc_api.h"
     20 
     21 #define LOG2_MAX_FRAME_NUM_MINUS4   12   /* 12 default */
     22 #define SLICE_GROUP_CHANGE_CYCLE    1    /* default */
     23 
     24 /* initialized variables to be used in SPS*/
     25 AVCEnc_Status  SetEncodeParam(AVCHandle* avcHandle, AVCEncParams* encParam,
     26                               void* extSPS, void* extPPS)
     27 {
     28     AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
     29     AVCCommonObj *video = encvid->common;
     30     AVCSeqParamSet *seqParam = video->currSeqParams;
     31     AVCPicParamSet *picParam = video->currPicParams;
     32     AVCSliceHeader *sliceHdr = video->sliceHdr;
     33     AVCRateControl *rateCtrl = encvid->rateCtrl;
     34     AVCEnc_Status status;
     35     void *userData = avcHandle->userData;
     36     int ii, maxFrameNum;
     37 
     38     AVCSeqParamSet* extS = NULL;
     39     AVCPicParamSet* extP = NULL;
     40 
     41     if (extSPS) extS = (AVCSeqParamSet*) extSPS;
     42     if (extPPS) extP = (AVCPicParamSet*) extPPS;
     43 
     44     /* This part sets the default values of the encoding options this
     45     library supports in seqParam, picParam and sliceHdr structures and
     46     also copy the values from the encParam into the above 3 structures.
     47 
     48     Some parameters will be assigned later when we encode SPS or PPS such as
     49     the seq_parameter_id or pic_parameter_id. Also some of the slice parameters
     50     have to be re-assigned per slice basis such as frame_num, slice_type,
     51     first_mb_in_slice, pic_order_cnt_lsb, slice_qp_delta, slice_group_change_cycle */
     52 
     53     /* profile_idc, constrained_setx_flag and level_idc is set by VerifyProfile(),
     54     and VerifyLevel() functions later. */
     55 
     56     encvid->fullsearch_enable = encParam->fullsearch;
     57 
     58     encvid->outOfBandParamSet = ((encParam->out_of_band_param_set == AVC_ON) ? TRUE : FALSE);
     59 
     60     /* parameters derived from the the encParam that are used in SPS */
     61     if (extS)
     62     {
     63         video->MaxPicOrderCntLsb =  1 << (extS->log2_max_pic_order_cnt_lsb_minus4 + 4);
     64         video->PicWidthInMbs = extS->pic_width_in_mbs_minus1 + 1;
     65         video->PicHeightInMapUnits = extS->pic_height_in_map_units_minus1 + 1 ;
     66         video->FrameHeightInMbs = (2 - extS->frame_mbs_only_flag) * video->PicHeightInMapUnits ;
     67     }
     68     else
     69     {
     70         video->MaxPicOrderCntLsb =  1 << (encParam->log2_max_poc_lsb_minus_4 + 4);
     71         video->PicWidthInMbs = (encParam->width + 15) >> 4; /* round it to multiple of 16 */
     72         video->FrameHeightInMbs = (encParam->height + 15) >> 4; /* round it to multiple of 16 */
     73         video->PicHeightInMapUnits = video->FrameHeightInMbs;
     74     }
     75 
     76     video->PicWidthInSamplesL = video->PicWidthInMbs * 16 ;
     77     if (video->PicWidthInSamplesL + 32 > 0xFFFF)
     78     {
     79         return AVCENC_NOT_SUPPORTED; // we use 2-bytes for pitch
     80     }
     81 
     82     video->PicWidthInSamplesC = video->PicWidthInMbs * 8 ;
     83     video->PicHeightInMbs = video->FrameHeightInMbs;
     84     video->PicSizeInMapUnits = video->PicWidthInMbs * video->PicHeightInMapUnits ;
     85     video->PicHeightInSamplesL = video->PicHeightInMbs * 16;
     86     video->PicHeightInSamplesC = video->PicHeightInMbs * 8;
     87     video->PicSizeInMbs = video->PicWidthInMbs * video->PicHeightInMbs;
     88 
     89     if (!extS && !extP)
     90     {
     91         maxFrameNum = (encParam->idr_period == -1) ? (1 << 16) : encParam->idr_period;
     92         ii = 0;
     93         while (maxFrameNum > 0)
     94         {
     95             ii++;
     96             maxFrameNum >>= 1;
     97         }
     98         if (ii < 4) ii = 4;
     99         else if (ii > 16) ii = 16;
    100 
    101         seqParam->log2_max_frame_num_minus4 = ii - 4;//LOG2_MAX_FRAME_NUM_MINUS4; /* default */
    102 
    103         video->MaxFrameNum = 1 << ii; //(LOG2_MAX_FRAME_NUM_MINUS4 + 4); /* default */
    104         video->MaxPicNum = video->MaxFrameNum;
    105 
    106         /************* set the SPS *******************/
    107         seqParam->seq_parameter_set_id = 0; /* start with zero */
    108         /* POC */
    109         seqParam->pic_order_cnt_type = encParam->poc_type; /* POC type */
    110         if (encParam->poc_type == 0)
    111         {
    112             if (/*encParam->log2_max_poc_lsb_minus_4<0 || (no need, it's unsigned)*/
    113                 encParam->log2_max_poc_lsb_minus_4 > 12)
    114             {
    115                 return AVCENC_INVALID_POC_LSB;
    116             }
    117             seqParam->log2_max_pic_order_cnt_lsb_minus4 = encParam->log2_max_poc_lsb_minus_4;
    118         }
    119         else if (encParam->poc_type == 1)
    120         {
    121             seqParam->delta_pic_order_always_zero_flag = encParam->delta_poc_zero_flag;
    122             seqParam->offset_for_non_ref_pic = encParam->offset_poc_non_ref;
    123             seqParam->offset_for_top_to_bottom_field = encParam->offset_top_bottom;
    124             seqParam->num_ref_frames_in_pic_order_cnt_cycle = encParam->num_ref_in_cycle;
    125             if (encParam->offset_poc_ref == NULL)
    126             {
    127                 return AVCENC_ENCPARAM_MEM_FAIL;
    128             }
    129             for (ii = 0; ii < encParam->num_ref_frame; ii++)
    130             {
    131                 seqParam->offset_for_ref_frame[ii] = encParam->offset_poc_ref[ii];
    132             }
    133         }
    134         /* number of reference frame */
    135         if (encParam->num_ref_frame > 16 || encParam->num_ref_frame < 0)
    136         {
    137             return AVCENC_INVALID_NUM_REF;
    138         }
    139         seqParam->num_ref_frames = encParam->num_ref_frame; /* num reference frame range 0...16*/
    140         seqParam->gaps_in_frame_num_value_allowed_flag = FALSE;
    141         seqParam->pic_width_in_mbs_minus1 = video->PicWidthInMbs - 1;
    142         seqParam->pic_height_in_map_units_minus1 = video->PicHeightInMapUnits - 1;
    143         seqParam->frame_mbs_only_flag = TRUE;
    144         seqParam->mb_adaptive_frame_field_flag = FALSE;
    145         seqParam->direct_8x8_inference_flag = FALSE; /* default */
    146         seqParam->frame_cropping_flag = FALSE;
    147         seqParam->frame_crop_bottom_offset = 0;
    148         seqParam->frame_crop_left_offset = 0;
    149         seqParam->frame_crop_right_offset = 0;
    150         seqParam->frame_crop_top_offset = 0;
    151         seqParam->vui_parameters_present_flag = FALSE; /* default */
    152     }
    153     else if (extS) // use external SPS and PPS
    154     {
    155         seqParam->seq_parameter_set_id = extS->seq_parameter_set_id;
    156         seqParam->log2_max_frame_num_minus4 = extS->log2_max_frame_num_minus4;
    157         video->MaxFrameNum = 1 << (extS->log2_max_frame_num_minus4 + 4);
    158         video->MaxPicNum = video->MaxFrameNum;
    159         if (encParam->idr_period > (int)(video->MaxFrameNum) || (encParam->idr_period == -1))
    160         {
    161             encParam->idr_period = (int)video->MaxFrameNum;
    162         }
    163 
    164         seqParam->pic_order_cnt_type = extS->pic_order_cnt_type;
    165         if (seqParam->pic_order_cnt_type == 0)
    166         {
    167             if (/*extS->log2_max_pic_order_cnt_lsb_minus4<0 || (no need it's unsigned)*/
    168                 extS->log2_max_pic_order_cnt_lsb_minus4 > 12)
    169             {
    170                 return AVCENC_INVALID_POC_LSB;
    171             }
    172             seqParam->log2_max_pic_order_cnt_lsb_minus4 = extS->log2_max_pic_order_cnt_lsb_minus4;
    173         }
    174         else if (seqParam->pic_order_cnt_type == 1)
    175         {
    176             seqParam->delta_pic_order_always_zero_flag = extS->delta_pic_order_always_zero_flag;
    177             seqParam->offset_for_non_ref_pic = extS->offset_for_non_ref_pic;
    178             seqParam->offset_for_top_to_bottom_field = extS->offset_for_top_to_bottom_field;
    179             seqParam->num_ref_frames_in_pic_order_cnt_cycle = extS->num_ref_frames_in_pic_order_cnt_cycle;
    180             if (extS->offset_for_ref_frame == NULL)
    181             {
    182                 return AVCENC_ENCPARAM_MEM_FAIL;
    183             }
    184             for (ii = 0; ii < (int) extS->num_ref_frames; ii++)
    185             {
    186                 seqParam->offset_for_ref_frame[ii] = extS->offset_for_ref_frame[ii];
    187             }
    188         }
    189         /* number of reference frame */
    190         if (extS->num_ref_frames > 16 /*|| extS->num_ref_frames<0 (no need, it's unsigned)*/)
    191         {
    192             return AVCENC_INVALID_NUM_REF;
    193         }
    194         seqParam->num_ref_frames = extS->num_ref_frames; /* num reference frame range 0...16*/
    195         seqParam->gaps_in_frame_num_value_allowed_flag = extS->gaps_in_frame_num_value_allowed_flag;
    196         seqParam->pic_width_in_mbs_minus1 = extS->pic_width_in_mbs_minus1;
    197         seqParam->pic_height_in_map_units_minus1 = extS->pic_height_in_map_units_minus1;
    198         seqParam->frame_mbs_only_flag = extS->frame_mbs_only_flag;
    199         if (extS->frame_mbs_only_flag != TRUE)
    200         {
    201             return AVCENC_NOT_SUPPORTED;
    202         }
    203         seqParam->mb_adaptive_frame_field_flag = extS->mb_adaptive_frame_field_flag;
    204         if (extS->mb_adaptive_frame_field_flag != FALSE)
    205         {
    206             return AVCENC_NOT_SUPPORTED;
    207         }
    208 
    209         seqParam->direct_8x8_inference_flag = extS->direct_8x8_inference_flag;
    210         seqParam->frame_cropping_flag = extS->frame_cropping_flag ;
    211         if (extS->frame_cropping_flag != FALSE)
    212         {
    213             return AVCENC_NOT_SUPPORTED;
    214         }
    215 
    216         seqParam->frame_crop_bottom_offset = 0;
    217         seqParam->frame_crop_left_offset = 0;
    218         seqParam->frame_crop_right_offset = 0;
    219         seqParam->frame_crop_top_offset = 0;
    220         seqParam->vui_parameters_present_flag = extS->vui_parameters_present_flag;
    221         if (extS->vui_parameters_present_flag)
    222         {
    223             memcpy(&(seqParam->vui_parameters), &(extS->vui_parameters), sizeof(AVCVUIParams));
    224         }
    225     }
    226     else
    227     {
    228         return AVCENC_NOT_SUPPORTED;
    229     }
    230 
    231     /***************** now PPS ******************************/
    232     if (!extP && !extS)
    233     {
    234         picParam->pic_parameter_set_id = (uint)(-1); /* start with zero */
    235         picParam->seq_parameter_set_id = (uint)(-1); /* start with zero */
    236         picParam->entropy_coding_mode_flag = 0; /* default to CAVLC */
    237         picParam->pic_order_present_flag = 0; /* default for now, will need it for B-slice */
    238         /* FMO */
    239         if (encParam->num_slice_group < 1 || encParam->num_slice_group > MAX_NUM_SLICE_GROUP)
    240         {
    241             return AVCENC_INVALID_NUM_SLICEGROUP;
    242         }
    243         picParam->num_slice_groups_minus1 = encParam->num_slice_group - 1;
    244 
    245         if (picParam->num_slice_groups_minus1 > 0)
    246         {
    247             picParam->slice_group_map_type = encParam->fmo_type;
    248             switch (encParam->fmo_type)
    249             {
    250                 case 0:
    251                     for (ii = 0; ii <= (int)picParam->num_slice_groups_minus1; ii++)
    252                     {
    253                         picParam->run_length_minus1[ii] = encParam->run_length_minus1[ii];
    254                     }
    255                     break;
    256                 case 2:
    257                     for (ii = 0; ii < (int)picParam->num_slice_groups_minus1; ii++)
    258                     {
    259                         picParam->top_left[ii] = encParam->top_left[ii];
    260                         picParam->bottom_right[ii] = encParam->bottom_right[ii];
    261                     }
    262                     break;
    263                 case 3:
    264                 case 4:
    265                 case 5:
    266                     if (encParam->change_dir_flag == AVC_ON)
    267                     {
    268                         picParam->slice_group_change_direction_flag = TRUE;
    269                     }
    270                     else
    271                     {
    272                         picParam->slice_group_change_direction_flag = FALSE;
    273                     }
    274                     if (/*encParam->change_rate_minus1 < 0 || (no need it's unsigned) */
    275                         encParam->change_rate_minus1 > video->PicSizeInMapUnits - 1)
    276                     {
    277                         return AVCENC_INVALID_CHANGE_RATE;
    278                     }
    279                     picParam->slice_group_change_rate_minus1 = encParam->change_rate_minus1;
    280                     video->SliceGroupChangeRate = picParam->slice_group_change_rate_minus1 + 1;
    281                     break;
    282                 case 6:
    283                     picParam->pic_size_in_map_units_minus1 = video->PicSizeInMapUnits - 1;
    284 
    285                     /* allocate picParam->slice_group_id */
    286                     picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits, DEFAULT_ATTR);
    287                     if (picParam->slice_group_id == NULL)
    288                     {
    289                         return AVCENC_MEMORY_FAIL;
    290                     }
    291 
    292                     if (encParam->slice_group == NULL)
    293                     {
    294                         return AVCENC_ENCPARAM_MEM_FAIL;
    295                     }
    296                     for (ii = 0; ii < (int)video->PicSizeInMapUnits; ii++)
    297                     {
    298                         picParam->slice_group_id[ii] = encParam->slice_group[ii];
    299                     }
    300                     break;
    301                 default:
    302                     return AVCENC_INVALID_FMO_TYPE;
    303             }
    304         }
    305         picParam->num_ref_idx_l0_active_minus1 = encParam->num_ref_frame - 1; /* assume frame only */
    306         picParam->num_ref_idx_l1_active_minus1 = 0; /* default value */
    307         picParam->weighted_pred_flag = 0; /* no weighted prediction supported */
    308         picParam->weighted_bipred_idc = 0; /* range 0,1,2 */
    309         if (/*picParam->weighted_bipred_idc < 0 || (no need, it's unsigned) */
    310             picParam->weighted_bipred_idc > 2)
    311         {
    312             return AVCENC_WEIGHTED_BIPRED_FAIL;
    313         }
    314         picParam->pic_init_qp_minus26 = 0; /* default, will be changed at slice level anyway */
    315         if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
    316         {
    317             return AVCENC_INIT_QP_FAIL; /* out of range */
    318         }
    319         picParam->pic_init_qs_minus26 = 0;
    320         if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
    321         {
    322             return AVCENC_INIT_QS_FAIL; /* out of range */
    323         }
    324 
    325         picParam->chroma_qp_index_offset = 0; /* default to zero for now */
    326         if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
    327         {
    328             return AVCENC_CHROMA_QP_FAIL; /* out of range */
    329         }
    330         /* deblocking */
    331         picParam->deblocking_filter_control_present_flag = (encParam->db_filter == AVC_ON) ? TRUE : FALSE ;
    332         /* constrained intra prediction */
    333         picParam->constrained_intra_pred_flag = (encParam->constrained_intra_pred == AVC_ON) ? TRUE : FALSE;
    334         picParam->redundant_pic_cnt_present_flag = 0; /* default */
    335     }
    336     else if (extP)// external PPS
    337     {
    338         picParam->pic_parameter_set_id = extP->pic_parameter_set_id - 1; /* to be increased by one */
    339         picParam->seq_parameter_set_id = extP->seq_parameter_set_id;
    340         picParam->entropy_coding_mode_flag = extP->entropy_coding_mode_flag;
    341         if (extP->entropy_coding_mode_flag != 0) /* default to CAVLC */
    342         {
    343             return AVCENC_NOT_SUPPORTED;
    344         }
    345         picParam->pic_order_present_flag = extP->pic_order_present_flag; /* default for now, will need it for B-slice */
    346         if (extP->pic_order_present_flag != 0)
    347         {
    348             return AVCENC_NOT_SUPPORTED;
    349         }
    350         /* FMO */
    351         if (/*(extP->num_slice_groups_minus1<0) || (no need it's unsigned) */
    352             (extP->num_slice_groups_minus1 > MAX_NUM_SLICE_GROUP - 1))
    353         {
    354             return AVCENC_INVALID_NUM_SLICEGROUP;
    355         }
    356         picParam->num_slice_groups_minus1 = extP->num_slice_groups_minus1;
    357 
    358         if (picParam->num_slice_groups_minus1 > 0)
    359         {
    360             picParam->slice_group_map_type = extP->slice_group_map_type;
    361             switch (extP->slice_group_map_type)
    362             {
    363                 case 0:
    364                     for (ii = 0; ii <= (int)extP->num_slice_groups_minus1; ii++)
    365                     {
    366                         picParam->run_length_minus1[ii] = extP->run_length_minus1[ii];
    367                     }
    368                     break;
    369                 case 2:
    370                     for (ii = 0; ii < (int)picParam->num_slice_groups_minus1; ii++)
    371                     {
    372                         picParam->top_left[ii] = extP->top_left[ii];
    373                         picParam->bottom_right[ii] = extP->bottom_right[ii];
    374                     }
    375                     break;
    376                 case 3:
    377                 case 4:
    378                 case 5:
    379                     picParam->slice_group_change_direction_flag = extP->slice_group_change_direction_flag;
    380                     if (/*extP->slice_group_change_rate_minus1 < 0 || (no need, it's unsigned) */
    381                         extP->slice_group_change_rate_minus1 > video->PicSizeInMapUnits - 1)
    382                     {
    383                         return AVCENC_INVALID_CHANGE_RATE;
    384                     }
    385                     picParam->slice_group_change_rate_minus1 = extP->slice_group_change_rate_minus1;
    386                     video->SliceGroupChangeRate = picParam->slice_group_change_rate_minus1 + 1;
    387                     break;
    388                 case 6:
    389                     if (extP->pic_size_in_map_units_minus1 != video->PicSizeInMapUnits - 1)
    390                     {
    391                         return AVCENC_NOT_SUPPORTED;
    392                     }
    393 
    394                     picParam->pic_size_in_map_units_minus1 = extP->pic_size_in_map_units_minus1;
    395 
    396                     /* allocate picParam->slice_group_id */
    397                     picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits, DEFAULT_ATTR);
    398                     if (picParam->slice_group_id == NULL)
    399                     {
    400                         return AVCENC_MEMORY_FAIL;
    401                     }
    402 
    403                     if (extP->slice_group_id == NULL)
    404                     {
    405                         return AVCENC_ENCPARAM_MEM_FAIL;
    406                     }
    407                     for (ii = 0; ii < (int)video->PicSizeInMapUnits; ii++)
    408                     {
    409                         picParam->slice_group_id[ii] = extP->slice_group_id[ii];
    410                     }
    411                     break;
    412                 default:
    413                     return AVCENC_INVALID_FMO_TYPE;
    414             }
    415         }
    416         picParam->num_ref_idx_l0_active_minus1 = extP->num_ref_idx_l0_active_minus1;
    417         picParam->num_ref_idx_l1_active_minus1 = extP->num_ref_idx_l1_active_minus1; /* default value */
    418         if (picParam->num_ref_idx_l1_active_minus1 != 0)
    419         {
    420             return AVCENC_NOT_SUPPORTED;
    421         }
    422 
    423         if (extP->weighted_pred_flag)
    424         {
    425             return AVCENC_NOT_SUPPORTED;
    426         }
    427 
    428         picParam->weighted_pred_flag = 0; /* no weighted prediction supported */
    429         picParam->weighted_bipred_idc = extP->weighted_bipred_idc; /* range 0,1,2 */
    430         if (/*picParam->weighted_bipred_idc < 0 || (no need, it's unsigned) */
    431             picParam->weighted_bipred_idc > 2)
    432         {
    433             return AVCENC_WEIGHTED_BIPRED_FAIL;
    434         }
    435         picParam->pic_init_qp_minus26 = extP->pic_init_qp_minus26; /* default, will be changed at slice level anyway */
    436         if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
    437         {
    438             return AVCENC_INIT_QP_FAIL; /* out of range */
    439         }
    440         picParam->pic_init_qs_minus26 = extP->pic_init_qs_minus26;
    441         if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
    442         {
    443             return AVCENC_INIT_QS_FAIL; /* out of range */
    444         }
    445 
    446         picParam->chroma_qp_index_offset = extP->chroma_qp_index_offset; /* default to zero for now */
    447         if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
    448         {
    449             return AVCENC_CHROMA_QP_FAIL; /* out of range */
    450         }
    451         /* deblocking */
    452         picParam->deblocking_filter_control_present_flag = extP->deblocking_filter_control_present_flag;
    453         /* constrained intra prediction */
    454         picParam->constrained_intra_pred_flag = extP->constrained_intra_pred_flag;
    455         if (extP->redundant_pic_cnt_present_flag  != 0)
    456         {
    457             return AVCENC_NOT_SUPPORTED;
    458         }
    459         picParam->redundant_pic_cnt_present_flag = extP->redundant_pic_cnt_present_flag; /* default */
    460     }
    461     else
    462     {
    463         return AVCENC_NOT_SUPPORTED;
    464     }
    465 
    466     /****************** now set up some SliceHeader parameters ***********/
    467     if (picParam->deblocking_filter_control_present_flag == TRUE)
    468     {
    469         /* these values only present when db_filter is ON */
    470         if (encParam->disable_db_idc > 2)
    471         {
    472             return AVCENC_INVALID_DEBLOCK_IDC; /* out of range */
    473         }
    474         sliceHdr->disable_deblocking_filter_idc = encParam->disable_db_idc;
    475 
    476         if (encParam->alpha_offset < -6 || encParam->alpha_offset > 6)
    477         {
    478             return AVCENC_INVALID_ALPHA_OFFSET;
    479         }
    480         sliceHdr->slice_alpha_c0_offset_div2 = encParam->alpha_offset;
    481 
    482         if (encParam->beta_offset < -6 || encParam->beta_offset > 6)
    483         {
    484             return AVCENC_INVALID_BETA_OFFSET;
    485         }
    486         sliceHdr->slice_beta_offset_div_2 =  encParam->beta_offset;
    487     }
    488     if (encvid->outOfBandParamSet == TRUE)
    489     {
    490         sliceHdr->idr_pic_id = 0;
    491     }
    492     else
    493     {
    494         sliceHdr->idr_pic_id = (uint)(-1); /* start with zero */
    495     }
    496     sliceHdr->field_pic_flag = FALSE;
    497     sliceHdr->bottom_field_flag = FALSE;  /* won't be used anyway */
    498     video->MbaffFrameFlag = (seqParam->mb_adaptive_frame_field_flag && !sliceHdr->field_pic_flag);
    499 
    500     /* the rest will be set in InitSlice() */
    501 
    502     /* now the rate control and performance related parameters */
    503     rateCtrl->scdEnable = (encParam->auto_scd == AVC_ON) ? TRUE : FALSE;
    504     rateCtrl->idrPeriod = encParam->idr_period + 1;
    505     rateCtrl->intraMBRate = encParam->intramb_refresh;
    506     rateCtrl->dpEnable = (encParam->data_par == AVC_ON) ? TRUE : FALSE;
    507 
    508     rateCtrl->subPelEnable = (encParam->sub_pel == AVC_ON) ? TRUE : FALSE;
    509     rateCtrl->mvRange = encParam->search_range;
    510 
    511     rateCtrl->subMBEnable = (encParam->submb_pred == AVC_ON) ? TRUE : FALSE;
    512     rateCtrl->rdOptEnable = (encParam->rdopt_mode == AVC_ON) ? TRUE : FALSE;
    513     rateCtrl->bidirPred = (encParam->bidir_pred == AVC_ON) ? TRUE : FALSE;
    514 
    515     rateCtrl->rcEnable = (encParam->rate_control == AVC_ON) ? TRUE : FALSE;
    516     rateCtrl->initQP = encParam->initQP;
    517     rateCtrl->initQP = AVC_CLIP3(0, 51, rateCtrl->initQP);
    518 
    519     rateCtrl->bitRate = encParam->bitrate;
    520     rateCtrl->cpbSize = encParam->CPB_size;
    521     rateCtrl->initDelayOffset = (rateCtrl->bitRate * encParam->init_CBP_removal_delay / 1000);
    522 
    523     if (encParam->frame_rate == 0)
    524     {
    525         return AVCENC_INVALID_FRAMERATE;
    526     }
    527 
    528     rateCtrl->frame_rate = (OsclFloat)(encParam->frame_rate * 1.0 / 1000);
    529 //  rateCtrl->srcInterval = encParam->src_interval;
    530     rateCtrl->first_frame = 1; /* set this flag for the first time */
    531 
    532     /* contrained_setx_flag will be set inside the VerifyProfile called below.*/
    533     if (!extS && !extP)
    534     {
    535         seqParam->profile_idc = encParam->profile;
    536         seqParam->constrained_set0_flag = FALSE;
    537         seqParam->constrained_set1_flag = FALSE;
    538         seqParam->constrained_set2_flag = FALSE;
    539         seqParam->constrained_set3_flag = FALSE;
    540         seqParam->level_idc = encParam->level;
    541     }
    542     else
    543     {
    544         seqParam->profile_idc = extS->profile_idc;
    545         seqParam->constrained_set0_flag = extS->constrained_set0_flag;
    546         seqParam->constrained_set1_flag = extS->constrained_set1_flag;
    547         seqParam->constrained_set2_flag = extS->constrained_set2_flag;
    548         seqParam->constrained_set3_flag = extS->constrained_set3_flag;
    549         seqParam->level_idc = extS->level_idc;
    550     }
    551 
    552 
    553     status = VerifyProfile(encvid, seqParam, picParam);
    554     if (status != AVCENC_SUCCESS)
    555     {
    556         return status;
    557     }
    558 
    559     status = VerifyLevel(encvid, seqParam, picParam);
    560     if (status != AVCENC_SUCCESS)
    561     {
    562         return status;
    563     }
    564 
    565     return AVCENC_SUCCESS;
    566 }
    567 
    568 /* verify the profile setting */
    569 AVCEnc_Status VerifyProfile(AVCEncObject *encvid, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam)
    570 {
    571     AVCRateControl *rateCtrl = encvid->rateCtrl;
    572     AVCEnc_Status status = AVCENC_SUCCESS;
    573 
    574     if (seqParam->profile_idc == 0) /* find profile for this setting */
    575     {
    576         /* find the right profile for it */
    577         if (seqParam->direct_8x8_inference_flag == TRUE &&
    578                 picParam->entropy_coding_mode_flag == FALSE &&
    579                 picParam->num_slice_groups_minus1 <= 7 /*&&
    580             picParam->num_slice_groups_minus1>=0 (no need, it's unsigned) */)
    581         {
    582             seqParam->profile_idc = AVC_EXTENDED;
    583             seqParam->constrained_set2_flag = TRUE;
    584         }
    585 
    586         if (rateCtrl->dpEnable == FALSE &&
    587                 picParam->num_slice_groups_minus1 == 0 &&
    588                 picParam->redundant_pic_cnt_present_flag == FALSE)
    589         {
    590             seqParam->profile_idc = AVC_MAIN;
    591             seqParam->constrained_set1_flag = TRUE;
    592         }
    593 
    594         if (rateCtrl->bidirPred == FALSE &&
    595                 rateCtrl->dpEnable == FALSE &&
    596                 seqParam->frame_mbs_only_flag == TRUE &&
    597                 picParam->weighted_pred_flag == FALSE &&
    598                 picParam->weighted_bipred_idc == 0 &&
    599                 picParam->entropy_coding_mode_flag == FALSE &&
    600                 picParam->num_slice_groups_minus1 <= 7 /*&&
    601             picParam->num_slice_groups_minus1>=0 (no need, it's unsigned)*/)
    602         {
    603             seqParam->profile_idc = AVC_BASELINE;
    604             seqParam->constrained_set0_flag = TRUE;
    605         }
    606 
    607         if (seqParam->profile_idc == 0) /* still zero */
    608         {
    609             return AVCENC_PROFILE_NOT_SUPPORTED;
    610         }
    611     }
    612 
    613     /* check the list of supported profile by this library */
    614     switch (seqParam->profile_idc)
    615     {
    616         case AVC_BASELINE:
    617             if (rateCtrl->bidirPred == TRUE ||
    618                     rateCtrl->dpEnable == TRUE ||
    619                     seqParam->frame_mbs_only_flag != TRUE ||
    620                     picParam->weighted_pred_flag == TRUE ||
    621                     picParam->weighted_bipred_idc != 0 ||
    622                     picParam->entropy_coding_mode_flag == TRUE ||
    623                     picParam->num_slice_groups_minus1 > 7 /*||
    624             picParam->num_slice_groups_minus1<0 (no need, it's unsigned) */)
    625             {
    626                 status = AVCENC_TOOLS_NOT_SUPPORTED;
    627             }
    628             break;
    629 
    630         case AVC_MAIN:
    631         case AVC_EXTENDED:
    632             status = AVCENC_PROFILE_NOT_SUPPORTED;
    633     }
    634 
    635     return status;
    636 }
    637 
    638 /* verify the level setting */
    639 AVCEnc_Status VerifyLevel(AVCEncObject *encvid, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam)
    640 {
    641     (void)(picParam);
    642 
    643     AVCRateControl *rateCtrl = encvid->rateCtrl;
    644     AVCCommonObj *video = encvid->common;
    645     int mb_per_sec, ii;
    646     int lev_idx;
    647     int dpb_size;
    648 
    649     mb_per_sec = (int)(video->PicSizeInMbs * rateCtrl->frame_rate + 0.5);
    650     dpb_size = (seqParam->num_ref_frames * video->PicSizeInMbs * 3) >> 6;
    651 
    652     if (seqParam->level_idc == 0) /* find level for this setting */
    653     {
    654         for (ii = 0; ii < MAX_LEVEL_IDX; ii++)
    655         {
    656             if (mb_per_sec <= MaxMBPS[ii] &&
    657                     video->PicSizeInMbs <= (uint)MaxFS[ii] &&
    658                     rateCtrl->bitRate <= (int32)MaxBR[ii]*1000 &&
    659                     rateCtrl->cpbSize <= (int32)MaxCPB[ii]*1000 &&
    660                     rateCtrl->mvRange <= MaxVmvR[ii] &&
    661                     dpb_size <= MaxDPBX2[ii]*512)
    662             {
    663                 seqParam->level_idc = mapIdx2Lev[ii];
    664                 break;
    665             }
    666         }
    667         if (seqParam->level_idc == 0)
    668         {
    669             return AVCENC_LEVEL_NOT_SUPPORTED;
    670         }
    671     }
    672 
    673     /* check if this level is supported by this library */
    674     lev_idx = mapLev2Idx[seqParam->level_idc];
    675     if (seqParam->level_idc == AVC_LEVEL1_B)
    676     {
    677         seqParam->constrained_set3_flag = 1;
    678     }
    679 
    680 
    681     if (lev_idx == 255) /* not defined */
    682     {
    683         return AVCENC_LEVEL_NOT_SUPPORTED;
    684     }
    685 
    686     /* check if the encoding setting complies with the level */
    687     if (mb_per_sec > MaxMBPS[lev_idx] ||
    688             video->PicSizeInMbs > (uint)MaxFS[lev_idx] ||
    689             rateCtrl->bitRate > (int32)MaxBR[lev_idx]*1000 ||
    690             rateCtrl->cpbSize > (int32)MaxCPB[lev_idx]*1000 ||
    691             rateCtrl->mvRange > MaxVmvR[lev_idx])
    692     {
    693         return AVCENC_LEVEL_FAIL;
    694     }
    695 
    696     return AVCENC_SUCCESS;
    697 }
    698 
    699 /* initialize variables at the beginning of each frame */
    700 /* determine the picture type */
    701 /* encode POC */
    702 /* maybe we should do more stuff here. MotionEstimation+SCD and generate a new SPS and PPS */
    703 AVCEnc_Status InitFrame(AVCEncObject *encvid)
    704 {
    705     AVCStatus ret;
    706     AVCEnc_Status status;
    707     AVCCommonObj *video = encvid->common;
    708     AVCSliceHeader *sliceHdr = video->sliceHdr;
    709 
    710     /* look for the next frame in coding_order and look for available picture
    711        in the DPB. Note, video->currFS->PicOrderCnt, currFS->FrameNum and currPic->PicNum
    712        are set to wrong number in this function (right for decoder). */
    713     if (video->nal_unit_type == AVC_NALTYPE_IDR)
    714     {
    715         // call init DPB in here.
    716         ret = AVCConfigureSequence(encvid->avcHandle, video, TRUE);
    717         if (ret != AVC_SUCCESS)
    718         {
    719             return AVCENC_FAIL;
    720         }
    721     }
    722 
    723     /* flexible macroblock ordering (every frame)*/
    724     /* populate video->mapUnitToSliceGroupMap and video->MbToSliceGroupMap */
    725     /* It changes once per each PPS. */
    726     FMOInit(video);
    727 
    728     ret = DPBInitBuffer(encvid->avcHandle, video); // get new buffer
    729 
    730     if (ret != AVC_SUCCESS)
    731     {
    732         return (AVCEnc_Status)ret; // AVCENC_PICTURE_READY, FAIL
    733     }
    734 
    735     DPBInitPic(video, 0); /* 0 is dummy */
    736 
    737     /************* determine picture type IDR or non-IDR ***********/
    738     video->currPicType = AVC_FRAME;
    739     video->slice_data_partitioning = FALSE;
    740     encvid->currInput->is_reference = 1; /* default to all frames */
    741     video->nal_ref_idc = 1;  /* need to set this for InitPOC */
    742     video->currPic->isReference = TRUE;
    743 
    744     /************* set frame_num ********************/
    745     if (video->nal_unit_type == AVC_NALTYPE_IDR)
    746     {
    747         video->prevFrameNum = video->MaxFrameNum;
    748         video->PrevRefFrameNum = 0;
    749         sliceHdr->frame_num = 0;
    750     }
    751     /* otherwise, it's set to previous reference frame access unit's frame_num in decoding order,
    752        see the end of PVAVCDecodeSlice()*/
    753     /* There's also restriction on the frame_num, see page 59 of JVT-I1010.doc. */
    754     /* Basically, frame_num can't be repeated unless it's opposite fields or non reference fields */
    755     else
    756     {
    757         sliceHdr->frame_num = (video->PrevRefFrameNum + 1) % video->MaxFrameNum;
    758     }
    759     video->CurrPicNum = sliceHdr->frame_num;  /* for field_pic_flag = 0 */
    760     //video->CurrPicNum = 2*sliceHdr->frame_num + 1; /* for field_pic_flag = 1 */
    761 
    762     /* assign pic_order_cnt, video->PicOrderCnt */
    763     status = InitPOC(encvid);
    764     if (status != AVCENC_SUCCESS)  /* incorrigable fail */
    765     {
    766         return status;
    767     }
    768 
    769     /* Initialize refListIdx for this picture */
    770     RefListInit(video);
    771 
    772     /************* motion estimation and scene analysis ************/
    773     // , to move this to MB-based MV search for comparison
    774     // use sub-optimal QP for mv search
    775     AVCMotionEstimation(encvid);  /* AVCENC_SUCCESS or AVCENC_NEW_IDR */
    776 
    777     /* after this point, the picture type will be fixed to either IDR or non-IDR */
    778     video->currFS->PicOrderCnt = video->PicOrderCnt;
    779     video->currFS->FrameNum = video->sliceHdr->frame_num;
    780     video->currPic->PicNum = video->CurrPicNum;
    781     video->mbNum = 0; /* start from zero MB */
    782     encvid->currSliceGroup = 0; /* start from slice group #0 */
    783     encvid->numIntraMB = 0; /* reset this counter */
    784 
    785     if (video->nal_unit_type == AVC_NALTYPE_IDR)
    786     {
    787         RCInitGOP(encvid);
    788 
    789         /* calculate picture QP */
    790         RCInitFrameQP(encvid);
    791 
    792         return AVCENC_NEW_IDR;
    793     }
    794 
    795     /* calculate picture QP */
    796     RCInitFrameQP(encvid); /* get QP after MV search */
    797 
    798     return AVCENC_SUCCESS;
    799 }
    800 
    801 /* initialize variables for this slice */
    802 AVCEnc_Status InitSlice(AVCEncObject *encvid)
    803 {
    804     AVCCommonObj *video = encvid->common;
    805     AVCSliceHeader *sliceHdr = video->sliceHdr;
    806     AVCPicParamSet *currPPS = video->currPicParams;
    807     AVCSeqParamSet *currSPS = video->currSeqParams;
    808     int slice_type = video->slice_type;
    809 
    810     sliceHdr->first_mb_in_slice = video->mbNum;
    811     if (video->mbNum) // not first slice of a frame
    812     {
    813         video->sliceHdr->slice_type = (AVCSliceType)slice_type;
    814     }
    815 
    816     /* sliceHdr->slice_type already set in InitFrame */
    817 
    818     sliceHdr->pic_parameter_set_id = video->currPicParams->pic_parameter_set_id;
    819 
    820     /* sliceHdr->frame_num already set in InitFrame */
    821 
    822     if (!currSPS->frame_mbs_only_flag)  /* we shouldn't need this check */
    823     {
    824         sliceHdr->field_pic_flag = sliceHdr->bottom_field_flag = FALSE;
    825         return AVCENC_TOOLS_NOT_SUPPORTED;
    826     }
    827 
    828     /* sliceHdr->idr_pic_id already set in PVAVCEncodeNAL
    829 
    830      sliceHdr->pic_order_cnt_lsb already set in InitFrame..InitPOC
    831      sliceHdr->delta_pic_order_cnt_bottom  already set in InitPOC
    832 
    833     sliceHdr->delta_pic_order_cnt[0] already set in InitPOC
    834     sliceHdr->delta_pic_order_cnt[1] already set in InitPOC
    835     */
    836 
    837     sliceHdr->redundant_pic_cnt = 0; /* default if(currPPS->redundant_pic_cnt_present_flag), range 0..127 */
    838     sliceHdr->direct_spatial_mv_pred_flag = 0; // default if(slice_type == AVC_B_SLICE)
    839 
    840     sliceHdr->num_ref_idx_active_override_flag = FALSE; /* default, if(slice_type== P,SP or B)*/
    841     sliceHdr->num_ref_idx_l0_active_minus1 = 0; /* default, if (num_ref_idx_active_override_flag) */
    842     sliceHdr->num_ref_idx_l1_active_minus1 = 0; /* default, if above and B_slice */
    843     /* the above 2 values range from 0..15 for frame picture and 0..31 for field picture */
    844 
    845     /* ref_pic_list_reordering(), currently we don't do anything */
    846     sliceHdr->ref_pic_list_reordering_flag_l0 = FALSE; /* default */
    847     sliceHdr->ref_pic_list_reordering_flag_l1 = FALSE; /* default */
    848     /* if the above are TRUE, some other params must be set */
    849 
    850     if ((currPPS->weighted_pred_flag && (slice_type == AVC_P_SLICE || slice_type == AVC_SP_SLICE)) ||
    851             (currPPS->weighted_bipred_idc == 1 && slice_type == AVC_B_SLICE))
    852     {
    853         //      pred_weight_table(); // not supported !!
    854         return AVCENC_TOOLS_NOT_SUPPORTED;
    855     }
    856 
    857     /* dec_ref_pic_marking(), this will be done later*/
    858     sliceHdr->no_output_of_prior_pics_flag = FALSE; /* default */
    859     sliceHdr->long_term_reference_flag = FALSE; /* for IDR frame, do not make it long term */
    860     sliceHdr->adaptive_ref_pic_marking_mode_flag = FALSE; /* default */
    861     /* other params are not set here because they are not used */
    862 
    863     sliceHdr->cabac_init_idc = 0; /* default, if entropy_coding_mode_flag && slice_type==I or SI, range 0..2  */
    864     sliceHdr->slice_qp_delta = 0; /* default for now */
    865     sliceHdr->sp_for_switch_flag = FALSE; /* default, if slice_type == SP */
    866     sliceHdr->slice_qs_delta = 0; /* default, if slice_type == SP or SI */
    867 
    868     /* derived variables from encParam */
    869     /* deblocking filter */
    870     video->FilterOffsetA = video->FilterOffsetB = 0;
    871     if (currPPS->deblocking_filter_control_present_flag == TRUE)
    872     {
    873         video->FilterOffsetA = sliceHdr->slice_alpha_c0_offset_div2 << 1;
    874         video->FilterOffsetB = sliceHdr->slice_beta_offset_div_2 << 1;
    875     }
    876 
    877     /* flexible macroblock ordering */
    878     /* populate video->mapUnitToSliceGroupMap and video->MbToSliceGroupMap */
    879     /* We already call it at the end of PVAVCEncInitialize(). It changes once per each PPS. */
    880     if (video->currPicParams->num_slice_groups_minus1 > 0 && video->currPicParams->slice_group_map_type >= 3
    881             && video->currPicParams->slice_group_map_type <= 5)
    882     {
    883         sliceHdr->slice_group_change_cycle = SLICE_GROUP_CHANGE_CYCLE;  /* default, don't understand how to set it!!!*/
    884 
    885         video->MapUnitsInSliceGroup0 =
    886             AVC_MIN(sliceHdr->slice_group_change_cycle * video->SliceGroupChangeRate, video->PicSizeInMapUnits);
    887 
    888         FMOInit(video);
    889     }
    890 
    891     /* calculate SliceQPy first  */
    892     /* calculate QSy first */
    893 
    894     sliceHdr->slice_qp_delta = video->QPy - 26 - currPPS->pic_init_qp_minus26;
    895     //sliceHdr->slice_qs_delta = video->QSy - 26 - currPPS->pic_init_qs_minus26;
    896 
    897     return AVCENC_SUCCESS;
    898 }
    899 
    900