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

Side by Side Diff: webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.cc

Issue 1732953003: Fix VideoToolbox backgrounding issues (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Update gyp Created 4 years, 9 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) 2015 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 */
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 CFRelease(contiguous_buffer); 154 CFRelease(contiguous_buffer);
155 return true; 155 return true;
156 } 156 }
157 157
158 bool H264AnnexBBufferToCMSampleBuffer(const uint8_t* annexb_buffer, 158 bool H264AnnexBBufferToCMSampleBuffer(const uint8_t* annexb_buffer,
159 size_t annexb_buffer_size, 159 size_t annexb_buffer_size,
160 CMVideoFormatDescriptionRef video_format, 160 CMVideoFormatDescriptionRef video_format,
161 CMSampleBufferRef* out_sample_buffer) { 161 CMSampleBufferRef* out_sample_buffer) {
162 RTC_DCHECK(annexb_buffer); 162 RTC_DCHECK(annexb_buffer);
163 RTC_DCHECK(out_sample_buffer); 163 RTC_DCHECK(out_sample_buffer);
164 RTC_DCHECK(video_format);
164 *out_sample_buffer = nullptr; 165 *out_sample_buffer = nullptr;
165 166
166 // The buffer we receive via RTP has 00 00 00 01 start code artifically
167 // embedded by the RTP depacketizer. Extract NALU information.
168 // TODO(tkchin): handle potential case where sps and pps are delivered
169 // separately.
170 uint8_t first_nalu_type = annexb_buffer[4] & 0x1f;
171 bool is_first_nalu_type_sps = first_nalu_type == 0x7;
172
173 AnnexBBufferReader reader(annexb_buffer, annexb_buffer_size); 167 AnnexBBufferReader reader(annexb_buffer, annexb_buffer_size);
174 CMVideoFormatDescriptionRef description = nullptr; 168 if (H264AnnexBBufferHasVideoFormatDescription(annexb_buffer,
175 OSStatus status = noErr; 169 annexb_buffer_size)) {
176 if (is_first_nalu_type_sps) { 170 // Advance past the SPS and PPS.
177 // Parse the SPS and PPS into a CMVideoFormatDescription. 171 const uint8_t* data = nullptr;
178 const uint8_t* param_set_ptrs[2] = {}; 172 size_t data_len = 0;
179 size_t param_set_sizes[2] = {}; 173 if (!reader.ReadNalu(&data, &data_len)) {
180 if (!reader.ReadNalu(&param_set_ptrs[0], &param_set_sizes[0])) {
181 LOG(LS_ERROR) << "Failed to read SPS"; 174 LOG(LS_ERROR) << "Failed to read SPS";
182 return false; 175 return false;
183 } 176 }
184 if (!reader.ReadNalu(&param_set_ptrs[1], &param_set_sizes[1])) { 177 if (!reader.ReadNalu(&data, &data_len)) {
185 LOG(LS_ERROR) << "Failed to read PPS"; 178 LOG(LS_ERROR) << "Failed to read PPS";
186 return false; 179 return false;
187 } 180 }
188 status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
189 kCFAllocatorDefault, 2, param_set_ptrs, param_set_sizes, 4,
190 &description);
191 if (status != noErr) {
192 LOG(LS_ERROR) << "Failed to create video format description.";
193 return false;
194 }
195 } else {
196 RTC_DCHECK(video_format);
197 description = video_format;
198 // We don't need to retain, but it makes logic easier since we are creating
199 // in the other block.
200 CFRetain(description);
201 } 181 }
202 182
203 // Allocate memory as a block buffer. 183 // Allocate memory as a block buffer.
204 // TODO(tkchin): figure out how to use a pool. 184 // TODO(tkchin): figure out how to use a pool.
205 CMBlockBufferRef block_buffer = nullptr; 185 CMBlockBufferRef block_buffer = nullptr;
206 status = CMBlockBufferCreateWithMemoryBlock( 186 OSStatus status = CMBlockBufferCreateWithMemoryBlock(
207 nullptr, nullptr, reader.BytesRemaining(), nullptr, nullptr, 0, 187 nullptr, nullptr, reader.BytesRemaining(), nullptr, nullptr, 0,
208 reader.BytesRemaining(), kCMBlockBufferAssureMemoryNowFlag, 188 reader.BytesRemaining(), kCMBlockBufferAssureMemoryNowFlag,
209 &block_buffer); 189 &block_buffer);
210 if (status != kCMBlockBufferNoErr) { 190 if (status != kCMBlockBufferNoErr) {
211 LOG(LS_ERROR) << "Failed to create block buffer."; 191 LOG(LS_ERROR) << "Failed to create block buffer.";
212 CFRelease(description);
213 return false; 192 return false;
214 } 193 }
215 194
216 // Make sure block buffer is contiguous. 195 // Make sure block buffer is contiguous.
217 CMBlockBufferRef contiguous_buffer = nullptr; 196 CMBlockBufferRef contiguous_buffer = nullptr;
218 if (!CMBlockBufferIsRangeContiguous(block_buffer, 0, 0)) { 197 if (!CMBlockBufferIsRangeContiguous(block_buffer, 0, 0)) {
219 status = CMBlockBufferCreateContiguous( 198 status = CMBlockBufferCreateContiguous(
220 nullptr, block_buffer, nullptr, nullptr, 0, 0, 0, &contiguous_buffer); 199 nullptr, block_buffer, nullptr, nullptr, 0, 0, 0, &contiguous_buffer);
221 if (status != noErr) { 200 if (status != noErr) {
222 LOG(LS_ERROR) << "Failed to flatten non-contiguous block buffer: " 201 LOG(LS_ERROR) << "Failed to flatten non-contiguous block buffer: "
223 << status; 202 << status;
224 CFRelease(description);
225 CFRelease(block_buffer); 203 CFRelease(block_buffer);
226 return false; 204 return false;
227 } 205 }
228 } else { 206 } else {
229 contiguous_buffer = block_buffer; 207 contiguous_buffer = block_buffer;
230 block_buffer = nullptr; 208 block_buffer = nullptr;
231 } 209 }
232 210
233 // Get a raw pointer into allocated memory. 211 // Get a raw pointer into allocated memory.
234 size_t block_buffer_size = 0; 212 size_t block_buffer_size = 0;
235 char* data_ptr = nullptr; 213 char* data_ptr = nullptr;
236 status = CMBlockBufferGetDataPointer(contiguous_buffer, 0, nullptr, 214 status = CMBlockBufferGetDataPointer(contiguous_buffer, 0, nullptr,
237 &block_buffer_size, &data_ptr); 215 &block_buffer_size, &data_ptr);
238 if (status != kCMBlockBufferNoErr) { 216 if (status != kCMBlockBufferNoErr) {
239 LOG(LS_ERROR) << "Failed to get block buffer data pointer."; 217 LOG(LS_ERROR) << "Failed to get block buffer data pointer.";
240 CFRelease(description);
241 CFRelease(contiguous_buffer); 218 CFRelease(contiguous_buffer);
242 return false; 219 return false;
243 } 220 }
244 RTC_DCHECK(block_buffer_size == reader.BytesRemaining()); 221 RTC_DCHECK(block_buffer_size == reader.BytesRemaining());
245 222
246 // Write Avcc NALUs into block buffer memory. 223 // Write Avcc NALUs into block buffer memory.
247 AvccBufferWriter writer(reinterpret_cast<uint8_t*>(data_ptr), 224 AvccBufferWriter writer(reinterpret_cast<uint8_t*>(data_ptr),
248 block_buffer_size); 225 block_buffer_size);
249 while (reader.BytesRemaining() > 0) { 226 while (reader.BytesRemaining() > 0) {
250 const uint8_t* nalu_data_ptr = nullptr; 227 const uint8_t* nalu_data_ptr = nullptr;
251 size_t nalu_data_size = 0; 228 size_t nalu_data_size = 0;
252 if (reader.ReadNalu(&nalu_data_ptr, &nalu_data_size)) { 229 if (reader.ReadNalu(&nalu_data_ptr, &nalu_data_size)) {
253 writer.WriteNalu(nalu_data_ptr, nalu_data_size); 230 writer.WriteNalu(nalu_data_ptr, nalu_data_size);
254 } 231 }
255 } 232 }
256 233
257 // Create sample buffer. 234 // Create sample buffer.
258 status = CMSampleBufferCreate(nullptr, contiguous_buffer, true, nullptr, 235 status = CMSampleBufferCreate(nullptr, contiguous_buffer, true, nullptr,
259 nullptr, description, 1, 0, nullptr, 0, nullptr, 236 nullptr, video_format, 1, 0, nullptr, 0,
260 out_sample_buffer); 237 nullptr, out_sample_buffer);
261 if (status != noErr) { 238 if (status != noErr) {
262 LOG(LS_ERROR) << "Failed to create sample buffer."; 239 LOG(LS_ERROR) << "Failed to create sample buffer.";
263 CFRelease(description);
264 CFRelease(contiguous_buffer); 240 CFRelease(contiguous_buffer);
265 return false; 241 return false;
266 } 242 }
267 CFRelease(description);
268 CFRelease(contiguous_buffer); 243 CFRelease(contiguous_buffer);
269 return true; 244 return true;
270 } 245 }
271 246
247 bool H264AnnexBBufferHasVideoFormatDescription(const uint8_t* annexb_buffer,
248 size_t annexb_buffer_size) {
249 RTC_DCHECK(annexb_buffer);
250 RTC_DCHECK_GT(annexb_buffer_size, 4u);
251
252 // The buffer we receive via RTP has 00 00 00 01 start code artifically
253 // embedded by the RTP depacketizer. Extract NALU information.
254 // TODO(tkchin): handle potential case where sps and pps are delivered
255 // separately.
256 uint8_t first_nalu_type = annexb_buffer[4] & 0x1f;
257 bool is_first_nalu_type_sps = first_nalu_type == 0x7;
258 return is_first_nalu_type_sps;
259 }
260
261 CMVideoFormatDescriptionRef CreateVideoFormatDescription(
262 const uint8_t* annexb_buffer,
263 size_t annexb_buffer_size) {
264 if (!H264AnnexBBufferHasVideoFormatDescription(annexb_buffer,
265 annexb_buffer_size)) {
266 return nullptr;
267 }
268 AnnexBBufferReader reader(annexb_buffer, annexb_buffer_size);
269 CMVideoFormatDescriptionRef description = nullptr;
270 OSStatus status = noErr;
271 // Parse the SPS and PPS into a CMVideoFormatDescription.
272 const uint8_t* param_set_ptrs[2] = {};
273 size_t param_set_sizes[2] = {};
274 if (!reader.ReadNalu(&param_set_ptrs[0], &param_set_sizes[0])) {
275 LOG(LS_ERROR) << "Failed to read SPS";
276 return nullptr;
277 }
278 if (!reader.ReadNalu(&param_set_ptrs[1], &param_set_sizes[1])) {
279 LOG(LS_ERROR) << "Failed to read PPS";
280 return nullptr;
281 }
282 status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
283 kCFAllocatorDefault, 2, param_set_ptrs, param_set_sizes, 4,
284 &description);
285 if (status != noErr) {
286 LOG(LS_ERROR) << "Failed to create video format description.";
287 return nullptr;
288 }
289 return description;
290 }
291
272 AnnexBBufferReader::AnnexBBufferReader(const uint8_t* annexb_buffer, 292 AnnexBBufferReader::AnnexBBufferReader(const uint8_t* annexb_buffer,
273 size_t length) 293 size_t length)
274 : start_(annexb_buffer), offset_(0), next_offset_(0), length_(length) { 294 : start_(annexb_buffer), offset_(0), next_offset_(0), length_(length) {
275 RTC_DCHECK(annexb_buffer); 295 RTC_DCHECK(annexb_buffer);
276 offset_ = FindNextNaluHeader(start_, length_, 0); 296 offset_ = FindNextNaluHeader(start_, length_, 0);
277 next_offset_ = 297 next_offset_ =
278 FindNextNaluHeader(start_, length_, offset_ + sizeof(kAnnexBHeaderBytes)); 298 FindNextNaluHeader(start_, length_, offset_ + sizeof(kAnnexBHeaderBytes));
279 } 299 }
280 300
281 bool AnnexBBufferReader::ReadNalu(const uint8_t** out_nalu, 301 bool AnnexBBufferReader::ReadNalu(const uint8_t** out_nalu,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 return true; 367 return true;
348 } 368 }
349 369
350 size_t AvccBufferWriter::BytesRemaining() const { 370 size_t AvccBufferWriter::BytesRemaining() const {
351 return length_ - offset_; 371 return length_ - offset_;
352 } 372 }
353 373
354 } // namespace webrtc 374 } // namespace webrtc
355 375
356 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) 376 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698