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