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

Side by Side Diff: media/cast/sender/h264_vt_encoder.cc

Issue 863083002: [cast] Add optional VideoEncoder method to flush frames. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/cast/sender/h264_vt_encoder.h" 5 #include "media/cast/sender/h264_vt_encoder.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/big_endian.h" 9 #include "base/big_endian.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/macros.h"
14 #include "media/base/mac/corevideo_glue.h" 15 #include "media/base/mac/corevideo_glue.h"
15 #include "media/base/mac/video_frame_mac.h" 16 #include "media/base/mac/video_frame_mac.h"
16 #include "media/cast/sender/video_frame_factory.h" 17 #include "media/cast/sender/video_frame_factory.h"
17 18
18 namespace media { 19 namespace media {
19 namespace cast { 20 namespace cast {
20 21
21 namespace { 22 namespace {
22 23
23 // Container for the associated data of a video frame being processed. 24 // Container for the associated data of a video frame being processed.
(...skipping 12 matching lines...) Expand all
36 37
37 base::ScopedCFTypeRef<CFDictionaryRef> DictionaryWithKeyValue(CFTypeRef key, 38 base::ScopedCFTypeRef<CFDictionaryRef> DictionaryWithKeyValue(CFTypeRef key,
38 CFTypeRef value) { 39 CFTypeRef value) {
39 CFTypeRef keys[1] = {key}; 40 CFTypeRef keys[1] = {key};
40 CFTypeRef values[1] = {value}; 41 CFTypeRef values[1] = {value};
41 return base::ScopedCFTypeRef<CFDictionaryRef>(CFDictionaryCreate( 42 return base::ScopedCFTypeRef<CFDictionaryRef>(CFDictionaryCreate(
42 kCFAllocatorDefault, keys, values, 1, &kCFTypeDictionaryKeyCallBacks, 43 kCFAllocatorDefault, keys, values, 1, &kCFTypeDictionaryKeyCallBacks,
43 &kCFTypeDictionaryValueCallBacks)); 44 &kCFTypeDictionaryValueCallBacks));
44 } 45 }
45 46
47 base::ScopedCFTypeRef<CFArrayRef> ArrayWithIntegers(const std::vector<int>& v) {
48 std::vector<CFNumberRef> numbers;
49 numbers.reserve(v.size());
50 for (const int i : v) {
51 numbers.push_back(CFNumberCreate(nullptr, kCFNumberSInt32Type, &i));
52 }
53 base::ScopedCFTypeRef<CFArrayRef> array(CFArrayCreate(
54 kCFAllocatorDefault, reinterpret_cast<const void**>(&numbers[0]),
55 numbers.size(), &kCFTypeArrayCallBacks));
56 for (CFNumberRef number : numbers) {
57 CFRelease(number);
58 }
59 return array;
60 }
61
46 template <typename NalSizeType> 62 template <typename NalSizeType>
47 void CopyNalsToAnnexB(char* avcc_buffer, 63 void CopyNalsToAnnexB(char* avcc_buffer,
48 const size_t avcc_size, 64 const size_t avcc_size,
49 std::string* annexb_buffer) { 65 std::string* annexb_buffer) {
50 static_assert(sizeof(NalSizeType) == 1 || sizeof(NalSizeType) == 2 || 66 static_assert(sizeof(NalSizeType) == 1 || sizeof(NalSizeType) == 2 ||
51 sizeof(NalSizeType) == 4, 67 sizeof(NalSizeType) == 4,
52 "NAL size type has unsupported size"); 68 "NAL size type has unsupported size");
53 static const char startcode_3[3] = {0, 0, 1}; 69 static const char startcode_3[3] = {0, 0, 1};
54 DCHECK(avcc_buffer); 70 DCHECK(avcc_buffer);
55 DCHECK(annexb_buffer); 71 DCHECK(annexb_buffer);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 // On OS X, allow the hardware encoder. Don't require it, it does not support 266 // On OS X, allow the hardware encoder. Don't require it, it does not support
251 // all configurations (some of which are used for testing). 267 // all configurations (some of which are used for testing).
252 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec; 268 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec;
253 #if !defined(OS_IOS) 269 #if !defined(OS_IOS)
254 encoder_spec = DictionaryWithKeyValue( 270 encoder_spec = DictionaryWithKeyValue(
255 videotoolbox_glue_ 271 videotoolbox_glue_
256 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder() , 272 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder() ,
257 kCFBooleanTrue); 273 kCFBooleanTrue);
258 #endif 274 #endif
259 275
276 // Certain encoders prefer kCVPixelFormatType_422YpCbCr8, which is not
277 // supported through VideoFrame. We can force 420 formats to be used instead.
278 const int formats[] = {
279 kCVPixelFormatType_420YpCbCr8Planar,
280 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange};
281 base::ScopedCFTypeRef<CFArrayRef> formats_array = ArrayWithIntegers(
282 std::vector<int>(formats, formats + arraysize(formats)));
283 base::ScopedCFTypeRef<CFDictionaryRef> buffer_attributes =
284 DictionaryWithKeyValue(kCVPixelBufferPixelFormatTypeKey, formats_array);
285
260 VTCompressionSessionRef session; 286 VTCompressionSessionRef session;
261 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( 287 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate(
262 kCFAllocatorDefault, video_config.width, video_config.height, 288 kCFAllocatorDefault, video_config.width, video_config.height,
263 CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, 289 CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, buffer_attributes,
264 nullptr /* sourceImageBufferAttributes */,
265 nullptr /* compressedDataAllocator */, 290 nullptr /* compressedDataAllocator */,
266 &H264VideoToolboxEncoder::CompressionCallback, 291 &H264VideoToolboxEncoder::CompressionCallback,
267 reinterpret_cast<void*>(this), &session); 292 reinterpret_cast<void*>(this), &session);
268 if (status != noErr) { 293 if (status != noErr) {
269 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status; 294 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status;
270 return false; 295 return false;
271 } 296 }
272 compression_session_.reset(session); 297 compression_session_.reset(session);
273 298
274 ConfigureSession(video_config); 299 ConfigureSession(video_config);
(...skipping 27 matching lines...) Expand all
302 video_config.max_frame_rate); 327 video_config.max_frame_rate);
303 SetSessionProperty( 328 SetSessionProperty(
304 videotoolbox_glue_->kVTCompressionPropertyKey_ColorPrimaries(), 329 videotoolbox_glue_->kVTCompressionPropertyKey_ColorPrimaries(),
305 kCVImageBufferColorPrimaries_ITU_R_709_2); 330 kCVImageBufferColorPrimaries_ITU_R_709_2);
306 SetSessionProperty( 331 SetSessionProperty(
307 videotoolbox_glue_->kVTCompressionPropertyKey_TransferFunction(), 332 videotoolbox_glue_->kVTCompressionPropertyKey_TransferFunction(),
308 kCVImageBufferTransferFunction_ITU_R_709_2); 333 kCVImageBufferTransferFunction_ITU_R_709_2);
309 SetSessionProperty( 334 SetSessionProperty(
310 videotoolbox_glue_->kVTCompressionPropertyKey_YCbCrMatrix(), 335 videotoolbox_glue_->kVTCompressionPropertyKey_YCbCrMatrix(),
311 kCVImageBufferYCbCrMatrix_ITU_R_709_2); 336 kCVImageBufferYCbCrMatrix_ITU_R_709_2);
337 if (video_config.max_number_of_video_buffers_used > 0) {
338 SetSessionProperty(
339 videotoolbox_glue_->kVTCompressionPropertyKey_MaxFrameDelayCount(),
340 video_config.max_number_of_video_buffers_used);
miu 2015/01/21 23:24:27 VideoSenderConfig::max_number_of_video_buffers_use
341 }
312 } 342 }
313 343
314 void H264VideoToolboxEncoder::Teardown() { 344 void H264VideoToolboxEncoder::Teardown() {
315 DCHECK(thread_checker_.CalledOnValidThread()); 345 DCHECK(thread_checker_.CalledOnValidThread());
316 346
317 // If the compression session exists, invalidate it. This blocks until all 347 // If the compression session exists, invalidate it. This blocks until all
318 // pending output callbacks have returned and any internal threads have 348 // pending output callbacks have returned and any internal threads have
319 // joined, ensuring no output callback ever sees a dangling encoder pointer. 349 // joined, ensuring no output callback ever sees a dangling encoder pointer.
320 if (compression_session_) { 350 if (compression_session_) {
321 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); 351 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 scoped_ptr<VideoFrameFactory> 427 scoped_ptr<VideoFrameFactory>
398 H264VideoToolboxEncoder::CreateVideoFrameFactory() { 428 H264VideoToolboxEncoder::CreateVideoFrameFactory() {
399 base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool( 429 base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool(
400 videotoolbox_glue_->VTCompressionSessionGetPixelBufferPool( 430 videotoolbox_glue_->VTCompressionSessionGetPixelBufferPool(
401 compression_session_), 431 compression_session_),
402 base::scoped_policy::RETAIN); 432 base::scoped_policy::RETAIN);
403 return scoped_ptr<VideoFrameFactory>( 433 return scoped_ptr<VideoFrameFactory>(
404 new VideoFrameFactoryCVPixelBufferPoolImpl(pool)); 434 new VideoFrameFactoryCVPixelBufferPoolImpl(pool));
405 } 435 }
406 436
437 void H264VideoToolboxEncoder::EmitFrames() {
438 DCHECK(thread_checker_.CalledOnValidThread());
439
440 if (!compression_session_) {
441 DLOG(ERROR) << " compression session is null";
442 return;
443 }
444
445 OSStatus status = videotoolbox_glue_->VTCompressionSessionCompleteFrames(
446 compression_session_, CoreMediaGlue::CMTime{0, 0, 0, 0});
447 if (status != noErr) {
448 DLOG(ERROR) << " VTCompressionSessionCompleteFrames failed: " << status;
449 }
450 }
451
407 bool H264VideoToolboxEncoder::SetSessionProperty(CFStringRef key, 452 bool H264VideoToolboxEncoder::SetSessionProperty(CFStringRef key,
408 int32_t value) { 453 int32_t value) {
409 base::ScopedCFTypeRef<CFNumberRef> cfvalue( 454 base::ScopedCFTypeRef<CFNumberRef> cfvalue(
410 CFNumberCreate(nullptr, kCFNumberSInt32Type, &value)); 455 CFNumberCreate(nullptr, kCFNumberSInt32Type, &value));
411 return videotoolbox_glue_->VTSessionSetProperty(compression_session_, key, 456 return videotoolbox_glue_->VTSessionSetProperty(compression_session_, key,
412 cfvalue) == noErr; 457 cfvalue) == noErr;
413 } 458 }
414 459
415 bool H264VideoToolboxEncoder::SetSessionProperty(CFStringRef key, bool value) { 460 bool H264VideoToolboxEncoder::SetSessionProperty(CFStringRef key, bool value) {
416 CFBooleanRef cfvalue = (value) ? kCFBooleanTrue : kCFBooleanFalse; 461 CFBooleanRef cfvalue = (value) ? kCFBooleanTrue : kCFBooleanFalse;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 CopySampleBufferToAnnexBBuffer(sbuf, &encoded_frame->data, keyframe); 524 CopySampleBufferToAnnexBBuffer(sbuf, &encoded_frame->data, keyframe);
480 525
481 encoder->cast_environment_->PostTask( 526 encoder->cast_environment_->PostTask(
482 CastEnvironment::MAIN, FROM_HERE, 527 CastEnvironment::MAIN, FROM_HERE,
483 base::Bind(request->frame_encoded_callback, 528 base::Bind(request->frame_encoded_callback,
484 base::Passed(&encoded_frame))); 529 base::Passed(&encoded_frame)));
485 } 530 }
486 531
487 } // namespace cast 532 } // namespace cast
488 } // namespace media 533 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698