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

Side by Side Diff: webrtc/modules/rtp_rtcp/source/h264/bitstream_parser.cc

Issue 1979443004: Add H264 bitstream rewriting to limit frame reordering marker in header (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rewriting on the receiver side as well Created 4 years, 7 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 <memory>
13 #include <vector>
14
15 #include "webrtc/base/bitbuffer.h"
16 #include "webrtc/base/bytebuffer.h"
17 #include "webrtc/base/checks.h"
18
19 #include "webrtc/modules/rtp_rtcp/source/h264/h264_common.h"
20 #include "webrtc/base/logging.h"
21
22 namespace webrtc {
23
24 #define RETURN_FALSE_ON_FAIL(x) \
25 if (!(x)) { \
26 LOG_F(LS_ERROR) << "FAILED: " #x; \
27 return false; \
28 }
29
30 H264BitstreamParser::H264BitstreamParser() {}
31 H264BitstreamParser::~H264BitstreamParser() {}
32
33 bool H264BitstreamParser::ParseNonParameterSetNalu(const uint8_t* source,
34 size_t source_length,
35 uint8_t nalu_type) {
36 RTC_CHECK(sps_);
37 RTC_CHECK(pps_);
38 last_slice_qp_delta_ = rtc::Optional<int32_t>();
39 std::unique_ptr<rtc::ByteBufferWriter> slice_rbsp(H264Common::ParseRbsp(
40 source + H264Common::kNaluHeaderAndTypeSize,
41 source_length - H264Common::kNaluHeaderAndTypeSize));
42 rtc::BitBuffer slice_reader(
43 reinterpret_cast<const uint8_t*>(slice_rbsp->Data()),
44 slice_rbsp->Length());
45 // Check to see if this is an IDR slice, which has an extra field to parse
46 // out.
47 bool is_idr = (source[H264Common::kNaluHeaderSize] & 0x0F) ==
48 H264Common::NaluType::kIdr;
49 uint8_t nal_ref_idc = (source[H264Common::kNaluHeaderSize] & 0x60) >> 5;
50 uint32_t golomb_tmp;
51 uint32_t bits_tmp;
52
53 // first_mb_in_slice: ue(v)
54 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
55 // slice_type: ue(v)
56 uint32_t slice_type;
57 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&slice_type));
58 // slice_type's 5..9 range is used to indicate that all slices of a picture
59 // have the same value of slice_type % 5, we don't care about that, so we map
60 // to the corresponding 0..4 range.
61 slice_type %= 5;
62 // pic_parameter_set_id: ue(v)
63 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
64 if (sps_->separate_colour_plane_flag == 1) {
65 // colour_plane_id
66 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
67 }
68 // frame_num: u(v)
69 // Represented by log2_max_frame_num_minus4 + 4 bits.
70 RETURN_FALSE_ON_FAIL(
71 slice_reader.ReadBits(&bits_tmp, sps_->log2_max_frame_num_minus4 + 4));
72 uint32_t field_pic_flag = 0;
73 if (sps_->frame_mbs_only_flag == 0) {
74 // field_pic_flag: u(1)
75 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&field_pic_flag, 1));
76 if (field_pic_flag != 0) {
77 // bottom_field_flag: u(1)
78 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
79 }
80 }
81 if (is_idr) {
82 // idr_pic_id: ue(v)
83 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
84 }
85 // pic_order_cnt_lsb: u(v)
86 // Represented by sps_.log2_max_pic_order_cnt_lsb_minus4 + 4 bits.
87 if (sps_->pic_order_cnt_type == 0) {
88 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(
89 &bits_tmp, sps_->log2_max_pic_order_cnt_lsb_minus4 + 4));
90 if (pps_->bottom_field_pic_order_in_frame_present_flag &&
91 field_pic_flag == 0) {
92 // delta_pic_order_cnt_bottom: se(v)
93 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
94 }
95 }
96 if (sps_->pic_order_cnt_type == 1 &&
97 !sps_->delta_pic_order_always_zero_flag) {
98 // delta_pic_order_cnt[0]: se(v)
99 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
100 if (pps_->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) {
101 // delta_pic_order_cnt[1]: se(v)
102 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
103 }
104 }
105 if (pps_->redundant_pic_cnt_present_flag) {
106 // redundant_pic_cnt: ue(v)
107 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
108 }
109 if (slice_type == H264Common::SliceType::B) {
110 // direct_spatial_mv_pred_flag: u(1)
111 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 1));
112 }
113 switch (slice_type) {
114 case H264Common::SliceType::P:
115 case H264Common::SliceType::B:
116 case H264Common::SliceType::Sp:
117 uint32_t num_ref_idx_active_override_flag;
118 // num_ref_idx_active_override_flag: u(1)
119 RETURN_FALSE_ON_FAIL(
120 slice_reader.ReadBits(&num_ref_idx_active_override_flag, 1));
121 if (num_ref_idx_active_override_flag != 0) {
122 // num_ref_idx_l0_active_minus1: ue(v)
123 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
124 if (slice_type == H264Common::SliceType::B) {
125 // num_ref_idx_l1_active_minus1: ue(v)
126 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(&golomb_tmp));
127 }
128 }
129 break;
130 default:
131 break;
132 }
133 // assume nal_unit_type != 20 && nal_unit_type != 21:
134 RTC_CHECK_NE(nalu_type, 20);
135 RTC_CHECK_NE(nalu_type, 21);
136 // if (nal_unit_type == 20 || nal_unit_type == 21)
137 // ref_pic_list_mvc_modification()
138 // else
139 {
140 // ref_pic_list_modification():
141 // |slice_type| checks here don't use named constants as they aren't named
142 // in the spec for this segment. Keeping them consistent makes it easier to
143 // verify that they are both the same.
144 if (slice_type % 5 != 2 && slice_type % 5 != 4) {
145 // ref_pic_list_modification_flag_l0: u(1)
146 uint32_t ref_pic_list_modification_flag_l0;
147 RETURN_FALSE_ON_FAIL(
148 slice_reader.ReadBits(&ref_pic_list_modification_flag_l0, 1));
149 if (ref_pic_list_modification_flag_l0) {
150 uint32_t modification_of_pic_nums_idc;
151 do {
152 // modification_of_pic_nums_idc: ue(v)
153 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
154 &modification_of_pic_nums_idc));
155 if (modification_of_pic_nums_idc == 0 ||
156 modification_of_pic_nums_idc == 1) {
157 // abs_diff_pic_num_minus1: ue(v)
158 RETURN_FALSE_ON_FAIL(
159 slice_reader.ReadExponentialGolomb(&golomb_tmp));
160 } else if (modification_of_pic_nums_idc == 2) {
161 // long_term_pic_num: ue(v)
162 RETURN_FALSE_ON_FAIL(
163 slice_reader.ReadExponentialGolomb(&golomb_tmp));
164 }
165 } while (modification_of_pic_nums_idc != 3);
166 }
167 }
168 if (slice_type % 5 == 1) {
169 // ref_pic_list_modification_flag_l1: u(1)
170 uint32_t ref_pic_list_modification_flag_l1;
171 RETURN_FALSE_ON_FAIL(
172 slice_reader.ReadBits(&ref_pic_list_modification_flag_l1, 1));
173 if (ref_pic_list_modification_flag_l1) {
174 uint32_t modification_of_pic_nums_idc;
175 do {
176 // modification_of_pic_nums_idc: ue(v)
177 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
178 &modification_of_pic_nums_idc));
179 if (modification_of_pic_nums_idc == 0 ||
180 modification_of_pic_nums_idc == 1) {
181 // abs_diff_pic_num_minus1: ue(v)
182 RETURN_FALSE_ON_FAIL(
183 slice_reader.ReadExponentialGolomb(&golomb_tmp));
184 } else if (modification_of_pic_nums_idc == 2) {
185 // long_term_pic_num: ue(v)
186 RETURN_FALSE_ON_FAIL(
187 slice_reader.ReadExponentialGolomb(&golomb_tmp));
188 }
189 } while (modification_of_pic_nums_idc != 3);
190 }
191 }
192 }
193 // TODO(pbos): Do we need support for pred_weight_table()?
194 RTC_CHECK(!(
195 (pps_->weighted_pred_flag && (slice_type == H264Common::SliceType::P ||
196 slice_type == H264Common::SliceType::Sp)) ||
197 (pps_->weighted_bipred_idc != 0 &&
198 slice_type == H264Common::SliceType::B)))
199 << "Missing support for pred_weight_table().";
200 // if ((weighted_pred_flag && (slice_type == P || slice_type == SP)) ||
201 // (weighted_bipred_idc == 1 && slice_type == B)) {
202 // pred_weight_table()
203 // }
204 if (nal_ref_idc != 0) {
205 // dec_ref_pic_marking():
206 if (is_idr) {
207 // no_output_of_prior_pics_flag: u(1)
208 // long_term_reference_flag: u(1)
209 RETURN_FALSE_ON_FAIL(slice_reader.ReadBits(&bits_tmp, 2));
210 } else {
211 // adaptive_ref_pic_marking_mode_flag: u(1)
212 uint32_t adaptive_ref_pic_marking_mode_flag;
213 RETURN_FALSE_ON_FAIL(
214 slice_reader.ReadBits(&adaptive_ref_pic_marking_mode_flag, 1));
215 if (adaptive_ref_pic_marking_mode_flag) {
216 uint32_t memory_management_control_operation;
217 do {
218 // memory_management_control_operation: ue(v)
219 RETURN_FALSE_ON_FAIL(slice_reader.ReadExponentialGolomb(
220 &memory_management_control_operation));
221 if (memory_management_control_operation == 1 ||
222 memory_management_control_operation == 3) {
223 // difference_of_pic_nums_minus1: ue(v)
224 RETURN_FALSE_ON_FAIL(
225 slice_reader.ReadExponentialGolomb(&golomb_tmp));
226 }
227 if (memory_management_control_operation == 2) {
228 // long_term_pic_num: ue(v)
229 RETURN_FALSE_ON_FAIL(
230 slice_reader.ReadExponentialGolomb(&golomb_tmp));
231 }
232 if (memory_management_control_operation == 3 ||
233 memory_management_control_operation == 6) {
234 // long_term_frame_idx: ue(v)
235 RETURN_FALSE_ON_FAIL(
236 slice_reader.ReadExponentialGolomb(&golomb_tmp));
237 }
238 if (memory_management_control_operation == 4) {
239 // max_long_term_frame_idx_plus1: ue(v)
240 RETURN_FALSE_ON_FAIL(
241 slice_reader.ReadExponentialGolomb(&golomb_tmp));
242 }
243 } while (memory_management_control_operation != 0);
244 }
245 }
246 }
247 // cabac not supported: entropy_coding_mode_flag == 0 asserted above.
248 // if (entropy_coding_mode_flag && slice_type != I && slice_type != SI)
249 // cabac_init_idc
250 int32_t last_slice_qp_delta;
251 RETURN_FALSE_ON_FAIL(
252 slice_reader.ReadSignedExponentialGolomb(&last_slice_qp_delta));
253 last_slice_qp_delta_ = rtc::Optional<int32_t>(last_slice_qp_delta);
254 return true;
255 }
256
257 void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) {
258 // Parse out the RBSP. It should be small, so it's OK that we create a copy.
259 // We'll eventually write this back.
260 std::unique_ptr<rtc::ByteBufferWriter> rbsp(
261 H264Common::ParseRbsp(slice + H264Common::kNaluHeaderAndTypeSize,
262 length - H264Common::kNaluHeaderAndTypeSize));
263 const uint8_t* parsed_data = reinterpret_cast<const uint8_t*>(rbsp->Data());
264 const size_t parsed_length = rbsp->Length();
265 H264Common::NaluType nalu_type = H264Common::ParseNaluType(slice[4]);
266 switch (nalu_type) {
267 case H264Common::NaluType::kSps: {
268 SpsParser sps_parser(parsed_data, parsed_length);
269 if (!sps_parser.Parse())
270 FATAL() << "Unable to parse SPS from H264 bitstream.";
271 sps_ = rtc::Optional<SpsParser::SpsState>(sps_parser.GetState());
272 break;
273 }
274 case H264Common::NaluType::kPps: {
275 PpsParser pps_parser(parsed_data, parsed_length);
276 if (!pps_parser.Parse())
277 FATAL() << "Unable to parse PPS from H264 bitstream.";
278 pps_ = rtc::Optional<PpsParser::PpsState>(pps_parser.GetState());
279 break;
280 }
281 default:
282 RTC_CHECK(ParseNonParameterSetNalu(slice, length, nalu_type))
283 << "Failed to parse picture slice.";
284 break;
285 }
286 }
287
288 void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream,
289 size_t length) {
290 std::vector<size_t> offsets =
291 H264Common::FindNaluStartOffsets(bitstream, length);
292 RTC_CHECK(!offsets.empty());
293 offsets.push_back(length); // End for the last slice.
294 for (size_t i = 0; i < offsets.size() - 1; ++i)
295 ParseSlice(bitstream + offsets[i], offsets[i + 1] - offsets[i]);
296 }
297
298 bool H264BitstreamParser::GetLastSliceQp(int* qp) const {
299 if (!last_slice_qp_delta_ || !pps_)
300 return false;
301 *qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_;
302 return true;
303 }
304
305 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698