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

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: remove DCHECK_GT 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.
27 static const uint8_t kNaluSps = 7;
28 static const uint8_t kNaluPps = 8;
29 static const uint8_t kNaluIdr = 0x5;
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;
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.
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?
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 static_cast<bool>(bottom_field_pic_order_in_frame_present_flag);
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 printf("pic_init_qp: %d\n", pic_init_qp_minus26_ + 26);
264 // pic_init_qs_minus26: se(v)
265 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
266 // chroma_qp_index_offset: se(v)
267 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored));
268 // deblocking_filter_control_present_flag: u(1)
269 RETURN_FALSE_ON_FAIL(parser.ReadBits(&bits_tmp, 1));
270 // constrained_intra_pred_flag: u(1)
271 RETURN_FALSE_ON_FAIL(parser.ReadBits(&bits_tmp, 1));
272 // redundant_pic_cnt_present_flag: u(1)
273 RETURN_FALSE_ON_FAIL(parser.ReadBits(&redundant_pic_cnt_present_flag_, 1));
274
275 return true;
276 }
277
278 bool H264BitstreamParser::ParseNonParameterSetNalu(const uint8_t* source,
279 size_t source_length) {
280 rtc::scoped_ptr<rtc::ByteBuffer> slice_rbsp(ParseRbsp(
281 source + kNaluHeaderAndTypeSize, source_length - kNaluHeaderAndTypeSize));
282 rtc::BitBuffer slice_reader(
283 reinterpret_cast<const uint8*>(slice_rbsp->Data()), slice_rbsp->Length());
284 // Check to see if this is an IDR slice, which has an extra field to parse
285 // out.
286 bool is_idr = (source[kNaluHeaderSize] & 0x0F) == kNaluIdr;
287 uint8_t nal_ref_idc = (source[kNaluHeaderSize] & 0x60) >> 5;
288 uint32_t golomb_tmp;
289 uint32_t bits_tmp;
290
291 // first_mb_in_slice: ue(v)
292 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
293 // slice_type: ue(v)
294 uint32_t slice_type;
295 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&slice_type));
296 // slice_type's 5..9 range is used to indicate things.that all slices of a
297 // picture have the same value of slice_type % 5, we don't care about that, so
298 // we map to the corresponding 0..4 range.
299 slice_type %= 5;
300 // pic_parameter_set_id: ue(v)
301 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
302 if (separate_colour_plane_flag_ == 1) {
303 // colour_plane_id
304 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
305 }
306 // frame_num: u(v)
307 // Represented by log2_max_frame_num_minus4 + 4 bits.
308 RETURN_FALSE_ON_FAIL(
309 slice_reader.ReadBits(&bits_tmp, log2_max_frame_num_minus4_ + 4));
310 uint32 field_pic_flag = 0;
311 if (frame_mbs_only_flag_ == 0) {
312 // field_pic_flag: u(1)
313 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&field_pic_flag, 1));
314 if (field_pic_flag != 0) {
315 // bottom_field_flag: u(1)
316 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
317 }
318 }
319 if (is_idr) {
320 // idr_pic_id: ue(v)
321 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
322 }
323 // pic_order_cnt_lsb: u(v)
noahric 2015/09/03 17:48:58 This needs to be behind a pic_order_cnt_type == 0
pbos-webrtc 2015/09/04 10:01:20 This gives me more reasonable values. Thanks a lot
324 // Represented by log2_max_pic_order_cnt_lsb_minus4_ + 4 bits.
325 RETURN_FALSE_ON_FAIL(
326 slice_reader.ReadBits(&bits_tmp, log2_max_pic_order_cnt_lsb_minus4_ + 4));
327 if (bottom_field_pic_order_in_frame_present_flag_ && field_pic_flag == 0) {
noahric 2015/09/03 17:49:37 (This is also part of pic_order_cnt_type == 0)
pbos-webrtc 2015/09/04 10:01:20 Done.
328 // delta_pic_order_cnt_bottom: se(v)
329 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
330 }
331 if (pic_order_cnt_type_ == 1 && !delta_pic_order_always_zero_flag_) {
332 // delta_pic_order_cnt[0]: se(v)
333 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
334 if (bottom_field_pic_order_in_frame_present_flag_ && !field_pic_flag) {
335 // delta_pic_order_cnt[1]: se(v)
336 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
337 }
338 }
339 if (redundant_pic_cnt_present_flag_) {
340 // redundant_pic_cnt: ue(v)
341 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
342 }
343 if (slice_type == kSliceTypeB) {
344 // direct_spatial_mv_pred_flag: u(1)
345 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
346 }
347 if (slice_type == kSliceTypeP || slice_type == kSliceTypeSp ||
348 slice_type == kSliceTypeB) {
349 uint32_t num_ref_idx_active_override_flag;
350 // num_ref_idx_active_override_flag: u(1)
351 RETURN_FALSE_ON_FAIL(
352 slice_reader.ReadBits(&num_ref_idx_active_override_flag, 1));
353 if (num_ref_idx_active_override_flag) {
354 // num_ref_idx_l0_active_minus1: ue(v)
355 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
356 if (slice_type == kSliceTypeB) {
357 // num_ref_idx_l1_active_minus1: ue(v)
358 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
359 }
360 }
361 }
362 // assume nal_unit_type != 20 && nal_unit_type != 21:
363 // if (nal_unit_type == 20 || nal_unit_type == 21)
364 // ref_pic_list_mvc_modification()
365 // else
366 {
367 // ref_pic_list_modification():
368 // |slice_type| checks here don't use named constants as they aren't named
369 // in the spec for this segment. Keeping them consistent makes it easier to
370 // verify that they are both the same.
371 if (slice_type % 5 != 2 && slice_type % 5 != 4) {
372 // ref_pic_list_modification_flag_l0: u(1)
373 uint32_t ref_pic_list_modification_flag_l0;
374 RETURN_FALSE_ON_FAIL(
375 slice_reader.ReadBits(&ref_pic_list_modification_flag_l0, 1));
376 if (ref_pic_list_modification_flag_l0) {
377 uint32_t modification_of_pic_nums_idc;
378 do {
379 // modification_of_pic_nums_idc: ue(v)
380 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
381 &modification_of_pic_nums_idc));
382 if (modification_of_pic_nums_idc == 0 ||
383 modification_of_pic_nums_idc == 1) {
384 // abs_diff_pic_num_minus1: ue(v)
385 RETURN_FALSE_ON_FAIL(
386 slice_reader.ReadExponentialGolomb(&golomb_tmp));
387 } else if (modification_of_pic_nums_idc == 2) {
388 // long_term_pic_num: ue(v)
389 RETURN_FALSE_ON_FAIL(
390 slice_reader.ReadExponentialGolomb(&golomb_tmp));
391 }
392 } while (modification_of_pic_nums_idc != 3);
393 }
394 }
395 if (slice_type % 5 == 1) {
396 // ref_pic_list_modification_flag_l1: u(1)
397 uint32_t ref_pic_list_modification_flag_l1;
398 RETURN_FALSE_ON_FAIL(
399 slice_reader.ReadBits(&ref_pic_list_modification_flag_l1, 1));
400 if (ref_pic_list_modification_flag_l1) {
401 uint32_t modification_of_pic_nums_idc;
402 do {
403 // modification_of_pic_nums_idc: ue(v)
404 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
405 &modification_of_pic_nums_idc));
406 if (modification_of_pic_nums_idc == 0 ||
407 modification_of_pic_nums_idc == 1) {
408 // abs_diff_pic_num_minus1: ue(v)
409 RETURN_FALSE_ON_FAIL(
410 slice_reader.ReadExponentialGolomb(&golomb_tmp));
411 } else if (modification_of_pic_nums_idc == 2) {
412 // long_term_pic_num: ue(v)
413 RETURN_FALSE_ON_FAIL(
414 slice_reader.ReadExponentialGolomb(&golomb_tmp));
415 }
416 } while (modification_of_pic_nums_idc != 3);
417 }
418 }
419 }
420 // TODO(pbos): Do we need support for pred_weight_table()?
421 // if ((weighted_pred_flag && (slice_type == P || slice_type == SP)) ||
422 // (weighted_bipred_idc == 1 && slice_type == B)) {
423 // pred_weight_table()
424 // }
425 if (nal_ref_idc) {
426 // dec_ref_pic_marking():
427 if (is_idr) {
428 // no_output_of_prior_pics_flag: u(1)
429 // long_term_reference_flag: u(1)
430 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
431 } else {
432 // adaptive_ref_pic_marking_mode_flag: u(1)
433 uint32_t adaptive_ref_pic_marking_mode_flag;
434 RETURN_FALSE_ON_FAIL(
435 slice_reader.ReadBits(&adaptive_ref_pic_marking_mode_flag, 1));
436 if (adaptive_ref_pic_marking_mode_flag) {
437 uint32_t memory_management_control_operation;
438 do {
439 // memory_management_control_operation: ue(v)
440 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
441 &memory_management_control_operation));
442 if (memory_management_control_operation == 1 ||
443 memory_management_control_operation == 3) {
444 // difference_of_pic_nums_minus1: ue(v)
445 RETURN_FALSE_ON_FAIL(
446 slice_reader.ReadExponentialGolomb(&golomb_tmp));
447 }
448 if (memory_management_control_operation == 2) {
449 // long_term_pic_num: ue(v)
450 RETURN_FALSE_ON_FAIL(
451 slice_reader.ReadExponentialGolomb(&golomb_tmp));
452 }
453 if (memory_management_control_operation == 3 ||
454 memory_management_control_operation == 6) {
455 // long_term_frame_idx: ue(v)
456 RETURN_FALSE_ON_FAIL(
457 slice_reader.ReadExponentialGolomb(&golomb_tmp));
458 }
459 if (memory_management_control_operation == 4) {
460 // max_long_term_frame_idx_plus1: ue(v)
461 RETURN_FALSE_ON_FAIL(
462 slice_reader.ReadExponentialGolomb(&golomb_tmp));
463 }
464 } while (memory_management_control_operation != 0);
465 }
466 }
467 }
468 // cabac not supported: entropy_coding_mode_flag == 0 asserted above.
469 // if (entropy_coding_mode_flag && slice_type != I && slice_type != SI)
470 // cabac_init_idc
471 RETURN_FALSE_ON_FAIL(
472 slice_reader.ReadSignedExponentialGolomb(&slice_qp_delta_));
473 printf("Slice QP: %d\n", GetLastSliceQp());
474 return true;
475 }
476
477 void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) {
478 printf("ParseSlice(%p, %zu): [%u..\n", slice, length, slice[4]);
479 uint8_t nalu_type = slice[4] & kNaluTypeMask;
480 switch (nalu_type) {
481 case kNaluSps:
482 CHECK(ParseSpsNalu(slice, length)) << "Failed to parse bitstream SPS.";
483 break;
484 case kNaluPps:
485 CHECK(ParsePpsNalu(slice, length)) << "Failed to parse bitstream PPS.";
486 break;
487 default:
488 CHECK(ParseNonParameterSetNalu(slice, length))
489 << "Failed to parse picture slice.";
490 break;
491 }
492 }
493
494 void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream,
495 size_t length) {
496 assert(length >= 4);
497 // Skip first marker.
498 bitstream += 4;
499 length -= 4;
500 const uint8_t* head = bitstream;
501
502 // Set end buffer pointer to 4 bytes before actual buffer end so we can
503 // access head[1], head[2] and head[3] in a loop without buffer overrun.
504 const uint8_t* end = bitstream + length;
505
506 while (head < end - 4) {
507 if (head[0]) {
noahric 2015/09/03 17:48:58 There's a much faster way to loop this (I did an e
508 head++;
509 continue;
510 }
511 if (head[1]) { // got 00xx
512 head += 2;
513 continue;
514 }
515 if (head[2]) { // got 0000xx
516 head += 3;
517 continue;
518 }
519 if (head[3] != 0x01) { // got 000000xx
520 head++; // xx != 1, continue searching.
521 continue;
522 }
523 size_t slice_length = head - bitstream + 4;
524 ParseSlice(bitstream - 4, slice_length);
525 // Skip separator.
526 head += 4;
527 bitstream = head;
528 }
529 // Parse the last slice.
530 ParseSlice(bitstream - 4, end - bitstream + 4);
531 }
532
533 int H264BitstreamParser::GetLastSliceQp() const {
534 return 26 + pic_init_qp_minus26_ + slice_qp_delta_;
535 }
536
537 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698