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

Side by Side 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: Header comment 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <CoreVideo/CoreVideo.h> 5 #include <CoreVideo/CoreVideo.h>
6 #include <OpenGL/CGLIOSurface.h> 6 #include <OpenGL/CGLIOSurface.h>
7 #include <OpenGL/gl.h> 7 #include <OpenGL/gl.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 20 matching lines...) Expand all
31 31
32 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4). 32 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4).
33 static const int kNALUHeaderLength = 4; 33 static const int kNALUHeaderLength = 4;
34 34
35 // We request 5 picture buffers from the client, each of which has a texture ID 35 // We request 5 picture buffers from the client, each of which has a texture ID
36 // that we can bind decoded frames to. We need enough to satisfy preroll, and 36 // that we can bind decoded frames to. We need enough to satisfy preroll, and
37 // enough to avoid unnecessary stalling, but no more than that. The resource 37 // enough to avoid unnecessary stalling, but no more than that. The resource
38 // requirements are low, as we don't need the textures to be backed by storage. 38 // requirements are low, as we don't need the textures to be backed by storage.
39 static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1; 39 static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1;
40 40
41 // Build an |image_config| dictionary for VideoToolbox initialization.
42 static CFMutableDictionaryRef BuildImageConfig(
43 CMVideoDimensions coded_dimensions) {
44 // TODO(sandersd): RGBA option for 4:4:4 video.
45 int32_t pixel_format = kCVPixelFormatType_422YpCbCr8;
46
47 #define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
48 base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
49 base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
50 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
51 #undef CFINT
52
53 CFMutableDictionaryRef image_config = CFDictionaryCreateMutable(
54 kCFAllocatorDefault,
55 4, // capacity
56 &kCFTypeDictionaryKeyCallBacks,
57 &kCFTypeDictionaryValueCallBacks);
58 CFDictionarySetValue(image_config, kCVPixelBufferPixelFormatTypeKey,
59 cf_pixel_format);
60 CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
61 CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);
62 CFDictionarySetValue(image_config, kCVPixelBufferOpenGLCompatibilityKey,
63 kCFBooleanTrue);
64
65 return image_config;
66 }
67
68 // The purpose of this function is to preload the generic and hardware-specific
69 // libraries required by VideoToolbox before the GPU sandbox is enabled.
70 // VideoToolbox normally loads the hardware-specific libraries lazily, so we
71 // must actually create a decompression session.
72 //
73 // If creating a decompression session fails, hardware decoding will be disabled
74 // (Initialize() will always return false). If it succeeds but a required
75 // library is not loaded yet (I have not experienced this, but the details are
76 // not documented), then VideoToolbox will fall back on software decoding
DaleCurtis 2014/11/21 21:00:49 Is there a way you record when this happens as a U
sandersd (OOO until July 31) 2014/11/21 21:20:19 It's possible, but is also expected when the resol
77 // internally. If that happens, the likely solution is to expand the scope of
78 // this initialization.
79 void InitializeVideoToolbox() {
80 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
81 switches::kDisableAcceleratedVideoDecode)) {
82 return;
83 }
84
85 if (!IsVtInitialized()) {
86 // CoreVideo is also required, but the loader stops after the first path is
87 // loaded. Instead we rely on the transitive dependency from VideoToolbox to
88 // CoreVideo.
89 // TODO(sandersd): Fallback to PrivateFrameworks.
90 StubPathMap paths;
91 paths[kModuleVt].push_back(FILE_PATH_LITERAL(
92 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox"));
93 if (!InitializeStubs(paths))
94 return;
95 }
96
97 // Create a decoding session.
98 // SPS and PPS data were taken from the 480p encoding of Big Buck Bunny.
99 const uint8_t sps[] = {0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x80, 0xd4, 0x3d,
100 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03,
101 0x00, 0x30, 0x8f, 0x16, 0x2d, 0x9a};
102 const uint8_t pps[] = {0x68, 0xe9, 0x7b, 0xcb};
103 const uint8_t* data_ptrs[] = {sps, pps};
104 const size_t data_sizes[] = {arraysize(sps), arraysize(pps)};
105
106 base::ScopedCFTypeRef<CMFormatDescriptionRef> format;
107 OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
108 kCFAllocatorDefault,
109 2, // parameter_set_count
110 data_ptrs, // &parameter_set_pointers
111 data_sizes, // &parameter_set_sizes
112 kNALUHeaderLength, // nal_unit_header_length
113 format.InitializeInto());
114 if (status) {
115 LOG(ERROR) << "Failed to create CMVideoFormatDescription while "
DaleCurtis 2014/11/21 21:00:49 Check out OSSTATUS_LOG and OSSTATUS_DLOG. You can
sandersd (OOO until July 31) 2014/11/21 21:20:19 Done.
116 << "initializing VideoToolbox";
117 content_common_gpu_media::UninitializeVt();
118 return;
119 }
120
121 base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config(
122 CFDictionaryCreateMutable(
123 kCFAllocatorDefault,
124 1, // capacity
125 &kCFTypeDictionaryKeyCallBacks,
126 &kCFTypeDictionaryValueCallBacks));
127
128 CFDictionarySetValue(
129 decoder_config,
130 // kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder
131 CFSTR("RequireHardwareAcceleratedVideoDecoder"),
132 kCFBooleanTrue);
133
134 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config(
135 BuildImageConfig(CMVideoFormatDescriptionGetDimensions(format)));
136
137 VTDecompressionOutputCallbackRecord callback;
DaleCurtis 2014/11/21 21:00:49 Worth using = {0} to zero all potential fields?
sandersd (OOO until July 31) 2014/11/21 21:20:19 Done. (Although the regular path does not do this.
138 callback.decompressionOutputCallback = NULL;
139 callback.decompressionOutputRefCon = NULL;
140
141 base::ScopedCFTypeRef<VTDecompressionSessionRef> session;
142 status = VTDecompressionSessionCreate(
143 kCFAllocatorDefault,
144 format, // video_format_description
145 decoder_config, // video_decoder_specification
146 image_config, // destination_image_buffer_attributes
147 &callback, // output_callback
148 session.InitializeInto());
149 if (status) {
150 LOG(ERROR) << "Initializing VideoToolbox failed with status " << status;
151 content_common_gpu_media::UninitializeVt();
152 return;
153 }
DaleCurtis 2014/11/21 21:00:49 Is the session automatically dropped once all refs
sandersd (OOO until July 31) 2014/11/21 21:20:19 It is, VTDecompressionSessionInvalidate() just let
154 }
155
41 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. 156 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
42 static void OutputThunk( 157 static void OutputThunk(
43 void* decompression_output_refcon, 158 void* decompression_output_refcon,
44 void* source_frame_refcon, 159 void* source_frame_refcon,
45 OSStatus status, 160 OSStatus status,
46 VTDecodeInfoFlags info_flags, 161 VTDecodeInfoFlags info_flags,
47 CVImageBufferRef image_buffer, 162 CVImageBufferRef image_buffer,
48 CMTime presentation_time_stamp, 163 CMTime presentation_time_stamp,
49 CMTime presentation_duration) { 164 CMTime presentation_duration) {
50 VTVideoDecodeAccelerator* vda = 165 VTVideoDecodeAccelerator* vda =
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 200
86 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { 201 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() {
87 } 202 }
88 203
89 bool VTVideoDecodeAccelerator::Initialize( 204 bool VTVideoDecodeAccelerator::Initialize(
90 media::VideoCodecProfile profile, 205 media::VideoCodecProfile profile,
91 Client* client) { 206 Client* client) {
92 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 207 DCHECK(gpu_thread_checker_.CalledOnValidThread());
93 client_ = client; 208 client_ = client;
94 209
210 if (!IsVtInitialized())
211 return false;
212
95 // Only H.264 is supported. 213 // Only H.264 is supported.
96 if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX) 214 if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX)
97 return false; 215 return false;
98 216
99 // Require --no-sandbox until VideoToolbox library loading is part of sandbox
100 // startup (and this VDA is ready for regular users).
101 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox))
102 return false;
103
104 if (!IsVtInitialized()) {
105 // CoreVideo is also required, but the loader stops after the first
106 // path is loaded. Instead we rely on the transitive dependency from
107 // VideoToolbox to CoreVideo.
108 // TODO(sandersd): Fallback to PrivateFrameworks for VideoToolbox.
109 StubPathMap paths;
110 paths[kModuleVt].push_back(FILE_PATH_LITERAL(
111 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox"));
112 if (!InitializeStubs(paths))
113 return false;
114 }
115
116 // Spawn a thread to handle parsing and calling VideoToolbox. 217 // Spawn a thread to handle parsing and calling VideoToolbox.
117 if (!decoder_thread_.Start()) 218 if (!decoder_thread_.Start())
118 return false; 219 return false;
119 220
120 return true; 221 return true;
121 } 222 }
122 223
123 bool VTVideoDecodeAccelerator::FinishDelayedFrames() { 224 bool VTVideoDecodeAccelerator::FinishDelayedFrames() {
124 DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread()); 225 DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
125 if (session_) { 226 if (session_) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 &kCFTypeDictionaryKeyCallBacks, 287 &kCFTypeDictionaryKeyCallBacks,
187 &kCFTypeDictionaryValueCallBacks)); 288 &kCFTypeDictionaryValueCallBacks));
188 289
189 CFDictionarySetValue( 290 CFDictionarySetValue(
190 decoder_config, 291 decoder_config,
191 // kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder 292 // kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
192 CFSTR("EnableHardwareAcceleratedVideoDecoder"), 293 CFSTR("EnableHardwareAcceleratedVideoDecoder"),
193 kCFBooleanTrue); 294 kCFBooleanTrue);
194 295
195 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config( 296 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config(
196 CFDictionaryCreateMutable( 297 BuildImageConfig(coded_dimensions));
197 kCFAllocatorDefault,
198 4, // capacity
199 &kCFTypeDictionaryKeyCallBacks,
200 &kCFTypeDictionaryValueCallBacks));
201
202 #define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
203 // TODO(sandersd): RGBA option for 4:4:4 video.
204 int32_t pixel_format = kCVPixelFormatType_422YpCbCr8;
205 base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
206 base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
207 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
208 #undef CFINT
209 CFDictionarySetValue(
210 image_config, kCVPixelBufferPixelFormatTypeKey, cf_pixel_format);
211 CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
212 CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);
213 CFDictionarySetValue(
214 image_config, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue);
215 298
216 // TODO(sandersd): Does the old session need to be flushed first? 299 // TODO(sandersd): Does the old session need to be flushed first?
217 session_.reset(); 300 session_.reset();
218 status = VTDecompressionSessionCreate( 301 status = VTDecompressionSessionCreate(
219 kCFAllocatorDefault, 302 kCFAllocatorDefault,
220 format_, // video_format_description 303 format_, // video_format_description
221 decoder_config, // video_decoder_specification 304 decoder_config, // video_decoder_specification
222 image_config, // destination_image_buffer_attributes 305 image_config, // destination_image_buffer_attributes
223 &callback_, // output_callback 306 &callback_, // output_callback
224 session_.InitializeInto()); 307 session_.InitializeInto());
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 assigned_bitstream_ids_.clear(); 755 assigned_bitstream_ids_.clear();
673 state_ = STATE_DESTROYING; 756 state_ = STATE_DESTROYING;
674 QueueFlush(TASK_DESTROY); 757 QueueFlush(TASK_DESTROY);
675 } 758 }
676 759
677 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { 760 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() {
678 return false; 761 return false;
679 } 762 }
680 763
681 } // namespace content 764 } // namespace content
OLDNEW
« 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