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

Unified Diff: content/common/gpu/media/vt_video_decode_accelerator.cc

Issue 723993003: Sandbox initialization for VideoToolbox. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@vt_queue_frames
Patch Set: Rebase. Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/common/gpu/media/vt_video_decode_accelerator.h ('k') | content/common/sandbox_mac.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/common/gpu/media/vt_video_decode_accelerator.cc
diff --git a/content/common/gpu/media/vt_video_decode_accelerator.cc b/content/common/gpu/media/vt_video_decode_accelerator.cc
index 62658fb70dfd64018f7a1c6a256adde726639372..136a308a6be6f5650aa533ac7f9c41656590f453 100644
--- a/content/common/gpu/media/vt_video_decode_accelerator.cc
+++ b/content/common/gpu/media/vt_video_decode_accelerator.cc
@@ -10,6 +10,8 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/mac/mac_logging.h"
#include "base/sys_byteorder.h"
#include "base/thread_task_runner_handle.h"
#include "content/common/gpu/media/vt_video_decode_accelerator.h"
@@ -22,10 +24,10 @@ using content_common_gpu_media::InitializeStubs;
using content_common_gpu_media::IsVtInitialized;
using content_common_gpu_media::StubPathMap;
-#define NOTIFY_STATUS(name, status) \
- do { \
- DLOG(ERROR) << name << " failed with status " << status; \
- NotifyError(PLATFORM_FAILURE); \
+#define NOTIFY_STATUS(name, status) \
+ do { \
+ OSSTATUS_DLOG(ERROR, status) << name; \
+ NotifyError(PLATFORM_FAILURE); \
} while (0)
namespace content {
@@ -44,6 +46,121 @@ static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1;
// reorder queue.)
static const int kMaxReorderQueueSize = 16;
+// Build an |image_config| dictionary for VideoToolbox initialization.
+static base::ScopedCFTypeRef<CFMutableDictionaryRef>
+BuildImageConfig(CMVideoDimensions coded_dimensions) {
+ // TODO(sandersd): RGBA option for 4:4:4 video.
+ int32_t pixel_format = kCVPixelFormatType_422YpCbCr8;
+
+#define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
+ base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
+ base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
+ base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
+#undef CFINT
+
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config(
+ CFDictionaryCreateMutable(
+ kCFAllocatorDefault,
+ 4, // capacity
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ CFDictionarySetValue(image_config, kCVPixelBufferPixelFormatTypeKey,
+ cf_pixel_format);
+ CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
+ CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);
+ CFDictionarySetValue(image_config, kCVPixelBufferOpenGLCompatibilityKey,
+ kCFBooleanTrue);
+
+ return image_config;
+}
+
+// The purpose of this function is to preload the generic and hardware-specific
+// libraries required by VideoToolbox before the GPU sandbox is enabled.
+// VideoToolbox normally loads the hardware-specific libraries lazily, so we
+// must actually create a decompression session.
+//
+// If creating a decompression session fails, hardware decoding will be disabled
+// (Initialize() will always return false). If it succeeds but a required
+// library is not loaded yet (I have not experienced this, but the details are
+// not documented), then VideoToolbox will fall back on software decoding
+// internally. If that happens, the likely solution is to expand the scope of
+// this initialization.
+void InitializeVideoToolbox() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableAcceleratedVideoDecode)) {
+ return;
+ }
+
+ if (!IsVtInitialized()) {
+ // CoreVideo is also required, but the loader stops after the first path is
+ // loaded. Instead we rely on the transitive dependency from VideoToolbox to
+ // CoreVideo.
+ // TODO(sandersd): Fallback to PrivateFrameworks to support OS X < 10.8.
+ StubPathMap paths;
+ paths[kModuleVt].push_back(FILE_PATH_LITERAL(
+ "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox"));
+ if (!InitializeStubs(paths))
+ return;
+ }
+
+ // Create a decoding session.
+ // SPS and PPS data were taken from the 480p encoding of Big Buck Bunny.
+ const uint8_t sps[] = {0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x80, 0xd4, 0x3d,
+ 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03,
+ 0x00, 0x30, 0x8f, 0x16, 0x2d, 0x9a};
+ const uint8_t pps[] = {0x68, 0xe9, 0x7b, 0xcb};
+ const uint8_t* data_ptrs[] = {sps, pps};
+ const size_t data_sizes[] = {arraysize(sps), arraysize(pps)};
+
+ base::ScopedCFTypeRef<CMFormatDescriptionRef> format;
+ OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
+ kCFAllocatorDefault,
+ 2, // parameter_set_count
+ data_ptrs, // &parameter_set_pointers
+ data_sizes, // &parameter_set_sizes
+ kNALUHeaderLength, // nal_unit_header_length
+ format.InitializeInto());
+ if (status) {
+ OSSTATUS_LOG(ERROR, status) << "Failed to create CMVideoFormatDescription "
+ << "while initializing VideoToolbox";
+ content_common_gpu_media::UninitializeVt();
+ return;
+ }
+
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config(
+ CFDictionaryCreateMutable(
+ kCFAllocatorDefault,
+ 1, // capacity
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ CFDictionarySetValue(
+ decoder_config,
+ // kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
+ CFSTR("RequireHardwareAcceleratedVideoDecoder"),
+ kCFBooleanTrue);
+
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config(
+ BuildImageConfig(CMVideoFormatDescriptionGetDimensions(format)));
+
+ VTDecompressionOutputCallbackRecord callback = {0};
+
+ base::ScopedCFTypeRef<VTDecompressionSessionRef> session;
+ status = VTDecompressionSessionCreate(
+ kCFAllocatorDefault,
+ format, // video_format_description
+ decoder_config, // video_decoder_specification
+ image_config, // destination_image_buffer_attributes
+ &callback, // output_callback
+ session.InitializeInto());
+ if (status) {
+ OSSTATUS_LOG(ERROR, status) << "Failed to create VTDecompressionSession "
+ << "while initializing VideoToolbox";
+ content_common_gpu_media::UninitializeVt();
+ return;
+ }
+}
+
// Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
static void OutputThunk(
void* decompression_output_refcon,
@@ -112,27 +229,13 @@ bool VTVideoDecodeAccelerator::Initialize(
DCHECK(gpu_thread_checker_.CalledOnValidThread());
client_ = client;
- // Only H.264 is supported.
- if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX)
+ if (!IsVtInitialized())
return false;
- // Require --no-sandbox until VideoToolbox library loading is part of sandbox
- // startup (and this VDA is ready for regular users).
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox))
+ // Only H.264 is supported.
+ if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX)
return false;
- if (!IsVtInitialized()) {
- // CoreVideo is also required, but the loader stops after the first
- // path is loaded. Instead we rely on the transitive dependency from
- // VideoToolbox to CoreVideo.
- // TODO(sandersd): Fallback to PrivateFrameworks for VideoToolbox.
- StubPathMap paths;
- paths[kModuleVt].push_back(FILE_PATH_LITERAL(
- "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox"));
- if (!InitializeStubs(paths))
- return false;
- }
-
// Spawn a thread to handle parsing and calling VideoToolbox.
if (!decoder_thread_.Start())
return false;
@@ -213,25 +316,7 @@ bool VTVideoDecodeAccelerator::ConfigureDecoder() {
kCFBooleanTrue);
base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config(
- CFDictionaryCreateMutable(
- kCFAllocatorDefault,
- 4, // capacity
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
-#define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
- // TODO(sandersd): RGBA option for 4:4:4 video.
- int32_t pixel_format = kCVPixelFormatType_422YpCbCr8;
- base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
- base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
- base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
-#undef CFINT
- CFDictionarySetValue(
- image_config, kCVPixelBufferPixelFormatTypeKey, cf_pixel_format);
- CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
- CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);
- CFDictionarySetValue(
- image_config, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue);
+ BuildImageConfig(coded_dimensions));
// TODO(sandersd): Does the old session need to be flushed first?
session_.reset();
« no previous file with comments | « content/common/gpu/media/vt_video_decode_accelerator.h ('k') | content/common/sandbox_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698