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*/
25AVCEnc_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 */
565AVCEnc_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 */
635AVCEnc_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 */
699AVCEnc_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 */
798AVCEnc_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