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