1 /**
2  * Copyright (C) 2022 The Android Open Source Project
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 express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <media/NdkMediaCodec.h>
18 #include <media/NdkMediaFormat.h>
19 #include <ImsMediaVideoUtil.h>
20 #include <ImsMediaBitReader.h>
21 #include <ImsMediaBinaryFormat.h>
22 #include <ImsMediaTrace.h>
23 #include <VideoConfig.h>
24 #include <memory>
25 #include <string.h>
26 
27 #define START_CODE_PREFIX_LEN           4
28 #define MAX_OUTPUT_BUFFER_READ_ATTEMPTS 5
29 #define FRAME_TYPE_SPS                  7
30 #define FRAME_TYPE_PPS                  8
31 
ImsMediaVideoUtil()32 ImsMediaVideoUtil::ImsMediaVideoUtil() {}
33 
~ImsMediaVideoUtil()34 ImsMediaVideoUtil::~ImsMediaVideoUtil() {}
35 
ConvertCodecType(int32_t type)36 int32_t ImsMediaVideoUtil::ConvertCodecType(int32_t type)
37 {
38     switch (type)
39     {
40         default:
41         case VideoConfig::CODEC_AVC:
42             return kVideoCodecAvc;
43         case VideoConfig::CODEC_HEVC:
44             return kVideoCodecHevc;
45     }
46 }
47 
GetResolutionFromSize(uint32_t nWidth,uint32_t nHeight)48 uint32_t ImsMediaVideoUtil::GetResolutionFromSize(uint32_t nWidth, uint32_t nHeight)
49 {
50     if (nWidth == 128 && nHeight == 96)
51         return kVideoResolutionSqcifLandscape;
52     else if (nWidth == 96 && nHeight == 128)
53         return kVideoResolutionSqcifPortrait;
54     else if (nWidth == 480 && nHeight == 640)
55         return kVideoResolutionVgaPortrait;
56     else if (nWidth == 640 && nHeight == 480)
57         return kVideoResolutionVgaLandscape;
58     else if (nWidth == 240 && nHeight == 320)
59         return kVideoResolutionQvgaPortrait;
60     else if (nWidth == 320 && nHeight == 240)
61         return kVideoResolutionQvgaLandscape;
62     else if (nWidth == 144 && nHeight == 176)
63         return kVideoResolutionQcifPortrait;
64     else if (nWidth == 176 && nHeight == 144)
65         return kVideoResolutionQcifLandscape;
66     else if (nWidth == 352 && nHeight == 288)
67         return kVideoResolutionCifLandscape;
68     else if (nWidth == 288 && nHeight == 352)
69         return kVideoResolutionCifPortrait;
70     else if (nWidth == 240 && nHeight == 352)
71         return kVideoResolutionSifPortrait;
72     else if (nWidth == 352 && nHeight == 240)
73         return kVideoResolutionSifLandscape;
74     else if (nWidth == 1280 && nHeight == 720)
75         return kVideoResolutionHdLandscape;
76     else if (nWidth == 720 && nHeight == 1280)
77         return kVideoResolutionHdPortrait;
78     else
79         return kVideoResolutionInvalid;
80 }
81 
ParseAvcSpropParam(const char * szSpropparam,tCodecConfig * pInfo)82 ImsMediaResult ImsMediaVideoUtil::ParseAvcSpropParam(const char* szSpropparam, tCodecConfig* pInfo)
83 {
84     ImsMediaBitReader bitreader;
85     bool ret = false;
86     uint8_t pbSPSConfig[MAX_CONFIG_LEN] = {'\0'};
87     char pSPSConfig[MAX_CONFIG_LEN] = {'\0'};
88     uint32_t nSPSConfigSize = 0;
89     uint32_t chroma_format_idc = 0;
90 
91     memset(pSPSConfig, 0x00, MAX_CONFIG_LEN);
92 
93     for (int32_t i = 0; i < MAX_CONFIG_LEN; i++)
94     {
95         uint8_t Comma = ',';
96         char cmpConfig = *(szSpropparam + i);
97         if (Comma == cmpConfig)
98         {
99             memset(pSPSConfig, 0x00, MAX_CONFIG_LEN);
100             memcpy(pSPSConfig, szSpropparam, i);
101         }
102     }
103 
104     ret = ImsMediaBinaryFormat::Base00ToBinary(
105             pbSPSConfig, &nSPSConfigSize, MAX_CONFIG_LEN, pSPSConfig, BINARY_FORMAT_BASE64);
106 
107     if (ret == false)
108     {
109         IMLOGW0("[ParseAvcSpropParam] sps convert fail");
110         return RESULT_INVALID_PARAM;
111     }
112 
113     uint8_t* pszSpropparam = reinterpret_cast<uint8_t*>(malloc(nSPSConfigSize));
114 
115     if (pszSpropparam == nullptr)
116     {
117         pInfo->nProfile = 0;
118         pInfo->nLevel = 0;
119         pInfo->nHeight = 0;
120         pInfo->nWidth = 0;
121 
122         return RESULT_NO_MEMORY;
123     }
124 
125     memcpy(pszSpropparam, pbSPSConfig, nSPSConfigSize);
126 
127     bitreader.SetBuffer(pszSpropparam, nSPSConfigSize);
128     bitreader.Read(8);
129 
130     uint32_t Profile_idc = bitreader.Read(8);  // Read profile_idc
131 
132     // Read constraint
133     bitreader.Read(1);  // Constraint_set0
134     bitreader.Read(1);  // Constraint_set1
135     bitreader.Read(1);  // Constraint_set2
136     bitreader.Read(1);  // Constraint_set3
137     bitreader.Read(1);  // Constraint_set4
138     bitreader.Read(3);  // Read reserved_zeor_3bits
139 
140     uint32_t Level_idc = bitreader.Read(8);  // Read level_idc
141     bitreader.ReadByUEMode();                // Read Seq_parameter_set_id
142 
143     if (Profile_idc == 100 || Profile_idc == 11 || Profile_idc == 122 || Profile_idc == 244 ||
144             Profile_idc == 44 || Profile_idc == 83 || Profile_idc == 86 || Profile_idc == 118)
145     {
146         chroma_format_idc = bitreader.ReadByUEMode();
147 
148         if (chroma_format_idc == 3)
149         {
150             bitreader.Read(1);  // Separate_colour_plane
151         }
152 
153         bitreader.ReadByUEMode();  // Read bit_depth_luma_minus8
154         bitreader.ReadByUEMode();  // Read bit_depth_chroma_minus8
155         bitreader.Read(1);         // Read qpprime_y_zero_transformypass
156 
157         // Read seq_scaling_matrix_present
158         if (bitreader.Read(1))
159         {
160             uint32_t i = ((chroma_format_idc != 3) ? 8 : 12);
161             // Set scaling_list... not implement
162             bitreader.Read(i);
163         }
164     }
165 
166     pInfo->nProfile = Profile_idc;
167     pInfo->nLevel = Level_idc;
168 
169     bitreader.ReadByUEMode();                                // Read log2_max_frame_num_minus4
170     uint32_t pic_order_cnt_type = bitreader.ReadByUEMode();  // Read pic_order_cnt_type
171 
172     if (pic_order_cnt_type == 0)
173     {
174         bitreader.ReadByUEMode();  // Read log2_max_pic_order_cnt_lsb_minus4
175     }
176     else if (pic_order_cnt_type == 1)
177     {
178         bitreader.Read(1);         // Read delta_pic_order_always_zero_flag
179         bitreader.ReadByUEMode();  // Reda offset_for_non_ref_pic...
180         bitreader.ReadByUEMode();  // Read offset_for_top_to_bottom_field
181         uint32_t num_ref_frames_in_pic_order_cnt_cycle =
182                 bitreader.ReadByUEMode();  // Read num_ref_frames_in_pic_order_cnt_cycle
183         for (int32_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
184         {
185             bitreader.ReadByUEMode();  // Read offset_for_ref_frame[i];
186         }
187     }
188 
189     bitreader.ReadByUEMode();  // Read max_num_ref_frames
190     bitreader.Read(1);         // Read gaps_in_frame_num_value_allowed
191 
192     uint32_t pic_width_in_mbs_minus1 = bitreader.ReadByUEMode();  // Read pic_width_in_mbs_minus1
193     uint32_t pic_height_in_map_units_minus1 =
194             bitreader.ReadByUEMode();  // Read pic_height_in_map_units_minus1
195     uint32_t frame_mbs_only = bitreader.Read(1);
196 
197     pInfo->nWidth = pic_width_in_mbs_minus1 * 16 + 16;
198     pInfo->nHeight = (2 - frame_mbs_only) * (pic_height_in_map_units_minus1 * 16 + 16);
199 
200     if (!frame_mbs_only)
201     {
202         bitreader.Read(1);  // Read mb_adaptive_frame_field
203     }
204 
205     bitreader.Read(1);                            // Read direct_8x8_inferencce_flag
206     uint32_t frame_cropping = bitreader.Read(1);  // Read frame_cropping_flag
207 
208     if (frame_cropping)
209     {
210         uint32_t frame_crop_left_offset = bitreader.ReadByUEMode();   // Read frame_crop_left_offset
211         uint32_t frame_crop_right_offset = bitreader.ReadByUEMode();  // Read
212                                                                       // frame_crop_right_offset
213         uint32_t frame_crop_top_offset = bitreader.ReadByUEMode();    // Read frame_crop_top_offset
214         uint32_t frame_crop_bottom_offset =
215                 bitreader.ReadByUEMode();  // Read frame_crop_bottom_offset
216         uint32_t cropX, cropY = 0;
217 
218         if (chroma_format_idc == 0 /* Monochrome */)
219         {
220             cropX = 1;
221             cropY = 2 - frame_mbs_only;
222         }
223         else
224         {
225             uint32_t subWidthC = (chroma_format_idc == 3) ? 1 : 2;
226             uint32_t subHeightC = (chroma_format_idc == 1) ? 2 : 1;
227             cropX = subWidthC;
228             cropY = subHeightC * (2 - frame_mbs_only);
229         }
230 
231         pInfo->nWidth -= (frame_crop_left_offset + frame_crop_right_offset) * cropX;
232         pInfo->nHeight -= (frame_crop_top_offset + frame_crop_bottom_offset) * cropY;
233     }
234 
235     free(pszSpropparam);
236 
237     IMLOGD4("[ParseAvcSpropParam] width[%d],height[%d],nProfile[%d],nLevel[%d]", pInfo->nWidth,
238             pInfo->nHeight, pInfo->nProfile, pInfo->nLevel);
239 
240     return RESULT_SUCCESS;
241 }
242 
ParseHevcSpropParam(const char * szSpropparam,tCodecConfig * pInfo)243 ImsMediaResult ImsMediaVideoUtil::ParseHevcSpropParam(const char* szSpropparam, tCodecConfig* pInfo)
244 {
245     uint32_t nSize = strlen(szSpropparam);
246 
247     if (nSize == 0)
248     {
249         return RESULT_INVALID_PARAM;
250     }
251 
252     IMLOGD1("[ParseHevcSpropParam] szSpropparam[%s]", szSpropparam);
253 
254     uint8_t pbSPSConfig[MAX_CONFIG_LEN] = {'\0'};
255     char pSPSConfig[MAX_CONFIG_LEN] = {'\0'};
256     uint32_t nSPSConfigSize = 0;
257 
258     memset(pSPSConfig, 0x00, MAX_CONFIG_LEN);
259     strlcpy(pSPSConfig, szSpropparam, MAX_CONFIG_LEN);
260 
261     uint8_t* pszSpropparam = nullptr;
262 
263     if (ImsMediaBinaryFormat::Base00ToBinary(pbSPSConfig, &nSPSConfigSize, MAX_CONFIG_LEN,
264                 pSPSConfig, BINARY_FORMAT_BASE64) == false)
265     {
266         IMLOGW0("[ParseAvcSpropParam] sps convert fail");
267         return RESULT_INVALID_PARAM;
268     }
269 
270     if (nSPSConfigSize == 0)
271         return RESULT_INVALID_PARAM;
272 
273     pszSpropparam = reinterpret_cast<uint8_t*>(malloc(nSPSConfigSize));
274 
275     if (pszSpropparam == nullptr)
276     {
277         pInfo->nProfile = 0;
278         pInfo->nLevel = 0;
279         pInfo->nHeight = 0;
280         pInfo->nWidth = 0;
281 
282         return RESULT_INVALID_PARAM;
283     }
284 
285     memcpy(pszSpropparam, pbSPSConfig, nSPSConfigSize);
286 
287     // Check binary
288     ImsMediaTrace::IMLOGD_BINARY("[ParseHevcSpropParam] sps=",
289             reinterpret_cast<const char*>(pszSpropparam), nSPSConfigSize);
290 
291     uint32_t nOffset = 0;
292 
293     for (int32_t i = 0; i < nSPSConfigSize - 6; i++)
294     {
295         // NAL unit header offset
296         if (pszSpropparam[i] == 0x00 && pszSpropparam[i + 1] == 0x00 &&
297                 pszSpropparam[i + 2] == 0x00 && pszSpropparam[i + 3] == 0x01 &&
298                 pszSpropparam[i + 4] == 0x42 && pszSpropparam[i + 5] == 0x01)
299         {
300             nOffset = i + 6;
301             break;
302         }
303     }
304 
305     IMLOGD2("[ParseHevcSpropParam] nSPSConfigSize[%d], offset[%d]", nSPSConfigSize, nOffset);
306 
307     ImsMediaBitReader objBitReader;
308     objBitReader.SetBuffer(pszSpropparam + nOffset, nSPSConfigSize - nOffset);
309 
310     objBitReader.Read(4);  // sps_video_parameter_set_id;
311     uint32_t sps_max_sub_layers_minus1 = objBitReader.Read(3);
312 
313     IMLOGD1("[ParseHevcSpropParam] sps_max_sub_layers_minus1[%d]", sps_max_sub_layers_minus1);
314 
315     objBitReader.Read(1);  // sps_temporal_id_nesting_flag;
316 
317     /*-----------profile_tier_level start-----------------------*/
318     objBitReader.Read(3);  // general_profile_spac, general_tier_flag
319     uint32_t general_profile_idc = objBitReader.Read(5);
320 
321     IMLOGD1("[ParseHevcSpropParam] general_profile_idc[%d]", general_profile_idc);
322 
323     // skip 13byte - flags, not handle
324     objBitReader.Read(24);
325     objBitReader.Read(24);
326     objBitReader.Read(24);
327     objBitReader.Read(24);
328     objBitReader.Read(8);
329 
330     uint32_t general_level_idc = objBitReader.Read(8);
331 
332     IMLOGD1("[ParseHevcSpropParam] general_level_idc[%d]", general_level_idc);
333 
334     uint8_t sub_layer_profile_present_flag[sps_max_sub_layers_minus1];
335     uint8_t sub_layer_level_present_flag[sps_max_sub_layers_minus1];
336 
337     for (int32_t i = 0; i < sps_max_sub_layers_minus1; i++)
338     {
339         sub_layer_profile_present_flag[i] = objBitReader.Read(1);
340         sub_layer_level_present_flag[i] = objBitReader.Read(1);
341     }
342 
343     if (sps_max_sub_layers_minus1 > 0)
344     {
345         for (int32_t j = sps_max_sub_layers_minus1; j < 8; j++)
346         {
347             objBitReader.Read(2);
348         }
349     }
350 
351     for (int32_t i = 0; i < sps_max_sub_layers_minus1; i++)
352     {
353         if (sub_layer_profile_present_flag[i])
354         {
355             objBitReader.Read(2);   // sub_layer_profile_space
356             objBitReader.Read(1);   // sub_layer_tier_flag
357             objBitReader.Read(5);   // sub_layer_profile_idc
358             objBitReader.Read(24);  // sub_layer_profile_compatibility_flag
359             objBitReader.Read(8);   // sub_layer_profile_compatibility_flag
360             objBitReader.Read(24);  // sub_layer_constraint_indicator_flags
361             objBitReader.Read(24);  // sub_layer_constraint_indicator_flags
362         }
363 
364         if (sub_layer_level_present_flag[i])
365         {
366             objBitReader.Read(8);  // sub_layer_level_idc
367         }
368     }
369 
370     /*-----------profile_tier_level done-----------------------*/
371     objBitReader.ReadByUEMode();  // sps_seq_parameter_set_id
372 
373     uint32_t chroma_format_idc;
374     chroma_format_idc = objBitReader.ReadByUEMode();
375 
376     IMLOGD1("[ParseHevcSpropParam] chroma_format_idc[%d]", chroma_format_idc);
377 
378     if (chroma_format_idc == 3)
379     {
380         objBitReader.Read(1);  // separate_colour_plane_flag
381     }
382 
383     int32_t pic_width_in_luma_samples = objBitReader.ReadByUEMode();
384     int32_t pic_height_in_luma_samples = objBitReader.ReadByUEMode();
385 
386     IMLOGD1("[ParseHevcSpropParam] pic_width_in_luma_samples[%d]", pic_width_in_luma_samples);
387 
388     IMLOGD1("[ParseHevcSpropParam] pic_height_in_luma_samples[%d]", pic_height_in_luma_samples);
389 
390     pInfo->nWidth = pic_width_in_luma_samples;
391     pInfo->nHeight = pic_height_in_luma_samples;
392 
393     uint8_t conformance_window_flag = objBitReader.Read(1);
394 
395     IMLOGD1("[ParseHevcSpropParam] conformance_window_flag[%d]", conformance_window_flag);
396 
397     if (conformance_window_flag)
398     {
399         uint32_t conf_win_left_offset = objBitReader.ReadByUEMode();
400         uint32_t conf_win_right_offset = objBitReader.ReadByUEMode();
401         uint32_t conf_win_top_offset = objBitReader.ReadByUEMode();
402         uint32_t conf_win_bottom_offset = objBitReader.ReadByUEMode();
403 
404         pInfo->nWidth -= conf_win_left_offset + conf_win_right_offset;
405         pInfo->nHeight -= conf_win_top_offset + conf_win_bottom_offset;
406 
407         IMLOGD4("[ParseHevcSpropParam] frame_crop = [%u, %u, %u, %u]", conf_win_left_offset,
408                 conf_win_right_offset, conf_win_top_offset, conf_win_bottom_offset);
409     }
410 
411     // Round down by 16 unit
412     uint32_t nRoundDownWidth = (pInfo->nWidth) / 16 * 16;
413     uint32_t nRoundDownHeight = (pInfo->nHeight) / 16 * 16;
414 
415     pInfo->nWidth = nRoundDownWidth;
416     pInfo->nHeight = nRoundDownHeight;
417     free(pszSpropparam);
418     return RESULT_SUCCESS;
419 }
420 
ParseAvcSps(uint8_t * pbBuffer,uint32_t nBufferSize,tCodecConfig * pInfo)421 bool ImsMediaVideoUtil::ParseAvcSps(uint8_t* pbBuffer, uint32_t nBufferSize, tCodecConfig* pInfo)
422 {
423     ImsMediaBitReader bitreader;
424     uint32_t chroma_format_idc = 0;
425     uint8_t* pszSPS = reinterpret_cast<uint8_t*>(malloc(nBufferSize));
426 
427     if (pszSPS == nullptr)
428     {
429         pInfo->nProfile = 0;
430         pInfo->nLevel = 0;
431         pInfo->nHeight = 0;
432         pInfo->nWidth = 0;
433         return false;
434     }
435 
436     memcpy(pszSPS, pbBuffer, nBufferSize);
437 
438     IMLOGD_PACKET1(IM_PACKET_LOG_VIDEO, "[ParseAvcSps] pszSPS[%02X]", pszSPS[0]);
439 
440     bitreader.SetBuffer(pszSPS, nBufferSize);
441     bitreader.Read(8);
442     bitreader.Read(8);
443     bitreader.Read(8);
444     bitreader.Read(8);
445     bitreader.Read(8);
446 
447     uint32_t Profile_idc = bitreader.Read(8);  // Read profile_idc
448     // Read constraint
449     uint32_t constraint_set0 = bitreader.Read(1);
450     uint32_t constraint_set1 = bitreader.Read(1);
451     uint32_t constraint_set2 = bitreader.Read(1);
452     uint32_t constraint_set3 = bitreader.Read(1);
453     uint32_t constraint_set4 = bitreader.Read(1);
454     bitreader.Read(3);                       // Read reserved_zeor_3bits
455     uint32_t Level_idc = bitreader.Read(8);  // Read level_idc
456     bitreader.ReadByUEMode();                // Read Seq_parameter_set_id
457 
458     if (Profile_idc == 100 || Profile_idc == 110 || Profile_idc == 122 || Profile_idc == 244 ||
459             Profile_idc == 44 || Profile_idc == 83 || Profile_idc == 86 || Profile_idc == 118)
460     {
461         chroma_format_idc = bitreader.ReadByUEMode();
462 
463         if (chroma_format_idc == 3)
464         {
465             bitreader.Read(1);  // separate_colour_plane
466         }
467 
468         bitreader.ReadByUEMode();  // Read bit_depth_luma_minus8
469         bitreader.ReadByUEMode();  // Read bit_depth_chroma_minus8
470         bitreader.Read(1);         // Read qpprime_y_zero_transform_bypass
471 
472         // Read seq_scaling_matrix_present
473         if (bitreader.Read(1))
474         {
475             uint32_t i = ((chroma_format_idc != 3) ? 8 : 12);
476             // set scaling_list... not implement
477             bitreader.Read(i);
478         }
479     }
480     else if (Profile_idc == 183)
481     {
482         chroma_format_idc = 0;
483     }
484     else
485     {
486         chroma_format_idc = 1;  // if chroma_format_idc not present in SPS it should be set to 1;
487     }
488     pInfo->nProfile = Profile_idc;
489     pInfo->nLevel = Level_idc;
490 
491     IMLOGD_PACKET5(IM_PACKET_LOG_VIDEO, "[ParseAvcSps] constraint_set[%d][%d][%d][%d][%d]",
492             constraint_set0, constraint_set1, constraint_set2, constraint_set3, constraint_set4);
493     IMLOGD_PACKET2(IM_PACKET_LOG_VIDEO, "[ParseAvcSps] Profile_idc[%d], Level_idc[%d]", Profile_idc,
494             Level_idc);
495 
496     bitreader.ReadByUEMode();                                // Read log2_max_frame_num_minus4
497     uint32_t pic_order_cnt_type = bitreader.ReadByUEMode();  // Read pic_order_cnt_type
498 
499     if (pic_order_cnt_type == 0)
500     {
501         bitreader.ReadByUEMode();  // Read log2_max_pic_order_cnt_lsb_minus4
502     }
503     else if (pic_order_cnt_type == 1)
504     {
505         bitreader.Read(1);         // Read delta_pic_order_always_zero_flag
506         bitreader.ReadByUEMode();  // Reda offset_for_non_ref_pic...
507         bitreader.ReadByUEMode();  // Read offset_for_top_to_bottom_field
508         uint32_t num_ref_frames_in_pic_order_cnt_cycle = bitreader.ReadByUEMode();
509 
510         for (int32_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
511         {
512             bitreader.ReadByUEMode();  // Read offset_for_ref_frame[i];
513         }
514     }
515 
516     bitreader.ReadByUEMode();  // Read max_num_ref_frames
517     bitreader.Read(1);         // Read gaps_in_frame_num_value_allowed
518 
519     uint32_t pic_width_in_mbs_minus1 = bitreader.ReadByUEMode();
520     uint32_t pic_height_in_map_units_minus1 = bitreader.ReadByUEMode();
521     uint32_t frame_mbs_only = bitreader.Read(1);
522 
523     pInfo->nWidth = pic_width_in_mbs_minus1 * 16 + 16;
524     pInfo->nHeight = (2 - frame_mbs_only) * (pic_height_in_map_units_minus1 * 16 + 16);
525 
526     if (!frame_mbs_only)
527     {
528         bitreader.Read(1);  // Read mb_adaptive_frame_field
529     }
530 
531     bitreader.Read(1);                            // Read direct_8x8_inferencce_flag
532     uint32_t frame_cropping = bitreader.Read(1);  // Read frame_cropping_flag
533 
534     if (frame_cropping)
535     {
536         uint32_t frame_crop_left_offset = bitreader.ReadByUEMode();
537         uint32_t frame_crop_right_offset = bitreader.ReadByUEMode();
538         uint32_t frame_crop_top_offset = bitreader.ReadByUEMode();
539         uint32_t frame_crop_bottom_offset = bitreader.ReadByUEMode();
540         uint32_t cropX, cropY = 0;
541         if (chroma_format_idc == 0 /* monochrome */)
542         {
543             cropX = 1;
544             cropY = 2 - frame_mbs_only;
545         }
546         else
547         {
548             uint32_t subWidthC = (chroma_format_idc == 3) ? 1 : 2;
549             uint32_t subHeightC = (chroma_format_idc == 1) ? 2 : 1;
550             cropX = subWidthC;
551             cropY = subHeightC * (2 - frame_mbs_only);
552         }
553 
554         pInfo->nWidth -= (frame_crop_left_offset + frame_crop_right_offset) * cropX;
555         pInfo->nHeight -= (frame_crop_top_offset + frame_crop_bottom_offset) * cropY;
556     }
557 
558     free(pszSPS);
559 
560     IMLOGD_PACKET2(IM_PACKET_LOG_VIDEO, "[ParseAvcSps] width[%d],height[%d]", pInfo->nWidth,
561             pInfo->nHeight);
562     IMLOGD_PACKET2(IM_PACKET_LOG_VIDEO, "[ParseAvcSps] nProfile[%d],nLevel[%d]", pInfo->nProfile,
563             pInfo->nLevel);
564     return true;
565 }
566 
ParseHevcSps(uint8_t * pbBuffer,uint32_t nBufferSize,tCodecConfig * pInfo)567 bool ImsMediaVideoUtil::ParseHevcSps(uint8_t* pbBuffer, uint32_t nBufferSize, tCodecConfig* pInfo)
568 {
569     if (pbBuffer == nullptr || nBufferSize == 0)
570     {
571         pInfo->nProfile = 0;
572         pInfo->nLevel = 0;
573         pInfo->nHeight = 0;
574         pInfo->nWidth = 0;
575         return false;
576     }
577 
578     uint32_t nOffset = 0;
579 
580     for (int32_t i = 0; i < nBufferSize - 6; i++)
581     {
582         // NAL unit header offset
583         if (pbBuffer[i] == 0x00 && pbBuffer[i + 1] == 0x00 && pbBuffer[i + 2] == 0x00 &&
584                 pbBuffer[i + 3] == 0x01 && pbBuffer[i + 4] == 0x42 && pbBuffer[i + 5] == 0x01)
585         {
586             nOffset = i + 6;
587             break;
588         }
589     }
590 
591     ImsMediaBitReader objBitReader;
592     objBitReader.SetBuffer(pbBuffer + nOffset, nBufferSize - nOffset);
593     objBitReader.Read(4);                                       // sps_video_parameter_set_id;
594     uint32_t sps_max_sub_layers_minus1 = objBitReader.Read(3);  // 0
595     objBitReader.Read(1);                                       // sps_temporal_id_nesting_flag;
596 
597     objBitReader.Read(3);                    // general_profile_spac, general_tier_flag
598     pInfo->nProfile = objBitReader.Read(5);  // general_profile_idc
599 
600     // skip 10byte - flags, not handle
601     objBitReader.Read(24);
602     objBitReader.Read(24);
603     objBitReader.Read(24);
604     objBitReader.Read(8);
605 
606     pInfo->nLevel = objBitReader.Read(8);  // general_level_idc
607 
608     uint8_t sub_layer_profile_present_flag[sps_max_sub_layers_minus1];
609     uint8_t sub_layer_level_present_flag[sps_max_sub_layers_minus1];
610 
611     for (int32_t i = 0; i < sps_max_sub_layers_minus1; i++)
612     {
613         sub_layer_profile_present_flag[i] = objBitReader.Read(1);
614         sub_layer_level_present_flag[i] = objBitReader.Read(1);
615     }
616 
617     if (sps_max_sub_layers_minus1 > 0)
618     {
619         for (int32_t j = sps_max_sub_layers_minus1; j < 8; j++)
620         {
621             objBitReader.Read(2);
622         }
623     }
624 
625     for (int32_t i = 0; i < sps_max_sub_layers_minus1; i++)
626     {
627         if (sub_layer_profile_present_flag[i])
628         {
629             objBitReader.Read(2);   // sub_layer_profile_space
630             objBitReader.Read(1);   // sub_layer_tier_flag
631             objBitReader.Read(5);   // sub_layer_profile_idc
632             objBitReader.Read(24);  // sub_layer_profile_compatibility_flag
633             objBitReader.Read(8);   // sub_layer_profile_compatibility_flag
634             objBitReader.Read(24);  // sub_layer_constraint_indicator_flags
635             objBitReader.Read(24);  // sub_layer_constraint_indicator_flags
636         }
637 
638         if (sub_layer_level_present_flag[i])
639         {
640             objBitReader.Read(8);  // sub_layer_level_idc
641         }
642     }
643 
644     objBitReader.ReadByUEMode();  // sps_seq_parameter_set_id
645 
646     uint32_t chroma_format_idc = objBitReader.ReadByUEMode();
647 
648     if (chroma_format_idc == 3)
649     {
650         objBitReader.Read(1);  // separate_colour_plane_flag
651     }
652 
653     pInfo->nWidth = objBitReader.ReadByUEMode();
654     pInfo->nHeight = objBitReader.ReadByUEMode();
655 
656     uint8_t conformance_window_flag = objBitReader.Read(1);
657 
658     if (conformance_window_flag)
659     {
660         uint32_t conf_win_left_offset = objBitReader.ReadByUEMode();
661         uint32_t conf_win_right_offset = objBitReader.ReadByUEMode();
662         uint32_t conf_win_top_offset = objBitReader.ReadByUEMode();
663         uint32_t conf_win_bottom_offset = objBitReader.ReadByUEMode();
664 
665         pInfo->nWidth -= conf_win_left_offset + conf_win_right_offset;
666         pInfo->nHeight -= conf_win_top_offset + conf_win_bottom_offset;
667     }
668 
669     // Round down by 16 unit
670     uint32_t nRoundDownWidth = (pInfo->nWidth) / 16 * 16;
671     uint32_t nRoundDownHeight = (pInfo->nHeight) / 16 * 16;
672 
673     pInfo->nWidth = nRoundDownWidth;
674     pInfo->nHeight = nRoundDownHeight;
675 
676     return true;
677 }
678 
FindAvcStartCode(uint8_t * pData,uint32_t nDataSize,uint32_t * pnSkipSize)679 uint8_t* FindAvcStartCode(uint8_t* pData, uint32_t nDataSize, uint32_t* pnSkipSize)
680 {
681     uint8_t* pCurDataPos = pData;
682     uint32_t nSkipSize = 0;
683 
684     // Remove leading zero bytes and start code prefix
685     while (nDataSize >= START_CODE_PREFIX_LEN)
686     {
687         // Start Code 00 00 00 01 case.
688         if (pCurDataPos[0] == 0x00 && pCurDataPos[1] == 0x00 && pCurDataPos[2] == 0x00 &&
689                 pCurDataPos[3] == 0x01)
690         {
691             if (pnSkipSize)
692                 *pnSkipSize = nSkipSize;
693             return pCurDataPos;
694         }
695         else
696         {
697             pCurDataPos += 1;
698             nDataSize -= 1;
699             nSkipSize += 1;
700         }
701     }
702 
703     if (pnSkipSize)
704         *pnSkipSize = nSkipSize;
705     return nullptr;
706 }
707 
GenerateVideoSprop(VideoConfig * pVideoConfig)708 char* ImsMediaVideoUtil::GenerateVideoSprop(VideoConfig* pVideoConfig)
709 {
710     if (pVideoConfig == nullptr)
711     {
712         IMLOGE0("[GenerateVideoSprop] pVideoConfig is null");
713         return nullptr;
714     }
715 
716     // Configure Encoder
717     AMediaFormat* pFormat = AMediaFormat_new();
718     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_WIDTH, pVideoConfig->getResolutionWidth());
719     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_HEIGHT, pVideoConfig->getResolutionHeight());
720 
721     char kMimeType[128] = {'\0'};
722     sprintf(kMimeType, "video/avc");
723     if (pVideoConfig->getCodecType() == VideoConfig::CODEC_HEVC)
724     {
725         sprintf(kMimeType, "video/hevc");
726     }
727 
728     IMLOGD1("[GenerateVideoSprop] MimeType[%s]", kMimeType);
729     IMLOGD2("[GenerateVideoSprop] Resolution[%dx%d].", pVideoConfig->getResolutionWidth(),
730             pVideoConfig->getResolutionHeight());
731     IMLOGD2("[GenerateVideoSprop] Profile[%d] level[%d]", pVideoConfig->getCodecProfile(),
732             pVideoConfig->getCodecLevel());
733     IMLOGD2("[GenerateVideoSprop] Bitrate[%d], FrameRate[%d]", pVideoConfig->getBitrate(),
734             pVideoConfig->getFramerate());
735 
736     AMediaFormat_setString(pFormat, AMEDIAFORMAT_KEY_MIME, kMimeType);
737     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT,
738             0x00000015);  // COLOR_FormatYUV420SemiPlanar
739 
740     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_BIT_RATE, pVideoConfig->getBitrate() * 1000);
741     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_PROFILE, pVideoConfig->getCodecProfile());
742     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_LEVEL, pVideoConfig->getCodecLevel());
743     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_BITRATE_MODE, 2);  // #2 : BITRATE_MODE_CBR
744     AMediaFormat_setFloat(pFormat, AMEDIAFORMAT_KEY_FRAME_RATE, pVideoConfig->getFramerate());
745     AMediaFormat_setInt32(
746             pFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, pVideoConfig->getIntraFrameInterval());
747     AMediaFormat_setInt32(pFormat, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE,
748             pVideoConfig->getResolutionWidth() * pVideoConfig->getResolutionHeight() * 10);
749 
750     AMediaCodec* pCodec = AMediaCodec_createEncoderByType(kMimeType);
751     if (pCodec == nullptr)
752     {
753         IMLOGE1("[GenerateVideoSprop] Unable to create encoder. MimeType[%s]", kMimeType);
754         return nullptr;
755     }
756 
757     media_status_t err = AMediaCodec_configure(
758             pCodec, pFormat, nullptr, nullptr, AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
759     if (err != AMEDIA_OK)
760     {
761         IMLOGE1("[GenerateVideoSprop] Encoder configure error[%d]", err);
762         AMediaCodec_delete(pCodec);
763         pCodec = nullptr;
764         AMediaFormat_delete(pFormat);
765         pFormat = nullptr;
766         return nullptr;
767     }
768 
769     err = AMediaCodec_start(pCodec);
770     if (err != AMEDIA_OK)
771     {
772         IMLOGE1("[GenerateVideoSprop] Encoder start Err[%d]", err);
773         AMediaCodec_delete(pCodec);
774         pCodec = nullptr;
775         AMediaFormat_delete(pFormat);
776         pFormat = nullptr;
777         return nullptr;
778     }
779 
780     bool bSpsRead = false, bPpsRead = false;
781     int8_t nMaxBufferReads = MAX_OUTPUT_BUFFER_READ_ATTEMPTS;
782     char* pSpropStr = reinterpret_cast<char*>(malloc(MAX_CONFIG_LEN));
783     pSpropStr[0] = '\0';
784 
785     while (!bSpsRead || !bPpsRead)
786     {
787         // Get output buffer
788         AMediaCodecBufferInfo info;
789         auto index = AMediaCodec_dequeueOutputBuffer(pCodec, &info, 100000);
790         IMLOGD2("[GenerateVideoSprop] dequeueOutputBuffer returned index[%d] frameSize[%d]", index,
791                 info.size);
792         if (index >= 0 && info.size > 0)
793         {
794             size_t buffCapacity = 0;
795             uint8_t* buf = AMediaCodec_getOutputBuffer(pCodec, index, &buffCapacity);
796             IMLOGD1("[GenerateVideoSprop] getOutputBuffer returned buffCapacity[%d]", buffCapacity);
797 
798             buf += info.offset;
799             buffCapacity = info.size;
800 
801             while (buf != nullptr && buffCapacity > 0)
802             {
803                 uint32_t skipLen = 0;
804                 uint8_t* tempBufPtr = FindAvcStartCode(buf, buffCapacity, &skipLen);
805                 if (tempBufPtr != nullptr)
806                 {
807                     buf = tempBufPtr;
808                     buffCapacity -= skipLen;
809                 }
810 
811                 if (buf == nullptr || buffCapacity < START_CODE_PREFIX_LEN)
812                     continue;
813 
814                 // Remove start sequence
815                 buf += START_CODE_PREFIX_LEN;
816                 buffCapacity -= START_CODE_PREFIX_LEN;
817 
818                 uint8_t frameType = buf[0] & 0x1F;
819 
820                 // Extract frame
821                 int frameLen = buffCapacity;
822                 tempBufPtr = FindAvcStartCode(buf, buffCapacity, &skipLen);
823                 if (tempBufPtr != nullptr)
824                 {
825                     frameLen = tempBufPtr - buf;
826                 }
827 
828                 int16_t SpropStrlen = strlen(pSpropStr);
829                 bool ret = ImsMediaBinaryFormat::BinaryToBase00(pSpropStr + SpropStrlen,
830                         MAX_CONFIG_LEN, buf, frameLen, BINARY_FORMAT_BASE64);
831                 if (ret == false)
832                 {
833                     IMLOGE0("[GenerateVideoSprop] BinaryToBase64 failed");
834                     free(pSpropStr);
835                     pSpropStr = nullptr;
836                     AMediaCodec_releaseOutputBuffer(pCodec, index, false);
837                     goto JP_Exit_GenerateSprop;
838                 }
839 
840                 if (frameType == FRAME_TYPE_SPS)  // Check if SPS
841                 {
842                     strlcat(pSpropStr, ",", MAX_CONFIG_LEN);
843                     bSpsRead = true;
844                 }
845                 else if (frameType == FRAME_TYPE_PPS)  // Check if PPS
846                 {
847                     bPpsRead = true;
848                 }
849 
850                 buffCapacity -= frameLen;
851                 buf += frameLen;
852             }
853 
854             AMediaCodec_releaseOutputBuffer(pCodec, index, false);
855         }
856         else
857         {
858             IMLOGE2("[GenerateVideoSprop] dequeueOutputBuffer returned invalid index[%d] "
859                     "info.size[%d]",
860                     index, info.size);
861         }
862 
863         if (--nMaxBufferReads <= 0)
864         {
865             free(pSpropStr);
866             pSpropStr = nullptr;
867             goto JP_Exit_GenerateSprop;
868         }
869     }
870 
871 JP_Exit_GenerateSprop:
872     // Stop Encoder
873     if (pCodec != nullptr)
874     {
875         IMLOGD0("[GenerateVideoSprop] Stop encoder");
876         AMediaCodec_signalEndOfInputStream(pCodec);
877         AMediaCodec_stop(pCodec);
878         AMediaCodec_delete(pCodec);
879     }
880 
881     if (pFormat != nullptr)
882     {
883         AMediaFormat_delete(pFormat);
884     }
885 
886     IMLOGD1("[GenerateVideoSprop] Returning sprop[%s]", pSpropStr);
887     return pSpropStr;
888 }
889 
ConvertBitrateToPower(const uint32_t nInputBitrate,uint32_t & nOutExp,uint32_t & nOutMantissa)890 void ImsMediaVideoUtil::ConvertBitrateToPower(
891         const uint32_t nInputBitrate, uint32_t& nOutExp, uint32_t& nOutMantissa)
892 {
893     if (nInputBitrate == 0)
894     {
895         return;
896     }
897 
898     nOutExp = 0;
899     nOutMantissa = (nInputBitrate % 2 == 0) ? (nInputBitrate) : (nInputBitrate + 1);
900 
901     while (nOutMantissa % 2 == 0)
902     {
903         nOutExp++;
904         nOutMantissa = nOutMantissa >> 1;
905 
906         if (nOutMantissa >= 0x1ffff)
907         {
908             nOutMantissa = (nOutMantissa % 2 == 0) ? (nOutMantissa) : (nOutMantissa + 1);
909         }
910     }
911 }
912