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