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

Side by Side Diff: content/common/gpu/media/mac_video_decode_accelerator.mm

Issue 10411085: Build AVC decoder configuration record (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address review comments Created 8 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/common/gpu/media/mac_video_decode_accelerator.h" 5 #include "content/common/gpu/media/mac_video_decode_accelerator.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_path.h" 8 #include "base/file_path.h"
9 #import "base/mac/foundation_util.h" 9 #import "base/mac/foundation_util.h"
10 #import "base/memory/ref_counted_memory.h" 10 #import "base/memory/ref_counted_memory.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 0) != kCGLNoError) { 88 0) != kCGLNoError) {
89 DVLOG(1) << "Failed to bind image to texture."; 89 DVLOG(1) << "Failed to bind image to texture.";
90 return false; 90 return false;
91 } 91 }
92 return glGetError() == GL_NO_ERROR; 92 return glGetError() == GL_NO_ERROR;
93 } 93 }
94 94
95 MacVideoDecodeAccelerator::MacVideoDecodeAccelerator( 95 MacVideoDecodeAccelerator::MacVideoDecodeAccelerator(
96 media::VideoDecodeAccelerator::Client* client) 96 media::VideoDecodeAccelerator::Client* client)
97 : client_(client), 97 : client_(client),
98 cgl_context_(NULL), 98 cgl_context_(NULL) {
99 nalu_len_field_size_(0),
100 did_request_pictures_(false) {
101 } 99 }
102 100
103 void MacVideoDecodeAccelerator::SetCGLContext(CGLContextObj cgl_context) { 101 void MacVideoDecodeAccelerator::SetCGLContext(CGLContextObj cgl_context) {
104 DCHECK(CalledOnValidThread()); 102 DCHECK(CalledOnValidThread());
105 cgl_context_ = cgl_context; 103 cgl_context_ = cgl_context;
106 } 104 }
107 105
108 bool MacVideoDecodeAccelerator::SetConfigInfo(
109 uint32_t frame_width,
110 uint32_t frame_height,
111 const std::vector<uint8_t>& avc_data) {
112 DCHECK(CalledOnValidThread());
113 frame_size_ = gfx::Size(frame_width, frame_height);
114 nalu_len_field_size_ = (avc_data[4] & 0x03) + 1;
115
116 DCHECK(!vda_support_.get());
117 vda_support_ = new gfx::VideoDecodeAccelerationSupport();
118 gfx::VideoDecodeAccelerationSupport::Status status = vda_support_->Create(
119 frame_size_.width(), frame_size_.height(), kCVPixelFormatType_422YpCbCr8,
120 &avc_data.front(), avc_data.size());
121 RETURN_ON_FAILURE(status == gfx::VideoDecodeAccelerationSupport::SUCCESS,
122 "Creating video decoder failed with error: " << status,
123 PLATFORM_FAILURE, false);
124 return true;
125 }
126
127 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) { 106 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
128 DCHECK(CalledOnValidThread()); 107 DCHECK(CalledOnValidThread());
129 108
130 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); 109 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
131 if (!io_surface_support) 110 if (!io_surface_support)
132 return false; 111 return false;
133 112
134 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 113 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
135 &MacVideoDecodeAccelerator::NotifyInitializeDone, this)); 114 &MacVideoDecodeAccelerator::NotifyInitializeDone, this));
136 return true; 115 return true;
137 } 116 }
138 117
139 void MacVideoDecodeAccelerator::Decode( 118 void MacVideoDecodeAccelerator::Decode(
140 const media::BitstreamBuffer& bitstream_buffer) { 119 const media::BitstreamBuffer& bitstream_buffer) {
141 DCHECK(CalledOnValidThread()); 120 DCHECK(CalledOnValidThread());
142 RETURN_ON_FAILURE(client_, 121 RETURN_ON_FAILURE(client_,
143 "Call to Decode() during invalid state.", ILLEGAL_STATE,); 122 "Call to Decode() during invalid state.", ILLEGAL_STATE,);
144 123
145 base::SharedMemory memory(bitstream_buffer.handle(), true); 124 base::SharedMemory memory(bitstream_buffer.handle(), true);
146 RETURN_ON_FAILURE(memory.Map(bitstream_buffer.size()), 125 RETURN_ON_FAILURE(memory.Map(bitstream_buffer.size()),
147 "Failed to SharedMemory::Map().", UNREADABLE_INPUT,); 126 "Failed to SharedMemory::Map().", UNREADABLE_INPUT,);
148 127
149 size_t buffer_size = bitstream_buffer.size(); 128 h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()),
150 RETURN_ON_FAILURE(buffer_size > nalu_len_field_size_, 129 bitstream_buffer.size());
151 "Bitstream contains invalid data.", INVALID_ARGUMENT,); 130 while (true) {
152 131 content::H264NALU nalu;
153 // The decoder can only handle slice types 1-5. 132 content::H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu);
154 const uint8_t* buffer = static_cast<const uint8_t*>(memory.memory()); 133 if (result == content::H264Parser::kEOStream) {
155 uint8_t nalu_type = buffer[nalu_len_field_size_] & 0x1f; 134 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
156 if (nalu_type < 1 || nalu_type > 5) { 135 &MacVideoDecodeAccelerator::NotifyInputBufferRead, this,
157 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 136 bitstream_buffer.id()));
158 &MacVideoDecodeAccelerator::NotifyInputBufferRead, this, 137 return;
159 bitstream_buffer.id())); 138 }
160 return; 139 RETURN_ON_FAILURE(result == content::H264Parser::kOk,
161 } 140 "Unable to parse bitstream.", UNREADABLE_INPUT,);
162 141 if (!did_build_config_record_) {
163 // Keep a ref counted copy of the buffer. 142 std::vector<uint8_t> config_record;
164 std::vector<uint8_t> vbuffer(buffer, buffer + buffer_size); 143 RETURN_ON_FAILURE(config_record_builder_.ProcessNALU(&h264_parser_, nalu,
165 scoped_refptr<base::RefCountedBytes> bytes( 144 &config_record),
166 base::RefCountedBytes::TakeVector(&vbuffer)); 145 "Unable to build AVC configuraiton record.",
167 146 UNREADABLE_INPUT,);
168 // Store the buffer size at the beginning of the buffer as the decoder 147 if (!config_record.empty()) {
169 // expects. 148 did_build_config_record_ = true;
170 size_t frame_buffer_size = buffer_size - nalu_len_field_size_; 149 if (!CreateDecoder(config_record))
171 const uint64_t max_frame_buffer_size = 150 return;
172 (1llu << (nalu_len_field_size_ * 8)) - 1; 151 }
173 DCHECK_LE(nalu_len_field_size_, 4u); 152 }
174 RETURN_ON_FAILURE(frame_buffer_size <= max_frame_buffer_size, 153 // If the decoder has been created and this is a slice type then pass it
175 "Bitstream buffer is too large.", INVALID_ARGUMENT,); 154 // to the decoder.
176 for (size_t i = 0; i < nalu_len_field_size_; ++i) { 155 if (vda_support_.get() && nalu.nal_unit_type >= 1 &&
177 size_t shift = nalu_len_field_size_ * 8 - (i + 1) * 8; 156 nalu.nal_unit_type <= 5) {
178 bytes->data()[i] = (frame_buffer_size >> shift) & 0xff; 157 DecodeNALU(nalu, bitstream_buffer.id());
179 } 158 }
180
181 vda_support_->Decode(bytes->front(), bytes->size(),
182 base::Bind(&MacVideoDecodeAccelerator::OnFrameReady,
183 this, bitstream_buffer.id(), bytes));
184
185 if (!did_request_pictures_) {
186 did_request_pictures_ = true;
187 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
188 &MacVideoDecodeAccelerator::RequestPictures, this));
189 } 159 }
190 } 160 }
191 161
192 void MacVideoDecodeAccelerator::AssignPictureBuffers( 162 void MacVideoDecodeAccelerator::AssignPictureBuffers(
193 const std::vector<media::PictureBuffer>& buffers) { 163 const std::vector<media::PictureBuffer>& buffers) {
194 DCHECK(CalledOnValidThread()); 164 DCHECK(CalledOnValidThread());
195 RETURN_ON_FAILURE(client_, 165 RETURN_ON_FAILURE(client_,
196 "Call to AssignPictureBuffers() during invalid state.", 166 "Call to AssignPictureBuffers() during invalid state.",
197 ILLEGAL_STATE,); 167 ILLEGAL_STATE,);
198 available_pictures_.insert( 168 available_pictures_.insert(
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 } 266 }
297 } 267 }
298 268
299 void MacVideoDecodeAccelerator::StopOnError( 269 void MacVideoDecodeAccelerator::StopOnError(
300 media::VideoDecodeAccelerator::Error error) { 270 media::VideoDecodeAccelerator::Error error) {
301 if (client_) 271 if (client_)
302 client_->NotifyError(error); 272 client_->NotifyError(error);
303 Destroy(); 273 Destroy();
304 } 274 }
305 275
276 bool MacVideoDecodeAccelerator::CreateDecoder(
277 const std::vector<uint8_t>& extra_data) {
278 DCHECK(client_);
279 DCHECK(!vda_support_.get());
280
281 vda_support_ = new gfx::VideoDecodeAccelerationSupport();
282 gfx::VideoDecodeAccelerationSupport::Status status = vda_support_->Create(
283 config_record_builder_.coded_width(),
284 config_record_builder_.coded_height(),
285 kCVPixelFormatType_422YpCbCr8,
286 &extra_data[0], extra_data.size());
287 RETURN_ON_FAILURE(status == gfx::VideoDecodeAccelerationSupport::SUCCESS,
288 "Creating video decoder failed with error: " << status,
289 PLATFORM_FAILURE, false);
290
291 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
292 &MacVideoDecodeAccelerator::RequestPictures, this));
293 return true;
294 }
295
296 void MacVideoDecodeAccelerator::DecodeNALU(const content::H264NALU& nalu,
297 int32 bitstream_buffer_id) {
298 // Assume the NALU length field size is 4 bytes.
299 const int kNALULengthFieldSize = 4;
300 std::vector<uint8_t> data(kNALULengthFieldSize + nalu.size);
301
302 // Store the buffer size at the beginning of the buffer as the decoder
303 // expects.
304 for (size_t i = 0; i < kNALULengthFieldSize; ++i) {
305 size_t shift = kNALULengthFieldSize * 8 - (i + 1) * 8;
306 data[i] = (nalu.size >> shift) & 0xff;
307 }
308
309 // Copy the NALU data.
310 memcpy(&data[kNALULengthFieldSize], nalu.data, nalu.size);
311
312 // Keep a ref counted copy of the buffer.
313 scoped_refptr<base::RefCountedBytes> bytes(
314 base::RefCountedBytes::TakeVector(&data));
315 vda_support_->Decode(bytes->front(), bytes->size(),
316 base::Bind(&MacVideoDecodeAccelerator::OnFrameReady,
317 this, bitstream_buffer_id, bytes));
318 }
319
306 void MacVideoDecodeAccelerator::NotifyInitializeDone() { 320 void MacVideoDecodeAccelerator::NotifyInitializeDone() {
307 if (client_) 321 if (client_)
308 client_->NotifyInitializeDone(); 322 client_->NotifyInitializeDone();
309 } 323 }
310 324
311 void MacVideoDecodeAccelerator::RequestPictures() { 325 void MacVideoDecodeAccelerator::RequestPictures() {
312 if (client_) 326 if (client_) {
313 client_->ProvidePictureBuffers(kNumPictureBuffers, frame_size_); 327 client_->ProvidePictureBuffers(
328 kNumPictureBuffers,
329 gfx::Size(config_record_builder_.coded_width(),
330 config_record_builder_.coded_height()));
331 }
314 } 332 }
315 333
316 void MacVideoDecodeAccelerator::NotifyFlushDone() { 334 void MacVideoDecodeAccelerator::NotifyFlushDone() {
317 if (client_) 335 if (client_)
318 client_->NotifyFlushDone(); 336 client_->NotifyFlushDone();
319 } 337 }
320 338
321 void MacVideoDecodeAccelerator::NotifyResetDone() { 339 void MacVideoDecodeAccelerator::NotifyResetDone() {
322 decoded_images_.clear(); 340 decoded_images_.clear();
323 if (client_) 341 if (client_)
(...skipping 13 matching lines...) Expand all
337 } 355 }
338 356
339 MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() { 357 MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() {
340 } 358 }
341 359
342 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() { 360 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() {
343 } 361 }
344 362
345 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() { 363 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() {
346 } 364 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698