| 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 |