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