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

Side by Side Diff: webrtc/modules/rtp_rtcp/source/h264/sps_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
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/rtp_rtcp/source/h264_sps_parser.h" 11 #include "webrtc/modules/rtp_rtcp/source/h264/sps_parser.h"
12 12
13 #include "webrtc/modules/rtp_rtcp/source/h264/h264_common.h"
13 #include "webrtc/base/bitbuffer.h" 14 #include "webrtc/base/bitbuffer.h"
14 #include "webrtc/base/bytebuffer.h" 15 #include "webrtc/base/bytebuffer.h"
15 #include "webrtc/base/logging.h" 16 #include "webrtc/base/logging.h"
16 17
17 #define RETURN_FALSE_ON_FAIL(x) \ 18 #define RETURN_FALSE_ON_FAIL(x) \
18 if (!(x)) { \ 19 if (!(x)) { \
19 return false; \ 20 return false; \
20 } 21 }
21 22
22 namespace webrtc { 23 namespace webrtc {
23 24
24 H264SpsParser::H264SpsParser(const uint8_t* sps, size_t byte_length) 25 SpsParser::SpsParser() : buffer_(nullptr), buffer_length_(0) {}
25 : sps_(sps), byte_length_(byte_length), width_(), height_() {
26 }
27 26
28 bool H264SpsParser::Parse() { 27 SpsParser::SpsParser(const uint8_t* buffer, size_t buffer_length)
28 : buffer_(buffer), buffer_length_(buffer_length) {}
29
30 bool SpsParser::Parse() {
31 if (buffer_length_ < H264Common::kNaluHeaderSize)
32 return false;
33
29 // General note: this is based off the 02/2014 version of the H.264 standard. 34 // General note: this is based off the 02/2014 version of the H.264 standard.
30 // You can find it on this page: 35 // You can find it on this page:
31 // http://www.itu.int/rec/T-REC-H.264 36 // http://www.itu.int/rec/T-REC-H.264
32 37
33 const char* sps_bytes = reinterpret_cast<const char*>(sps_);
34 // First, parse out rbsp, which is basically the source buffer minus emulation 38 // First, parse out rbsp, which is basically the source buffer minus emulation
35 // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in 39 // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in
36 // section 7.3.1 of the H.264 standard. 40 // section 7.3.1 of the H.264 standard.
37 rtc::ByteBufferWriter rbsp_buffer; 41 std::unique_ptr<rtc::ByteBufferWriter> rbsp_buffer(
38 for (size_t i = 0; i < byte_length_;) { 42 H264Common::ParseRbsp(buffer_, buffer_length_));
39 // Be careful about over/underflow here. byte_length_ - 3 can underflow, and
40 // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_
41 // above, and that expression will produce the number of bytes left in
42 // the stream including the byte at i.
43 if (byte_length_ - i >= 3 && sps_[i] == 0 && sps_[i + 1] == 0 &&
44 sps_[i + 2] == 3) {
45 // Two rbsp bytes + the emulation byte.
46 rbsp_buffer.WriteBytes(sps_bytes + i, 2);
47 i += 3;
48 } else {
49 // Single rbsp byte.
50 rbsp_buffer.WriteBytes(sps_bytes + i, 1);
51 i++;
52 }
53 }
54 43
55 // Now, we need to use a bit buffer to parse through the actual AVC SPS 44 // Now, we need to use a bit buffer to parse through the actual AVC SPS
56 // format. See Section 7.3.2.1.1 ("Sequence parameter set data syntax") of the 45 // format. See Section 7.3.2.1.1 ("Sequence parameter set data syntax") of the
57 // H.264 standard for a complete description. 46 // H.264 standard for a complete description.
58 // Since we only care about resolution, we ignore the majority of fields, but 47 // Since we only care about resolution, we ignore the majority of fields, but
59 // we still have to actively parse through a lot of the data, since many of 48 // we still have to actively parse through a lot of the data, since many of
60 // the fields have variable size. 49 // the fields have variable size.
61 // We're particularly interested in: 50 // We're particularly interested in:
62 // chroma_format_idc -> affects crop units 51 // chroma_format_idc -> affects crop units
63 // pic_{width,height}_* -> resolution of the frame in macroblocks (16x16). 52 // pic_{width,height}_* -> resolution of the frame in macroblocks (16x16).
64 // frame_crop_*_offset -> crop information 53 // frame_crop_*_offset -> crop information
65 rtc::BitBuffer parser(reinterpret_cast<const uint8_t*>(rbsp_buffer.Data()), 54 rtc::BitBuffer parser(reinterpret_cast<const uint8_t*>(rbsp_buffer->Data()),
66 rbsp_buffer.Length()); 55 rbsp_buffer->Length());
56
57 return ParseFromRbspDecodedBitBuffer(&parser);
58 }
59
60 // Alternative parsing method, using a supplied BitBuffer where the RBSP
61 // decoding has already been performed. Useful if further parsing of the NAL
62 // shall follow.
63 bool SpsParser::ParseFromRbspDecodedBitBuffer(rtc::BitBuffer* parser) {
64 SpsState sps;
67 65
68 // The golomb values we have to read, not just consume. 66 // The golomb values we have to read, not just consume.
69 uint32_t golomb_ignored; 67 uint32_t golomb_ignored;
70 68
71 // separate_colour_plane_flag is optional (assumed 0), but has implications
72 // about the ChromaArrayType, which modifies how we treat crop coordinates.
73 uint32_t separate_colour_plane_flag = 0;
74 // chroma_format_idc will be ChromaArrayType if separate_colour_plane_flag is 69 // chroma_format_idc will be ChromaArrayType if separate_colour_plane_flag is
75 // 0. It defaults to 1, when not specified. 70 // 0. It defaults to 1, when not specified.
76 uint32_t chroma_format_idc = 1; 71 uint32_t chroma_format_idc = 1;
77 72
78 // profile_idc: u(8). We need it to determine if we need to read/skip chroma 73 // profile_idc: u(8). We need it to determine if we need to read/skip chroma
79 // formats. 74 // formats.
80 uint8_t profile_idc; 75 uint8_t profile_idc;
81 RETURN_FALSE_ON_FAIL(parser.ReadUInt8(&profile_idc)); 76 RETURN_FALSE_ON_FAIL(parser->ReadUInt8(&profile_idc));
82 // constraint_set0_flag through constraint_set5_flag + reserved_zero_2bits 77 // constraint_set0_flag through constraint_set5_flag + reserved_zero_2bits
83 // 1 bit each for the flags + 2 bits = 8 bits = 1 byte. 78 // 1 bit each for the flags + 2 bits = 8 bits = 1 byte.
84 RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); 79 RETURN_FALSE_ON_FAIL(parser->ConsumeBytes(1));
85 // level_idc: u(8) 80 // level_idc: u(8)
86 RETURN_FALSE_ON_FAIL(parser.ConsumeBytes(1)); 81 RETURN_FALSE_ON_FAIL(parser->ConsumeBytes(1));
87 // seq_parameter_set_id: ue(v) 82 // seq_parameter_set_id: ue(v)
88 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 83 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&golomb_ignored));
84 sps.separate_colour_plane_flag = 0;
89 // See if profile_idc has chroma format information. 85 // See if profile_idc has chroma format information.
90 if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || 86 if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
91 profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || 87 profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
92 profile_idc == 86 || profile_idc == 118 || profile_idc == 128 || 88 profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ||
93 profile_idc == 138 || profile_idc == 139 || profile_idc == 134) { 89 profile_idc == 138 || profile_idc == 139 || profile_idc == 134) {
94 // chroma_format_idc: ue(v) 90 // chroma_format_idc: ue(v)
95 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&chroma_format_idc)); 91 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&chroma_format_idc));
96 if (chroma_format_idc == 3) { 92 if (chroma_format_idc == 3) {
97 // separate_colour_plane_flag: u(1) 93 // separate_colour_plane_flag: u(1)
98 RETURN_FALSE_ON_FAIL(parser.ReadBits(&separate_colour_plane_flag, 1)); 94 RETURN_FALSE_ON_FAIL(
95 parser->ReadBits(&sps.separate_colour_plane_flag, 1));
99 } 96 }
100 // bit_depth_luma_minus8: ue(v) 97 // bit_depth_luma_minus8: ue(v)
101 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 98 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&golomb_ignored));
102 // bit_depth_chroma_minus8: ue(v) 99 // bit_depth_chroma_minus8: ue(v)
103 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 100 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&golomb_ignored));
104 // qpprime_y_zero_transform_bypass_flag: u(1) 101 // qpprime_y_zero_transform_bypass_flag: u(1)
105 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); 102 RETURN_FALSE_ON_FAIL(parser->ConsumeBits(1));
106 // seq_scaling_matrix_present_flag: u(1) 103 // seq_scaling_matrix_present_flag: u(1)
107 uint32_t seq_scaling_matrix_present_flag; 104 uint32_t seq_scaling_matrix_present_flag;
108 RETURN_FALSE_ON_FAIL(parser.ReadBits(&seq_scaling_matrix_present_flag, 1)); 105 RETURN_FALSE_ON_FAIL(parser->ReadBits(&seq_scaling_matrix_present_flag, 1));
109 if (seq_scaling_matrix_present_flag) { 106 if (seq_scaling_matrix_present_flag) {
110 // seq_scaling_list_present_flags. Either 8 or 12, depending on 107 // seq_scaling_list_present_flags. Either 8 or 12, depending on
111 // chroma_format_idc. 108 // chroma_format_idc.
112 uint32_t seq_scaling_list_present_flags; 109 uint32_t seq_scaling_list_present_flags;
113 if (chroma_format_idc != 3) { 110 if (chroma_format_idc != 3) {
114 RETURN_FALSE_ON_FAIL( 111 RETURN_FALSE_ON_FAIL(
115 parser.ReadBits(&seq_scaling_list_present_flags, 8)); 112 parser->ReadBits(&seq_scaling_list_present_flags, 8));
116 } else { 113 } else {
117 RETURN_FALSE_ON_FAIL( 114 RETURN_FALSE_ON_FAIL(
118 parser.ReadBits(&seq_scaling_list_present_flags, 12)); 115 parser->ReadBits(&seq_scaling_list_present_flags, 12));
119 } 116 }
120 // We don't support reading the sequence scaling list, and we don't really 117 // We don't support reading the sequence scaling list, and we don't really
121 // see/use them in practice, so we'll just reject the full sps if we see 118 // see/use them in practice, so we'll just reject the full sps if we see
122 // any provided. 119 // any provided.
123 if (seq_scaling_list_present_flags > 0) { 120 if (seq_scaling_list_present_flags > 0) {
124 LOG(LS_WARNING) << "SPS contains scaling lists, which are unsupported."; 121 LOG(LS_WARNING) << "SPS contains scaling lists, which are unsupported.";
125 return false; 122 return false;
126 } 123 }
127 } 124 }
128 } 125 }
129 // log2_max_frame_num_minus4: ue(v) 126 // log2_max_frame_num_minus4: ue(v)
130 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 127 RETURN_FALSE_ON_FAIL(
128 parser->ReadExponentialGolomb(&sps.log2_max_frame_num_minus4));
131 // pic_order_cnt_type: ue(v) 129 // pic_order_cnt_type: ue(v)
132 uint32_t pic_order_cnt_type; 130 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&sps.pic_order_cnt_type));
133 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_order_cnt_type)); 131 if (sps.pic_order_cnt_type == 0) {
134 if (pic_order_cnt_type == 0) {
135 // log2_max_pic_order_cnt_lsb_minus4: ue(v) 132 // log2_max_pic_order_cnt_lsb_minus4: ue(v)
136 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 133 RETURN_FALSE_ON_FAIL(
137 } else if (pic_order_cnt_type == 1) { 134 parser->ReadExponentialGolomb(&sps.log2_max_pic_order_cnt_lsb_minus4));
135 } else if (sps.pic_order_cnt_type == 1) {
138 // delta_pic_order_always_zero_flag: u(1) 136 // delta_pic_order_always_zero_flag: u(1)
139 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); 137 RETURN_FALSE_ON_FAIL(
138 parser->ReadBits(&sps.delta_pic_order_always_zero_flag, 1));
140 // offset_for_non_ref_pic: se(v) 139 // offset_for_non_ref_pic: se(v)
141 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 140 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&golomb_ignored));
142 // offset_for_top_to_bottom_field: se(v) 141 // offset_for_top_to_bottom_field: se(v)
143 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 142 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&golomb_ignored));
144 // num_ref_frames_in_pic_order_cnt_cycle: ue(v) 143 // num_ref_frames_in_pic_order_cnt_cycle: ue(v)
145 uint32_t num_ref_frames_in_pic_order_cnt_cycle; 144 uint32_t num_ref_frames_in_pic_order_cnt_cycle;
146 RETURN_FALSE_ON_FAIL( 145 RETURN_FALSE_ON_FAIL(
147 parser.ReadExponentialGolomb(&num_ref_frames_in_pic_order_cnt_cycle)); 146 parser->ReadExponentialGolomb(&num_ref_frames_in_pic_order_cnt_cycle));
148 for (size_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) { 147 for (size_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
149 // offset_for_ref_frame[i]: se(v) 148 // offset_for_ref_frame[i]: se(v)
150 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 149 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&golomb_ignored));
151 } 150 }
152 } 151 }
153 // max_num_ref_frames: ue(v) 152 // max_num_ref_frames: ue(v)
154 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&golomb_ignored)); 153 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&sps.max_num_ref_frames));
155 // gaps_in_frame_num_value_allowed_flag: u(1) 154 // gaps_in_frame_num_value_allowed_flag: u(1)
156 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); 155 RETURN_FALSE_ON_FAIL(parser->ConsumeBits(1));
157 // 156 //
158 // IMPORTANT ONES! Now we're getting to resolution. First we read the pic 157 // IMPORTANT ONES! Now we're getting to resolution. First we read the pic
159 // width/height in macroblocks (16x16), which gives us the base resolution, 158 // width/height in macroblocks (16x16), which gives us the base resolution,
160 // and then we continue on until we hit the frame crop offsets, which are used 159 // and then we continue on until we hit the frame crop offsets, which are used
161 // to signify resolutions that aren't multiples of 16. 160 // to signify resolutions that aren't multiples of 16.
162 // 161 //
163 // pic_width_in_mbs_minus1: ue(v) 162 // pic_width_in_mbs_minus1: ue(v)
164 uint32_t pic_width_in_mbs_minus1; 163 uint32_t pic_width_in_mbs_minus1;
165 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&pic_width_in_mbs_minus1)); 164 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&pic_width_in_mbs_minus1));
166 // pic_height_in_map_units_minus1: ue(v) 165 // pic_height_in_map_units_minus1: ue(v)
167 uint32_t pic_height_in_map_units_minus1; 166 uint32_t pic_height_in_map_units_minus1;
168 RETURN_FALSE_ON_FAIL( 167 RETURN_FALSE_ON_FAIL(
169 parser.ReadExponentialGolomb(&pic_height_in_map_units_minus1)); 168 parser->ReadExponentialGolomb(&pic_height_in_map_units_minus1));
170 // frame_mbs_only_flag: u(1) 169 // frame_mbs_only_flag: u(1)
171 uint32_t frame_mbs_only_flag; 170 RETURN_FALSE_ON_FAIL(parser->ReadBits(&sps.frame_mbs_only_flag, 1));
172 RETURN_FALSE_ON_FAIL(parser.ReadBits(&frame_mbs_only_flag, 1)); 171 if (!sps.frame_mbs_only_flag) {
173 if (!frame_mbs_only_flag) {
174 // mb_adaptive_frame_field_flag: u(1) 172 // mb_adaptive_frame_field_flag: u(1)
175 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); 173 RETURN_FALSE_ON_FAIL(parser->ConsumeBits(1));
176 } 174 }
177 // direct_8x8_inference_flag: u(1) 175 // direct_8x8_inference_flag: u(1)
178 RETURN_FALSE_ON_FAIL(parser.ConsumeBits(1)); 176 RETURN_FALSE_ON_FAIL(parser->ConsumeBits(1));
179 // 177 //
180 // MORE IMPORTANT ONES! Now we're at the frame crop information. 178 // MORE IMPORTANT ONES! Now we're at the frame crop information.
181 // 179 //
182 // frame_cropping_flag: u(1) 180 // frame_cropping_flag: u(1)
183 uint32_t frame_cropping_flag; 181 uint32_t frame_cropping_flag;
184 uint32_t frame_crop_left_offset = 0; 182 uint32_t frame_crop_left_offset = 0;
185 uint32_t frame_crop_right_offset = 0; 183 uint32_t frame_crop_right_offset = 0;
186 uint32_t frame_crop_top_offset = 0; 184 uint32_t frame_crop_top_offset = 0;
187 uint32_t frame_crop_bottom_offset = 0; 185 uint32_t frame_crop_bottom_offset = 0;
188 RETURN_FALSE_ON_FAIL(parser.ReadBits(&frame_cropping_flag, 1)); 186 RETURN_FALSE_ON_FAIL(parser->ReadBits(&frame_cropping_flag, 1));
189 if (frame_cropping_flag) { 187 if (frame_cropping_flag) {
190 // frame_crop_{left, right, top, bottom}_offset: ue(v) 188 // frame_crop_{left, right, top, bottom}_offset: ue(v)
191 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&frame_crop_left_offset));
192 RETURN_FALSE_ON_FAIL( 189 RETURN_FALSE_ON_FAIL(
193 parser.ReadExponentialGolomb(&frame_crop_right_offset)); 190 parser->ReadExponentialGolomb(&frame_crop_left_offset));
194 RETURN_FALSE_ON_FAIL(parser.ReadExponentialGolomb(&frame_crop_top_offset));
195 RETURN_FALSE_ON_FAIL( 191 RETURN_FALSE_ON_FAIL(
196 parser.ReadExponentialGolomb(&frame_crop_bottom_offset)); 192 parser->ReadExponentialGolomb(&frame_crop_right_offset));
193 RETURN_FALSE_ON_FAIL(parser->ReadExponentialGolomb(&frame_crop_top_offset));
194 RETURN_FALSE_ON_FAIL(
195 parser->ReadExponentialGolomb(&frame_crop_bottom_offset));
197 } 196 }
197 // vui_parameters_present_flag: u(1)
198 RETURN_FALSE_ON_FAIL(parser->ReadBits(&sps.vui_params_present, 1));
198 199
199 // Far enough! We don't use the rest of the SPS. 200 // Far enough! We don't use the rest of the SPS.
200 201
201 // Start with the resolution determined by the pic_width/pic_height fields. 202 // Start with the resolution determined by the pic_width/pic_height fields.
202 int width = 16 * (pic_width_in_mbs_minus1 + 1); 203 sps.width = 16 * (pic_width_in_mbs_minus1 + 1);
203 int height = 204 sps.height =
204 16 * (2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1); 205 16 * (2 - sps.frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1);
205 206
206 // Figure out the crop units in pixels. That's based on the chroma format's 207 // Figure out the crop units in pixels. That's based on the chroma format's
207 // sampling, which is indicated by chroma_format_idc. 208 // sampling, which is indicated by chroma_format_idc.
208 if (separate_colour_plane_flag || chroma_format_idc == 0) { 209 if (sps.separate_colour_plane_flag || chroma_format_idc == 0) {
209 frame_crop_bottom_offset *= (2 - frame_mbs_only_flag); 210 frame_crop_bottom_offset *= (2 - sps.frame_mbs_only_flag);
210 frame_crop_top_offset *= (2 - frame_mbs_only_flag); 211 frame_crop_top_offset *= (2 - sps.frame_mbs_only_flag);
211 } else if (!separate_colour_plane_flag && chroma_format_idc > 0) { 212 } else if (!sps.separate_colour_plane_flag && chroma_format_idc > 0) {
212 // Width multipliers for formats 1 (4:2:0) and 2 (4:2:2). 213 // Width multipliers for formats 1 (4:2:0) and 2 (4:2:2).
213 if (chroma_format_idc == 1 || chroma_format_idc == 2) { 214 if (chroma_format_idc == 1 || chroma_format_idc == 2) {
214 frame_crop_left_offset *= 2; 215 frame_crop_left_offset *= 2;
215 frame_crop_right_offset *= 2; 216 frame_crop_right_offset *= 2;
216 } 217 }
217 // Height multipliers for format 1 (4:2:0). 218 // Height multipliers for format 1 (4:2:0).
218 if (chroma_format_idc == 1) { 219 if (chroma_format_idc == 1) {
219 frame_crop_top_offset *= 2; 220 frame_crop_top_offset *= 2;
220 frame_crop_bottom_offset *= 2; 221 frame_crop_bottom_offset *= 2;
221 } 222 }
222 } 223 }
223 // Subtract the crop for each dimension. 224 // Subtract the crop for each dimension.
224 width -= (frame_crop_left_offset + frame_crop_right_offset); 225 sps.width -= (frame_crop_left_offset + frame_crop_right_offset);
225 height -= (frame_crop_top_offset + frame_crop_bottom_offset); 226 sps.height -= (frame_crop_top_offset + frame_crop_bottom_offset);
226 227
227 width_ = width; 228 state_ = rtc::Optional<SpsState>(sps);
228 height_ = height; 229
229 return true; 230 return true;
230 } 231 }
231 232
233 const rtc::Optional<SpsParser::SpsState>& SpsParser::GetState() const {
234 return state_;
235 }
236
232 } // namespace webrtc 237 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698