Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/cpu.h" | 9 #include "base/cpu.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/task_runner_util.h" | |
| 12 #include "media/base/bind_to_loop.h" | 13 #include "media/base/bind_to_loop.h" |
| 13 #include "media/base/decoder_buffer.h" | 14 #include "media/base/decoder_buffer.h" |
| 14 #include "media/base/demuxer_stream.h" | 15 #include "media/base/demuxer_stream.h" |
| 15 #include "media/base/pipeline.h" | 16 #include "media/base/pipeline.h" |
| 16 #include "media/base/pipeline_status.h" | 17 #include "media/base/pipeline_status.h" |
| 17 #include "media/base/video_decoder_config.h" | 18 #include "media/base/video_decoder_config.h" |
| 18 | 19 |
| 19 namespace media { | 20 namespace media { |
| 20 | 21 |
| 21 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. | 22 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 47 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), | 48 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), |
| 48 natural_size(ns) { | 49 natural_size(ns) { |
| 49 } | 50 } |
| 50 | 51 |
| 51 GpuVideoDecoder::BufferData::~BufferData() {} | 52 GpuVideoDecoder::BufferData::~BufferData() {} |
| 52 | 53 |
| 53 GpuVideoDecoder::GpuVideoDecoder( | 54 GpuVideoDecoder::GpuVideoDecoder( |
| 54 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 55 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
| 55 const scoped_refptr<Factories>& factories) | 56 const scoped_refptr<Factories>& factories) |
| 56 : gvd_loop_proxy_(message_loop), | 57 : gvd_loop_proxy_(message_loop), |
| 58 weak_factory_(this), | |
| 57 vda_loop_proxy_(factories->GetMessageLoop()), | 59 vda_loop_proxy_(factories->GetMessageLoop()), |
| 58 factories_(factories), | 60 factories_(factories), |
| 59 state_(kNormal), | 61 state_(kNormal), |
| 60 demuxer_read_in_progress_(false), | 62 demuxer_read_in_progress_(false), |
| 61 decoder_texture_target_(0), | 63 decoder_texture_target_(0), |
| 62 next_picture_buffer_id_(0), | 64 next_picture_buffer_id_(0), |
| 63 next_bitstream_buffer_id_(0), | 65 next_bitstream_buffer_id_(0), |
| 64 error_occured_(false), | 66 error_occured_(false), |
| 65 available_pictures_(-1) { | 67 available_pictures_(-1) { |
| 66 DCHECK(factories_); | 68 DCHECK(factories_); |
| 67 } | 69 } |
| 68 | 70 |
| 69 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 71 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
| 70 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 72 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 71 | 73 |
| 72 if (state_ == kDrainingDecoder) { | 74 if (state_ == kDrainingDecoder) { |
| 73 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 75 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 74 &GpuVideoDecoder::Reset, this, closure)); | 76 &GpuVideoDecoder::Reset, weak_this_, closure)); |
| 75 // NOTE: if we're deferring Reset() until a Flush() completes, return | 77 // NOTE: if we're deferring Reset() until a Flush() completes, return |
| 76 // queued pictures to the VDA so they can be used to finish that Flush(). | 78 // queued pictures to the VDA so they can be used to finish that Flush(). |
| 77 if (pending_read_cb_.is_null()) | 79 if (pending_read_cb_.is_null()) |
| 78 ready_video_frames_.clear(); | 80 ready_video_frames_.clear(); |
| 79 return; | 81 return; |
| 80 } | 82 } |
| 81 | 83 |
| 82 // Throw away any already-decoded, not-yet-delivered frames. | 84 // Throw away any already-decoded, not-yet-delivered frames. |
| 83 ready_video_frames_.clear(); | 85 ready_video_frames_.clear(); |
| 84 | 86 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 103 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 105 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 104 if (vda_.get()) | 106 if (vda_.get()) |
| 105 DestroyVDA(); | 107 DestroyVDA(); |
| 106 BindToCurrentLoop(closure).Run(); | 108 BindToCurrentLoop(closure).Run(); |
| 107 } | 109 } |
| 108 | 110 |
| 109 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, | 111 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, |
| 110 const PipelineStatusCB& orig_status_cb, | 112 const PipelineStatusCB& orig_status_cb, |
| 111 const StatisticsCB& statistics_cb) { | 113 const StatisticsCB& statistics_cb) { |
| 112 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 114 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 115 weak_this_ = weak_factory_.GetWeakPtr(); | |
| 116 | |
| 113 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( | 117 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( |
| 114 "Media.GpuVideoDecoderInitializeStatus", | 118 "Media.GpuVideoDecoderInitializeStatus", |
| 115 BindToCurrentLoop(orig_status_cb)); | 119 BindToCurrentLoop(orig_status_cb)); |
| 116 DCHECK(!demuxer_stream_); | 120 DCHECK(!demuxer_stream_); |
| 117 | 121 |
| 118 if (!stream) { | 122 if (!stream) { |
| 119 status_cb.Run(PIPELINE_ERROR_DECODE); | 123 status_cb.Run(PIPELINE_ERROR_DECODE); |
| 120 return; | 124 return; |
| 121 } | 125 } |
| 122 | 126 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 return; | 158 return; |
| 155 } | 159 } |
| 156 | 160 |
| 157 if (config.codec() == kCodecH264) | 161 if (config.codec() == kCodecH264) |
| 158 stream->EnableBitstreamConverter(); | 162 stream->EnableBitstreamConverter(); |
| 159 | 163 |
| 160 demuxer_stream_ = stream; | 164 demuxer_stream_ = stream; |
| 161 statistics_cb_ = statistics_cb; | 165 statistics_cb_ = statistics_cb; |
| 162 | 166 |
| 163 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; | 167 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; |
| 164 vda_loop_proxy_->PostTaskAndReply( | 168 PostTaskAndReplyWithResult( |
| 165 FROM_HERE, | 169 vda_loop_proxy_, FROM_HERE, |
| 166 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), | 170 base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)), |
| 167 base::Bind(status_cb, PIPELINE_OK)); | 171 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda)); |
| 168 } | 172 } |
| 169 | 173 |
| 170 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { | 174 void GpuVideoDecoder::SetVDA( |
| 171 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 175 const PipelineStatusCB& status_cb, |
| 176 VideoDecodeAccelerator* vda, | |
| 177 base::WeakPtr<VideoDecodeAccelerator> weak_vda) { | |
| 178 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | |
| 172 DCHECK(!vda_.get()); | 179 DCHECK(!vda_.get()); |
| 173 vda_.reset(vda); | 180 vda_.reset(vda); |
| 174 weak_vda_ = vda->AsWeakPtr(); | 181 weak_vda_ = weak_vda; |
| 182 status_cb.Run(PIPELINE_OK); | |
| 175 } | 183 } |
| 176 | 184 |
| 177 void GpuVideoDecoder::DestroyTextures() { | 185 void GpuVideoDecoder::DestroyTextures() { |
| 178 for (std::map<int32, PictureBuffer>::iterator it = | 186 for (std::map<int32, PictureBuffer>::iterator it = |
| 179 picture_buffers_in_decoder_.begin(); | 187 picture_buffers_in_decoder_.begin(); |
| 180 it != picture_buffers_in_decoder_.end(); ++it) { | 188 it != picture_buffers_in_decoder_.end(); ++it) { |
| 181 factories_->DeleteTexture(it->second.texture_id()); | 189 factories_->DeleteTexture(it->second.texture_id()); |
| 182 } | 190 } |
| 183 picture_buffers_in_decoder_.clear(); | 191 picture_buffers_in_decoder_.clear(); |
| 184 } | 192 } |
| 185 | 193 |
| 186 void GpuVideoDecoder::DestroyVDA() { | 194 void GpuVideoDecoder::DestroyVDA() { |
| 187 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 195 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 188 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); | 196 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); |
| 189 // Tricky: |this| needs to stay alive until after VDA::Destroy is actually | 197 |
| 190 // called, not just posted, so we take an artificial ref to |this| and release | 198 // Note: I don't think it's possible to guarantee that VDA *won't* call us |
|
scherkus (not reviewing)
2013/03/28 02:00:01
FYI
It's a bit late in the day, but I'm not sure
Ami GONE FROM CHROMIUM
2013/03/29 23:55:19
Yes, this is the key point of this CL :)
Today GVD
scherkus (not reviewing)
2013/04/05 01:18:30
I'd prefer to not mess around w/ transferring owne
| |
| 191 // it as |reply| after VDA::Destroy() returns. | 199 // after GVD has been destroyed. |
| 192 AddRef(); | 200 // |
| 193 vda_loop_proxy_->PostTaskAndReply( | 201 // Example: |
| 194 FROM_HERE, | 202 // * VDA runs on render thread |
| 195 base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_), | 203 // * WMPI is blocking render thread on Stop() |
| 196 base::Bind(&GpuVideoDecoder::Release, this)); | 204 // * GVD receives Stop() on media thread |
| 205 // * GVD posts VDA::Destroy() to render thread | |
| 206 // * GVD completes Stop() and WMPI becomes unblocked | |
| 207 // * WMPI + GVD are destroyed | |
| 208 // * VDA executes pending work on GVD on render thread | |
| 209 // * -- boom -- | |
| 210 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | |
| 211 &VideoDecodeAccelerator::Destroy, weak_vda_)); | |
| 197 | 212 |
| 198 DestroyTextures(); | 213 DestroyTextures(); |
| 199 } | 214 } |
| 200 | 215 |
| 201 void GpuVideoDecoder::Read(const ReadCB& read_cb) { | 216 void GpuVideoDecoder::Read(const ReadCB& read_cb) { |
| 202 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 217 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 203 DCHECK(pending_reset_cb_.is_null()); | 218 DCHECK(pending_reset_cb_.is_null()); |
| 204 DCHECK(pending_read_cb_.is_null()); | 219 DCHECK(pending_read_cb_.is_null()); |
| 205 pending_read_cb_ = BindToCurrentLoop(read_cb); | 220 pending_read_cb_ = BindToCurrentLoop(read_cb); |
| 206 | 221 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; | 253 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; |
| 239 } | 254 } |
| 240 | 255 |
| 241 void GpuVideoDecoder::RequestBufferDecode( | 256 void GpuVideoDecoder::RequestBufferDecode( |
| 242 DemuxerStream::Status status, | 257 DemuxerStream::Status status, |
| 243 const scoped_refptr<DecoderBuffer>& buffer) { | 258 const scoped_refptr<DecoderBuffer>& buffer) { |
| 244 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; | 259 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; |
| 245 | 260 |
| 246 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 261 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 247 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 262 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 248 &GpuVideoDecoder::RequestBufferDecode, this, status, buffer)); | 263 &GpuVideoDecoder::RequestBufferDecode, weak_this_, status, buffer)); |
| 249 return; | 264 return; |
| 250 } | 265 } |
| 251 demuxer_read_in_progress_ = false; | 266 demuxer_read_in_progress_ = false; |
| 252 | 267 |
| 253 if (status != DemuxerStream::kOk) { | 268 if (status != DemuxerStream::kOk) { |
| 254 if (pending_read_cb_.is_null()) | 269 if (pending_read_cb_.is_null()) |
| 255 return; | 270 return; |
| 256 | 271 |
| 257 // TODO(acolwell): Add support for reinitializing the decoder when | 272 // TODO(acolwell): Add support for reinitializing the decoder when |
| 258 // |status| == kConfigChanged. For now we just trigger a decode error. | 273 // |status| == kConfigChanged. For now we just trigger a decode error. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 344 | 359 |
| 345 void GpuVideoDecoder::NotifyInitializeDone() { | 360 void GpuVideoDecoder::NotifyInitializeDone() { |
| 346 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; | 361 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; |
| 347 } | 362 } |
| 348 | 363 |
| 349 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, | 364 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, |
| 350 const gfx::Size& size, | 365 const gfx::Size& size, |
| 351 uint32 texture_target) { | 366 uint32 texture_target) { |
| 352 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 367 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 353 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 368 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 354 &GpuVideoDecoder::ProvidePictureBuffers, this, count, size, | 369 &GpuVideoDecoder::ProvidePictureBuffers, weak_this_, count, size, |
| 355 texture_target)); | 370 texture_target)); |
| 356 return; | 371 return; |
| 357 } | 372 } |
| 358 | 373 |
| 359 std::vector<uint32> texture_ids; | 374 std::vector<uint32> texture_ids; |
| 360 decoder_texture_target_ = texture_target; | 375 decoder_texture_target_ = texture_target; |
| 361 if (!factories_->CreateTextures( | 376 if (!factories_->CreateTextures( |
| 362 count, size, &texture_ids, decoder_texture_target_)) { | 377 count, size, &texture_ids, decoder_texture_target_)) { |
| 363 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 378 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 364 return; | 379 return; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 379 DCHECK(inserted); | 394 DCHECK(inserted); |
| 380 } | 395 } |
| 381 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 396 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 382 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, | 397 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, |
| 383 picture_buffers)); | 398 picture_buffers)); |
| 384 } | 399 } |
| 385 | 400 |
| 386 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 401 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
| 387 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 402 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 388 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 403 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 389 &GpuVideoDecoder::DismissPictureBuffer, this, id)); | 404 &GpuVideoDecoder::DismissPictureBuffer, weak_this_, id)); |
| 390 return; | 405 return; |
| 391 } | 406 } |
| 392 std::map<int32, PictureBuffer>::iterator it = | 407 std::map<int32, PictureBuffer>::iterator it = |
| 393 picture_buffers_in_decoder_.find(id); | 408 picture_buffers_in_decoder_.find(id); |
| 394 if (it == picture_buffers_in_decoder_.end()) { | 409 if (it == picture_buffers_in_decoder_.end()) { |
| 395 NOTREACHED() << "Missing picture buffer: " << id; | 410 NOTREACHED() << "Missing picture buffer: " << id; |
| 396 return; | 411 return; |
| 397 } | 412 } |
| 398 factories_->DeleteTexture(it->second.texture_id()); | 413 factories_->DeleteTexture(it->second.texture_id()); |
| 399 picture_buffers_in_decoder_.erase(it); | 414 picture_buffers_in_decoder_.erase(it); |
| 400 } | 415 } |
| 401 | 416 |
| 402 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { | 417 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { |
| 403 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 418 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 404 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 419 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 405 &GpuVideoDecoder::PictureReady, this, picture)); | 420 &GpuVideoDecoder::PictureReady, weak_this_, picture)); |
| 406 return; | 421 return; |
| 407 } | 422 } |
| 408 std::map<int32, PictureBuffer>::iterator it = | 423 std::map<int32, PictureBuffer>::iterator it = |
| 409 picture_buffers_in_decoder_.find(picture.picture_buffer_id()); | 424 picture_buffers_in_decoder_.find(picture.picture_buffer_id()); |
| 410 if (it == picture_buffers_in_decoder_.end()) { | 425 if (it == picture_buffers_in_decoder_.end()) { |
| 411 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); | 426 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); |
| 412 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 427 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 413 return; | 428 return; |
| 414 } | 429 } |
| 415 const PictureBuffer& pb = it->second; | 430 const PictureBuffer& pb = it->second; |
| 416 | 431 |
| 417 // Update frame's timestamp. | 432 // Update frame's timestamp. |
| 418 base::TimeDelta timestamp; | 433 base::TimeDelta timestamp; |
| 419 gfx::Rect visible_rect; | 434 gfx::Rect visible_rect; |
| 420 gfx::Size natural_size; | 435 gfx::Size natural_size; |
| 421 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, | 436 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, |
| 422 &natural_size); | 437 &natural_size); |
| 423 DCHECK(decoder_texture_target_); | 438 DCHECK(decoder_texture_target_); |
| 424 scoped_refptr<VideoFrame> frame( | 439 scoped_refptr<VideoFrame> frame( |
| 425 VideoFrame::WrapNativeTexture( | 440 VideoFrame::WrapNativeTexture( |
| 426 pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect, | 441 pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect, |
| 427 natural_size, timestamp, | 442 natural_size, timestamp, |
| 428 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), | 443 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), |
| 429 decoder_texture_target_, | 444 decoder_texture_target_, |
| 430 gfx::Size(visible_rect.width(), visible_rect.height())), | 445 gfx::Size(visible_rect.width(), visible_rect.height())), |
| 431 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, | 446 BindToCurrentLoop(base::Bind( |
| 432 picture.picture_buffer_id()))); | 447 &GpuVideoDecoder::ReusePictureBuffer, weak_this_, |
| 448 picture.picture_buffer_id())))); | |
| 433 CHECK_GT(available_pictures_, 0); | 449 CHECK_GT(available_pictures_, 0); |
| 434 available_pictures_--; | 450 available_pictures_--; |
| 435 | 451 |
| 436 EnqueueFrameAndTriggerFrameDelivery(frame); | 452 EnqueueFrameAndTriggerFrameDelivery(frame); |
| 437 } | 453 } |
| 438 | 454 |
| 439 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 455 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
| 440 const scoped_refptr<VideoFrame>& frame) { | 456 const scoped_refptr<VideoFrame>& frame) { |
| 441 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 457 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 442 | 458 |
| 443 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the | 459 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the |
| 444 // floor and return. | 460 // floor and return. |
| 445 if (!pending_reset_cb_.is_null()) | 461 if (!pending_reset_cb_.is_null()) |
| 446 return; | 462 return; |
| 447 | 463 |
| 448 if (frame) | 464 if (frame) |
| 449 ready_video_frames_.push_back(frame); | 465 ready_video_frames_.push_back(frame); |
| 450 else | 466 else |
| 451 DCHECK(!ready_video_frames_.empty()); | 467 DCHECK(!ready_video_frames_.empty()); |
| 452 | 468 |
| 453 if (pending_read_cb_.is_null()) | 469 if (pending_read_cb_.is_null()) |
| 454 return; | 470 return; |
| 455 | 471 |
| 456 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); | 472 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); |
| 457 ready_video_frames_.pop_front(); | 473 ready_video_frames_.pop_front(); |
| 458 } | 474 } |
| 459 | 475 |
| 460 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { | 476 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { |
| 461 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 477 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 462 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | |
| 463 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); | |
| 464 return; | |
| 465 } | |
| 466 CHECK_GE(available_pictures_, 0); | 478 CHECK_GE(available_pictures_, 0); |
| 467 available_pictures_++; | 479 available_pictures_++; |
| 468 | 480 |
| 469 if (!vda_.get()) | 481 if (!vda_.get()) |
| 470 return; | 482 return; |
| 471 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 483 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 472 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, | 484 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, |
| 473 picture_buffer_id)); | 485 picture_buffer_id)); |
| 474 } | 486 } |
| 475 | 487 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 488 } | 500 } |
| 489 | 501 |
| 490 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { | 502 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { |
| 491 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 503 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 492 available_shm_segments_.push_back(shm_buffer); | 504 available_shm_segments_.push_back(shm_buffer); |
| 493 } | 505 } |
| 494 | 506 |
| 495 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { | 507 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
| 496 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 508 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 497 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 509 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 498 &GpuVideoDecoder::NotifyEndOfBitstreamBuffer, this, id)); | 510 &GpuVideoDecoder::NotifyEndOfBitstreamBuffer, weak_this_, id)); |
| 499 return; | 511 return; |
| 500 } | 512 } |
| 501 | 513 |
| 502 std::map<int32, BufferPair>::iterator it = | 514 std::map<int32, BufferPair>::iterator it = |
| 503 bitstream_buffers_in_decoder_.find(id); | 515 bitstream_buffers_in_decoder_.find(id); |
| 504 if (it == bitstream_buffers_in_decoder_.end()) { | 516 if (it == bitstream_buffers_in_decoder_.end()) { |
| 505 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 517 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 506 NOTREACHED() << "Missing bitstream buffer: " << id; | 518 NOTREACHED() << "Missing bitstream buffer: " << id; |
| 507 return; | 519 return; |
| 508 } | 520 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 DestroyTextures(); | 552 DestroyTextures(); |
| 541 } | 553 } |
| 542 | 554 |
| 543 void GpuVideoDecoder::EnsureDemuxOrDecode() { | 555 void GpuVideoDecoder::EnsureDemuxOrDecode() { |
| 544 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 556 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 545 if (demuxer_read_in_progress_) | 557 if (demuxer_read_in_progress_) |
| 546 return; | 558 return; |
| 547 demuxer_read_in_progress_ = true; | 559 demuxer_read_in_progress_ = true; |
| 548 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 560 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 549 &DemuxerStream::Read, demuxer_stream_.get(), | 561 &DemuxerStream::Read, demuxer_stream_.get(), |
| 550 base::Bind(&GpuVideoDecoder::RequestBufferDecode, this))); | 562 base::Bind(&GpuVideoDecoder::RequestBufferDecode, weak_this_))); |
| 551 } | 563 } |
| 552 | 564 |
| 553 void GpuVideoDecoder::NotifyFlushDone() { | 565 void GpuVideoDecoder::NotifyFlushDone() { |
| 554 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 566 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 555 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 567 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 556 &GpuVideoDecoder::NotifyFlushDone, this)); | 568 &GpuVideoDecoder::NotifyFlushDone, weak_this_)); |
| 557 return; | 569 return; |
| 558 } | 570 } |
| 559 DCHECK_EQ(state_, kDrainingDecoder); | 571 DCHECK_EQ(state_, kDrainingDecoder); |
| 560 state_ = kDecoderDrained; | 572 state_ = kDecoderDrained; |
| 561 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 573 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 562 } | 574 } |
| 563 | 575 |
| 564 void GpuVideoDecoder::NotifyResetDone() { | 576 void GpuVideoDecoder::NotifyResetDone() { |
| 565 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 577 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 566 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 578 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 567 &GpuVideoDecoder::NotifyResetDone, this)); | 579 &GpuVideoDecoder::NotifyResetDone, weak_this_)); |
| 568 return; | 580 return; |
| 569 } | 581 } |
| 570 | 582 |
| 571 if (!vda_.get()) | 583 if (!vda_.get()) |
| 572 return; | 584 return; |
| 573 | 585 |
| 574 DCHECK(ready_video_frames_.empty()); | 586 DCHECK(ready_video_frames_.empty()); |
| 575 | 587 |
| 576 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 588 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
| 577 // delivered during the reset can find their time data. | 589 // delivered during the reset can find their time data. |
| 578 input_buffer_data_.clear(); | 590 input_buffer_data_.clear(); |
| 579 | 591 |
| 580 if (!pending_reset_cb_.is_null()) | 592 if (!pending_reset_cb_.is_null()) |
| 581 base::ResetAndReturn(&pending_reset_cb_).Run(); | 593 base::ResetAndReturn(&pending_reset_cb_).Run(); |
| 582 | 594 |
| 583 if (!pending_read_cb_.is_null()) | 595 if (!pending_read_cb_.is_null()) |
| 584 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 596 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 585 } | 597 } |
| 586 | 598 |
| 587 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 599 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
| 588 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 600 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 589 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 601 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 590 &GpuVideoDecoder::NotifyError, this, error)); | 602 &GpuVideoDecoder::NotifyError, weak_this_, error)); |
| 591 return; | 603 return; |
| 592 } | 604 } |
| 593 if (!vda_.get()) | 605 if (!vda_.get()) |
| 594 return; | 606 return; |
| 595 | 607 |
| 596 DLOG(ERROR) << "VDA Error: " << error; | 608 DLOG(ERROR) << "VDA Error: " << error; |
| 597 DestroyVDA(); | 609 DestroyVDA(); |
| 598 | 610 |
| 599 error_occured_ = true; | 611 error_occured_ = true; |
| 600 | 612 |
| 601 if (!pending_read_cb_.is_null()) { | 613 if (!pending_read_cb_.is_null()) { |
| 602 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 614 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
| 603 return; | 615 return; |
| 604 } | 616 } |
| 605 } | 617 } |
| 606 | 618 |
| 607 } // namespace media | 619 } // namespace media |
| OLD | NEW |