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 "content/common/gpu/gpu_channel.h" | 11 #include "content/common/gpu/gpu_channel.h" |
12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
13 #include "media/base/bitstream_buffer.h" | 13 #include "media/base/bitstream_buffer.h" |
14 #include "media/base/limits.h" | 14 #include "media/base/limits.h" |
15 #include "media/video/picture.h" | 15 #include "media/video/picture.h" |
16 #include "ui/gl/android/scoped_java_surface.h" | 16 #include "ui/gl/android/scoped_java_surface.h" |
17 #include "ui/gl/android/surface_texture.h" | 17 #include "ui/gl/android/surface_texture.h" |
18 #include "ui/gl/gl_bindings.h" | 18 #include "ui/gl/gl_bindings.h" |
19 | 19 |
20 namespace content { | 20 namespace content { |
21 | 21 |
22 // Helper macros for dealing with failure. If |result| evaluates false, emit | 22 // Helper macros for dealing with failure. If |result| evaluates false, emit |
23 // |log| to ERROR, register |error| with the decoder, and return. | 23 // |log| to ERROR, register |error| with the decoder, and return. |
24 #define RETURN_ON_FAILURE(result, log, error) \ | 24 #define RETURN_ON_FAILURE(result, log, error) \ |
25 do { \ | 25 do { \ |
26 if (!(result)) { \ | 26 if (!(result)) { \ |
27 DLOG(ERROR) << log; \ | 27 DLOG(ERROR) << log; \ |
28 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( \ | 28 base::MessageLoop::current()->PostTask( \ |
29 &AndroidVideoDecodeAccelerator::NotifyError, \ | 29 FROM_HERE, \ |
30 base::AsWeakPtr(this), error)); \ | 30 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, \ |
31 state_ = ERROR; \ | 31 weak_this_factory_.GetWeakPtr(), \ |
32 return; \ | 32 error)); \ |
33 } \ | 33 state_ = ERROR; \ |
| 34 return; \ |
| 35 } \ |
34 } while (0) | 36 } while (0) |
35 | 37 |
36 // TODO(dwkang): We only need kMaxVideoFrames to pass media stack's prerolling | 38 // TODO(dwkang): We only need kMaxVideoFrames to pass media stack's prerolling |
37 // phase, but 1 is added due to crbug.com/176036. This should be tuned when we | 39 // phase, but 1 is added due to crbug.com/176036. This should be tuned when we |
38 // have actual use case. | 40 // have actual use case. |
39 enum { kNumPictureBuffers = media::limits::kMaxVideoFrames + 1 }; | 41 enum { kNumPictureBuffers = media::limits::kMaxVideoFrames + 1 }; |
40 | 42 |
41 // Max number of bitstreams notified to the client with | 43 // Max number of bitstreams notified to the client with |
42 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. | 44 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. |
43 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; | 45 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; |
(...skipping 22 matching lines...) Expand all Loading... |
66 | 68 |
67 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 69 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
68 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, | 70 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, |
69 const base::Callback<bool(void)>& make_context_current) | 71 const base::Callback<bool(void)>& make_context_current) |
70 : client_(NULL), | 72 : client_(NULL), |
71 make_context_current_(make_context_current), | 73 make_context_current_(make_context_current), |
72 codec_(media::kCodecH264), | 74 codec_(media::kCodecH264), |
73 state_(NO_ERROR), | 75 state_(NO_ERROR), |
74 surface_texture_id_(0), | 76 surface_texture_id_(0), |
75 picturebuffers_requested_(false), | 77 picturebuffers_requested_(false), |
76 gl_decoder_(decoder) {} | 78 gl_decoder_(decoder), |
| 79 weak_this_factory_(this) {} |
77 | 80 |
78 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 81 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
79 DCHECK(thread_checker_.CalledOnValidThread()); | 82 DCHECK(thread_checker_.CalledOnValidThread()); |
80 } | 83 } |
81 | 84 |
82 bool AndroidVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, | 85 bool AndroidVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
83 Client* client) { | 86 Client* client) { |
84 DCHECK(!media_codec_); | 87 DCHECK(!media_codec_); |
85 DCHECK(thread_checker_.CalledOnValidThread()); | 88 DCHECK(thread_checker_.CalledOnValidThread()); |
86 | 89 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 gl_decoder_->RestoreTextureUnitBindings(0); | 128 gl_decoder_->RestoreTextureUnitBindings(0); |
126 gl_decoder_->RestoreActiveTexture(); | 129 gl_decoder_->RestoreActiveTexture(); |
127 | 130 |
128 surface_texture_ = new gfx::SurfaceTexture(surface_texture_id_); | 131 surface_texture_ = new gfx::SurfaceTexture(surface_texture_id_); |
129 | 132 |
130 if (!ConfigureMediaCodec()) { | 133 if (!ConfigureMediaCodec()) { |
131 LOG(ERROR) << "Failed to create MediaCodec instance."; | 134 LOG(ERROR) << "Failed to create MediaCodec instance."; |
132 return false; | 135 return false; |
133 } | 136 } |
134 | 137 |
135 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
136 &AndroidVideoDecodeAccelerator::NotifyInitializeDone, | |
137 base::AsWeakPtr(this))); | |
138 return true; | 138 return true; |
139 } | 139 } |
140 | 140 |
141 void AndroidVideoDecodeAccelerator::DoIOTask() { | 141 void AndroidVideoDecodeAccelerator::DoIOTask() { |
| 142 DCHECK(thread_checker_.CalledOnValidThread()); |
142 if (state_ == ERROR) { | 143 if (state_ == ERROR) { |
143 return; | 144 return; |
144 } | 145 } |
145 | 146 |
146 QueueInput(); | 147 QueueInput(); |
147 DequeueOutput(); | 148 DequeueOutput(); |
148 } | 149 } |
149 | 150 |
150 void AndroidVideoDecodeAccelerator::QueueInput() { | 151 void AndroidVideoDecodeAccelerator::QueueInput() { |
| 152 DCHECK(thread_checker_.CalledOnValidThread()); |
151 if (bitstreams_notified_in_advance_.size() > kMaxBitstreamsNotifiedInAdvance) | 153 if (bitstreams_notified_in_advance_.size() > kMaxBitstreamsNotifiedInAdvance) |
152 return; | 154 return; |
153 if (pending_bitstream_buffers_.empty()) | 155 if (pending_bitstream_buffers_.empty()) |
154 return; | 156 return; |
155 | 157 |
156 int input_buf_index = 0; | 158 int input_buf_index = 0; |
157 media::MediaCodecStatus status = media_codec_->DequeueInputBuffer( | 159 media::MediaCodecStatus status = media_codec_->DequeueInputBuffer( |
158 NoWaitTimeOut(), &input_buf_index); | 160 NoWaitTimeOut(), &input_buf_index); |
159 if (status != media::MEDIA_CODEC_OK) { | 161 if (status != media::MEDIA_CODEC_OK) { |
160 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || | 162 DCHECK(status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER || |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 "Failed to QueueInputBuffer: " << status, | 198 "Failed to QueueInputBuffer: " << status, |
197 PLATFORM_FAILURE); | 199 PLATFORM_FAILURE); |
198 | 200 |
199 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output | 201 // We should call NotifyEndOfBitstreamBuffer(), when no more decoded output |
200 // will be returned from the bitstream buffer. However, MediaCodec API is | 202 // will be returned from the bitstream buffer. However, MediaCodec API is |
201 // not enough to guarantee it. | 203 // not enough to guarantee it. |
202 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to | 204 // So, here, we calls NotifyEndOfBitstreamBuffer() in advance in order to |
203 // keep getting more bitstreams from the client, and throttle them by using | 205 // keep getting more bitstreams from the client, and throttle them by using |
204 // |bitstreams_notified_in_advance_|. | 206 // |bitstreams_notified_in_advance_|. |
205 // TODO(dwkang): check if there is a way to remove this workaround. | 207 // TODO(dwkang): check if there is a way to remove this workaround. |
206 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 208 base::MessageLoop::current()->PostTask( |
207 &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 209 FROM_HERE, |
208 base::AsWeakPtr(this), bitstream_buffer.id())); | 210 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
| 211 weak_this_factory_.GetWeakPtr(), |
| 212 bitstream_buffer.id())); |
209 bitstreams_notified_in_advance_.push_back(bitstream_buffer.id()); | 213 bitstreams_notified_in_advance_.push_back(bitstream_buffer.id()); |
210 } | 214 } |
211 | 215 |
212 void AndroidVideoDecodeAccelerator::DequeueOutput() { | 216 void AndroidVideoDecodeAccelerator::DequeueOutput() { |
| 217 DCHECK(thread_checker_.CalledOnValidThread()); |
213 if (picturebuffers_requested_ && output_picture_buffers_.empty()) | 218 if (picturebuffers_requested_ && output_picture_buffers_.empty()) |
214 return; | 219 return; |
215 | 220 |
216 if (!output_picture_buffers_.empty() && free_picture_ids_.empty()) { | 221 if (!output_picture_buffers_.empty() && free_picture_ids_.empty()) { |
217 // Don't have any picture buffer to send. Need to wait more. | 222 // Don't have any picture buffer to send. Need to wait more. |
218 return; | 223 return; |
219 } | 224 } |
220 | 225 |
221 bool eos = false; | 226 bool eos = false; |
222 base::TimeDelta timestamp; | 227 base::TimeDelta timestamp; |
223 int32 buf_index = 0; | 228 int32 buf_index = 0; |
224 do { | 229 do { |
225 size_t offset = 0; | 230 size_t offset = 0; |
226 size_t size = 0; | 231 size_t size = 0; |
227 | 232 |
228 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 233 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
229 NoWaitTimeOut(), &buf_index, &offset, &size, ×tamp, &eos, NULL); | 234 NoWaitTimeOut(), &buf_index, &offset, &size, ×tamp, &eos, NULL); |
230 switch (status) { | 235 switch (status) { |
231 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 236 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
232 case media::MEDIA_CODEC_ERROR: | 237 case media::MEDIA_CODEC_ERROR: |
233 return; | 238 return; |
234 | 239 |
235 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { | 240 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { |
236 int32 width, height; | 241 int32 width, height; |
237 media_codec_->GetOutputFormat(&width, &height); | 242 media_codec_->GetOutputFormat(&width, &height); |
238 | 243 |
239 if (!picturebuffers_requested_) { | 244 if (!picturebuffers_requested_) { |
240 picturebuffers_requested_ = true; | 245 picturebuffers_requested_ = true; |
241 size_ = gfx::Size(width, height); | 246 size_ = gfx::Size(width, height); |
242 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 247 base::MessageLoop::current()->PostTask( |
243 &AndroidVideoDecodeAccelerator::RequestPictureBuffers, | 248 FROM_HERE, |
244 base::AsWeakPtr(this))); | 249 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, |
| 250 weak_this_factory_.GetWeakPtr())); |
245 } else { | 251 } else { |
246 // Dynamic resolution change support is not specified by the Android | 252 // Dynamic resolution change support is not specified by the Android |
247 // platform at and before JB-MR1, so it's not possible to smoothly | 253 // platform at and before JB-MR1, so it's not possible to smoothly |
248 // continue playback at this point. Instead, error out immediately, | 254 // continue playback at this point. Instead, error out immediately, |
249 // expecting clients to Reset() as appropriate to avoid this. | 255 // expecting clients to Reset() as appropriate to avoid this. |
250 // b/7093648 | 256 // b/7093648 |
251 RETURN_ON_FAILURE(size_ == gfx::Size(width, height), | 257 RETURN_ON_FAILURE(size_ == gfx::Size(width, height), |
252 "Dynamic resolution change is not supported.", | 258 "Dynamic resolution change is not supported.", |
253 PLATFORM_FAILURE); | 259 PLATFORM_FAILURE); |
254 } | 260 } |
(...skipping 26 matching lines...) Expand all Loading... |
281 // Unfortunately neither is possible: | 287 // Unfortunately neither is possible: |
282 // 1) MediaCodec's use of SurfaceTexture is a singleton, and the texture | 288 // 1) MediaCodec's use of SurfaceTexture is a singleton, and the texture |
283 // written to can't change during the codec's lifetime. b/11990461 | 289 // written to can't change during the codec's lifetime. b/11990461 |
284 // 2) The ByteBuffer is likely to contain the pixels in a vendor-specific, | 290 // 2) The ByteBuffer is likely to contain the pixels in a vendor-specific, |
285 // opaque/non-standard format. It's not possible to negotiate the decoder | 291 // opaque/non-standard format. It's not possible to negotiate the decoder |
286 // to emit a specific colorspace, even using HW CSC. b/10706245 | 292 // to emit a specific colorspace, even using HW CSC. b/10706245 |
287 // So, we live with these two extra copies per picture :( | 293 // So, we live with these two extra copies per picture :( |
288 media_codec_->ReleaseOutputBuffer(buf_index, true); | 294 media_codec_->ReleaseOutputBuffer(buf_index, true); |
289 | 295 |
290 if (eos) { | 296 if (eos) { |
291 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 297 base::MessageLoop::current()->PostTask( |
292 &AndroidVideoDecodeAccelerator::NotifyFlushDone, | 298 FROM_HERE, |
293 base::AsWeakPtr(this))); | 299 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, |
| 300 weak_this_factory_.GetWeakPtr())); |
294 } else { | 301 } else { |
295 int64 bitstream_buffer_id = timestamp.InMicroseconds(); | 302 int64 bitstream_buffer_id = timestamp.InMicroseconds(); |
296 SendCurrentSurfaceToClient(static_cast<int32>(bitstream_buffer_id)); | 303 SendCurrentSurfaceToClient(static_cast<int32>(bitstream_buffer_id)); |
297 | 304 |
298 // Removes ids former or equal than the id from decoder. Note that | 305 // Removes ids former or equal than the id from decoder. Note that |
299 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder | 306 // |bitstreams_notified_in_advance_| does not mean bitstream ids in decoder |
300 // because of frame reordering issue. We just maintain this roughly and use | 307 // because of frame reordering issue. We just maintain this roughly and use |
301 // for the throttling purpose. | 308 // for the throttling purpose. |
302 std::list<int32>::iterator it; | 309 std::list<int32>::iterator it; |
303 for (it = bitstreams_notified_in_advance_.begin(); | 310 for (it = bitstreams_notified_in_advance_.begin(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 // because: | 358 // because: |
352 // 1. Once we call detachFrameGLContext(), it deletes the texture previous | 359 // 1. Once we call detachFrameGLContext(), it deletes the texture previous |
353 // attached. | 360 // attached. |
354 // 2. SurfaceTexture requires us to apply a transform matrix when we show | 361 // 2. SurfaceTexture requires us to apply a transform matrix when we show |
355 // the texture. | 362 // the texture. |
356 copier_->DoCopyTexture(gl_decoder_.get(), GL_TEXTURE_EXTERNAL_OES, | 363 copier_->DoCopyTexture(gl_decoder_.get(), GL_TEXTURE_EXTERNAL_OES, |
357 GL_TEXTURE_2D, surface_texture_id_, | 364 GL_TEXTURE_2D, surface_texture_id_, |
358 picture_buffer_texture_id, 0, size_.width(), | 365 picture_buffer_texture_id, 0, size_.width(), |
359 size_.height(), false, false, false); | 366 size_.height(), false, false, false); |
360 | 367 |
361 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 368 base::MessageLoop::current()->PostTask( |
362 &AndroidVideoDecodeAccelerator::NotifyPictureReady, | 369 FROM_HERE, |
363 base::AsWeakPtr(this), media::Picture(picture_buffer_id, bitstream_id))); | 370 base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, |
| 371 weak_this_factory_.GetWeakPtr(), |
| 372 media::Picture(picture_buffer_id, bitstream_id))); |
364 } | 373 } |
365 | 374 |
366 void AndroidVideoDecodeAccelerator::Decode( | 375 void AndroidVideoDecodeAccelerator::Decode( |
367 const media::BitstreamBuffer& bitstream_buffer) { | 376 const media::BitstreamBuffer& bitstream_buffer) { |
368 DCHECK(thread_checker_.CalledOnValidThread()); | 377 DCHECK(thread_checker_.CalledOnValidThread()); |
369 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { | 378 if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) { |
370 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 379 base::MessageLoop::current()->PostTask( |
371 &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 380 FROM_HERE, |
372 base::AsWeakPtr(this), bitstream_buffer.id())); | 381 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
| 382 weak_this_factory_.GetWeakPtr(), |
| 383 bitstream_buffer.id())); |
373 return; | 384 return; |
374 } | 385 } |
375 | 386 |
376 pending_bitstream_buffers_.push( | 387 pending_bitstream_buffers_.push( |
377 std::make_pair(bitstream_buffer, base::Time::Now())); | 388 std::make_pair(bitstream_buffer, base::Time::Now())); |
378 | 389 |
379 DoIOTask(); | 390 DoIOTask(); |
380 } | 391 } |
381 | 392 |
382 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( | 393 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 DoIOTask(); | 432 DoIOTask(); |
422 } | 433 } |
423 | 434 |
424 void AndroidVideoDecodeAccelerator::Flush() { | 435 void AndroidVideoDecodeAccelerator::Flush() { |
425 DCHECK(thread_checker_.CalledOnValidThread()); | 436 DCHECK(thread_checker_.CalledOnValidThread()); |
426 | 437 |
427 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | 438 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); |
428 } | 439 } |
429 | 440 |
430 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { | 441 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() { |
| 442 DCHECK(thread_checker_.CalledOnValidThread()); |
431 DCHECK(surface_texture_.get()); | 443 DCHECK(surface_texture_.get()); |
432 | 444 |
433 gfx::ScopedJavaSurface surface(surface_texture_.get()); | 445 gfx::ScopedJavaSurface surface(surface_texture_.get()); |
434 | 446 |
435 // Pass a dummy 320x240 canvas size and let the codec signal the real size | 447 // Pass a dummy 320x240 canvas size and let the codec signal the real size |
436 // when it's known from the bitstream. | 448 // when it's known from the bitstream. |
437 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( | 449 media_codec_.reset(media::VideoCodecBridge::CreateDecoder( |
438 codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), NULL)); | 450 codec_, false, gfx::Size(320, 240), surface.j_surface().obj(), NULL)); |
439 if (!media_codec_) | 451 if (!media_codec_) |
440 return false; | 452 return false; |
441 | 453 |
442 io_timer_.Start(FROM_HERE, | 454 io_timer_.Start(FROM_HERE, |
443 DecodePollDelay(), | 455 DecodePollDelay(), |
444 this, | 456 this, |
445 &AndroidVideoDecodeAccelerator::DoIOTask); | 457 &AndroidVideoDecodeAccelerator::DoIOTask); |
446 return true; | 458 return true; |
447 } | 459 } |
448 | 460 |
449 void AndroidVideoDecodeAccelerator::Reset() { | 461 void AndroidVideoDecodeAccelerator::Reset() { |
450 DCHECK(thread_checker_.CalledOnValidThread()); | 462 DCHECK(thread_checker_.CalledOnValidThread()); |
451 | 463 |
452 while (!pending_bitstream_buffers_.empty()) { | 464 while (!pending_bitstream_buffers_.empty()) { |
453 int32 bitstream_buffer_id = pending_bitstream_buffers_.front().first.id(); | 465 int32 bitstream_buffer_id = pending_bitstream_buffers_.front().first.id(); |
454 pending_bitstream_buffers_.pop(); | 466 pending_bitstream_buffers_.pop(); |
455 | 467 |
456 if (bitstream_buffer_id != -1) { | 468 if (bitstream_buffer_id != -1) { |
457 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 469 base::MessageLoop::current()->PostTask( |
458 &AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 470 FROM_HERE, |
459 base::AsWeakPtr(this), bitstream_buffer_id)); | 471 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
| 472 weak_this_factory_.GetWeakPtr(), |
| 473 bitstream_buffer_id)); |
460 } | 474 } |
461 } | 475 } |
462 bitstreams_notified_in_advance_.clear(); | 476 bitstreams_notified_in_advance_.clear(); |
463 | 477 |
464 for (OutputBufferMap::iterator it = output_picture_buffers_.begin(); | 478 for (OutputBufferMap::iterator it = output_picture_buffers_.begin(); |
465 it != output_picture_buffers_.end(); | 479 it != output_picture_buffers_.end(); |
466 ++it) { | 480 ++it) { |
467 client_->DismissPictureBuffer(it->first); | 481 client_->DismissPictureBuffer(it->first); |
468 dismissed_picture_ids_.insert(it->first); | 482 dismissed_picture_ids_.insert(it->first); |
469 } | 483 } |
470 output_picture_buffers_.clear(); | 484 output_picture_buffers_.clear(); |
471 std::queue<int32> empty; | 485 std::queue<int32> empty; |
472 std::swap(free_picture_ids_, empty); | 486 std::swap(free_picture_ids_, empty); |
473 CHECK(free_picture_ids_.empty()); | 487 CHECK(free_picture_ids_.empty()); |
474 picturebuffers_requested_ = false; | 488 picturebuffers_requested_ = false; |
475 | 489 |
476 // On some devices, and up to at least JB-MR1, | 490 // On some devices, and up to at least JB-MR1, |
477 // - flush() can fail after EOS (b/8125974); and | 491 // - flush() can fail after EOS (b/8125974); and |
478 // - mid-stream resolution change is unsupported (b/7093648). | 492 // - mid-stream resolution change is unsupported (b/7093648). |
479 // To cope with these facts, we always stop & restart the codec on Reset(). | 493 // To cope with these facts, we always stop & restart the codec on Reset(). |
480 io_timer_.Stop(); | 494 io_timer_.Stop(); |
481 media_codec_->Stop(); | 495 media_codec_->Stop(); |
482 ConfigureMediaCodec(); | 496 ConfigureMediaCodec(); |
483 state_ = NO_ERROR; | 497 state_ = NO_ERROR; |
484 | 498 |
485 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 499 base::MessageLoop::current()->PostTask( |
486 &AndroidVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this))); | 500 FROM_HERE, |
| 501 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
| 502 weak_this_factory_.GetWeakPtr())); |
487 } | 503 } |
488 | 504 |
489 void AndroidVideoDecodeAccelerator::Destroy() { | 505 void AndroidVideoDecodeAccelerator::Destroy() { |
490 DCHECK(thread_checker_.CalledOnValidThread()); | 506 DCHECK(thread_checker_.CalledOnValidThread()); |
491 | 507 |
| 508 weak_this_factory_.InvalidateWeakPtrs(); |
492 if (media_codec_) { | 509 if (media_codec_) { |
493 io_timer_.Stop(); | 510 io_timer_.Stop(); |
494 media_codec_->Stop(); | 511 media_codec_->Stop(); |
495 } | 512 } |
496 if (surface_texture_id_) | 513 if (surface_texture_id_) |
497 glDeleteTextures(1, &surface_texture_id_); | 514 glDeleteTextures(1, &surface_texture_id_); |
498 if (copier_) | 515 if (copier_) |
499 copier_->Destroy(); | 516 copier_->Destroy(); |
500 delete this; | 517 delete this; |
501 } | 518 } |
502 | 519 |
503 void AndroidVideoDecodeAccelerator::NotifyInitializeDone() { | |
504 client_->NotifyInitializeDone(); | |
505 } | |
506 | |
507 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { | 520 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { |
508 client_->ProvidePictureBuffers(kNumPictureBuffers, size_, GL_TEXTURE_2D); | 521 client_->ProvidePictureBuffers(kNumPictureBuffers, size_, GL_TEXTURE_2D); |
509 } | 522 } |
510 | 523 |
511 void AndroidVideoDecodeAccelerator::NotifyPictureReady( | 524 void AndroidVideoDecodeAccelerator::NotifyPictureReady( |
512 const media::Picture& picture) { | 525 const media::Picture& picture) { |
513 client_->PictureReady(picture); | 526 client_->PictureReady(picture); |
514 } | 527 } |
515 | 528 |
516 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 529 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
517 int input_buffer_id) { | 530 int input_buffer_id) { |
518 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); | 531 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); |
519 } | 532 } |
520 | 533 |
521 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { | 534 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { |
522 client_->NotifyFlushDone(); | 535 client_->NotifyFlushDone(); |
523 } | 536 } |
524 | 537 |
525 void AndroidVideoDecodeAccelerator::NotifyResetDone() { | 538 void AndroidVideoDecodeAccelerator::NotifyResetDone() { |
526 client_->NotifyResetDone(); | 539 client_->NotifyResetDone(); |
527 } | 540 } |
528 | 541 |
529 void AndroidVideoDecodeAccelerator::NotifyError( | 542 void AndroidVideoDecodeAccelerator::NotifyError( |
530 media::VideoDecodeAccelerator::Error error) { | 543 media::VideoDecodeAccelerator::Error error) { |
531 client_->NotifyError(error); | 544 client_->NotifyError(error); |
532 } | 545 } |
533 | 546 |
534 } // namespace content | 547 } // namespace content |
OLD | NEW |