1 /*
2 * Copyright (c) 2020, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     encode_avc_header_packer.cpp
24 //! \brief    Defines header packing logic for avc encode
25 //!
26 
27 #include "encode_avc_header_packer.h"
28 #include "encode_utils.h"
29 
30 namespace encode
31 {
32 
33 #define ENCODE_AVC_EXTENDED_SAR 255
34 
SetNalUnit(uint8_t ** bsbuffer,uint8_t refIDC,CODECHAL_ENCODE_AVC_NAL_UNIT_TYPE nalType)35 static void SetNalUnit(uint8_t **bsbuffer, uint8_t refIDC, CODECHAL_ENCODE_AVC_NAL_UNIT_TYPE nalType)
36 {
37     uint8_t *byte = *bsbuffer;
38 
39     // for SPS and PPS NAL units zero_byte should exist
40     if (nalType == CODECHAL_ENCODE_AVC_NAL_UT_SPS || nalType == CODECHAL_ENCODE_AVC_NAL_UT_PPS || nalType == CODECHAL_ENCODE_AVC_NAL_UT_AUD)
41     {
42         *byte++ = 0;
43     }
44 
45     *byte++   = 0;
46     *byte++   = 0;
47     *byte++   = 1;
48     *byte++   = (uint8_t)((refIDC << 5) | nalType);
49     *byte     = 0;  // Clear the next byte
50     *bsbuffer = byte;
51 }
52 
PutBit(BSBuffer * bsbuffer,uint32_t code)53 static void PutBit(BSBuffer *bsbuffer, uint32_t code)
54 {
55     if (code & 1)
56     {
57         *(bsbuffer->pCurrent) = (*(bsbuffer->pCurrent) | (uint8_t)(0x01 << (7 - bsbuffer->BitOffset)));
58     }
59 
60     bsbuffer->BitOffset++;
61     if (bsbuffer->BitOffset == 8)
62     {
63         bsbuffer->BitOffset = 0;
64         bsbuffer->pCurrent++;
65         *(bsbuffer->pCurrent) = 0;
66     }
67 }
68 
PutBitsSub(BSBuffer * bsbuffer,uint32_t code,uint32_t length)69 static void PutBitsSub(BSBuffer *bsbuffer, uint32_t code, uint32_t length)
70 {
71     uint8_t *byte = bsbuffer->pCurrent;
72 
73     // make sure that the number of bits given is <= 24
74     ENCODE_ASSERT(length <= 24);
75 
76     code <<= (32 - length);
77 
78     // shift field so that the given code begins at the current bit
79     // offset in the most significant byte of the 32-bit word
80     length += bsbuffer->BitOffset;
81     code >>= bsbuffer->BitOffset;
82 
83     // write bytes back into memory, big-endian
84     byte[0] = (uint8_t)((code >> 24) | byte[0]);
85     byte[1] = (uint8_t)(code >> 16);
86     if (length > 16)
87     {
88         byte[2] = (uint8_t)(code >> 8);
89         byte[3] = (uint8_t)code;
90     }
91     else
92     {
93         byte[2] = 0;
94     }
95 
96     // update bitstream pointer and bit offset
97     bsbuffer->pCurrent += (length >> 3);
98     bsbuffer->BitOffset = (length & 7);
99 }
100 
PutBits(BSBuffer * bsbuffer,uint32_t code,uint32_t length)101 static void PutBits(BSBuffer *bsbuffer, uint32_t code, uint32_t length)
102 {
103     uint32_t code1, code2;
104 
105     // temp solution, only support up to 32 bits based on current usage
106     ENCODE_ASSERT(length <= 32);
107 
108     if (length >= 24)
109     {
110         code1 = code & 0xFFFF;
111         code2 = code >> 16;
112 
113         // high bits go first
114         PutBitsSub(bsbuffer, code2, length - 16);
115         PutBitsSub(bsbuffer, code1, 16);
116     }
117     else
118     {
119         PutBitsSub(bsbuffer, code, length);
120     }
121 }
122 
PutVLCCode(BSBuffer * bsbuffer,uint32_t code)123 static void PutVLCCode(BSBuffer *bsbuffer, uint32_t code)
124 {
125     uint8_t  leadingZeroBits, bitcount;
126     uint32_t code1, bits;
127 
128     code1    = code + 1;
129     bitcount = 0;
130     while (code1)
131     {
132         code1 >>= 1;
133         bitcount++;
134     }
135 
136     if (bitcount == 1)
137     {
138         PutBit(bsbuffer, 1);
139     }
140     else
141     {
142         leadingZeroBits = bitcount - 1;
143         bits            = code + 1 - (1 << leadingZeroBits);
144         PutBits(bsbuffer, 1, leadingZeroBits + 1);
145         PutBits(bsbuffer, bits, leadingZeroBits);
146     }
147 }
148 
SetTrailingBits(BSBuffer * bsbuffer)149 static void SetTrailingBits(BSBuffer *bsbuffer)
150 {
151     // Write Stop Bit
152     PutBits(bsbuffer, 1, 1);
153     // Make byte aligned
154     while (bsbuffer->BitOffset)
155     {
156         PutBit(bsbuffer, 0);
157     }
158 }
159 
PackScalingList(BSBuffer * bsbuffer,uint8_t * scalingList,uint8_t sizeOfScalingList)160 static void PackScalingList(BSBuffer *bsbuffer, uint8_t *scalingList, uint8_t sizeOfScalingList)
161 {
162     uint8_t lastScale, nextScale, j;
163     char    delta_scale;
164 
165     lastScale = nextScale = 8;
166 
167     for (j = 0; j < sizeOfScalingList; j++)
168     {
169         if (nextScale != 0)
170         {
171             delta_scale = (char)(scalingList[j] - lastScale);
172 
173             PutVLCCode(bsbuffer, SIGNED(delta_scale));
174 
175             nextScale = scalingList[j];
176         }
177         lastScale = (nextScale == 0) ? lastScale : nextScale;
178     }
179 }
180 
PackAUDParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)181 MOS_STATUS AvcEncodeHeaderPacker::PackAUDParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)
182 {
183     uint32_t   picType;
184     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
185 
186     ENCODE_CHK_NULL_RETURN(params);
187     ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
188 
189     // refer table 7-5 in H.264 spec on primary_pic_type
190     // Here I,P,B types are included
191     // According BD Spec 9.5.1.1, 0 - I; 1 - P; 2 - B
192 
193     picType = (uint32_t)(params->wPictureCodingType) - 1;
194     PutBits(params->pBsBuffer, picType, 3);
195 
196     return eStatus;
197 }
198 
PackHrdParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)199 MOS_STATUS AvcEncodeHeaderPacker::PackHrdParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)
200 {
201     PCODECHAL_ENCODE_AVC_VUI_PARAMS vuiParams;
202     PBSBuffer                       bsbuffer;
203     int                             schedSelIdx;
204     MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;
205 
206     ENCODE_CHK_NULL_RETURN(params);
207 
208     vuiParams = params->pAvcVuiParams;
209     bsbuffer  = params->pBsBuffer;
210 
211     PutVLCCode(bsbuffer, vuiParams->cpb_cnt_minus1);
212     PutBits(bsbuffer, vuiParams->bit_rate_scale, 4);
213     PutBits(bsbuffer, vuiParams->cpb_size_scale, 4);
214 
215     for (schedSelIdx = 0; schedSelIdx <= vuiParams->cpb_cnt_minus1; schedSelIdx++)
216     {
217         PutVLCCode(bsbuffer, vuiParams->bit_rate_value_minus1[schedSelIdx]);
218         PutVLCCode(bsbuffer, vuiParams->cpb_size_value_minus1[schedSelIdx]);
219         PutBit(bsbuffer, ((vuiParams->cbr_flag >> schedSelIdx) & 1));
220     }
221 
222     PutBits(bsbuffer, vuiParams->initial_cpb_removal_delay_length_minus1, 5);
223     PutBits(bsbuffer, vuiParams->cpb_removal_delay_length_minus1, 5);
224     PutBits(bsbuffer, vuiParams->dpb_output_delay_length_minus1, 5);
225     PutBits(bsbuffer, vuiParams->time_offset_length, 5);
226 
227     return eStatus;
228 }
229 
PackVuiParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)230 MOS_STATUS AvcEncodeHeaderPacker::PackVuiParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)
231 {
232     PCODECHAL_ENCODE_AVC_VUI_PARAMS vuiParams;
233     PBSBuffer                       bsbuffer;
234     MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;
235 
236     ENCODE_CHK_NULL_RETURN(params);
237     ENCODE_CHK_NULL_RETURN(params->pAvcVuiParams);
238 
239     vuiParams = params->pAvcVuiParams;
240     bsbuffer  = params->pBsBuffer;
241 
242     PutBit(bsbuffer, vuiParams->aspect_ratio_info_present_flag);
243     if (vuiParams->aspect_ratio_info_present_flag)
244     {
245         PutBits(bsbuffer, vuiParams->aspect_ratio_idc, 8);
246         if (vuiParams->aspect_ratio_idc == ENCODE_AVC_EXTENDED_SAR)
247         {
248             PutBits(bsbuffer, vuiParams->sar_width, 16);
249             PutBits(bsbuffer, vuiParams->sar_height, 16);
250         }
251     }
252 
253     PutBit(bsbuffer, vuiParams->overscan_info_present_flag);
254     if (vuiParams->overscan_info_present_flag)
255     {
256         PutBit(bsbuffer, vuiParams->overscan_appropriate_flag);
257     }
258 
259     PutBit(bsbuffer, vuiParams->video_signal_type_present_flag);
260     if (vuiParams->video_signal_type_present_flag)
261     {
262         PutBits(bsbuffer, vuiParams->video_format, 3);
263         PutBit(bsbuffer, vuiParams->video_full_range_flag);
264         PutBit(bsbuffer, vuiParams->colour_description_present_flag);
265         if (vuiParams->colour_description_present_flag)
266         {
267             PutBits(bsbuffer, vuiParams->colour_primaries, 8);
268             PutBits(bsbuffer, vuiParams->transfer_characteristics, 8);
269             PutBits(bsbuffer, vuiParams->matrix_coefficients, 8);
270         }
271     }
272 
273     PutBit(bsbuffer, vuiParams->chroma_loc_info_present_flag);
274     if (vuiParams->chroma_loc_info_present_flag)
275     {
276         PutVLCCode(bsbuffer, vuiParams->chroma_sample_loc_type_top_field);
277         PutVLCCode(bsbuffer, vuiParams->chroma_sample_loc_type_bottom_field);
278     }
279 
280     PutBit(bsbuffer, vuiParams->timing_info_present_flag);
281     if (vuiParams->timing_info_present_flag)
282     {
283         PutBits(bsbuffer, vuiParams->num_units_in_tick, 32);
284         PutBits(bsbuffer, vuiParams->time_scale, 32);
285         PutBit(bsbuffer, vuiParams->fixed_frame_rate_flag);
286     }
287 
288     PutBit(bsbuffer, vuiParams->nal_hrd_parameters_present_flag);
289     if (vuiParams->nal_hrd_parameters_present_flag)
290     {
291         ENCODE_CHK_STATUS_RETURN(PackHrdParams(params));
292     }
293 
294     PutBit(bsbuffer, vuiParams->vcl_hrd_parameters_present_flag);
295     if (vuiParams->vcl_hrd_parameters_present_flag)
296     {
297         ENCODE_CHK_STATUS_RETURN(PackHrdParams(params));
298     }
299 
300     if (vuiParams->nal_hrd_parameters_present_flag || vuiParams->vcl_hrd_parameters_present_flag)
301     {
302         PutBit(bsbuffer, vuiParams->low_delay_hrd_flag);
303     }
304 
305     PutBit(bsbuffer, vuiParams->pic_struct_present_flag);
306     PutBit(bsbuffer, vuiParams->bitstream_restriction_flag);
307     if (vuiParams->bitstream_restriction_flag)
308     {
309         PutBit(bsbuffer, vuiParams->motion_vectors_over_pic_boundaries_flag);
310         PutVLCCode(bsbuffer, vuiParams->max_bytes_per_pic_denom);
311         PutVLCCode(bsbuffer, vuiParams->max_bits_per_mb_denom);
312         PutVLCCode(bsbuffer, vuiParams->log2_max_mv_length_horizontal);
313         PutVLCCode(bsbuffer, vuiParams->log2_max_mv_length_vertical);
314         PutVLCCode(bsbuffer, vuiParams->num_reorder_frames);
315         PutVLCCode(bsbuffer, vuiParams->max_dec_frame_buffering);
316     }
317 
318     return eStatus;
319 }
320 
PackSeqParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)321 MOS_STATUS AvcEncodeHeaderPacker::PackSeqParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)
322 {
323     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams;
324     BSBuffer *                        bsbuffer;
325     uint8_t                           i;
326     MOS_STATUS                        eStatus = MOS_STATUS_SUCCESS;
327 
328     ENCODE_CHK_NULL_RETURN(params);
329     ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
330     ENCODE_CHK_NULL_RETURN(params->pSeqParams);
331 
332     seqParams = params->pSeqParams;
333     bsbuffer  = params->pBsBuffer;
334 
335     PutBits(bsbuffer, seqParams->Profile, 8);
336 
337     PutBit(bsbuffer, seqParams->constraint_set0_flag);
338     PutBit(bsbuffer, seqParams->constraint_set1_flag);
339     PutBit(bsbuffer, seqParams->constraint_set2_flag);
340     PutBit(bsbuffer, seqParams->constraint_set3_flag);
341 
342     PutBits(bsbuffer, 0, 4);
343     PutBits(bsbuffer, seqParams->Level, 8);
344     PutVLCCode(bsbuffer, seqParams->seq_parameter_set_id);
345 
346     if (seqParams->Profile == CODEC_AVC_HIGH_PROFILE ||
347         seqParams->Profile == CODEC_AVC_HIGH10_PROFILE ||
348         seqParams->Profile == CODEC_AVC_HIGH422_PROFILE ||
349         seqParams->Profile == CODEC_AVC_HIGH444_PROFILE ||
350         seqParams->Profile == CODEC_AVC_CAVLC444_INTRA_PROFILE ||
351         seqParams->Profile == CODEC_AVC_SCALABLE_BASE_PROFILE ||
352         seqParams->Profile == CODEC_AVC_SCALABLE_HIGH_PROFILE)
353     {
354         PutVLCCode(bsbuffer, seqParams->chroma_format_idc);
355         if (seqParams->chroma_format_idc == 3)
356         {
357             PutBit(bsbuffer, seqParams->separate_colour_plane_flag);
358         }
359         PutVLCCode(bsbuffer, seqParams->bit_depth_luma_minus8);
360         PutVLCCode(bsbuffer, seqParams->bit_depth_chroma_minus8);
361         PutBit(bsbuffer, seqParams->qpprime_y_zero_transform_bypass_flag);
362         PutBit(bsbuffer, seqParams->seq_scaling_matrix_present_flag);
363         if (seqParams->seq_scaling_matrix_present_flag)
364         {
365             //Iterate thro' the scaling lists. Refer to ITU-T H.264 std. section 7.3.2.1
366             for (i = 0; i < 8; i++)
367             {
368                 // scaling list present flag
369                 PutBit(bsbuffer, seqParams->seq_scaling_list_present_flag[i]);
370                 if (seqParams->seq_scaling_list_present_flag[i])
371                 {
372                     if (i < 6)
373                     {
374                         PackScalingList(bsbuffer, &params->pAvcIQMatrixParams->ScalingList4x4[i][0], 16);
375                     }
376                     else
377                     {
378                         PackScalingList(bsbuffer, &params->pAvcIQMatrixParams->ScalingList8x8[i - 6][0], 64);
379                     }
380                 }
381             }
382         }
383     }
384 
385     PutVLCCode(bsbuffer, seqParams->log2_max_frame_num_minus4);
386     PutVLCCode(bsbuffer, seqParams->pic_order_cnt_type);
387     if (seqParams->pic_order_cnt_type == 0)
388     {
389         PutVLCCode(bsbuffer, seqParams->log2_max_pic_order_cnt_lsb_minus4);
390     }
391     else if (seqParams->pic_order_cnt_type == 1)
392     {
393         PutBit(bsbuffer, seqParams->delta_pic_order_always_zero_flag);
394         PutVLCCode(bsbuffer, SIGNED(seqParams->offset_for_non_ref_pic));
395         PutVLCCode(bsbuffer, SIGNED(seqParams->offset_for_top_to_bottom_field));
396         PutVLCCode(bsbuffer, seqParams->num_ref_frames_in_pic_order_cnt_cycle);
397         for (i = 0; i < seqParams->num_ref_frames_in_pic_order_cnt_cycle; i++)
398         {
399             PutVLCCode(bsbuffer, SIGNED(seqParams->offset_for_ref_frame[i]));
400         }
401     }
402 
403     PutVLCCode(bsbuffer, seqParams->NumRefFrames);
404     PutBit(bsbuffer, seqParams->gaps_in_frame_num_value_allowed_flag);
405     PutVLCCode(bsbuffer, seqParams->pic_width_in_mbs_minus1);
406     PutVLCCode(bsbuffer, seqParams->pic_height_in_map_units_minus1);
407     PutBit(bsbuffer, seqParams->frame_mbs_only_flag);
408 
409     if (!seqParams->frame_mbs_only_flag)
410     {
411         PutBit(bsbuffer, seqParams->mb_adaptive_frame_field_flag);
412     }
413 
414     PutBit(bsbuffer, seqParams->direct_8x8_inference_flag);
415 
416     if ((!seqParams->frame_cropping_flag) &&
417         (params->dwFrameHeight != params->dwOriFrameHeight))
418     {
419         seqParams->frame_cropping_flag = 1;
420         seqParams->frame_crop_bottom_offset =
421             (int16_t)((params->dwFrameHeight - params->dwOriFrameHeight) >>
422                       (2 - seqParams->frame_mbs_only_flag));  // 4:2:0
423     }
424 
425     PutBit(bsbuffer, seqParams->frame_cropping_flag);
426 
427     if (seqParams->frame_cropping_flag)
428     {
429         PutVLCCode(bsbuffer, seqParams->frame_crop_left_offset);
430         PutVLCCode(bsbuffer, seqParams->frame_crop_right_offset);
431         PutVLCCode(bsbuffer, seqParams->frame_crop_top_offset);
432         PutVLCCode(bsbuffer, seqParams->frame_crop_bottom_offset);
433     }
434 
435     PutBit(bsbuffer, seqParams->vui_parameters_present_flag);
436 
437     if (seqParams->vui_parameters_present_flag)
438     {
439         ENCODE_CHK_STATUS_RETURN(PackVuiParams(params));
440     }
441 
442     *params->pbNewSeqHeader = 1;
443 
444     return eStatus;
445 }
446 
PackPicParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)447 MOS_STATUS AvcEncodeHeaderPacker::PackPicParams(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)
448 {
449     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams;
450     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams;
451     PBSBuffer                         bsbuffer;
452     MOS_STATUS                        eStatus = MOS_STATUS_SUCCESS;
453 
454     ENCODE_CHK_NULL_RETURN(params);
455     ENCODE_CHK_NULL_RETURN(params->pSeqParams);
456     ENCODE_CHK_NULL_RETURN(params->pPicParams);
457     ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
458 
459     seqParams = params->pSeqParams;
460     picParams = params->pPicParams;
461     bsbuffer  = params->pBsBuffer;
462 
463     PutVLCCode(bsbuffer, picParams->pic_parameter_set_id);
464     PutVLCCode(bsbuffer, picParams->seq_parameter_set_id);
465 
466     PutBit(bsbuffer, picParams->entropy_coding_mode_flag);
467     PutBit(bsbuffer, picParams->pic_order_present_flag);
468 
469     PutVLCCode(bsbuffer, picParams->num_slice_groups_minus1);
470 
471     PutVLCCode(bsbuffer, picParams->num_ref_idx_l0_active_minus1);
472     PutVLCCode(bsbuffer, picParams->num_ref_idx_l1_active_minus1);
473 
474     PutBit(bsbuffer, picParams->weighted_pred_flag);
475     PutBits(bsbuffer, picParams->weighted_bipred_idc, 2);
476 
477     PutVLCCode(bsbuffer, SIGNED(picParams->pic_init_qp_minus26));
478     PutVLCCode(bsbuffer, SIGNED(picParams->pic_init_qs_minus26));
479     PutVLCCode(bsbuffer, SIGNED(picParams->chroma_qp_index_offset));
480 
481     PutBit(bsbuffer, picParams->deblocking_filter_control_present_flag);
482     PutBit(bsbuffer, picParams->constrained_intra_pred_flag);
483     PutBit(bsbuffer, picParams->redundant_pic_cnt_present_flag);
484 
485     // The syntax elements transform_8x8_mode_flag, pic_scaling_matrix_present_flag, and second_chroma_qp_index_offset
486     // shall not be present for main profile
487     if (seqParams->Profile == CODEC_AVC_MAIN_PROFILE || seqParams->Profile == CODEC_AVC_BASE_PROFILE)
488     {
489         return eStatus;
490     }
491 
492     PutBit(bsbuffer, picParams->transform_8x8_mode_flag);
493     PutBit(bsbuffer, picParams->pic_scaling_matrix_present_flag);
494     if (picParams->pic_scaling_matrix_present_flag)
495     {
496         uint8_t i;
497 
498         //Iterate thro' the scaling lists. Refer to ITU-T H.264 std. section 7.3.2.2
499         for (i = 0; i < 6 + 2 * picParams->transform_8x8_mode_flag; i++)
500         {
501             //Put scaling list present flag
502             PutBit(bsbuffer, picParams->pic_scaling_list_present_flag[i]);
503             if (picParams->pic_scaling_list_present_flag[i])
504             {
505                 if (i < 6)
506                 {
507                     PackScalingList(bsbuffer, &params->pAvcIQMatrixParams->ScalingList4x4[i][0], 16);
508                 }
509                 else
510                 {
511                     PackScalingList(bsbuffer, &params->pAvcIQMatrixParams->ScalingList8x8[i - 6][0], 64);
512                 }
513             }
514         }
515     }
516 
517     PutVLCCode(bsbuffer, SIGNED(picParams->second_chroma_qp_index_offset));
518 
519     *params->pbNewPPSHeader = 1;
520 
521     return eStatus;
522 }
523 
PackPictureHeader(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)524 MOS_STATUS AvcEncodeHeaderPacker::PackPictureHeader(PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params)
525 {
526     ENCODE_FUNC_CALL();
527 
528     PBSBuffer  bsbuffer;
529     uint32_t   indexNALUnit;
530     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
531 
532     ENCODE_CHK_NULL_RETURN(params);
533     ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
534     ENCODE_CHK_NULL_RETURN(params->pSeqParams);
535     ENCODE_CHK_NULL_RETURN(params->ppNALUnitParams);
536 
537     bsbuffer              = params->pBsBuffer;
538     *(bsbuffer->pBase)    = 0;  // init first byte to 0
539     bsbuffer->pCurrent    = bsbuffer->pBase;
540     bsbuffer->SliceOffset = 0;
541     bsbuffer->BitOffset   = 0;
542     bsbuffer->BitSize     = 0;
543 
544     MOS_ZeroMemory(params->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * CODECHAL_ENCODE_AVC_MAX_NAL_TYPE);
545     indexNALUnit = 0;
546 
547     // AU_Delimiter
548     // nal_ref_idc to be 0 for all nal_unit_type equal to 6, 9, 10, 11 or12
549     params->ppNALUnitParams[indexNALUnit]->uiOffset                  = 0;
550     params->ppNALUnitParams[indexNALUnit]->uiNalUnitType             = CODECHAL_ENCODE_AVC_NAL_UT_AUD;
551     params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes     = true;
552     params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4;
553     SetNalUnit(&bsbuffer->pCurrent, 0, CODECHAL_ENCODE_AVC_NAL_UT_AUD);
554     ENCODE_CHK_STATUS_RETURN(PackAUDParams(params));
555     SetTrailingBits(bsbuffer);
556     //NAL unit are byte aligned, bsbuffer->BitOffset should be 0
557     params->ppNALUnitParams[indexNALUnit]->uiSize =
558         (uint32_t)(bsbuffer->pCurrent -
559                    bsbuffer->pBase -
560                    params->ppNALUnitParams[indexNALUnit]->uiOffset);
561     indexNALUnit++;
562 
563     // If this is a new sequence, write the seq set
564     if (params->bNewSeq && !params->pSeqParams->bNoAcceleratorSPSInsertion)
565     {
566         // Pack SPS
567         params->ppNALUnitParams[indexNALUnit]->uiOffset                  = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase);
568         params->ppNALUnitParams[indexNALUnit]->uiNalUnitType             = CODECHAL_ENCODE_AVC_NAL_UT_SPS;
569         params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes     = true;
570         params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4;
571         SetNalUnit(&bsbuffer->pCurrent, 1, CODECHAL_ENCODE_AVC_NAL_UT_SPS);
572         ENCODE_CHK_STATUS_RETURN(PackSeqParams(params));
573         SetTrailingBits(bsbuffer);
574         params->ppNALUnitParams[indexNALUnit]->uiSize =
575             (uint32_t)(bsbuffer->pCurrent -
576                        bsbuffer->pBase -
577                        params->ppNALUnitParams[indexNALUnit]->uiOffset);
578         indexNALUnit++;
579     }
580 
581     // Pack PPS
582     params->ppNALUnitParams[indexNALUnit]->uiOffset                  = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase);
583     params->ppNALUnitParams[indexNALUnit]->uiNalUnitType             = CODECHAL_ENCODE_AVC_NAL_UT_PPS;
584     params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes     = true;
585     params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4;
586     SetNalUnit(&bsbuffer->pCurrent, 1, CODECHAL_ENCODE_AVC_NAL_UT_PPS);
587     ENCODE_CHK_STATUS_RETURN(PackPicParams(params));
588     SetTrailingBits(bsbuffer);
589     params->ppNALUnitParams[indexNALUnit]->uiSize =
590         (uint32_t)(bsbuffer->pCurrent -
591                    bsbuffer->pBase -
592                    params->ppNALUnitParams[indexNALUnit]->uiOffset);
593     indexNALUnit++;
594 
595     // Pack SEI
596     if (params->pSeiData->newSEIData)
597     {
598         params->ppNALUnitParams[indexNALUnit]->uiOffset                  = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase);
599         params->ppNALUnitParams[indexNALUnit]->uiNalUnitType             = CODECHAL_ENCODE_AVC_NAL_UT_SEI;
600         params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes     = false;
601         params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4;
602         eStatus                                                          = MOS_SecureMemcpy(bsbuffer->pCurrent,
603             params->pSeiData->dwSEIBufSize,
604             params->pSeiData->pSEIBuffer,
605             params->pSeiData->dwSEIBufSize);
606         if (eStatus != MOS_STATUS_SUCCESS)
607         {
608             ENCODE_ASSERTMESSAGE("Failed to copy memory.");
609             return eStatus;
610         }
611         bsbuffer->pCurrent += params->pSeiData->dwSEIDataSize;
612         params->pSeiData->newSEIData = false;
613         params->ppNALUnitParams[indexNALUnit]->uiSize =
614             (uint32_t)(bsbuffer->pCurrent -
615                        bsbuffer->pBase -
616                        params->ppNALUnitParams[indexNALUnit]->uiOffset);
617         indexNALUnit++;
618     }
619 
620     bsbuffer->SliceOffset = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase);
621 
622     return eStatus;
623 }
624 
PackSliceHeader(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)625 MOS_STATUS AvcEncodeHeaderPacker::PackSliceHeader(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)
626 {
627     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams;
628     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams;
629     PCODEC_AVC_ENCODE_SLICE_PARAMS    slcParams;
630     PBSBuffer                         bsbuffer;
631     uint8_t                           sliceType;
632     CODECHAL_ENCODE_AVC_NAL_UNIT_TYPE nalType;
633     bool                              ref;
634     MOS_STATUS                        eStatus = MOS_STATUS_SUCCESS;
635 
636     ENCODE_CHK_NULL_RETURN(params);
637     ENCODE_CHK_NULL_RETURN(params->pSeqParams);
638     ENCODE_CHK_NULL_RETURN(params->pPicParams);
639     ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams);
640     ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
641 
642     slcParams = params->pAvcSliceParams;
643     picParams = params->pPicParams;
644     seqParams = params->pSeqParams;
645     bsbuffer  = params->pBsBuffer;
646     sliceType = Slice_Type[slcParams->slice_type];
647     nalType   = params->NalUnitType;
648     ref       = params->ppRefList[params->CurrReconPic.FrameIdx]->bUsedAsRef;
649 
650     // Make slice header uint8_t aligned
651     while (bsbuffer->BitOffset)
652     {
653         PutBit(bsbuffer, 0);
654     }
655 
656     // zero byte shall exist when the byte stream NAL unit syntax structure contains the first
657     // NAL unit of an access unit in decoding order, as specified by subclause 7.4.1.2.3.
658     // VDEnc Slice header packing handled by PAK does not need the 0 byte inserted
659     if (params->UserFlags.bDisableAcceleratorHeaderPacking && (!params->bVdencEnabled))
660     {
661         *bsbuffer->pCurrent = 0;
662         bsbuffer->pCurrent++;
663     }
664 
665     SetNalUnit(&bsbuffer->pCurrent, (uint8_t)ref, nalType);
666 
667     // In the VDEnc mode, PAK only gets this command at the beginning of the frame for slice position X=0, Y=0
668     PutVLCCode(bsbuffer, params->bVdencEnabled ? 0 : slcParams->first_mb_in_slice);
669     PutVLCCode(bsbuffer, slcParams->slice_type);
670     PutVLCCode(bsbuffer, slcParams->pic_parameter_set_id);
671 
672     if (seqParams->separate_colour_plane_flag)
673     {
674         PutBits(bsbuffer, slcParams->colour_plane_id, 2);
675     }
676 
677     PutBits(bsbuffer, slcParams->frame_num, seqParams->log2_max_frame_num_minus4 + 4);
678 
679     if (!seqParams->frame_mbs_only_flag)
680     {
681         PutBit(bsbuffer, slcParams->field_pic_flag);
682         if (slcParams->field_pic_flag)
683         {
684             PutBit(bsbuffer, slcParams->bottom_field_flag);
685         }
686     }
687 
688     if (nalType == CODECHAL_ENCODE_AVC_NAL_UT_IDR_SLICE)
689     {
690         PutVLCCode(bsbuffer, slcParams->idr_pic_id);
691     }
692 
693     if (seqParams->pic_order_cnt_type == 0)
694     {
695         PutBits(bsbuffer, slcParams->pic_order_cnt_lsb, seqParams->log2_max_pic_order_cnt_lsb_minus4 + 4);
696         if (picParams->pic_order_present_flag && !slcParams->field_pic_flag)
697         {
698             PutVLCCode(bsbuffer, SIGNED(slcParams->delta_pic_order_cnt_bottom));
699         }
700     }
701 
702     if (seqParams->pic_order_cnt_type == 1 && !seqParams->delta_pic_order_always_zero_flag)
703     {
704         PutVLCCode(bsbuffer, SIGNED(slcParams->delta_pic_order_cnt[0]));
705         if (picParams->pic_order_present_flag && !slcParams->field_pic_flag)
706         {
707             PutVLCCode(bsbuffer, SIGNED(slcParams->delta_pic_order_cnt[1]));
708         }
709     }
710 
711     if (picParams->redundant_pic_cnt_present_flag)
712     {
713         PutVLCCode(bsbuffer, slcParams->redundant_pic_cnt);
714     }
715 
716     if (sliceType == SLICE_B)
717     {
718         PutBit(bsbuffer, slcParams->direct_spatial_mv_pred_flag);
719     }
720 
721     if (sliceType == SLICE_P || sliceType == SLICE_SP || sliceType == SLICE_B)
722     {
723         PutBit(bsbuffer, slcParams->num_ref_idx_active_override_flag);
724         if (slcParams->num_ref_idx_active_override_flag)
725         {
726             PutVLCCode(bsbuffer, slcParams->num_ref_idx_l0_active_minus1);
727             if (sliceType == SLICE_B)
728             {
729                 PutVLCCode(bsbuffer, slcParams->num_ref_idx_l1_active_minus1);
730             }
731         }
732     }
733 
734     // ref_pic_list_reordering()
735     ENCODE_CHK_STATUS_RETURN(RefPicListReordering(params));
736 
737     if ((picParams->weighted_pred_flag &&
738             (sliceType == SLICE_P || sliceType == SLICE_SP)) ||
739         (picParams->weighted_bipred_idc == EXPLICIT_WEIGHTED_INTER_PRED_MODE &&
740             sliceType == SLICE_B))
741     {
742         ENCODE_CHK_STATUS_RETURN(PredWeightTable(params));
743     }
744 
745     if (ref)
746     {
747         // dec_ref_pic_marking()
748         if (nalType == CODECHAL_ENCODE_AVC_NAL_UT_IDR_SLICE)
749         {
750             PutBit(bsbuffer, slcParams->no_output_of_prior_pics_flag);
751             PutBit(bsbuffer, slcParams->long_term_reference_flag);
752         }
753         else
754         {
755             PutBit(bsbuffer, slcParams->adaptive_ref_pic_marking_mode_flag);
756             if (slcParams->adaptive_ref_pic_marking_mode_flag)
757             {
758                 ENCODE_CHK_STATUS_RETURN(MMCO(params));
759             }
760         }
761     }
762 
763     if (picParams->entropy_coding_mode_flag && sliceType != SLICE_I && sliceType != SLICE_SI)
764     {
765         PutVLCCode(bsbuffer, slcParams->cabac_init_idc);
766     }
767 
768     PutVLCCode(bsbuffer, SIGNED(slcParams->slice_qp_delta));
769 
770     if (sliceType == SLICE_SP || sliceType == SLICE_SI)
771     {
772         if (sliceType == SLICE_SP)
773         {
774             PutBit(bsbuffer, slcParams->sp_for_switch_flag);
775         }
776         PutVLCCode(bsbuffer, SIGNED(slcParams->slice_qs_delta));
777     }
778 
779     if (picParams->deblocking_filter_control_present_flag)
780     {
781         PutVLCCode(bsbuffer, slcParams->disable_deblocking_filter_idc);
782         if (slcParams->disable_deblocking_filter_idc != 1)
783         {
784             PutVLCCode(bsbuffer, SIGNED(slcParams->slice_alpha_c0_offset_div2));
785             PutVLCCode(bsbuffer, SIGNED(slcParams->slice_beta_offset_div2));
786         }
787     }
788 
789     bsbuffer->BitSize =
790         (uint32_t)((bsbuffer->pCurrent - bsbuffer->SliceOffset - bsbuffer->pBase) * 8 + bsbuffer->BitOffset);
791     bsbuffer->SliceOffset =
792         (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase + (bsbuffer->BitOffset != 0));
793 
794     return eStatus;
795 }
796 
RefPicListReordering(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)797 MOS_STATUS AvcEncodeHeaderPacker::RefPicListReordering(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)
798 {
799     PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams;
800     PBSBuffer                      bsbuffer;
801     CODEC_PIC_REORDER *            picOrder;
802     uint8_t                        sliceType;
803     MOS_STATUS                     eStatus = MOS_STATUS_SUCCESS;
804 
805     ENCODE_CHK_NULL_RETURN(params);
806     ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams);
807 
808     slcParams = params->pAvcSliceParams;
809     bsbuffer  = params->pBsBuffer;
810     sliceType = Slice_Type[slcParams->slice_type];
811 
812     if (!params->UserFlags.bDisableAcceleratorRefPicListReordering)
813     {
814         // Generate the initial reference list (PicOrder)
815         SetInitialRefPicList(params);
816     }
817 
818     if (sliceType != SLICE_I && sliceType != SLICE_SI)
819     {
820         if (slcParams->ref_pic_list_reordering_flag_l0)
821         {
822             if (!params->UserFlags.bDisableAcceleratorRefPicListReordering)
823             {
824                 ENCODE_CHK_STATUS_RETURN(SetRefPicListParam(params, 0));
825             }
826 
827             PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l0);
828 
829             if (slcParams->ref_pic_list_reordering_flag_l0)
830             {
831                 picOrder = &slcParams->PicOrder[0][0];
832                 do
833                 {
834                     PutVLCCode(bsbuffer, picOrder->ReorderPicNumIDC);
835                     if (picOrder->ReorderPicNumIDC == 0 ||
836                         picOrder->ReorderPicNumIDC == 1)
837                     {
838                         PutVLCCode(bsbuffer, picOrder->DiffPicNumMinus1);
839                     } else
840                     if (picOrder->ReorderPicNumIDC == 2)
841                     {
842                         PutVLCCode(bsbuffer, picOrder->LongTermPicNum);
843                     }
844                 } while ((picOrder++)->ReorderPicNumIDC != 3);
845             }
846         }
847         else
848         {
849             PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l0);
850         }
851     }
852     if (sliceType == SLICE_B)
853     {
854         if (slcParams->ref_pic_list_reordering_flag_l1)
855         {
856             if (!params->UserFlags.bDisableAcceleratorRefPicListReordering)
857             {
858                 SetRefPicListParam(params, 1);
859             }
860 
861             PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l1);
862 
863             if (slcParams->ref_pic_list_reordering_flag_l1)
864             {
865                 picOrder = &slcParams->PicOrder[1][0];
866                 do
867                 {
868                     PutVLCCode(bsbuffer, picOrder->ReorderPicNumIDC);
869                     if (picOrder->ReorderPicNumIDC == 0 ||
870                         picOrder->ReorderPicNumIDC == 1)
871                     {
872                         PutVLCCode(bsbuffer, picOrder->DiffPicNumMinus1);
873                     } else
874                     if (picOrder->ReorderPicNumIDC == 2)
875                     {
876                         PutVLCCode(bsbuffer, picOrder->PicNum);
877                     }
878                 } while ((picOrder++)->ReorderPicNumIDC != 3);
879             }
880         }
881         else
882         {
883             PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l1);
884         }
885     }
886 
887     return eStatus;
888 }
889 
PredWeightTable(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)890 MOS_STATUS AvcEncodeHeaderPacker::PredWeightTable(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)
891 {
892     PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams;
893     PBSBuffer                      bsbuffer;
894     int16_t                        weight, offset, weight2, offset2;
895     uint8_t                        i, weight_flag, chromaIDC;
896     MOS_STATUS                     eStatus = MOS_STATUS_SUCCESS;
897 
898     ENCODE_CHK_NULL_RETURN(params);
899     ENCODE_CHK_NULL_RETURN(params->pSeqParams);
900     ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams);
901     ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
902 
903     bsbuffer  = params->pBsBuffer;
904     slcParams = params->pAvcSliceParams;
905     chromaIDC = params->pSeqParams->chroma_format_idc;
906 
907     PutVLCCode(bsbuffer, slcParams->luma_log2_weight_denom);
908 
909     if (chromaIDC)
910     {
911         PutVLCCode(bsbuffer, slcParams->chroma_log2_weight_denom);
912     }
913 
914     for (i = 0; i <= slcParams->num_ref_idx_l0_active_minus1; i++)
915     {
916         // Luma
917         weight      = slcParams->Weights[0][i][0][0];
918         offset      = slcParams->Weights[0][i][0][1];
919         weight_flag = (weight != (1 << slcParams->luma_log2_weight_denom)) || (offset != 0);
920         PutBit(bsbuffer, weight_flag);
921         if (weight_flag)
922         {
923             PutVLCCode(bsbuffer, SIGNED(weight));
924             PutVLCCode(bsbuffer, SIGNED(offset));
925         }
926 
927         // Chroma
928         if (chromaIDC)
929         {
930             weight      = slcParams->Weights[0][i][1][0];
931             offset      = slcParams->Weights[0][i][1][1];
932             weight2     = slcParams->Weights[0][i][2][0];
933             offset2     = slcParams->Weights[0][i][2][1];
934             weight_flag = (weight != (1 << slcParams->chroma_log2_weight_denom)) ||
935                           (weight2 != (1 << slcParams->chroma_log2_weight_denom)) ||
936                           (offset != 0) || (offset2 != 0);
937             PutBit(bsbuffer, weight_flag);
938             if (weight_flag)
939             {
940                 PutVLCCode(bsbuffer, SIGNED(weight));
941                 PutVLCCode(bsbuffer, SIGNED(offset));
942                 PutVLCCode(bsbuffer, SIGNED(weight2));
943                 PutVLCCode(bsbuffer, SIGNED(offset2));
944             }
945         }
946     }
947 
948     if (Slice_Type[slcParams->slice_type] == SLICE_B)
949     {
950         for (i = 0; i <= slcParams->num_ref_idx_l1_active_minus1; i++)
951         {
952             // Luma
953             weight      = slcParams->Weights[1][i][0][0];
954             offset      = slcParams->Weights[1][i][0][1];
955             weight_flag = (weight != (1 << slcParams->luma_log2_weight_denom)) || (offset != 0);
956             PutBit(bsbuffer, weight_flag);
957             if (weight_flag)
958             {
959                 PutVLCCode(bsbuffer, SIGNED(weight));
960                 PutVLCCode(bsbuffer, SIGNED(offset));
961             }
962 
963             // Chroma
964             if (chromaIDC)
965             {
966                 weight      = slcParams->Weights[1][i][1][0];
967                 offset      = slcParams->Weights[1][i][1][1];
968                 weight2     = slcParams->Weights[1][i][2][0];
969                 offset2     = slcParams->Weights[1][i][2][1];
970                 weight_flag = (weight != (1 << slcParams->chroma_log2_weight_denom)) ||
971                               (weight2 != (1 << slcParams->chroma_log2_weight_denom)) ||
972                               (offset != 0) || (offset2 != 0);
973                 PutBit(bsbuffer, weight_flag);
974                 if (weight_flag)
975                 {
976                     PutVLCCode(bsbuffer, SIGNED(weight));
977                     PutVLCCode(bsbuffer, SIGNED(offset));
978                     PutVLCCode(bsbuffer, SIGNED(weight2));
979                     PutVLCCode(bsbuffer, SIGNED(offset2));
980                 }
981             }
982         }
983     }
984 
985     return eStatus;
986 }
987 
MMCO(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)988 MOS_STATUS AvcEncodeHeaderPacker::MMCO(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)
989 {
990     PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams;
991     PBSBuffer                      bsbuffer;
992     MOS_STATUS                     eStatus = MOS_STATUS_SUCCESS;
993 
994     ENCODE_CHK_NULL_RETURN(params);
995     ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams);
996     ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
997 
998     bsbuffer  = params->pBsBuffer;
999     slcParams = params->pAvcSliceParams;
1000 
1001     PCODEC_SLICE_MMCO mmco = &slcParams->MMCO[0];
1002     do
1003     {
1004         PutVLCCode(bsbuffer, mmco->MmcoIDC);
1005         if (mmco->MmcoIDC == 1 ||
1006             mmco->MmcoIDC == 3)
1007             PutVLCCode(bsbuffer, mmco->DiffPicNumMinus1);
1008         if (mmco->MmcoIDC == 2)
1009             PutVLCCode(bsbuffer, mmco->LongTermPicNum);
1010         if (mmco->MmcoIDC == 3 ||
1011             mmco->MmcoIDC == 6)
1012             PutVLCCode(bsbuffer, mmco->LongTermFrameIdx);
1013         if (mmco->MmcoIDC == 4)
1014             PutVLCCode(bsbuffer, mmco->MaxLongTermFrameIdxPlus1);
1015     } while ((mmco++)->MmcoIDC != 0);
1016 
1017     return eStatus;
1018 }
1019 
SetInitialRefPicList(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)1020 void AvcEncodeHeaderPacker::SetInitialRefPicList(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params)
1021 {
1022     PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams;
1023     PCODEC_REF_LIST *              refList;
1024     CODEC_PIC_REORDER *            picOrder, pTempPicOrder[32];
1025     CODEC_PICTURE                  picture;
1026     uint8_t                        i, j, botField;
1027     uint32_t                       picNum, picOC;
1028     uint8_t                        topIdx, botIdx, listSize;
1029     uint32_t                       defaultPicNumOrder[32];
1030     bool                           reorder;
1031 
1032     ENCODE_CHK_NULL_NO_STATUS_RETURN(params);
1033     ENCODE_CHK_NULL_NO_STATUS_RETURN(params->pAvcSliceParams);
1034     ENCODE_CHK_NULL_NO_STATUS_RETURN(params->ppRefList);
1035 
1036     slcParams = params->pAvcSliceParams;
1037     refList   = params->ppRefList;
1038     reorder   = false;
1039     topIdx    = 0;
1040     botIdx    = 0;
1041     listSize  = 0;
1042 
1043     if (params->wPictureCodingType == P_TYPE)
1044     {
1045         GetPicNum(params, 0);  // list 0
1046         picOrder = &slcParams->PicOrder[0][0];
1047         // Save the default pic order.
1048         for (i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++)
1049         {
1050             defaultPicNumOrder[i] = picOrder[i].PicNum;
1051         }
1052         for (i = 1; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++)
1053         {
1054             picNum  = picOrder[i].PicNum;
1055             picture = picOrder[i].Picture;
1056             picOC   = picOrder[i].POC;
1057             j       = i;
1058             while ((j > 0) && (picOrder[j - 1].PicNum < picNum))
1059             {
1060                 picOrder[j].PicNum  = picOrder[j - 1].PicNum;
1061                 picOrder[j].Picture = picOrder[j - 1].Picture;
1062                 picOrder[j].POC     = picOrder[j - 1].POC;
1063                 j--;
1064                 reorder = true;
1065             }
1066             picOrder[j].PicNum  = picNum;
1067             picOrder[j].Picture = picture;
1068             picOrder[j].POC     = picOC;
1069         }
1070 
1071         // Sort picOrder[] based on polarity in field case
1072         if (CodecHal_PictureIsTopField(params->CurrPic))
1073         {
1074             while ((topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1)) ||
1075                    (botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1)))
1076             {
1077                 for (; topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); topIdx++)
1078                 {
1079                     if (CodecHal_PictureIsTopField(picOrder[topIdx].Picture))  //TOP_FIELD
1080                     {
1081                         pTempPicOrder[listSize].PicNum  = picOrder[topIdx].PicNum;
1082                         pTempPicOrder[listSize].Picture = picOrder[topIdx].Picture;
1083                         pTempPicOrder[listSize].POC     = picOrder[topIdx].POC;
1084                         listSize++;
1085                         topIdx++;
1086                         break;
1087                     }
1088                 }
1089                 for (; botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); botIdx++)
1090                 {
1091                     if (CodecHal_PictureIsBottomField(picOrder[botIdx].Picture))  //BOTTOM_FIELD
1092                     {
1093                         pTempPicOrder[listSize].PicNum  = picOrder[botIdx].PicNum;
1094                         pTempPicOrder[listSize].Picture = picOrder[botIdx].Picture;
1095                         pTempPicOrder[listSize].POC     = picOrder[botIdx].POC;
1096                         listSize++;
1097                         botIdx++;
1098                         break;
1099                     }
1100                 }
1101             }
1102         }
1103         if (CodecHal_PictureIsBottomField(params->CurrPic))
1104         {
1105             while ((topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1)) ||
1106                    (botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1)))
1107             {
1108                 for (; botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); botIdx++)
1109                 {
1110                     if (CodecHal_PictureIsBottomField(picOrder[botIdx].Picture))  //BOTTOM_FIELD
1111                     {
1112                         pTempPicOrder[listSize].PicNum  = picOrder[botIdx].PicNum;
1113                         pTempPicOrder[listSize].Picture = picOrder[botIdx].Picture;
1114                         pTempPicOrder[listSize].POC     = picOrder[botIdx].POC;
1115                         listSize++;
1116                         botIdx++;
1117                         break;
1118                     }
1119                 }
1120                 for (; topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); topIdx++)
1121                 {
1122                     if (CodecHal_PictureIsTopField(picOrder[topIdx].Picture))  //TOP_FIELD
1123                     {
1124                         pTempPicOrder[listSize].PicNum  = picOrder[topIdx].PicNum;
1125                         pTempPicOrder[listSize].Picture = picOrder[topIdx].Picture;
1126                         pTempPicOrder[listSize].POC     = picOrder[topIdx].POC;
1127                         listSize++;
1128                         topIdx++;
1129                         break;
1130                     }
1131                 }
1132             }
1133         }
1134 
1135         if (!CodecHal_PictureIsFrame(params->CurrPic))
1136         {
1137             listSize = MOS_MIN(listSize, 32);
1138             // Copy temp array back to picOrder[]
1139             for (i = 0; i < listSize; i++)
1140             {
1141                 picOrder[i].PicNum  = pTempPicOrder[i].PicNum;
1142                 picOrder[i].Picture = pTempPicOrder[i].Picture;
1143                 picOrder[i].POC     = pTempPicOrder[i].POC;
1144             }
1145 
1146             // Check if picOrder[] has been shuffled compared to the original list
1147             reorder = false;
1148             for (i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++)
1149             {
1150                 if (defaultPicNumOrder[i] != picOrder[i].PicNum)
1151                 {
1152                     reorder = true;
1153                     break;
1154                 }
1155             }
1156         }
1157 
1158         if (reorder)
1159         {
1160             slcParams->ref_pic_list_reordering_flag_l0 = 1;
1161         }
1162         else
1163         {
1164             slcParams->ref_pic_list_reordering_flag_l0 = 0;
1165         }
1166         for (i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++)
1167         {
1168             botField = (CodecHal_PictureIsBottomField(picOrder[i].Picture)) ? 1 : 0;
1169             refList[picOrder[i].Picture.FrameIdx]->ucInitialIdx[0][botField] = i;
1170         }
1171     }
1172     if (params->wPictureCodingType == B_TYPE)
1173     {
1174     }
1175 
1176     return;
1177 }
1178 
SetRefPicListParam(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params,uint8_t list)1179 MOS_STATUS AvcEncodeHeaderPacker::SetRefPicListParam(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params, uint8_t list)
1180 {
1181     PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams;
1182     PCODEC_REF_LIST *              refList;
1183     PCODEC_PIC_REORDER             picOrder;
1184     uint8_t                        i, j, idx, picIdx, numReorder, numActiveMinus1, refPolarity;
1185     uint32_t                       picNumPred, currPicNum, picNumNoWrap, maxPicNum;
1186     int16_t                        frameNum;
1187     MOS_STATUS                     eStatus = MOS_STATUS_SUCCESS;
1188 
1189     ENCODE_CHK_NULL_RETURN(params);
1190     ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams);
1191     ENCODE_CHK_NULL_RETURN(params->ppRefList);
1192 
1193     slcParams = params->pAvcSliceParams;
1194     refList   = params->ppRefList;
1195     frameNum  = refList[params->CurrReconPic.FrameIdx]->sFrameNumber;
1196 
1197     currPicNum = (CodecHal_PictureIsFrame(params->CurrPic)) ? frameNum : 2 * frameNum + 1;
1198     picNumPred = currPicNum;
1199     maxPicNum  = (CodecHal_PictureIsFrame(params->CurrPic)) ? slcParams->MaxFrameNum : (2 * slcParams->MaxFrameNum);
1200 
1201     numActiveMinus1 = list ? slcParams->num_ref_idx_l1_active_minus1 : slcParams->num_ref_idx_l0_active_minus1;
1202 
1203     picOrder = &slcParams->PicOrder[list][0];
1204 
1205     idx         = 0;
1206     picIdx      = picOrder[idx].Picture.FrameIdx;
1207     refPolarity = (CodecHal_PictureIsBottomField(picOrder[idx].Picture)) ? 1 : 0;
1208     if (refList[picIdx]->ucFinalIdx[list][refPolarity] ==
1209         refList[picIdx]->ucInitialIdx[list][refPolarity])
1210     {
1211         // Should never happen, something must be wrong in CodecHal_PackSliceHeader_SetInitialRefPicList()
1212         ENCODE_ASSERT(false);
1213         if (list)  // L1
1214         {
1215             slcParams->ref_pic_list_reordering_flag_l1 = 0;
1216         }
1217         else  // L0
1218         {
1219             slcParams->ref_pic_list_reordering_flag_l0 = 0;
1220         }
1221         eStatus = MOS_STATUS_UNKNOWN;
1222         return eStatus;
1223     }
1224 
1225     numReorder = refList[picIdx]->ucFinalIdx[list][refPolarity] - refList[picIdx]->ucInitialIdx[list][refPolarity];
1226     if (numReorder > numActiveMinus1)
1227     {
1228         numReorder = numActiveMinus1;
1229     }
1230     slcParams->NumReorder = numReorder;
1231     do
1232     {
1233         for (i = (idx + 1); i <= numActiveMinus1; i++)
1234         {
1235             picIdx      = picOrder[i].Picture.FrameIdx;
1236             refPolarity = (CodecHal_PictureIsBottomField(picOrder[i].Picture)) ? 1 : 0;
1237             if (refList[picIdx]->ucFinalIdx[list][refPolarity] == idx)
1238             {
1239                 break;
1240             }
1241         }
1242         if (i == (numActiveMinus1 + 1))
1243         {
1244             // Should never happen, something must be wrong
1245             ENCODE_ASSERT(false);
1246             if (list)  // L1
1247             {
1248                 slcParams->ref_pic_list_reordering_flag_l1 = 0;
1249             }
1250             else  // L0
1251             {
1252                 slcParams->ref_pic_list_reordering_flag_l0 = 0;
1253             }
1254             eStatus = MOS_STATUS_UNKNOWN;
1255             return eStatus;
1256         }
1257 
1258         if (picOrder[i].PicNum > picNumPred)
1259         {
1260             picOrder[idx].ReorderPicNumIDC = 1;
1261         }
1262         else
1263         {
1264             picOrder[idx].ReorderPicNumIDC = 0;
1265         }
1266 
1267         if (picOrder[i].PicNum > currPicNum)
1268         {
1269             picNumNoWrap = picOrder[i].PicNum + maxPicNum;
1270         }
1271         else
1272         {
1273             picNumNoWrap = picOrder[i].PicNum;
1274         }
1275 
1276         if (picOrder[idx].ReorderPicNumIDC == 0)
1277         {
1278             if (picNumPred > picNumNoWrap)
1279             {
1280                 picOrder[idx].DiffPicNumMinus1 = picNumPred - picNumNoWrap - 1;
1281             }
1282             else
1283             {
1284                 picOrder[idx].DiffPicNumMinus1 = picNumPred + maxPicNum - picNumNoWrap - 1;
1285             }
1286         }
1287         else
1288         {
1289             if (picNumNoWrap > picNumPred)
1290             {
1291                 picOrder[idx].DiffPicNumMinus1 = picNumNoWrap - picNumPred - 1;
1292             }
1293             else
1294             {
1295                 picOrder[idx].DiffPicNumMinus1 = picNumNoWrap + maxPicNum - picNumPred - 1;
1296             }
1297         }
1298         picNumPred = picNumNoWrap;
1299 
1300         for (j = i; j > idx; j--)
1301         {
1302             picOrder[j].Picture = picOrder[j - 1].Picture;
1303             picOrder[j].PicNum  = picOrder[j - 1].PicNum;
1304             picOrder[j].POC     = picOrder[j - 1].POC;
1305         }
1306 
1307         idx++;
1308     } while (--numReorder);
1309     picOrder[idx].ReorderPicNumIDC = 3;
1310 
1311     return eStatus;
1312 }
1313 
GetPicNum(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params,uint8_t list)1314 void AvcEncodeHeaderPacker::GetPicNum(PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params,uint8_t list)
1315 {
1316     PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams;
1317     PCODEC_REF_LIST *              refList;
1318     uint32_t                       frameNum, frameNumWrap, picNum;
1319     uint8_t                        i, botField, size;
1320     CODEC_PICTURE                  picture;
1321 
1322     ENCODE_CHK_NULL_NO_STATUS_RETURN(params);
1323     ENCODE_CHK_NULL_NO_STATUS_RETURN(params->pAvcSliceParams);
1324     ENCODE_CHK_NULL_NO_STATUS_RETURN(params->ppRefList);
1325 
1326     slcParams = params->pAvcSliceParams;
1327     refList   = params->ppRefList;
1328 
1329     size = list ? (slcParams->num_ref_idx_l1_active_minus1 + 1) : (slcParams->num_ref_idx_l0_active_minus1 + 1);
1330 
1331     for (i = 0; i < size; i++)
1332     {
1333         picture                                               = slcParams->PicOrder[list][i].Picture;
1334         botField                                              = (CodecHal_PictureIsBottomField(picture)) ? 1 : 0;
1335         refList[picture.FrameIdx]->ucFinalIdx[list][botField] = i;
1336         frameNum                                              = refList[picture.FrameIdx]->sFrameNumber;
1337         if (frameNum > (uint32_t)refList[params->CurrReconPic.FrameIdx]->sFrameNumber)
1338         {
1339             frameNumWrap = frameNum - slcParams->MaxFrameNum;
1340         }
1341         else
1342         {
1343             frameNumWrap = frameNum;
1344         }
1345 
1346         if (CodecHal_PictureIsFrame(params->CurrPic))
1347         {
1348             picNum = frameNumWrap;
1349         }
1350         else if ((CodecHal_PictureIsTopField(params->CurrPic) &&
1351                      CodecHal_PictureIsTopField(picture)) ||
1352                  (CodecHal_PictureIsBottomField(params->CurrPic) &&
1353                      CodecHal_PictureIsBottomField(picture)))
1354         {
1355             // Same polarity
1356             picNum = (frameNumWrap << 1) + 1;
1357         }
1358         else
1359         {
1360             picNum = frameNumWrap << 1;
1361         }
1362         slcParams->PicOrder[list][i].PicNum = picNum;
1363         slcParams->PicOrder[list][i].POC =
1364             refList[picture.FrameIdx]->iFieldOrderCnt[botField];
1365     }
1366 
1367     return;
1368 }
1369 
1370 }  // namespace encode
1371