OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/trace_event/trace_event.h" |
11 #include "content/common/gpu/gpu_channel.h" | 12 #include "content/common/gpu/gpu_channel.h" |
| 13 #include "content/common/gpu/media/avda_return_on_failure.h" |
12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 14 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
13 #include "media/base/bitstream_buffer.h" | 15 #include "media/base/bitstream_buffer.h" |
14 #include "media/base/limits.h" | 16 #include "media/base/limits.h" |
15 #include "media/base/timestamp_constants.h" | 17 #include "media/base/timestamp_constants.h" |
16 #include "media/base/video_decoder_config.h" | 18 #include "media/base/video_decoder_config.h" |
17 #include "media/video/picture.h" | 19 #include "media/video/picture.h" |
18 #include "ui/gl/android/scoped_java_surface.h" | 20 #include "ui/gl/android/scoped_java_surface.h" |
19 #include "ui/gl/android/surface_texture.h" | 21 #include "ui/gl/android/surface_texture.h" |
20 #include "ui/gl/gl_bindings.h" | 22 #include "ui/gl/gl_bindings.h" |
21 | 23 |
22 namespace content { | 24 namespace content { |
23 | 25 |
24 // Helper macros for dealing with failure. If |result| evaluates false, emit | |
25 // |log| to ERROR, register |error| with the decoder, and return. | |
26 #define RETURN_ON_FAILURE(result, log, error) \ | |
27 do { \ | |
28 if (!(result)) { \ | |
29 DLOG(ERROR) << log; \ | |
30 base::MessageLoop::current()->PostTask( \ | |
31 FROM_HERE, \ | |
32 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, \ | |
33 weak_this_factory_.GetWeakPtr(), \ | |
34 error)); \ | |
35 state_ = ERROR; \ | |
36 return; \ | |
37 } \ | |
38 } while (0) | |
39 | |
40 // TODO(dwkang): We only need kMaxVideoFrames to pass media stack's prerolling | |
41 // phase, but 1 is added due to crbug.com/176036. This should be tuned when we | |
42 // have actual use case. | |
43 enum { kNumPictureBuffers = media::limits::kMaxVideoFrames + 1 }; | |
44 | |
45 // Max number of bitstreams notified to the client with | 26 // Max number of bitstreams notified to the client with |
46 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. | 27 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. |
47 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; | 28 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; |
48 | 29 |
49 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) | 30 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) |
50 // MediaCodec is only guaranteed to support baseline, but some devices may | 31 // MediaCodec is only guaranteed to support baseline, but some devices may |
51 // support others. Advertise support for all H264 profiles and let the | 32 // support others. Advertise support for all H264 profiles and let the |
52 // MediaCodec fail when decoding if it's not actually supported. It's assumed | 33 // MediaCodec fail when decoding if it's not actually supported. It's assumed |
53 // that consumers won't have software fallback for H264 on Android anyway. | 34 // that consumers won't have software fallback for H264 on Android anyway. |
54 static const media::VideoCodecProfile kSupportedH264Profiles[] = { | 35 static const media::VideoCodecProfile kSupportedH264Profiles[] = { |
(...skipping 28 matching lines...) Expand all Loading... |
83 // reasonably device-agnostic way to fill in the "believes" above). | 64 // reasonably device-agnostic way to fill in the "believes" above). |
84 return base::TimeDelta::FromMilliseconds(10); | 65 return base::TimeDelta::FromMilliseconds(10); |
85 } | 66 } |
86 | 67 |
87 static inline const base::TimeDelta NoWaitTimeOut() { | 68 static inline const base::TimeDelta NoWaitTimeOut() { |
88 return base::TimeDelta::FromMicroseconds(0); | 69 return base::TimeDelta::FromMicroseconds(0); |
89 } | 70 } |
90 | 71 |
91 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 72 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
92 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, | 73 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, |
93 const base::Callback<bool(void)>& make_context_current) | 74 const base::Callback<bool(void)>& make_context_current, |
| 75 scoped_ptr<BackingStrategy> strategy) |
94 : client_(NULL), | 76 : client_(NULL), |
95 make_context_current_(make_context_current), | 77 make_context_current_(make_context_current), |
96 codec_(media::kCodecH264), | 78 codec_(media::kCodecH264), |
97 state_(NO_ERROR), | 79 state_(NO_ERROR), |
98 surface_texture_id_(0), | 80 surface_texture_id_(0), |
99 picturebuffers_requested_(false), | 81 picturebuffers_requested_(false), |
100 gl_decoder_(decoder), | 82 gl_decoder_(decoder), |
| 83 strategy_(strategy.Pass()), |
101 weak_this_factory_(this) {} | 84 weak_this_factory_(this) {} |
102 | 85 |
103 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 86 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
104 DCHECK(thread_checker_.CalledOnValidThread()); | 87 DCHECK(thread_checker_.CalledOnValidThread()); |
105 } | 88 } |
106 | 89 |
107 bool AndroidVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, | 90 bool AndroidVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
108 Client* client) { | 91 Client* client) { |
109 DCHECK(!media_codec_); | 92 DCHECK(!media_codec_); |
110 DCHECK(thread_checker_.CalledOnValidThread()); | 93 DCHECK(thread_checker_.CalledOnValidThread()); |
111 TRACE_EVENT0("media", "AVDA::Initialize"); | 94 TRACE_EVENT0("media", "AVDA::Initialize"); |
112 | 95 |
113 client_ = client; | 96 client_ = client; |
114 codec_ = VideoCodecProfileToVideoCodec(profile); | 97 codec_ = VideoCodecProfileToVideoCodec(profile); |
115 | 98 |
| 99 strategy_->SetStateProvider(this); |
| 100 |
116 bool profile_supported = codec_ == media::kCodecVP8; | 101 bool profile_supported = codec_ == media::kCodecVP8; |
117 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) | 102 #if defined(ENABLE_MEDIA_PIPELINE_ON_ANDROID) |
118 profile_supported |= | 103 profile_supported |= |
119 (codec_ == media::kCodecVP9 || codec_ == media::kCodecH264); | 104 (codec_ == media::kCodecVP9 || codec_ == media::kCodecH264); |
120 #endif | 105 #endif |
121 | 106 |
122 if (!profile_supported) { | 107 if (!profile_supported) { |
123 LOG(ERROR) << "Unsupported profile: " << profile; | 108 LOG(ERROR) << "Unsupported profile: " << profile; |
124 return false; | 109 return false; |
125 } | 110 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 188 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
204 pending_bitstream_buffers_.size()); | 189 pending_bitstream_buffers_.size()); |
205 | 190 |
206 if (bitstream_buffer.id() == -1) { | 191 if (bitstream_buffer.id() == -1) { |
207 media_codec_->QueueEOS(input_buf_index); | 192 media_codec_->QueueEOS(input_buf_index); |
208 return; | 193 return; |
209 } | 194 } |
210 | 195 |
211 scoped_ptr<base::SharedMemory> shm( | 196 scoped_ptr<base::SharedMemory> shm( |
212 new base::SharedMemory(bitstream_buffer.handle(), true)); | 197 new base::SharedMemory(bitstream_buffer.handle(), true)); |
213 RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()), | 198 RETURN_ON_FAILURE(this, shm->Map(bitstream_buffer.size()), |
214 "Failed to SharedMemory::Map()", UNREADABLE_INPUT); | 199 "Failed to SharedMemory::Map()", UNREADABLE_INPUT); |
215 | 200 |
216 const base::TimeDelta presentation_timestamp = | 201 const base::TimeDelta presentation_timestamp = |
217 bitstream_buffer.presentation_timestamp(); | 202 bitstream_buffer.presentation_timestamp(); |
218 DCHECK(presentation_timestamp != media::kNoTimestamp()) | 203 DCHECK(presentation_timestamp != media::kNoTimestamp()) |
219 << "Bitstream buffers must have valid presentation timestamps"; | 204 << "Bitstream buffers must have valid presentation timestamps"; |
220 // There may already be a bitstream buffer with this timestamp, e.g., VP9 alt | 205 // There may already be a bitstream buffer with this timestamp, e.g., VP9 alt |
221 // ref frames, but it's OK to overwrite it because we only expect a single | 206 // ref frames, but it's OK to overwrite it because we only expect a single |
222 // output frame to have that timestamp. AVDA clients only use the bitstream | 207 // output frame to have that timestamp. AVDA clients only use the bitstream |
223 // buffer id in the returned Pictures to map a bitstream buffer back to a | 208 // buffer id in the returned Pictures to map a bitstream buffer back to a |
224 // timestamp on their side, so either one of the bitstream buffer ids will | 209 // timestamp on their side, so either one of the bitstream buffer ids will |
225 // result in them finding the right timestamp. | 210 // result in them finding the right timestamp. |
226 bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id(); | 211 bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id(); |
227 | 212 |
228 status = media_codec_->QueueInputBuffer( | 213 status = media_codec_->QueueInputBuffer( |
229 input_buf_index, static_cast<const uint8*>(shm->memory()), | 214 input_buf_index, static_cast<const uint8*>(shm->memory()), |
230 bitstream_buffer.size(), presentation_timestamp); | 215 bitstream_buffer.size(), presentation_timestamp); |
231 RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, | 216 RETURN_ON_FAILURE(this, status == media::MEDIA_CODEC_OK, |
232 "Failed to QueueInputBuffer: " << status, PLATFORM_FAILURE); | 217 "Failed to QueueInputBuffer: " << status, PLATFORM_FAILURE); |
233 | 218 |
234 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output | 219 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output |
235 // will be returned from the bitstream buffer. However, MediaCodec API is | 220 // will be returned from the bitstream buffer. However, MediaCodec API is |
236 // not enough to guarantee it. | 221 // not enough to guarantee it. |
237 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to | 222 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to |
238 // keep getting more bitstreams from the client, and throttle them by using | 223 // keep getting more bitstreams from the client, and throttle them by using |
239 // |bitstreams_notified_in_advance_|. | 224 // |bitstreams_notified_in_advance_|. |
240 // TODO(dwkang): check if there is a way to remove this workaround. | 225 // TODO(dwkang): check if there is a way to remove this workaround. |
241 base::MessageLoop::current()->PostTask( | 226 base::MessageLoop::current()->PostTask( |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 base::MessageLoop::current()->PostTask( | 271 base::MessageLoop::current()->PostTask( |
287 FROM_HERE, | 272 FROM_HERE, |
288 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, | 273 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, |
289 weak_this_factory_.GetWeakPtr())); | 274 weak_this_factory_.GetWeakPtr())); |
290 } else { | 275 } else { |
291 // Dynamic resolution change support is not specified by the Android | 276 // Dynamic resolution change support is not specified by the Android |
292 // platform at and before JB-MR1, so it's not possible to smoothly | 277 // platform at and before JB-MR1, so it's not possible to smoothly |
293 // continue playback at this point. Instead, error out immediately, | 278 // continue playback at this point. Instead, error out immediately, |
294 // expecting clients to Reset() as appropriate to avoid this. | 279 // expecting clients to Reset() as appropriate to avoid this. |
295 // b/7093648 | 280 // b/7093648 |
296 RETURN_ON_FAILURE(size_ == gfx::Size(width, height), | 281 RETURN_ON_FAILURE(this, size_ == gfx::Size(width, height), |
297 "Dynamic resolution change is not supported.", | 282 "Dynamic resolution change is not supported.", |
298 PLATFORM_FAILURE); | 283 PLATFORM_FAILURE); |
299 } | 284 } |
300 return; | 285 return; |
301 } | 286 } |
302 | 287 |
303 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 288 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
304 break; | 289 break; |
305 | 290 |
306 case media::MEDIA_CODEC_OK: | 291 case media::MEDIA_CODEC_OK: |
307 DCHECK_GE(buf_index, 0); | 292 DCHECK_GE(buf_index, 0); |
308 break; | 293 break; |
309 | 294 |
310 default: | 295 default: |
311 NOTREACHED(); | 296 NOTREACHED(); |
312 break; | 297 break; |
313 } | 298 } |
314 } while (buf_index < 0); | 299 } while (buf_index < 0); |
315 | 300 |
316 // This ignores the emitted ByteBuffer and instead relies on rendering to the | |
317 // codec's SurfaceTexture and then copying from that texture to the client's | |
318 // PictureBuffer's texture. This means that each picture's data is written | |
319 // three times: once to the ByteBuffer, once to the SurfaceTexture, and once | |
320 // to the client's texture. It would be nicer to either: | |
321 // 1) Render directly to the client's texture from MediaCodec (one write); or | |
322 // 2) Upload the ByteBuffer to the client's texture (two writes). | |
323 // Unfortunately neither is possible: | |
324 // 1) MediaCodec's use of SurfaceTexture is a singleton, and the texture | |
325 // written to can't change during the codec's lifetime. b/11990461 | |
326 // 2) The ByteBuffer is likely to contain the pixels in a vendor-specific, | |
327 // opaque/non-standard format. It's not possible to negotiate the decoder | |
328 // to emit a specific colorspace, even using HW CSC. b/10706245 | |
329 // So, we live with these two extra copies per picture :( | |
330 { | |
331 TRACE_EVENT0("media", "AVDA::ReleaseOutputBuffer"); | |
332 media_codec_->ReleaseOutputBuffer(buf_index, true); | |
333 } | |
334 | |
335 if (eos) { | 301 if (eos) { |
| 302 media_codec_->ReleaseOutputBuffer(buf_index, false); |
336 base::MessageLoop::current()->PostTask( | 303 base::MessageLoop::current()->PostTask( |
337 FROM_HERE, | 304 FROM_HERE, |
338 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | 305 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, |
339 weak_this_factory_.GetWeakPtr())); | 306 weak_this_factory_.GetWeakPtr())); |
340 } else { | 307 } else { |
341 // Get the bitstream buffer id from the timestamp. | 308 // Get the bitstream buffer id from the timestamp. |
342 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp); | 309 auto it = bitstream_buffers_in_decoder_.find(presentation_timestamp); |
343 // Require the decoder to output at most one frame for each distinct input | 310 // Require the decoder to output at most one frame for each distinct input |
344 // buffer timestamp. A VP9 alt ref frame is a case where an input buffer, | 311 // buffer timestamp. A VP9 alt ref frame is a case where an input buffer, |
345 // with a possibly unique timestamp, will not result in a corresponding | 312 // with a possibly unique timestamp, will not result in a corresponding |
346 // output frame. | 313 // output frame. |
347 CHECK(it != bitstream_buffers_in_decoder_.end()) | 314 CHECK(it != bitstream_buffers_in_decoder_.end()) |
348 << "Unexpected output frame timestamp"; | 315 << "Unexpected output frame timestamp"; |
349 const int32 bitstream_buffer_id = it->second; | 316 const int32 bitstream_buffer_id = it->second; |
350 bitstream_buffers_in_decoder_.erase(bitstream_buffers_in_decoder_.begin(), | 317 bitstream_buffers_in_decoder_.erase(bitstream_buffers_in_decoder_.begin(), |
351 ++it); | 318 ++it); |
352 SendCurrentSurfaceToClient(bitstream_buffer_id); | 319 SendCurrentSurfaceToClient(buf_index, bitstream_buffer_id); |
353 | 320 |
354 // Removes ids former or equal than the id from decoder. Note that | 321 // Removes ids former or equal than the id from decoder. Note that |
355 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder | 322 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder |
356 // because of frame reordering issue. We just maintain this roughly and use | 323 // because of frame reordering issue. We just maintain this roughly and use |
357 // for the throttling purpose. | 324 // for the throttling purpose. |
358 for (auto bitstream_it = bitstreams_notified_in_advance_.begin(); | 325 for (auto bitstream_it = bitstreams_notified_in_advance_.begin(); |
359 bitstream_it != bitstreams_notified_in_advance_.end(); | 326 bitstream_it != bitstreams_notified_in_advance_.end(); |
360 ++bitstream_it) { | 327 ++bitstream_it) { |
361 if (*bitstream_it == bitstream_buffer_id) { | 328 if (*bitstream_it == bitstream_buffer_id) { |
362 bitstreams_notified_in_advance_.erase( | 329 bitstreams_notified_in_advance_.erase( |
363 bitstreams_notified_in_advance_.begin(), ++bitstream_it); | 330 bitstreams_notified_in_advance_.begin(), ++bitstream_it); |
364 break; | 331 break; |
365 } | 332 } |
366 } | 333 } |
367 } | 334 } |
368 } | 335 } |
369 | 336 |
370 void AndroidVideoDecodeAccelerator::SendCurrentSurfaceToClient( | 337 void AndroidVideoDecodeAccelerator::SendCurrentSurfaceToClient( |
| 338 int32 codec_buffer_index, |
371 int32 bitstream_id) { | 339 int32 bitstream_id) { |
372 DCHECK(thread_checker_.CalledOnValidThread()); | 340 DCHECK(thread_checker_.CalledOnValidThread()); |
373 DCHECK_NE(bitstream_id, -1); | 341 DCHECK_NE(bitstream_id, -1); |
374 DCHECK(!free_picture_ids_.empty()); | 342 DCHECK(!free_picture_ids_.empty()); |
375 TRACE_EVENT0("media", "AVDA::SendCurrentSurfaceToClient"); | 343 TRACE_EVENT0("media", "AVDA::SendCurrentSurfaceToClient"); |
376 | 344 |
377 RETURN_ON_FAILURE(make_context_current_.Run(), | 345 RETURN_ON_FAILURE(this, make_context_current_.Run(), |
378 "Failed to make this decoder's GL context current.", | 346 "Failed to make this decoder's GL context current.", |
379 PLATFORM_FAILURE); | 347 PLATFORM_FAILURE); |
380 | 348 |
381 int32 picture_buffer_id = free_picture_ids_.front(); | 349 int32 picture_buffer_id = free_picture_ids_.front(); |
382 free_picture_ids_.pop(); | 350 free_picture_ids_.pop(); |
383 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 351 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
384 | 352 |
385 { | |
386 TRACE_EVENT0("media", "AVDA::UpdateTexImage"); | |
387 surface_texture_->UpdateTexImage(); | |
388 } | |
389 float transfrom_matrix[16]; | |
390 surface_texture_->GetTransformMatrix(transfrom_matrix); | |
391 | |
392 OutputBufferMap::const_iterator i = | 353 OutputBufferMap::const_iterator i = |
393 output_picture_buffers_.find(picture_buffer_id); | 354 output_picture_buffers_.find(picture_buffer_id); |
394 RETURN_ON_FAILURE(i != output_picture_buffers_.end(), | 355 RETURN_ON_FAILURE(this, i != output_picture_buffers_.end(), |
395 "Can't find a PictureBuffer for " << picture_buffer_id, | 356 "Can't find a PictureBuffer for " << picture_buffer_id, |
396 PLATFORM_FAILURE); | 357 PLATFORM_FAILURE); |
397 uint32 picture_buffer_texture_id = i->second.texture_id(); | |
398 | 358 |
399 RETURN_ON_FAILURE(gl_decoder_.get(), | 359 // Connect the PictureBuffer to the decoded frame, via whatever |
400 "Failed to get gles2 decoder instance.", | 360 // mechanism the strategy likes. |
401 ILLEGAL_STATE); | 361 strategy_->AssignCurrentSurfaceToPictureBuffer(codec_buffer_index, i->second); |
402 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is | |
403 // needed because it takes 10s of milliseconds to initialize. | |
404 if (!copier_) { | |
405 copier_.reset(new gpu::CopyTextureCHROMIUMResourceManager()); | |
406 copier_->Initialize(gl_decoder_.get()); | |
407 } | |
408 | |
409 // Here, we copy |surface_texture_id_| to the picture buffer instead of | |
410 // setting new texture to |surface_texture_| by calling attachToGLContext() | |
411 // because: | |
412 // 1. Once we call detachFrameGLContext(), it deletes the texture previous | |
413 // attached. | |
414 // 2. SurfaceTexture requires us to apply a transform matrix when we show | |
415 // the texture. | |
416 // TODO(hkuang): get the StreamTexture transform matrix in GPU process | |
417 // instead of using default matrix crbug.com/226218. | |
418 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, | |
419 0.0f, 1.0f, 0.0f, 0.0f, | |
420 0.0f, 0.0f, 1.0f, 0.0f, | |
421 0.0f, 0.0f, 0.0f, 1.0f}; | |
422 copier_->DoCopyTextureWithTransform(gl_decoder_.get(), | |
423 GL_TEXTURE_EXTERNAL_OES, | |
424 surface_texture_id_, | |
425 picture_buffer_texture_id, | |
426 size_.width(), | |
427 size_.height(), | |
428 false, | |
429 false, | |
430 false, | |
431 default_matrix); | |
432 | 362 |
433 // TODO(henryhsu): Pass (0, 0) as visible size will cause several test | 363 // TODO(henryhsu): Pass (0, 0) as visible size will cause several test |
434 // cases failed. We should make sure |size_| is coded size or visible size. | 364 // cases failed. We should make sure |size_| is coded size or visible size. |
435 base::MessageLoop::current()->PostTask( | 365 base::MessageLoop::current()->PostTask( |
436 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, | 366 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, |
437 weak_this_factory_.GetWeakPtr(), | 367 weak_this_factory_.GetWeakPtr(), |
438 media::Picture(picture_buffer_id, bitstream_id, | 368 media::Picture(picture_buffer_id, bitstream_id, |
439 gfx::Rect(size_), false))); | 369 gfx::Rect(size_), false))); |
440 } | 370 } |
441 | 371 |
442 void AndroidVideoDecodeAccelerator::Decode( | 372 void AndroidVideoDecodeAccelerator::Decode( |
443 const media::BitstreamBuffer& bitstream_buffer) { | 373 const media::BitstreamBuffer& bitstream_buffer) { |
444 DCHECK(thread_checker_.CalledOnValidThread()); | 374 DCHECK(thread_checker_.CalledOnValidThread()); |
445 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { | 375 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { |
446 base::MessageLoop::current()->PostTask( | 376 base::MessageLoop::current()->PostTask( |
447 FROM_HERE, | 377 FROM_HERE, |
448 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 378 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
449 weak_this_factory_.GetWeakPtr(), | 379 weak_this_factory_.GetWeakPtr(), bitstream_buffer.id())); |
450 bitstream_buffer.id())); | |
451 return; | 380 return; |
452 } | 381 } |
453 | 382 |
454 pending_bitstream_buffers_.push( | 383 pending_bitstream_buffers_.push( |
455 std::make_pair(bitstream_buffer, base::Time::Now())); | 384 std::make_pair(bitstream_buffer, base::Time::Now())); |
456 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 385 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
457 pending_bitstream_buffers_.size()); | 386 pending_bitstream_buffers_.size()); |
458 | 387 |
459 DoIOTask(); | 388 DoIOTask(); |
460 } | 389 } |
461 | 390 |
| 391 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { |
| 392 client_->ProvidePictureBuffers(strategy_->GetNumPictureBuffers(), size_, |
| 393 strategy_->GetTextureTarget()); |
| 394 } |
| 395 |
462 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( | 396 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( |
463 const std::vector<media::PictureBuffer>& buffers) { | 397 const std::vector<media::PictureBuffer>& buffers) { |
464 DCHECK(thread_checker_.CalledOnValidThread()); | 398 DCHECK(thread_checker_.CalledOnValidThread()); |
465 DCHECK(output_picture_buffers_.empty()); | 399 DCHECK(output_picture_buffers_.empty()); |
466 DCHECK(free_picture_ids_.empty()); | 400 DCHECK(free_picture_ids_.empty()); |
467 | 401 |
468 for (size_t i = 0; i < buffers.size(); ++i) { | 402 for (size_t i = 0; i < buffers.size(); ++i) { |
469 RETURN_ON_FAILURE(buffers[i].size() == size_, | 403 RETURN_ON_FAILURE(this, buffers[i].size() == size_, |
470 "Invalid picture buffer size was passed.", | 404 "Invalid picture buffer size was passed.", |
471 INVALID_ARGUMENT); | 405 INVALID_ARGUMENT); |
472 int32 id = buffers[i].id(); | 406 int32 id = buffers[i].id(); |
473 output_picture_buffers_.insert(std::make_pair(id, buffers[i])); | 407 output_picture_buffers_.insert(std::make_pair(id, buffers[i])); |
474 free_picture_ids_.push(id); | 408 free_picture_ids_.push(id); |
475 // Since the client might be re-using |picture_buffer_id| values, forget | 409 // Since the client might be re-using |picture_buffer_id| values, forget |
476 // about previously-dismissed IDs now. See ReusePictureBuffer() comment | 410 // about previously-dismissed IDs now. See ReusePictureBuffer() comment |
477 // about "zombies" for why we maintain this set in the first place. | 411 // about "zombies" for why we maintain this set in the first place. |
478 dismissed_picture_ids_.erase(id); | 412 dismissed_picture_ids_.erase(id); |
479 } | 413 } |
480 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 414 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
481 | 415 |
482 RETURN_ON_FAILURE(output_picture_buffers_.size() >= kNumPictureBuffers, | 416 RETURN_ON_FAILURE( |
483 "Invalid picture buffers were passed.", | 417 this, output_picture_buffers_.size() >= strategy_->GetNumPictureBuffers(), |
484 INVALID_ARGUMENT); | 418 "Invalid picture buffers were passed.", INVALID_ARGUMENT); |
485 | 419 |
486 DoIOTask(); | 420 DoIOTask(); |
487 } | 421 } |
488 | 422 |
489 void AndroidVideoDecodeAccelerator::ReusePictureBuffer( | 423 void AndroidVideoDecodeAccelerator::ReusePictureBuffer( |
490 int32 picture_buffer_id) { | 424 int32 picture_buffer_id) { |
491 DCHECK(thread_checker_.CalledOnValidThread()); | 425 DCHECK(thread_checker_.CalledOnValidThread()); |
492 | 426 |
493 // This ReusePictureBuffer() might have been in a pipe somewhere (queued in | 427 // This ReusePictureBuffer() might have been in a pipe somewhere (queued in |
494 // IPC, or in a PostTask either at the sender or receiver) when we sent a | 428 // IPC, or in a PostTask either at the sender or receiver) when we sent a |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 TRACE_EVENT0("media", "AVDA::Reset"); | 469 TRACE_EVENT0("media", "AVDA::Reset"); |
536 | 470 |
537 while (!pending_bitstream_buffers_.empty()) { | 471 while (!pending_bitstream_buffers_.empty()) { |
538 int32 bitstream_buffer_id = pending_bitstream_buffers_.front().first.id(); | 472 int32 bitstream_buffer_id = pending_bitstream_buffers_.front().first.id(); |
539 pending_bitstream_buffers_.pop(); | 473 pending_bitstream_buffers_.pop(); |
540 | 474 |
541 if (bitstream_buffer_id != -1) { | 475 if (bitstream_buffer_id != -1) { |
542 base::MessageLoop::current()->PostTask( | 476 base::MessageLoop::current()->PostTask( |
543 FROM_HERE, | 477 FROM_HERE, |
544 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 478 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
545 weak_this_factory_.GetWeakPtr(), | 479 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); |
546 bitstream_buffer_id)); | |
547 } | 480 } |
548 } | 481 } |
549 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); | 482 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); |
550 bitstreams_notified_in_advance_.clear(); | 483 bitstreams_notified_in_advance_.clear(); |
551 | 484 |
552 for (OutputBufferMap::iterator it = output_picture_buffers_.begin(); | 485 for (OutputBufferMap::iterator it = output_picture_buffers_.begin(); |
553 it != output_picture_buffers_.end(); | 486 it != output_picture_buffers_.end(); |
554 ++it) { | 487 ++it) { |
555 client_->DismissPictureBuffer(it->first); | 488 client_->DismissPictureBuffer(it->first); |
556 dismissed_picture_ids_.insert(it->first); | 489 dismissed_picture_ids_.insert(it->first); |
(...skipping 16 matching lines...) Expand all Loading... |
573 | 506 |
574 base::MessageLoop::current()->PostTask( | 507 base::MessageLoop::current()->PostTask( |
575 FROM_HERE, | 508 FROM_HERE, |
576 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, | 509 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
577 weak_this_factory_.GetWeakPtr())); | 510 weak_this_factory_.GetWeakPtr())); |
578 } | 511 } |
579 | 512 |
580 void AndroidVideoDecodeAccelerator::Destroy() { | 513 void AndroidVideoDecodeAccelerator::Destroy() { |
581 DCHECK(thread_checker_.CalledOnValidThread()); | 514 DCHECK(thread_checker_.CalledOnValidThread()); |
582 | 515 |
| 516 strategy_->Cleanup(); |
| 517 |
583 weak_this_factory_.InvalidateWeakPtrs(); | 518 weak_this_factory_.InvalidateWeakPtrs(); |
584 if (media_codec_) { | 519 if (media_codec_) { |
585 io_timer_.Stop(); | 520 io_timer_.Stop(); |
586 media_codec_->Stop(); | 521 media_codec_->Stop(); |
587 } | 522 } |
588 if (surface_texture_id_) | 523 if (surface_texture_id_) |
589 glDeleteTextures(1, &surface_texture_id_); | 524 glDeleteTextures(1, &surface_texture_id_); |
590 if (copier_) | |
591 copier_->Destroy(); | |
592 delete this; | 525 delete this; |
593 } | 526 } |
594 | 527 |
595 bool AndroidVideoDecodeAccelerator::CanDecodeOnIOThread() { | 528 bool AndroidVideoDecodeAccelerator::CanDecodeOnIOThread() { |
596 return false; | 529 return false; |
597 } | 530 } |
598 | 531 |
599 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { | 532 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { |
600 client_->ProvidePictureBuffers(kNumPictureBuffers, size_, GL_TEXTURE_2D); | 533 return size_; |
| 534 } |
| 535 |
| 536 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() |
| 537 const { |
| 538 return thread_checker_; |
| 539 } |
| 540 |
| 541 gfx::SurfaceTexture* AndroidVideoDecodeAccelerator::GetSurfaceTexture() const { |
| 542 return surface_texture_.get(); |
| 543 } |
| 544 |
| 545 uint32 AndroidVideoDecodeAccelerator::GetSurfaceTextureId() const { |
| 546 return surface_texture_id_; |
| 547 } |
| 548 |
| 549 gpu::gles2::GLES2Decoder* AndroidVideoDecodeAccelerator::GetGlDecoder() const { |
| 550 return gl_decoder_.get(); |
| 551 } |
| 552 |
| 553 media::VideoCodecBridge* AndroidVideoDecodeAccelerator::GetMediaCodec() { |
| 554 return media_codec_.get(); |
| 555 } |
| 556 |
| 557 void AndroidVideoDecodeAccelerator::PostError( |
| 558 const ::tracked_objects::Location& from_here, |
| 559 media::VideoDecodeAccelerator::Error error) { |
| 560 base::MessageLoop::current()->PostTask( |
| 561 from_here, base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, |
| 562 weak_this_factory_.GetWeakPtr(), error)); |
| 563 state_ = ERROR; |
601 } | 564 } |
602 | 565 |
603 void AndroidVideoDecodeAccelerator::NotifyPictureReady( | 566 void AndroidVideoDecodeAccelerator::NotifyPictureReady( |
604 const media::Picture& picture) { | 567 const media::Picture& picture) { |
605 client_->PictureReady(picture); | 568 client_->PictureReady(picture); |
606 } | 569 } |
607 | 570 |
608 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 571 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
609 int input_buffer_id) { | 572 int input_buffer_id) { |
610 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); | 573 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 // software fallback for H264 on Android anyway. | 619 // software fallback for H264 on Android anyway. |
657 profile.max_resolution.SetSize(3840, 2160); | 620 profile.max_resolution.SetSize(3840, 2160); |
658 profiles.push_back(profile); | 621 profiles.push_back(profile); |
659 } | 622 } |
660 #endif | 623 #endif |
661 | 624 |
662 return profiles; | 625 return profiles; |
663 } | 626 } |
664 | 627 |
665 } // namespace content | 628 } // namespace content |
OLD | NEW |