| OLD | NEW |
| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 int32_t bitstream_id) | 61 int32_t bitstream_id) |
| 62 : action(action), | 62 : action(action), |
| 63 bitstream_id(bitstream_id) { | 63 bitstream_id(bitstream_id) { |
| 64 } | 64 } |
| 65 | 65 |
| 66 VTVideoDecodeAccelerator::PendingAction::~PendingAction() { | 66 VTVideoDecodeAccelerator::PendingAction::~PendingAction() { |
| 67 } | 67 } |
| 68 | 68 |
| 69 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(CGLContextObj cgl_context) | 69 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(CGLContextObj cgl_context) |
| 70 : cgl_context_(cgl_context), | 70 : cgl_context_(cgl_context), |
| 71 client_(NULL), | 71 client_(nullptr), |
| 72 format_(NULL), | 72 format_(nullptr), |
| 73 session_(NULL), | 73 session_(nullptr), |
| 74 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 74 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 75 weak_this_factory_(this), | 75 weak_this_factory_(this), |
| 76 decoder_thread_("VTDecoderThread") { | 76 decoder_thread_("VTDecoderThread") { |
| 77 callback_.decompressionOutputCallback = OutputThunk; | 77 callback_.decompressionOutputCallback = OutputThunk; |
| 78 callback_.decompressionOutputRefCon = this; | 78 callback_.decompressionOutputRefCon = this; |
| 79 } | 79 } |
| 80 | 80 |
| 81 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { | 81 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { |
| 82 } | 82 } |
| 83 | 83 |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 if (!session_) | 246 if (!session_) |
| 247 ConfigureDecoder(config_nalu_data_ptrs, config_nalu_data_sizes); | 247 ConfigureDecoder(config_nalu_data_ptrs, config_nalu_data_sizes); |
| 248 | 248 |
| 249 // If there are no non-configuration units, immediately return an empty | 249 // If there are no non-configuration units, immediately return an empty |
| 250 // (ie. dropped) frame. It is an error to create a MemoryBlock with zero | 250 // (ie. dropped) frame. It is an error to create a MemoryBlock with zero |
| 251 // size. | 251 // size. |
| 252 if (!data_size) { | 252 if (!data_size) { |
| 253 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( | 253 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 254 &VTVideoDecodeAccelerator::OutputTask, | 254 &VTVideoDecodeAccelerator::OutputTask, |
| 255 weak_this_factory_.GetWeakPtr(), | 255 weak_this_factory_.GetWeakPtr(), |
| 256 DecodedFrame(bitstream.id(), NULL))); | 256 DecodedFrame(bitstream.id(), nullptr))); |
| 257 return; | 257 return; |
| 258 } | 258 } |
| 259 | 259 |
| 260 // 3. Allocate a memory-backed CMBlockBuffer for the translated data. | 260 // 3. Allocate a memory-backed CMBlockBuffer for the translated data. |
| 261 base::ScopedCFTypeRef<CMBlockBufferRef> data; | 261 base::ScopedCFTypeRef<CMBlockBufferRef> data; |
| 262 CHECK(!CMBlockBufferCreateWithMemoryBlock( | 262 CHECK(!CMBlockBufferCreateWithMemoryBlock( |
| 263 kCFAllocatorDefault, | 263 kCFAllocatorDefault, |
| 264 NULL, // &memory_block | 264 nullptr, // &memory_block |
| 265 data_size, // block_length | 265 data_size, // block_length |
| 266 kCFAllocatorDefault, // block_allocator | 266 kCFAllocatorDefault, // block_allocator |
| 267 NULL, // &custom_block_source | 267 nullptr, // &custom_block_source |
| 268 0, // offset_to_data | 268 0, // offset_to_data |
| 269 data_size, // data_length | 269 data_size, // data_length |
| 270 0, // flags | 270 0, // flags |
| 271 data.InitializeInto())); | 271 data.InitializeInto())); |
| 272 | 272 |
| 273 // 4. Copy NALU data, inserting length headers. | 273 // 4. Copy NALU data, inserting length headers. |
| 274 size_t offset = 0; | 274 size_t offset = 0; |
| 275 for (size_t i = 0; i < nalus.size(); i++) { | 275 for (size_t i = 0; i < nalus.size(); i++) { |
| 276 media::H264NALU& nalu = nalus[i]; | 276 media::H264NALU& nalu = nalus[i]; |
| 277 uint32_t header = base::HostToNet32(static_cast<uint32_t>(nalu.size)); | 277 uint32_t header = base::HostToNet32(static_cast<uint32_t>(nalu.size)); |
| 278 CHECK(!CMBlockBufferReplaceDataBytes( | 278 CHECK(!CMBlockBufferReplaceDataBytes( |
| 279 &header, data, offset, kNALUHeaderLength)); | 279 &header, data, offset, kNALUHeaderLength)); |
| 280 offset += kNALUHeaderLength; | 280 offset += kNALUHeaderLength; |
| 281 CHECK(!CMBlockBufferReplaceDataBytes(nalu.data, data, offset, nalu.size)); | 281 CHECK(!CMBlockBufferReplaceDataBytes(nalu.data, data, offset, nalu.size)); |
| 282 offset += nalu.size; | 282 offset += nalu.size; |
| 283 } | 283 } |
| 284 | 284 |
| 285 // 5. Package the data for VideoToolbox and request decoding. | 285 // 5. Package the data for VideoToolbox and request decoding. |
| 286 base::ScopedCFTypeRef<CMSampleBufferRef> frame; | 286 base::ScopedCFTypeRef<CMSampleBufferRef> frame; |
| 287 CHECK(!CMSampleBufferCreate( | 287 CHECK(!CMSampleBufferCreate( |
| 288 kCFAllocatorDefault, | 288 kCFAllocatorDefault, |
| 289 data, // data_buffer | 289 data, // data_buffer |
| 290 true, // data_ready | 290 true, // data_ready |
| 291 NULL, // make_data_ready_callback | 291 nullptr, // make_data_ready_callback |
| 292 NULL, // make_data_ready_refcon | 292 nullptr, // make_data_ready_refcon |
| 293 format_, // format_description | 293 format_, // format_description |
| 294 1, // num_samples | 294 1, // num_samples |
| 295 0, // num_sample_timing_entries | 295 0, // num_sample_timing_entries |
| 296 NULL, // &sample_timing_array | 296 nullptr, // &sample_timing_array |
| 297 0, // num_sample_size_entries | 297 0, // num_sample_size_entries |
| 298 NULL, // &sample_size_array | 298 nullptr, // &sample_size_array |
| 299 frame.InitializeInto())); | 299 frame.InitializeInto())); |
| 300 | 300 |
| 301 // Asynchronous Decompression allows for parallel submission of frames | 301 // Asynchronous Decompression allows for parallel submission of frames |
| 302 // (without it, DecodeFrame() does not return until the frame has been | 302 // (without it, DecodeFrame() does not return until the frame has been |
| 303 // decoded). We don't enable Temporal Processing so that frames are always | 303 // decoded). We don't enable Temporal Processing so that frames are always |
| 304 // returned in decode order; this makes it easier to avoid deadlock. | 304 // returned in decode order; this makes it easier to avoid deadlock. |
| 305 VTDecodeFrameFlags decode_flags = | 305 VTDecodeFrameFlags decode_flags = |
| 306 kVTDecodeFrame_EnableAsynchronousDecompression; | 306 kVTDecodeFrame_EnableAsynchronousDecompression; |
| 307 | 307 |
| 308 intptr_t bitstream_id = bitstream.id(); | 308 intptr_t bitstream_id = bitstream.id(); |
| 309 CHECK(!VTDecompressionSessionDecodeFrame( | 309 CHECK(!VTDecompressionSessionDecodeFrame( |
| 310 session_, | 310 session_, |
| 311 frame, // sample_buffer | 311 frame, // sample_buffer |
| 312 decode_flags, // decode_flags | 312 decode_flags, // decode_flags |
| 313 reinterpret_cast<void*>(bitstream_id), // source_frame_refcon | 313 reinterpret_cast<void*>(bitstream_id), // source_frame_refcon |
| 314 NULL)); // &info_flags_out | 314 nullptr)); // &info_flags_out |
| 315 } | 315 } |
| 316 | 316 |
| 317 // This method may be called on any VideoToolbox thread. | 317 // This method may be called on any VideoToolbox thread. |
| 318 // TODO(sandersd): Proper error reporting instead of CHECKs. | 318 // TODO(sandersd): Proper error reporting instead of CHECKs. |
| 319 void VTVideoDecodeAccelerator::Output( | 319 void VTVideoDecodeAccelerator::Output( |
| 320 int32_t bitstream_id, | 320 int32_t bitstream_id, |
| 321 OSStatus status, | 321 OSStatus status, |
| 322 CVImageBufferRef image_buffer) { | 322 CVImageBufferRef image_buffer) { |
| 323 CHECK(!status); | 323 CHECK(!status); |
| 324 CHECK_EQ(CFGetTypeID(image_buffer), CVPixelBufferGetTypeID()); | 324 CHECK_EQ(CFGetTypeID(image_buffer), CVPixelBufferGetTypeID()); |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 pending_bitstream_ids_.pop(); | 546 pending_bitstream_ids_.pop(); |
| 547 } | 547 } |
| 548 QueueAction(ACTION_DESTROY); | 548 QueueAction(ACTION_DESTROY); |
| 549 } | 549 } |
| 550 | 550 |
| 551 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { | 551 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { |
| 552 return false; | 552 return false; |
| 553 } | 553 } |
| 554 | 554 |
| 555 } // namespace content | 555 } // namespace content |
| OLD | NEW |