xref: /aosp_15_r20/external/v4l2_codec2/common/H264NalParser.cpp (revision 0ec5a0ec62797f775085659156625e7f1bdb369f)
1 // Copyright 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "NalParser"
7 
8 #include <v4l2_codec2/common/H264NalParser.h>
9 
10 #include <media/stagefright/foundation/ABitReader.h>
11 #include <utils/Log.h>
12 
13 namespace android {
14 
15 namespace {
16 
17 enum H264ProfileIDC {
18     kProfileIDCAVLC444 = 44,
19     kProfileIDScalableBaseline = 83,
20     kProfileIDScalableHigh = 86,
21     kProfileIDCHigh = 100,
22     kProfileIDHigh10 = 110,
23     kProfileIDSMultiviewHigh = 118,
24     kProfileIDHigh422 = 122,
25     kProfileIDStereoHigh = 128,
26     kProfileIDHigh444Predictive = 244,
27 };
28 
29 constexpr uint32_t kYUV444Idc = 3;
30 
31 // Skip a H.264 sequence scaling list in the specified bitstream.
skipScalingList(ABitReader * br,size_t scalingListSize)32 bool skipScalingList(ABitReader* br, size_t scalingListSize) {
33     size_t nextScale = 8;
34     size_t lastScale = 8;
35     for (size_t j = 0; j < scalingListSize; ++j) {
36         if (nextScale != 0) {
37             int32_t deltaScale;
38             if (!NalParser::parseSE(br, &deltaScale)) return false;  // delta_sl
39             if (deltaScale < -128) {
40                 ALOGW("delta scale (%d) is below range, capping to -128", deltaScale);
41                 deltaScale = -128;
42             } else if (deltaScale > 127) {
43                 ALOGW("delta scale (%d) is above range, capping to 127", deltaScale);
44                 deltaScale = 127;
45             }
46             nextScale = (lastScale + (deltaScale + 256)) % 256;
47         }
48         lastScale = (nextScale == 0) ? lastScale : nextScale;
49     }
50     return true;
51 }
52 
53 // Skip the H.264 sequence scaling matrix in the specified bitstream.
skipScalingMatrix(ABitReader * br,size_t numScalingLists)54 bool skipScalingMatrix(ABitReader* br, size_t numScalingLists) {
55     for (size_t i = 0; i < numScalingLists; ++i) {
56         uint32_t seq_scaling_list_present_flag;
57         if (!br->getBitsGraceful(1, &seq_scaling_list_present_flag))
58             return false;  // seq_scaling_list_present_flag
59         if (seq_scaling_list_present_flag) {
60             if (i < 6) {
61                 if (!skipScalingList(br, 16)) return false;
62             } else {
63                 if (!skipScalingList(br, 64)) return false;
64             }
65         }
66     }
67     return true;
68 }
69 
70 }  // namespace
71 
H264NalParser(const uint8_t * data,size_t length)72 H264NalParser::H264NalParser(const uint8_t* data, size_t length) : NalParser(data, length) {}
73 
locateSPS()74 bool H264NalParser::locateSPS() {
75     while (locateNextNal()) {
76         if (length() == 0) continue;
77         if (type() != kSPSType) continue;
78         return true;
79     }
80 
81     return false;
82 }
83 
locateIDR()84 bool H264NalParser::locateIDR() {
85     while (locateNextNal()) {
86         if (length() == 0) continue;
87         if (type() != kIDRType) continue;
88         return true;
89     }
90 
91     return false;
92 }
93 
type() const94 uint8_t H264NalParser::type() const {
95     // First byte is forbidden_zero_bit (1) + nal_ref_idc (2) + nal_unit_type (5)
96     constexpr uint8_t kNALTypeMask = 0x1f;
97     return *mCurrNalDataPos & kNALTypeMask;
98 }
99 
findCodedColorAspects(ColorAspects * colorAspects)100 bool H264NalParser::findCodedColorAspects(ColorAspects* colorAspects) {
101     ALOG_ASSERT(colorAspects);
102     ALOG_ASSERT(type() == kSPSType);
103 
104     // Unfortunately we can't directly jump to the Video Usability Information (VUI) parameters that
105     // contain the color aspects. We need to parse the entire SPS header up until the values we
106     // need.
107 
108     // Skip first byte containing type.
109     NALBitReader br(mCurrNalDataPos + 1, length() - 1);
110 
111     uint32_t unused;
112     uint32_t profileIDC;
113     if (!br.getBitsGraceful(8, &profileIDC)) return false;  // profile_idc
114     br.skipBits(16);        // constraint flags + reserved bits + level_idc
115     parseUE(&br, &unused);  // seq_parameter_set_id
116 
117     if (profileIDC == kProfileIDCHigh || profileIDC == kProfileIDHigh10 ||
118         profileIDC == kProfileIDHigh422 || profileIDC == kProfileIDHigh444Predictive ||
119         profileIDC == kProfileIDCAVLC444 || profileIDC == kProfileIDScalableBaseline ||
120         profileIDC == kProfileIDScalableHigh || profileIDC == kProfileIDSMultiviewHigh ||
121         profileIDC == kProfileIDStereoHigh) {
122         uint32_t chromaFormatIDC;
123         if (!parseUE(&br, &chromaFormatIDC)) return false;
124         if (chromaFormatIDC == kYUV444Idc) {  // chroma_format_idc
125             br.skipBits(1);                   // separate_colour_plane_flag
126         }
127 
128         parseUE(&br, &unused);  // bit_depth_luma_minus8
129         parseUE(&br, &unused);  // bit_depth_chroma_minus8
130         br.skipBits(1);         // lossless_qpprime_y_zero_flag
131 
132         uint32_t seqScalingMatrixPresentFlag;
133         if (!br.getBitsGraceful(1, &seqScalingMatrixPresentFlag))
134             return false;  // seq_scaling_matrix_present_flag
135         if (seqScalingMatrixPresentFlag) {
136             const size_t numScalingLists = (chromaFormatIDC != kYUV444Idc) ? 8 : 12;
137             if (!skipScalingMatrix(&br, numScalingLists)) return false;
138         }
139     }
140 
141     parseUE(&br, &unused);  // log2_max_frame_num_minus4
142     uint32_t pictureOrderCountType;
143     if (!parseUE(&br, &pictureOrderCountType)) return false;  // pic_order_cnt_type
144     if (pictureOrderCountType == 0) {
145         parseUE(&br, &unused);  // log2_max_pic_order_cnt_lsb_minus4
146     } else if (pictureOrderCountType == 1) {
147         br.skipBits(1);  // delta_pic_order_always_zero_flag
148         int32_t unused_i;
149         parseSE(&br, &unused_i);  // offset_for_non_ref_pic
150         parseSE(&br, &unused_i);  // offset_for_top_to_bottom_field
151         uint32_t numReferenceFrames;
152         if (!parseUE(&br, &numReferenceFrames))
153             return false;  // num_ref_frames_in_pic_order_cnt_cycle
154         for (uint32_t i = 0; i < numReferenceFrames; ++i) {
155             parseUE(&br, &unused);  // offset_for_ref_frame
156         }
157     }
158 
159     parseUE(&br, &unused);  // num_ref_frames
160     br.skipBits(1);         // gaps_in_frame_num_value_allowed_flag
161     parseUE(&br, &unused);  // pic_width_in_mbs_minus1
162     parseUE(&br, &unused);  // pic_height_in_map_units_minus1
163     uint32_t frameMbsOnlyFlag;
164     if (!br.getBitsGraceful(1, &frameMbsOnlyFlag)) return false;  // frame_mbs_only_flag
165     if (!frameMbsOnlyFlag) {
166         br.skipBits(1);  // mb_adaptive_frame_field_flag
167     }
168     br.skipBits(1);  // direct_8x8_inference_flag
169 
170     uint32_t frameCroppingFlag;
171     if (!br.getBitsGraceful(1, &frameCroppingFlag)) return false;  // frame_cropping_flag
172     if (frameCroppingFlag) {
173         parseUE(&br, &unused);  // frame_cropping_rect_left_offset
174         parseUE(&br, &unused);  // frame_cropping_rect_right_offset
175         parseUE(&br, &unused);  // frame_cropping_rect_top_offset
176         parseUE(&br, &unused);  // frame_cropping_rect_bottom_offset
177     }
178 
179     uint32_t vuiParametersPresentFlag;
180     if (!br.getBitsGraceful(1, &vuiParametersPresentFlag))
181         return false;  // vui_parameters_present_flag
182     if (vuiParametersPresentFlag) {
183         uint32_t aspectRatioInfoPresentFlag;
184         if (!br.getBitsGraceful(1, &aspectRatioInfoPresentFlag))
185             return false;  // VUI aspect_ratio_info_present_flag
186         if (aspectRatioInfoPresentFlag) {
187             uint32_t aspectRatioIdc;
188             if (!br.getBitsGraceful(8, &aspectRatioIdc)) return false;  // VUI aspect_ratio_idc
189             if (aspectRatioIdc == 255) {  // VUI aspect_ratio_idc == extended sample aspect ratio
190                 br.skipBits(32);          // VUI sar_width + sar_height
191             }
192         }
193 
194         uint32_t overscanInfoPresentFlag;
195         if (!br.getBitsGraceful(1, &overscanInfoPresentFlag))
196             return false;  // VUI overscan_info_present_flag
197         if (overscanInfoPresentFlag) {
198             br.skipBits(1);  // VUI overscan_appropriate_flag
199         }
200         uint32_t videoSignalTypePresentFlag;
201         if (!br.getBitsGraceful(1, &videoSignalTypePresentFlag))
202             return false;  // VUI video_signal_type_present_flag
203         if (videoSignalTypePresentFlag) {
204             br.skipBits(3);  // VUI video_format
205             uint32_t videoFullRangeFlag;
206             if (!br.getBitsGraceful(1, &videoFullRangeFlag))
207                 return false;  // VUI videoFullRangeFlag
208             colorAspects->fullRange = videoFullRangeFlag;
209             uint32_t color_description_present_flag;
210             if (!br.getBitsGraceful(1, &color_description_present_flag))
211                 return false;  // VUI color_description_present_flag
212             if (color_description_present_flag) {
213                 if (!br.getBitsGraceful(8, &colorAspects->primaries))
214                     return false;  // VUI colour_primaries
215                 if (!br.getBitsGraceful(8, &colorAspects->transfer))
216                     return false;  // VUI transfer_characteristics
217                 if (!br.getBitsGraceful(8, &colorAspects->coeffs))
218                     return false;  // VUI matrix_coefficients
219                 return true;
220             }
221         }
222     }
223 
224     return false;  // The NAL unit doesn't contain color aspects info.
225 }
226 
227 }  // namespace android
228