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

Side by Side Diff: media/gpu/vt_video_decode_accelerator_mac.cc

Issue 2272233002: VTVDA: Fix computation of |reorder_window|. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 3 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
« no previous file with comments | « no previous file | media/video/h264_poc.cc » ('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 "media/gpu/vt_video_decode_accelerator_mac.h" 5 #include "media/gpu/vt_video_decode_accelerator_mac.h"
6 6
7 #include <CoreVideo/CoreVideo.h> 7 #include <CoreVideo/CoreVideo.h>
8 #include <OpenGL/CGLIOSurface.h> 8 #include <OpenGL/CGLIOSurface.h>
9 #include <OpenGL/gl.h> 9 #include <OpenGL/gl.h>
10 #include <stddef.h> 10 #include <stddef.h>
(...skipping 24 matching lines...) Expand all
35 using media_gpu::StubPathMap; 35 using media_gpu::StubPathMap;
36 36
37 #define NOTIFY_STATUS(name, status, session_failure) \ 37 #define NOTIFY_STATUS(name, status, session_failure) \
38 do { \ 38 do { \
39 OSSTATUS_DLOG(ERROR, status) << name; \ 39 OSSTATUS_DLOG(ERROR, status) << name; \
40 NotifyError(PLATFORM_FAILURE, session_failure); \ 40 NotifyError(PLATFORM_FAILURE, session_failure); \
41 } while (0) 41 } while (0)
42 42
43 namespace media { 43 namespace media {
44 44
45 namespace {
46
45 // Only H.264 with 4:2:0 chroma sampling is supported. 47 // Only H.264 with 4:2:0 chroma sampling is supported.
46 static const VideoCodecProfile kSupportedProfiles[] = { 48 const VideoCodecProfile kSupportedProfiles[] = {
47 H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_EXTENDED, 49 H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_EXTENDED,
48 H264PROFILE_HIGH, 50 H264PROFILE_HIGH,
49 // TODO(hubbe): Try to re-enable this again somehow. Currently it seems 51 // TODO(hubbe): Try to re-enable this again somehow. Currently it seems
50 // that some codecs fail to check the profile during initialization and 52 // that some codecs fail to check the profile during initialization and
51 // then fail on the first frame decode, which currently results in a 53 // then fail on the first frame decode, which currently results in a
52 // pipeline failure. 54 // pipeline failure.
53 // H264PROFILE_HIGH10PROFILE, 55 // H264PROFILE_HIGH10PROFILE,
54 H264PROFILE_SCALABLEBASELINE, H264PROFILE_SCALABLEHIGH, 56 H264PROFILE_SCALABLEBASELINE, H264PROFILE_SCALABLEHIGH,
55 H264PROFILE_STEREOHIGH, H264PROFILE_MULTIVIEWHIGH, 57 H264PROFILE_STEREOHIGH, H264PROFILE_MULTIVIEWHIGH,
56 }; 58 };
57 59
58 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4). 60 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4).
59 static const int kNALUHeaderLength = 4; 61 const int kNALUHeaderLength = 4;
60 62
61 // We request 5 picture buffers from the client, each of which has a texture ID 63 // We request 5 picture buffers from the client, each of which has a texture ID
62 // that we can bind decoded frames to. We need enough to satisfy preroll, and 64 // that we can bind decoded frames to. We need enough to satisfy preroll, and
63 // enough to avoid unnecessary stalling, but no more than that. The resource 65 // enough to avoid unnecessary stalling, but no more than that. The resource
64 // requirements are low, as we don't need the textures to be backed by storage. 66 // requirements are low, as we don't need the textures to be backed by storage.
65 static const int kNumPictureBuffers = limits::kMaxVideoFrames + 1; 67 const int kNumPictureBuffers = limits::kMaxVideoFrames + 1;
66 68
67 // Maximum number of frames to queue for reordering before we stop asking for 69 // Maximum number of frames to queue for reordering before we stop asking for
68 // more. (NotifyEndOfBitstreamBuffer() is called when frames are moved into the 70 // more. (NotifyEndOfBitstreamBuffer() is called when frames are moved into the
69 // reorder queue.) 71 // reorder queue.)
70 static const int kMaxReorderQueueSize = 16; 72 const int kMaxReorderQueueSize = 16;
71 73
72 // Build an |image_config| dictionary for VideoToolbox initialization. 74 // Build an |image_config| dictionary for VideoToolbox initialization.
73 static base::ScopedCFTypeRef<CFMutableDictionaryRef> BuildImageConfig( 75 base::ScopedCFTypeRef<CFMutableDictionaryRef> BuildImageConfig(
74 CMVideoDimensions coded_dimensions) { 76 CMVideoDimensions coded_dimensions) {
75 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config; 77 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config;
76 78
77 // Note that 4:2:0 textures cannot be used directly as RGBA in OpenGL, but are 79 // Note that 4:2:0 textures cannot be used directly as RGBA in OpenGL, but are
78 // lower power than 4:2:2 when composited directly by CoreAnimation. 80 // lower power than 4:2:2 when composited directly by CoreAnimation.
79 int32_t pixel_format = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; 81 int32_t pixel_format = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
80 #define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i) 82 #define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
81 base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format)); 83 base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
82 base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width)); 84 base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
83 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height)); 85 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
(...skipping 15 matching lines...) Expand all
99 101
100 return image_config; 102 return image_config;
101 } 103 }
102 104
103 // Create a VTDecompressionSession using the provided |pps| and |sps|. If 105 // Create a VTDecompressionSession using the provided |pps| and |sps|. If
104 // |require_hardware| is true, the session must uses real hardware decoding 106 // |require_hardware| is true, the session must uses real hardware decoding
105 // (as opposed to software decoding inside of VideoToolbox) to be considered 107 // (as opposed to software decoding inside of VideoToolbox) to be considered
106 // successful. 108 // successful.
107 // 109 //
108 // TODO(sandersd): Merge with ConfigureDecoder(), as the code is very similar. 110 // TODO(sandersd): Merge with ConfigureDecoder(), as the code is very similar.
109 static bool CreateVideoToolboxSession(const uint8_t* sps, 111 bool CreateVideoToolboxSession(const uint8_t* sps,
110 size_t sps_size, 112 size_t sps_size,
111 const uint8_t* pps, 113 const uint8_t* pps,
112 size_t pps_size, 114 size_t pps_size,
113 bool require_hardware) { 115 bool require_hardware) {
114 const uint8_t* data_ptrs[] = {sps, pps}; 116 const uint8_t* data_ptrs[] = {sps, pps};
115 const size_t data_sizes[] = {sps_size, pps_size}; 117 const size_t data_sizes[] = {sps_size, pps_size};
116 118
117 base::ScopedCFTypeRef<CMFormatDescriptionRef> format; 119 base::ScopedCFTypeRef<CMFormatDescriptionRef> format;
118 OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets( 120 OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
119 kCFAllocatorDefault, 121 kCFAllocatorDefault,
120 2, // parameter_set_count 122 2, // parameter_set_count
121 data_ptrs, // &parameter_set_pointers 123 data_ptrs, // &parameter_set_pointers
122 data_sizes, // &parameter_set_sizes 124 data_sizes, // &parameter_set_sizes
123 kNALUHeaderLength, // nal_unit_header_length 125 kNALUHeaderLength, // nal_unit_header_length
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 167
166 return true; 168 return true;
167 } 169 }
168 170
169 // The purpose of this function is to preload the generic and hardware-specific 171 // The purpose of this function is to preload the generic and hardware-specific
170 // libraries required by VideoToolbox before the GPU sandbox is enabled. 172 // libraries required by VideoToolbox before the GPU sandbox is enabled.
171 // VideoToolbox normally loads the hardware-specific libraries lazily, so we 173 // VideoToolbox normally loads the hardware-specific libraries lazily, so we
172 // must actually create a decompression session. If creating a decompression 174 // must actually create a decompression session. If creating a decompression
173 // session fails, hardware decoding will be disabled (Initialize() will always 175 // session fails, hardware decoding will be disabled (Initialize() will always
174 // return false). 176 // return false).
175 static bool InitializeVideoToolboxInternal() { 177 bool InitializeVideoToolboxInternal() {
176 if (!IsVtInitialized()) { 178 if (!IsVtInitialized()) {
177 // CoreVideo is also required, but the loader stops after the first path is 179 // CoreVideo is also required, but the loader stops after the first path is
178 // loaded. Instead we rely on the transitive dependency from VideoToolbox to 180 // loaded. Instead we rely on the transitive dependency from VideoToolbox to
179 // CoreVideo. 181 // CoreVideo.
180 StubPathMap paths; 182 StubPathMap paths;
181 paths[kModuleVt].push_back(FILE_PATH_LITERAL( 183 paths[kModuleVt].push_back(FILE_PATH_LITERAL(
182 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox")); 184 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox"));
183 if (!InitializeStubs(paths)) { 185 if (!InitializeStubs(paths)) {
184 DLOG(WARNING) << "Failed to initialize VideoToolbox framework"; 186 DLOG(WARNING) << "Failed to initialize VideoToolbox framework";
185 return false; 187 return false;
(...skipping 20 matching lines...) Expand all
206 const uint8_t pps_small[] = {0x68, 0xe9, 0x79, 0x72, 0xc0}; 208 const uint8_t pps_small[] = {0x68, 0xe9, 0x79, 0x72, 0xc0};
207 if (!CreateVideoToolboxSession(sps_small, arraysize(sps_small), pps_small, 209 if (!CreateVideoToolboxSession(sps_small, arraysize(sps_small), pps_small,
208 arraysize(pps_small), false)) { 210 arraysize(pps_small), false)) {
209 DLOG(WARNING) << "Failed to create software VideoToolbox session"; 211 DLOG(WARNING) << "Failed to create software VideoToolbox session";
210 return false; 212 return false;
211 } 213 }
212 214
213 return true; 215 return true;
214 } 216 }
215 217
216 bool InitializeVideoToolbox() { 218 // TODO(sandersd): Share this computation with the VAAPI decoder.
217 // InitializeVideoToolbox() is called only from the GPU process main thread; 219 int32_t ComputeReorderWindow(const H264SPS* sps) {
218 // once for sandbox warmup, and then once each time a VTVideoDecodeAccelerator 220 // TODO(sandersd): Compute MaxDpbFrames.
219 // is initialized. 221 int32_t max_dpb_frames = kMaxReorderQueueSize;
220 static bool attempted = false;
221 static bool succeeded = false;
222 222
223 if (!attempted) { 223 // See AVC spec section E.2.1 definition of |max_num_reorder_frames|.
224 attempted = true; 224 if (sps->vui_parameters_present_flag && sps->bitstream_restriction_flag) {
225 succeeded = InitializeVideoToolboxInternal(); 225 return std::min(sps->max_num_reorder_frames, max_dpb_frames);
226 } else if (sps->constraint_set3_flag) {
227 if (sps->profile_idc == 44 || sps->profile_idc == 86 ||
228 sps->profile_idc == 100 || sps->profile_idc == 110 ||
229 sps->profile_idc == 122 || sps->profile_idc == 244) {
230 return 0;
231 }
226 } 232 }
227 233 return max_dpb_frames;
228 return succeeded;
229 } 234 }
230 235
231 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. 236 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
232 static void OutputThunk(void* decompression_output_refcon, 237 void OutputThunk(void* decompression_output_refcon,
233 void* source_frame_refcon, 238 void* source_frame_refcon,
234 OSStatus status, 239 OSStatus status,
235 VTDecodeInfoFlags info_flags, 240 VTDecodeInfoFlags info_flags,
236 CVImageBufferRef image_buffer, 241 CVImageBufferRef image_buffer,
237 CMTime presentation_time_stamp, 242 CMTime presentation_time_stamp,
238 CMTime presentation_duration) { 243 CMTime presentation_duration) {
239 VTVideoDecodeAccelerator* vda = 244 VTVideoDecodeAccelerator* vda =
240 reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon); 245 reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon);
241 vda->Output(source_frame_refcon, status, image_buffer); 246 vda->Output(source_frame_refcon, status, image_buffer);
242 } 247 }
243 248
249 } // namespace
250
251 bool InitializeVideoToolbox() {
252 // InitializeVideoToolbox() is called only from the GPU process main thread:
253 // once for sandbox warmup, and then once each time a VTVideoDecodeAccelerator
254 // is initialized. This ensures that everything is loaded whether or not the
255 // sandbox is enabled.
256 static bool succeeded = InitializeVideoToolboxInternal();
257 return succeeded;
258 }
259
244 VTVideoDecodeAccelerator::Task::Task(TaskType type) : type(type) {} 260 VTVideoDecodeAccelerator::Task::Task(TaskType type) : type(type) {}
245 261
246 VTVideoDecodeAccelerator::Task::Task(const Task& other) = default; 262 VTVideoDecodeAccelerator::Task::Task(const Task& other) = default;
247 263
248 VTVideoDecodeAccelerator::Task::~Task() {} 264 VTVideoDecodeAccelerator::Task::~Task() {}
249 265
250 VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id) 266 VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id)
251 : bitstream_id(bitstream_id), 267 : bitstream_id(bitstream_id),
252 pic_order_cnt(0), 268 pic_order_cnt(0),
253 is_idr(false), 269 is_idr(false),
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 606
591 if (!poc_.ComputePicOrderCnt(sps, slice_hdr, &frame->pic_order_cnt)) { 607 if (!poc_.ComputePicOrderCnt(sps, slice_hdr, &frame->pic_order_cnt)) {
592 DLOG(ERROR) << "Unable to compute POC"; 608 DLOG(ERROR) << "Unable to compute POC";
593 NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM); 609 NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
594 return; 610 return;
595 } 611 }
596 612
597 if (nalu.nal_unit_type == H264NALU::kIDRSlice) 613 if (nalu.nal_unit_type == H264NALU::kIDRSlice)
598 frame->is_idr = true; 614 frame->is_idr = true;
599 615
600 if (sps->vui_parameters_present_flag && 616 frame->reorder_window = ComputeReorderWindow(sps);
601 sps->bitstream_restriction_flag) {
602 frame->reorder_window =
603 std::min(sps->max_num_reorder_frames, kMaxReorderQueueSize - 1);
604 }
605 } 617 }
606 has_slice = true; 618 has_slice = true;
607 default: 619 default:
608 nalus.push_back(nalu); 620 nalus.push_back(nalu);
609 data_size += kNALUHeaderLength + nalu.size; 621 data_size += kNALUHeaderLength + nalu.size;
610 break; 622 break;
611 } 623 }
612 } 624 }
613 625
614 // Initialize VideoToolbox. 626 // Initialize VideoToolbox.
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 SupportedProfile profile; 1155 SupportedProfile profile;
1144 profile.profile = supported_profile; 1156 profile.profile = supported_profile;
1145 profile.min_resolution.SetSize(16, 16); 1157 profile.min_resolution.SetSize(16, 16);
1146 profile.max_resolution.SetSize(4096, 2160); 1158 profile.max_resolution.SetSize(4096, 2160);
1147 profiles.push_back(profile); 1159 profiles.push_back(profile);
1148 } 1160 }
1149 return profiles; 1161 return profiles;
1150 } 1162 }
1151 1163
1152 } // namespace media 1164 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/video/h264_poc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698