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