Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.cc

Issue 1314473008: H264 bitstream parser. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: win64 build warnings Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h"
11
12 #include "webrtc/base/bitbuffer.h"
13 #include "webrtc/base/bytebuffer.h"
14 #include "webrtc/base/checks.h"
15 #include "webrtc/base/logging.h"
16 #include "webrtc/base/scoped_ptr.h"
17
18 namespace webrtc {
19 namespace {
20 // The size of a NALU header {0 0 0 1}.
21 static const size_t kNaluHeaderSize = 4;
22
23 // The size of a NALU header plus the type byte.
24 static const size_t kNaluHeaderAndTypeSize = kNaluHeaderSize + 1;
25
26 // The IDR type.
noahric 2015/09/09 20:51:42 The NALU type. (only 5 is an IDR)
pbos-webrtc 2015/09/21 15:55:32 Done.
27 static const uint8_t kNaluSps = 7;
28 static const uint8_t kNaluPps = 8;
29 static const uint8_t kNaluIdr = 0x5;
noahric 2015/09/09 20:51:42 either 5 or make them all 0xn, for consistency.
pbos-webrtc 2015/09/21 15:55:32 Done.
30 static const uint8_t kNaluTypeMask = 0x1F;
31
32 static const uint8_t kSliceTypeP = 0;
33 static const uint8_t kSliceTypeB = 1;
34 // static const uint8_t kSliceTypeI = 2;
noahric 2015/09/09 20:51:42 Consider removing the commented out lines, since t
pbos-webrtc 2015/09/21 15:55:32 Done.
35 static const uint8_t kSliceTypeSp = 3;
36 // static const uint8_t kSliceTypeSi = 4;
37 } // namespace
38
39 // Parses RBSP from source bytes. Removes emulation bytes, but leaves the
40 // rbsp_trailing_bits() in the stream, since none of the parsing reads all the
41 // way to the end of a parsed RBSP sequence. When writing, that means the
42 // rbsp_trailing_bits() should be preserved and don't need to be restored (i.e.
43 // the rbsp_stop_one_bit, which is just a 1, then zero padded), and alignment
44 // should "just work".
45 // TODO(pbos): Make parsing RBSP something that can be integrated into BitBuffer
46 // so we don't have to copy the entire frames when only interested in the
47 // headers.
48 rtc::ByteBuffer* ParseRbsp(const uint8_t* bytes, size_t length) {
49 // Copied from webrtc::H264SpsParser::Parse.
50 rtc::ByteBuffer* rbsp_buffer = new rtc::ByteBuffer;
51 for (size_t i = 0; i < length;) {
52 if (length - i >= 3 && bytes[i] == 0 && bytes[i + 1] == 0 &&
53 bytes[i + 2] == 3) {
54 rbsp_buffer->WriteBytes(reinterpret_cast<const char*>(bytes) + i, 2);
55 i += 3;
56 } else {
57 rbsp_buffer->WriteBytes(reinterpret_cast<const char*>(bytes) + i, 1);
58 i++;
59 }
60 }
61 return rbsp_buffer;
62 }
63
64 #define RETURN_FALSE_ON_FAIL(x) \
65 if (!(x)) { \
66 LOG_F(LS_ERROR) << "FAILED: " #x; \
67 return false; \
68 }
69
70 // These functions are similar to webrtc::H264SpsParser::Parse, and based on the
71 // same version of the H.264 standard. You can find it here:
72 // http://www.itu.int/rec/T-REC-H.264
73 bool H264BitstreamParser::ParseSpsNalu(const uint8_t* sps, size_t length) {
74 // Parse out the SPS RBSP. It should be small, so it's ok that we create a
75 // copy. We'll eventually write this back.
76 rtc::scoped_ptr<rtc::ByteBuffer> sps_rbsp(
77 ParseRbsp(sps + kNaluHeaderAndTypeSize, length - kNaluHeaderAndTypeSize));
78 rtc::BitBuffer sps_parser(reinterpret_cast<const uint8*>(sps_rbsp->Data()),
79 sps_rbsp->Length());
80
81 uint8_t byte_tmp;
82 uint32_t golomb_tmp;
83 uint32_t bits_tmp;
84
85 // profile_idc: u(8).
86 uint8 profile_idc;
87 RETURN_FALSE_ON_FAIL(sps_parser.ReadUInt8(&profile_idc));
88 // constraint_set0_flag through constraint_set5_flag + reserved_zero_2bits
89 // 1 bit each for the flags + 2 bits = 8 bits = 1 byte.
90 RETURN_FALSE_ON_FAIL(sps_parser.ReadUInt8(&byte_tmp));
91 // level_idc: u(8)
92 RETURN_FALSE_ON_FAIL(sps_parser.ReadUInt8(&byte_tmp));
93 // seq_parameter_set_id: ue(v)
94 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
95 separate_colour_plane_flag_ = 0;
96 // See if profile_idc has chroma format information.
97 if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
98 profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
99 profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ||
100 profile_idc == 138 || profile_idc == 139 || profile_idc == 134) {
101 // chroma_format_idc: ue(v)
102 uint32 chroma_format_idc;
103 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&chroma_format_idc));
104 if (chroma_format_idc == 3) {
105 // separate_colour_plane_flag: u(1)
106 RETURN_FALSE_ON_FAIL(
107 sps_parser.ReadBits(&separate_colour_plane_flag_, 1));
108 }
109 // bit_depth_luma_minus8: ue(v)
110 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
111 // bit_depth_chroma_minus8: ue(v)
112 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
113 // qpprime_y_zero_transform_bypass_flag: u(1)
114 RETURN_FALSE_ON_FAIL(sps_parser.ReadBits(&bits_tmp, 1));
115 // seq_scaling_matrix_present_flag: u(1)
116 uint32_t seq_scaling_matrix_present_flag;
117 RETURN_FALSE_ON_FAIL(
118 sps_parser.ReadBits(&seq_scaling_matrix_present_flag, 1));
119 if (seq_scaling_matrix_present_flag) {
120 // seq_scaling_list_present_flags. Either 8 or 12, depending on
121 // chroma_format_idc.
122 uint32_t seq_scaling_list_present_flags;
123 if (chroma_format_idc != 3) {
124 RETURN_FALSE_ON_FAIL(
125 sps_parser.ReadBits(&seq_scaling_list_present_flags, 8));
126 } else {
127 RETURN_FALSE_ON_FAIL(
128 sps_parser.ReadBits(&seq_scaling_list_present_flags, 12));
129 }
130 // TODO(pbos): Support parsing scaling lists if they're seen in practice.
131 CHECK(seq_scaling_list_present_flags == 0)
132 << "SPS contains scaling lists, which are unsupported.";
133 }
134 }
135 // log2_max_frame_num_minus4: ue(v)
136 RETURN_FALSE_ON_FAIL(
137 sps_parser.ReadExponentialGolomb(&log2_max_frame_num_minus4_));
138 // pic_order_cnt_type: ue(v)
139 RETURN_FALSE_ON_FAIL(
140 sps_parser.ReadExponentialGolomb(&pic_order_cnt_type_));
141
142 if (pic_order_cnt_type_ == 0) {
143 // log2_max_pic_order_cnt_lsb_minus4: ue(v)
144 RETURN_FALSE_ON_FAIL(
145 sps_parser.ReadExponentialGolomb(&log2_max_pic_order_cnt_lsb_minus4_));
146 } else if (pic_order_cnt_type_ == 1) {
147 // delta_pic_order_always_zero_flag: u(1)
148 RETURN_FALSE_ON_FAIL(
149 sps_parser.ReadBits(&delta_pic_order_always_zero_flag_, 1));
150 // offset_for_non_ref_pic: se(v)
151 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
152 // offset_for_top_to_bottom_field: se(v)
153 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
154 uint32_t num_ref_frames_in_pic_order_cnt_cycle;
155 // num_ref_frames_in_pic_order_cnt_cycle: ue(v)
156 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(
157 &num_ref_frames_in_pic_order_cnt_cycle));
158 for (uint32_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
159 // offset_for_ref_frame[i]: se(v)
160 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
161 }
162 }
163 // max_num_ref_frames: ue(v)
164 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
165 // gaps_in_frame_num_value_allowed_flag: u(1)
166 RETURN_FALSE_ON_FAIL(sps_parser.ReadBits(&bits_tmp, 1));
167 // pic_width_in_mbs_minus1: ue(v)
168 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
169 // pic_height_in_map_units_minus1: ue(v)
170 RETURN_FALSE_ON_FAIL(sps_parser.ReadExponentialGolomb(&golomb_tmp));
171 // frame_mbs_only_flag: u(1)
172 RETURN_FALSE_ON_FAIL(sps_parser.ReadBits(&frame_mbs_only_flag_, 1));
173 return true;
174 }
175
176 bool H264BitstreamParser::ParsePpsNalu(const uint8_t* pps, size_t length) {
177 // We're starting a new stream, so reset picture type rewriting values.
noahric 2015/09/09 20:51:42 Delete this comment. Alternatively, update it to:
pbos-webrtc 2015/09/21 15:55:32 Resetting.
178 rtc::scoped_ptr<rtc::ByteBuffer> buffer(
179 ParseRbsp(pps + kNaluHeaderAndTypeSize, length - kNaluHeaderAndTypeSize));
180 rtc::BitBuffer parser(reinterpret_cast<const uint8*>(buffer->Data()),
181 buffer->Length());
182
183 uint32_t bits_tmp;
184 uint32_t golomb_ignored;
185 // pic_parameter_set_id: ue(v)
186 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
187 // seq_parameter_set_id: ue(v)
188 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
189 // entropy_coding_mode_flag: u(1)
190 uint32_t entropy_coding_mode_flag;
191 RETURN_FALSE_ON_FAIL(parser.ReadBits(&entropy_coding_mode_flag, 1));
192 // TODO(pbos): Is this true when we don't need to rewrite alignment or is it
193 // trivial to parse?
noahric 2015/09/09 20:51:42 Yeah, it't not true anymore. There are a few diffe
pbos-webrtc 2015/09/21 15:55:32 TODO done.
194 CHECK(entropy_coding_mode_flag == 0)
195 << "Don't know how to parse CABAC streams.";
196 // bottom_field_pic_order_in_frame_present_flag: u(1)
197 uint32_t bottom_field_pic_order_in_frame_present_flag;
198 RETURN_FALSE_ON_FAIL(
199 parser.ReadBits(&bottom_field_pic_order_in_frame_present_flag, 1));
200 bottom_field_pic_order_in_frame_present_flag_ =
201 bottom_field_pic_order_in_frame_present_flag != 0;
202
203 // num_slice_groups_minus1: ue(v)
204 uint32_t num_slice_groups_minus1;
205 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&num_slice_groups_minus1));
206 if (num_slice_groups_minus1 > 0) {
207 uint32_t slice_group_map_type;
208 // slice_group_map_type: ue(v)
209 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&slice_group_map_type));
210 if (slice_group_map_type == 0) {
211 for (uint32_t i_group = 0; i_group <= num_slice_groups_minus1;
212 ++i_group) {
213 // run_length_minus1[iGroup]: ue(v)
214 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
215 }
216 } else if (slice_group_map_type == 2) {
217 for (uint32_t i_group = 0; i_group <= num_slice_groups_minus1;
218 ++i_group) {
219 // top_left[iGroup]: ue(v)
220 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
221 // bottom_right[iGroup]: ue(v)
222 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
223 }
224 } else if (slice_group_map_type == 3 || slice_group_map_type == 4 ||
225 slice_group_map_type == 5) {
226 // slice_group_change_direction_flag: u(1)
227 RETURN_FALSE_ON_FAIL(parser.ReadBits(&bits_tmp, 1));
228 // slice_group_change_rate_minus1: ue(v)
229 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
230 } else if (slice_group_map_type == 6) {
231 // pic_size_in_map_units_minus1: ue(v)
232 uint32_t pic_size_in_map_units_minus1;
233 RETURN_FALSE_ON_FAIL(
234 parser.ReadExponentialGolomb(&pic_size_in_map_units_minus1));
235 uint32_t slice_group_id_bits = 0;
236 uint32_t num_slice_groups = num_slice_groups_minus1 + 1;
237 // If num_slice_groups is not a power of two an additional bit is required
238 // to account for the ceil() of log2() below.
239 if ((num_slice_groups & (num_slice_groups - 1)) != 0)
240 ++slice_group_id_bits;
241 while (num_slice_groups > 0) {
242 num_slice_groups >>= 1;
243 ++slice_group_id_bits;
244 }
245 for (uint32_t i = 0; i <= pic_size_in_map_units_minus1; i++) {
246 // slice_group_id[i]: u(v)
247 // Represented by ceil(log2(num_slice_groups_minus1 + 1)) bits.
248 RETURN_FALSE_ON_FAIL(parser.ReadBits(&bits_tmp, slice_group_id_bits));
249 }
250 }
251 }
252 // num_ref_idx_l0_default_active_minus1: ue(v)
253 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
254 // num_ref_idx_l1_default_active_minus1: ue(v)
255 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
256 // weighted_pred_flag: u(1)
257 // weighted_bipred_idc: u(2)
258 RETURN_FALSE_ON_FAIL(parser.ReadBits(&bits_tmp, 3));
259
260 // pic_init_qp_minus26: se(v)
261 RETURN_FALSE_ON_FAIL(
262 parser.ReadSignedExponentialGolomb(&pic_init_qp_minus26_));
263 // pic_init_qs_minus26: se(v)
264 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
265 // chroma_qp_index_offset: se(v)
266 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
267 // deblocking_filter_control_present_flag: u(1)
268 RETURN_FALSE_ON_FAIL(parser.ReadBits(&bits_tmp, 1));
269 // constrained_intra_pred_flag: u(1)
270 RETURN_FALSE_ON_FAIL(parser.ReadBits(&bits_tmp, 1));
271 // redundant_pic_cnt_present_flag: u(1)
272 RETURN_FALSE_ON_FAIL(parser.ReadBits(&redundant_pic_cnt_present_flag_, 1));
273
274 return true;
275 }
276
277 bool H264BitstreamParser::ParseNonParameterSetNalu(const uint8_t* source,
278 size_t source_length) {
279 rtc::scoped_ptr<rtc::ByteBuffer> slice_rbsp(ParseRbsp(
280 source + kNaluHeaderAndTypeSize, source_length - kNaluHeaderAndTypeSize));
281 rtc::BitBuffer slice_reader(
282 reinterpret_cast<const uint8*>(slice_rbsp->Data()), slice_rbsp->Length());
283 // Check to see if this is an IDR slice, which has an extra field to parse
284 // out.
285 bool is_idr = (source[kNaluHeaderSize] & 0x0F) == kNaluIdr;
286 uint8_t nal_ref_idc = (source[kNaluHeaderSize] & 0x60) >> 5;
287 uint32_t golomb_tmp;
288 uint32_t bits_tmp;
289
290 // first_mb_in_slice: ue(v)
291 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
292 // slice_type: ue(v)
293 uint32_t slice_type;
294 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&slice_type));
295 // slice_type's 5..9 range is used to indicate things.that all slices of a
296 // picture have the same value of slice_type % 5, we don't care about that, so
297 // we map to the corresponding 0..4 range.
298 slice_type %= 5;
299 // pic_parameter_set_id: ue(v)
300 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
301 if (separate_colour_plane_flag_ == 1) {
302 // colour_plane_id
303 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
304 }
305 // frame_num: u(v)
306 // Represented by log2_max_frame_num_minus4 + 4 bits.
307 RETURN_FALSE_ON_FAIL(
308 slice_reader.ReadBits(&bits_tmp, log2_max_frame_num_minus4_ + 4));
309 uint32 field_pic_flag = 0;
310 if (frame_mbs_only_flag_ == 0) {
311 // field_pic_flag: u(1)
312 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&field_pic_flag, 1));
313 if (field_pic_flag != 0) {
314 // bottom_field_flag: u(1)
315 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
316 }
317 }
318 if (is_idr) {
319 // idr_pic_id: ue(v)
320 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
321 }
322 // pic_order_cnt_lsb: u(v)
323 // Represented by log2_max_pic_order_cnt_lsb_minus4_ + 4 bits.
324 if (pic_order_cnt_type_ == 0) {
325 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(
326 &bits_tmp, log2_max_pic_order_cnt_lsb_minus4_ + 4));
327 if (bottom_field_pic_order_in_frame_present_flag_ && field_pic_flag == 0) {
328 // delta_pic_order_cnt_bottom: se(v)
329 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
330 }
331 }
332 if (pic_order_cnt_type_ == 1 && !delta_pic_order_always_zero_flag_) {
333 // delta_pic_order_cnt[0]: se(v)
334 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
335 if (bottom_field_pic_order_in_frame_present_flag_ && !field_pic_flag) {
336 // delta_pic_order_cnt[1]: se(v)
337 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
338 }
339 }
340 if (redundant_pic_cnt_present_flag_) {
341 // redundant_pic_cnt: ue(v)
342 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
343 }
344 if (slice_type == kSliceTypeB) {
345 // direct_spatial_mv_pred_flag: u(1)
346 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
347 }
348 if (slice_type == kSliceTypeP || slice_type == kSliceTypeSp ||
349 slice_type == kSliceTypeB) {
350 uint32_t num_ref_idx_active_override_flag;
351 // num_ref_idx_active_override_flag: u(1)
352 RETURN_FALSE_ON_FAIL(
353 slice_reader.ReadBits(&num_ref_idx_active_override_flag, 1));
354 if (num_ref_idx_active_override_flag) {
355 // num_ref_idx_l0_active_minus1: ue(v)
356 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
357 if (slice_type == kSliceTypeB) {
358 // num_ref_idx_l1_active_minus1: ue(v)
359 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
360 }
361 }
362 }
363 // assume nal_unit_type != 20 && nal_unit_type != 21:
364 // if (nal_unit_type == 20 || nal_unit_type == 21)
365 // ref_pic_list_mvc_modification()
366 // else
367 {
368 // ref_pic_list_modification():
369 // |slice_type| checks here don't use named constants as they aren't named
370 // in the spec for this segment. Keeping them consistent makes it easier to
371 // verify that they are both the same.
372 if (slice_type % 5 != 2 && slice_type % 5 != 4) {
373 // ref_pic_list_modification_flag_l0: u(1)
374 uint32_t ref_pic_list_modification_flag_l0;
375 RETURN_FALSE_ON_FAIL(
376 slice_reader.ReadBits(&ref_pic_list_modification_flag_l0, 1));
377 if (ref_pic_list_modification_flag_l0) {
378 uint32_t modification_of_pic_nums_idc;
379 do {
380 // modification_of_pic_nums_idc: ue(v)
381 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
382 &modification_of_pic_nums_idc));
383 if (modification_of_pic_nums_idc == 0 ||
384 modification_of_pic_nums_idc == 1) {
385 // abs_diff_pic_num_minus1: ue(v)
386 RETURN_FALSE_ON_FAIL(
387 slice_reader.ReadExponentialGolomb(&golomb_tmp));
388 } else if (modification_of_pic_nums_idc == 2) {
389 // long_term_pic_num: ue(v)
390 RETURN_FALSE_ON_FAIL(
391 slice_reader.ReadExponentialGolomb(&golomb_tmp));
392 }
393 } while (modification_of_pic_nums_idc != 3);
394 }
395 }
396 if (slice_type % 5 == 1) {
397 // ref_pic_list_modification_flag_l1: u(1)
398 uint32_t ref_pic_list_modification_flag_l1;
399 RETURN_FALSE_ON_FAIL(
400 slice_reader.ReadBits(&ref_pic_list_modification_flag_l1, 1));
401 if (ref_pic_list_modification_flag_l1) {
402 uint32_t modification_of_pic_nums_idc;
403 do {
404 // modification_of_pic_nums_idc: ue(v)
405 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
406 &modification_of_pic_nums_idc));
407 if (modification_of_pic_nums_idc == 0 ||
408 modification_of_pic_nums_idc == 1) {
409 // abs_diff_pic_num_minus1: ue(v)
410 RETURN_FALSE_ON_FAIL(
411 slice_reader.ReadExponentialGolomb(&golomb_tmp));
412 } else if (modification_of_pic_nums_idc == 2) {
413 // long_term_pic_num: ue(v)
414 RETURN_FALSE_ON_FAIL(
415 slice_reader.ReadExponentialGolomb(&golomb_tmp));
416 }
417 } while (modification_of_pic_nums_idc != 3);
418 }
419 }
420 }
421 // TODO(pbos): Do we need support for pred_weight_table()?
noahric 2015/09/09 20:51:42 Potentially for P slices. Not B slices, since thos
pbos-webrtc 2015/09/21 15:55:32 Do you think we can punt adding support for this?
422 // if ((weighted_pred_flag && (slice_type == P || slice_type == SP)) ||
423 // (weighted_bipred_idc == 1 && slice_type == B)) {
424 // pred_weight_table()
425 // }
426 if (nal_ref_idc) {
427 // dec_ref_pic_marking():
428 if (is_idr) {
429 // no_output_of_prior_pics_flag: u(1)
430 // long_term_reference_flag: u(1)
431 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
432 } else {
433 // adaptive_ref_pic_marking_mode_flag: u(1)
434 uint32_t adaptive_ref_pic_marking_mode_flag;
435 RETURN_FALSE_ON_FAIL(
436 slice_reader.ReadBits(&adaptive_ref_pic_marking_mode_flag, 1));
437 if (adaptive_ref_pic_marking_mode_flag) {
438 uint32_t memory_management_control_operation;
439 do {
440 // memory_management_control_operation: ue(v)
441 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
442 &memory_management_control_operation));
443 if (memory_management_control_operation == 1 ||
444 memory_management_control_operation == 3) {
445 // difference_of_pic_nums_minus1: ue(v)
446 RETURN_FALSE_ON_FAIL(
447 slice_reader.ReadExponentialGolomb(&golomb_tmp));
448 }
449 if (memory_management_control_operation == 2) {
450 // long_term_pic_num: ue(v)
451 RETURN_FALSE_ON_FAIL(
452 slice_reader.ReadExponentialGolomb(&golomb_tmp));
453 }
454 if (memory_management_control_operation == 3 ||
455 memory_management_control_operation == 6) {
456 // long_term_frame_idx: ue(v)
457 RETURN_FALSE_ON_FAIL(
458 slice_reader.ReadExponentialGolomb(&golomb_tmp));
459 }
460 if (memory_management_control_operation == 4) {
461 // max_long_term_frame_idx_plus1: ue(v)
462 RETURN_FALSE_ON_FAIL(
463 slice_reader.ReadExponentialGolomb(&golomb_tmp));
464 }
465 } while (memory_management_control_operation != 0);
466 }
467 }
468 }
469 // cabac not supported: entropy_coding_mode_flag == 0 asserted above.
470 // if (entropy_coding_mode_flag && slice_type != I && slice_type != SI)
471 // cabac_init_idc
472 RETURN_FALSE_ON_FAIL(
473 slice_reader.ReadSignedExponentialGolomb(&slice_qp_delta_));
474 return true;
475 }
476
477 void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) {
478 uint8_t nalu_type = slice[4] & kNaluTypeMask;
479 switch (nalu_type) {
480 case kNaluSps:
481 CHECK(ParseSpsNalu(slice, length)) << "Failed to parse bitstream SPS.";
482 break;
483 case kNaluPps:
484 CHECK(ParsePpsNalu(slice, length)) << "Failed to parse bitstream PPS.";
485 break;
486 default:
487 CHECK(ParseNonParameterSetNalu(slice, length))
488 << "Failed to parse picture slice.";
489 break;
490 }
491 }
492
493 void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream,
494 size_t length) {
495 assert(length >= 4);
496 // Skip first marker.
497 bitstream += 4;
498 length -= 4;
499 const uint8_t* head = bitstream;
500
501 // Set end buffer pointer to 4 bytes before actual buffer end so we can
502 // access head[1], head[2] and head[3] in a loop without buffer overrun.
503 const uint8_t* end = bitstream + length;
504
505 while (head < end - 4) {
noahric 2015/09/09 20:51:42 You'll still definitely want to replace this. From
pbos-webrtc 2015/09/21 15:55:32 Done.
506 if (head[0]) {
507 head++;
508 continue;
509 }
510 if (head[1]) { // got 00xx
511 head += 2;
512 continue;
513 }
514 if (head[2]) { // got 0000xx
515 head += 3;
516 continue;
517 }
518 if (head[3] != 0x01) { // got 000000xx
519 head++; // xx != 1, continue searching.
520 continue;
521 }
522 size_t slice_length = head - bitstream + 4;
523 ParseSlice(bitstream - 4, slice_length);
524 // Skip separator.
525 head += 4;
526 bitstream = head;
527 }
528 // Parse the last slice.
529 ParseSlice(bitstream - 4, end - bitstream + 4);
530 }
531
532 int H264BitstreamParser::GetLastSliceQp() const {
533 return 26 + pic_init_qp_minus26_ + slice_qp_delta_;
534 }
535
536 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698