OLD | NEW |
---|---|
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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 } | 105 } |
106 | 106 |
107 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) { | 107 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) { |
108 DCHECK(CalledOnValidThread()); | 108 DCHECK(CalledOnValidThread()); |
109 | 109 |
110 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); | 110 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); |
111 if (!io_surface_support) | 111 if (!io_surface_support) |
112 return false; | 112 return false; |
113 | 113 |
114 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 114 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
115 &MacVideoDecodeAccelerator::NotifyInitializeDone, this)); | 115 &MacVideoDecodeAccelerator::NotifyInitializeDone, base::AsWeakPtr(this))); |
116 return true; | 116 return true; |
117 } | 117 } |
118 | 118 |
119 void MacVideoDecodeAccelerator::Decode( | 119 void MacVideoDecodeAccelerator::Decode( |
120 const media::BitstreamBuffer& bitstream_buffer) { | 120 const media::BitstreamBuffer& bitstream_buffer) { |
121 DCHECK(CalledOnValidThread()); | 121 DCHECK(CalledOnValidThread()); |
122 RETURN_ON_FAILURE(client_, | 122 RETURN_ON_FAILURE(client_, |
123 "Call to Decode() during invalid state.", ILLEGAL_STATE,); | 123 "Call to Decode() during invalid state.", ILLEGAL_STATE,); |
124 | 124 |
125 base::SharedMemory memory(bitstream_buffer.handle(), true); | 125 base::SharedMemory memory(bitstream_buffer.handle(), true); |
126 RETURN_ON_FAILURE(memory.Map(bitstream_buffer.size()), | 126 RETURN_ON_FAILURE(memory.Map(bitstream_buffer.size()), |
127 "Failed to SharedMemory::Map().", UNREADABLE_INPUT,); | 127 "Failed to SharedMemory::Map().", UNREADABLE_INPUT,); |
128 | 128 |
129 h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()), | 129 h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()), |
130 bitstream_buffer.size()); | 130 bitstream_buffer.size()); |
131 while (true) { | 131 while (true) { |
132 content::H264NALU nalu; | 132 content::H264NALU nalu; |
133 content::H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu); | 133 content::H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu); |
134 if (result == content::H264Parser::kEOStream) { | 134 if (result == content::H264Parser::kEOStream) { |
135 if (bitstream_nalu_count_.count(bitstream_buffer.id()) == 0) { | 135 if (bitstream_nalu_count_.count(bitstream_buffer.id()) == 0) { |
136 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 136 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
137 &MacVideoDecodeAccelerator::NotifyInputBufferRead, this, | 137 &MacVideoDecodeAccelerator::NotifyInputBufferRead, |
138 bitstream_buffer.id())); | 138 base::AsWeakPtr(this), bitstream_buffer.id())); |
139 } | 139 } |
140 return; | 140 return; |
141 } | 141 } |
142 RETURN_ON_FAILURE(result == content::H264Parser::kOk, | 142 RETURN_ON_FAILURE(result == content::H264Parser::kOk, |
143 "Unable to parse bitstream.", UNREADABLE_INPUT,); | 143 "Unable to parse bitstream.", UNREADABLE_INPUT,); |
144 if (!did_build_config_record_) { | 144 if (!did_build_config_record_) { |
145 std::vector<uint8_t> config_record; | 145 std::vector<uint8_t> config_record; |
146 RETURN_ON_FAILURE(config_record_builder_.ProcessNALU(&h264_parser_, nalu, | 146 RETURN_ON_FAILURE(config_record_builder_.ProcessNALU(&h264_parser_, nalu, |
147 &config_record), | 147 &config_record), |
148 "Unable to build AVC configuraiton record.", | 148 "Unable to build AVC configuraiton record.", |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 available_pictures_.push_back(info.picture_buffer); | 190 available_pictures_.push_back(info.picture_buffer); |
191 SendImages(); | 191 SendImages(); |
192 } | 192 } |
193 | 193 |
194 void MacVideoDecodeAccelerator::Flush() { | 194 void MacVideoDecodeAccelerator::Flush() { |
195 DCHECK(CalledOnValidThread()); | 195 DCHECK(CalledOnValidThread()); |
196 RETURN_ON_FAILURE(vda_support_, | 196 RETURN_ON_FAILURE(vda_support_, |
197 "Call to Flush() during invalid state.", ILLEGAL_STATE,); | 197 "Call to Flush() during invalid state.", ILLEGAL_STATE,); |
198 vda_support_->Flush(true); | 198 vda_support_->Flush(true); |
199 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 199 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
200 &MacVideoDecodeAccelerator::NotifyFlushDone, this)); | 200 &MacVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this))); |
201 } | 201 } |
202 | 202 |
203 void MacVideoDecodeAccelerator::Reset() { | 203 void MacVideoDecodeAccelerator::Reset() { |
204 DCHECK(CalledOnValidThread()); | 204 DCHECK(CalledOnValidThread()); |
205 RETURN_ON_FAILURE(vda_support_, | 205 RETURN_ON_FAILURE(vda_support_, |
206 "Call to Reset() during invalid state.", ILLEGAL_STATE,); | 206 "Call to Reset() during invalid state.", ILLEGAL_STATE,); |
207 vda_support_->Flush(false); | 207 vda_support_->Flush(false); |
208 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 208 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
209 &MacVideoDecodeAccelerator::NotifyResetDone, this)); | 209 &MacVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this))); |
210 } | 210 } |
211 | 211 |
212 void MacVideoDecodeAccelerator::Destroy() { | 212 void MacVideoDecodeAccelerator::Destroy(bool pass_ownership) { |
213 DCHECK(CalledOnValidThread()); | 213 DCHECK(CalledOnValidThread()); |
214 if (vda_support_) { | 214 if (vda_support_) { |
215 vda_support_->Destroy(); | 215 vda_support_->Destroy(); |
216 vda_support_ = NULL; | 216 vda_support_ = NULL; |
217 } | 217 } |
218 client_ = NULL; | 218 client_ = NULL; |
219 decoded_images_.clear(); | 219 decoded_images_.clear(); |
220 if (pass_ownership) | |
221 delete this; | |
220 } | 222 } |
221 | 223 |
222 MacVideoDecodeAccelerator::~MacVideoDecodeAccelerator() { | 224 MacVideoDecodeAccelerator::~MacVideoDecodeAccelerator() { |
223 DCHECK(CalledOnValidThread()); | 225 DCHECK(CalledOnValidThread()); |
224 Destroy(); | 226 DCHECK(!vda_support_); |
227 DCHECK(!client_); | |
228 DCHECK(decoded_images_.empty()); | |
225 } | 229 } |
226 | 230 |
227 void MacVideoDecodeAccelerator::OnFrameReady( | 231 void MacVideoDecodeAccelerator::OnFrameReady( |
228 int32 bitstream_buffer_id, | 232 int32 bitstream_buffer_id, |
229 scoped_refptr<base::RefCountedBytes> bytes, | 233 scoped_refptr<base::RefCountedBytes> bytes, |
230 CVImageBufferRef image, | 234 CVImageBufferRef image, |
231 int status) { | 235 int status) { |
232 DCHECK(CalledOnValidThread()); | 236 DCHECK(CalledOnValidThread()); |
233 RETURN_ON_FAILURE(status == noErr, | 237 RETURN_ON_FAILURE(status == noErr, |
234 "Decoding image failed with error code: " << status, | 238 "Decoding image failed with error code: " << status, |
235 PLATFORM_FAILURE,); | 239 PLATFORM_FAILURE,); |
236 if (!client_) | 240 if (!client_) |
237 return; | 241 return; |
238 if (image) { | 242 if (image) { |
239 DecodedImageInfo info; | 243 DecodedImageInfo info; |
240 info.image.reset(image, base::scoped_policy::RETAIN); | 244 info.image.reset(image, base::scoped_policy::RETAIN); |
241 info.bitstream_buffer_id = bitstream_buffer_id; | 245 info.bitstream_buffer_id = bitstream_buffer_id; |
242 decoded_images_.push_back(info); | 246 decoded_images_.push_back(info); |
243 SendImages(); | 247 SendImages(); |
244 } | 248 } |
245 std::map<int32, int>::iterator bitstream_count_it = | 249 std::map<int32, int>::iterator bitstream_count_it = |
246 bitstream_nalu_count_.find(bitstream_buffer_id); | 250 bitstream_nalu_count_.find(bitstream_buffer_id); |
247 if (--bitstream_count_it->second == 0) { | 251 if (--bitstream_count_it->second == 0) { |
248 bitstream_nalu_count_.erase(bitstream_count_it); | 252 bitstream_nalu_count_.erase(bitstream_count_it); |
249 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 253 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
250 &MacVideoDecodeAccelerator::NotifyInputBufferRead, this, | 254 &MacVideoDecodeAccelerator::NotifyInputBufferRead, this, |
sail
2012/07/17 16:15:14
also need base::AsWeakPtr here
Ami GONE FROM CHROMIUM
2012/07/17 16:54:23
Done.
| |
251 bitstream_buffer_id)); | 255 bitstream_buffer_id)); |
252 } | 256 } |
253 } | 257 } |
254 | 258 |
255 void MacVideoDecodeAccelerator::SendImages() { | 259 void MacVideoDecodeAccelerator::SendImages() { |
256 if (!client_) { | 260 if (!client_) { |
257 DCHECK(decoded_images_.empty()); | 261 DCHECK(decoded_images_.empty()); |
258 return; | 262 return; |
259 } | 263 } |
260 | 264 |
(...skipping 11 matching lines...) Expand all Loading... | |
272 picture_buffer.id(), UsedPictureInfo(picture_buffer, info.image))); | 276 picture_buffer.id(), UsedPictureInfo(picture_buffer, info.image))); |
273 client_->PictureReady( | 277 client_->PictureReady( |
274 media::Picture(picture_buffer.id(), info.bitstream_buffer_id)); | 278 media::Picture(picture_buffer.id(), info.bitstream_buffer_id)); |
275 } | 279 } |
276 } | 280 } |
277 | 281 |
278 void MacVideoDecodeAccelerator::StopOnError( | 282 void MacVideoDecodeAccelerator::StopOnError( |
279 media::VideoDecodeAccelerator::Error error) { | 283 media::VideoDecodeAccelerator::Error error) { |
280 if (client_) | 284 if (client_) |
281 client_->NotifyError(error); | 285 client_->NotifyError(error); |
282 Destroy(); | 286 Destroy(false); |
283 } | 287 } |
284 | 288 |
285 bool MacVideoDecodeAccelerator::CreateDecoder( | 289 bool MacVideoDecodeAccelerator::CreateDecoder( |
286 const std::vector<uint8_t>& extra_data) { | 290 const std::vector<uint8_t>& extra_data) { |
287 DCHECK(client_); | 291 DCHECK(client_); |
288 DCHECK(!vda_support_.get()); | 292 DCHECK(!vda_support_.get()); |
289 | 293 |
290 vda_support_ = new gfx::VideoDecodeAccelerationSupport(); | 294 vda_support_ = new gfx::VideoDecodeAccelerationSupport(); |
291 gfx::VideoDecodeAccelerationSupport::Status status = vda_support_->Create( | 295 gfx::VideoDecodeAccelerationSupport::Status status = vda_support_->Create( |
292 config_record_builder_.coded_width(), | 296 config_record_builder_.coded_width(), |
293 config_record_builder_.coded_height(), | 297 config_record_builder_.coded_height(), |
294 kCVPixelFormatType_422YpCbCr8, | 298 kCVPixelFormatType_422YpCbCr8, |
295 &extra_data[0], extra_data.size()); | 299 &extra_data[0], extra_data.size()); |
296 RETURN_ON_FAILURE(status == gfx::VideoDecodeAccelerationSupport::SUCCESS, | 300 RETURN_ON_FAILURE(status == gfx::VideoDecodeAccelerationSupport::SUCCESS, |
297 "Creating video decoder failed with error: " << status, | 301 "Creating video decoder failed with error: " << status, |
298 PLATFORM_FAILURE, false); | 302 PLATFORM_FAILURE, false); |
299 | 303 |
300 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 304 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
301 &MacVideoDecodeAccelerator::RequestPictures, this)); | 305 &MacVideoDecodeAccelerator::RequestPictures, base::AsWeakPtr(this))); |
302 return true; | 306 return true; |
303 } | 307 } |
304 | 308 |
305 void MacVideoDecodeAccelerator::DecodeNALU(const content::H264NALU& nalu, | 309 void MacVideoDecodeAccelerator::DecodeNALU(const content::H264NALU& nalu, |
306 int32 bitstream_buffer_id) { | 310 int32 bitstream_buffer_id) { |
307 // Assume the NALU length field size is 4 bytes. | 311 // Assume the NALU length field size is 4 bytes. |
308 const int kNALULengthFieldSize = 4; | 312 const int kNALULengthFieldSize = 4; |
309 std::vector<uint8_t> data(kNALULengthFieldSize + nalu.size); | 313 std::vector<uint8_t> data(kNALULengthFieldSize + nalu.size); |
310 | 314 |
311 // Store the buffer size at the beginning of the buffer as the decoder | 315 // Store the buffer size at the beginning of the buffer as the decoder |
312 // expects. | 316 // expects. |
313 for (size_t i = 0; i < kNALULengthFieldSize; ++i) { | 317 for (size_t i = 0; i < kNALULengthFieldSize; ++i) { |
314 size_t shift = kNALULengthFieldSize * 8 - (i + 1) * 8; | 318 size_t shift = kNALULengthFieldSize * 8 - (i + 1) * 8; |
315 data[i] = (nalu.size >> shift) & 0xff; | 319 data[i] = (nalu.size >> shift) & 0xff; |
316 } | 320 } |
317 | 321 |
318 // Copy the NALU data. | 322 // Copy the NALU data. |
319 memcpy(&data[kNALULengthFieldSize], nalu.data, nalu.size); | 323 memcpy(&data[kNALULengthFieldSize], nalu.data, nalu.size); |
320 | 324 |
321 // Keep a ref counted copy of the buffer. | 325 // Keep a ref counted copy of the buffer. |
322 scoped_refptr<base::RefCountedBytes> bytes( | 326 scoped_refptr<base::RefCountedBytes> bytes( |
323 base::RefCountedBytes::TakeVector(&data)); | 327 base::RefCountedBytes::TakeVector(&data)); |
324 vda_support_->Decode(bytes->front(), bytes->size(), | 328 vda_support_->Decode(bytes->front(), bytes->size(), base::Bind( |
325 base::Bind(&MacVideoDecodeAccelerator::OnFrameReady, | 329 &MacVideoDecodeAccelerator::OnFrameReady, |
326 this, bitstream_buffer_id, bytes)); | 330 base::AsWeakPtr(this), bitstream_buffer_id, bytes)); |
327 } | 331 } |
328 | 332 |
329 void MacVideoDecodeAccelerator::NotifyInitializeDone() { | 333 void MacVideoDecodeAccelerator::NotifyInitializeDone() { |
330 if (client_) | 334 if (client_) |
331 client_->NotifyInitializeDone(); | 335 client_->NotifyInitializeDone(); |
332 } | 336 } |
333 | 337 |
334 void MacVideoDecodeAccelerator::RequestPictures() { | 338 void MacVideoDecodeAccelerator::RequestPictures() { |
335 if (client_) { | 339 if (client_) { |
336 client_->ProvidePictureBuffers( | 340 client_->ProvidePictureBuffers( |
(...skipping 28 matching lines...) Expand all Loading... | |
365 } | 369 } |
366 | 370 |
367 MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() { | 371 MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() { |
368 } | 372 } |
369 | 373 |
370 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() { | 374 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() { |
371 } | 375 } |
372 | 376 |
373 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() { | 377 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() { |
374 } | 378 } |
OLD | NEW |