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