| 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/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 if (!gvd_loop_proxy_->BelongsToCurrentThread() || | 65 if (!gvd_loop_proxy_->BelongsToCurrentThread() || |
| 66 state_ == kDrainingDecoder) { | 66 state_ == kDrainingDecoder) { |
| 67 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 67 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 68 &GpuVideoDecoder::Reset, this, closure)); | 68 &GpuVideoDecoder::Reset, this, closure)); |
| 69 return; | 69 return; |
| 70 } | 70 } |
| 71 | 71 |
| 72 // Throw away any already-decoded, not-yet-delivered frames. | 72 // Throw away any already-decoded, not-yet-delivered frames. |
| 73 ready_video_frames_.clear(); | 73 ready_video_frames_.clear(); |
| 74 | 74 |
| 75 if (!vda_) { | 75 if (!vda_.get()) { |
| 76 closure.Run(); | 76 closure.Run(); |
| 77 return; | 77 return; |
| 78 } | 78 } |
| 79 | 79 |
| 80 DCHECK(pending_reset_cb_.is_null()); | 80 DCHECK(pending_reset_cb_.is_null()); |
| 81 DCHECK(!closure.is_null()); | 81 DCHECK(!closure.is_null()); |
| 82 | 82 |
| 83 // VideoRendererBase::Flush() can't complete while it has a pending read to | 83 // VideoRendererBase::Flush() can't complete while it has a pending read to |
| 84 // us, so we fulfill such a read here. | 84 // us, so we fulfill such a read here. |
| 85 if (!pending_read_cb_.is_null()) | 85 if (!pending_read_cb_.is_null()) |
| 86 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 86 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 87 | 87 |
| 88 if (shutting_down_) { | 88 if (shutting_down_) { |
| 89 // Immediately fire the callback instead of waiting for the reset to | 89 // Immediately fire the callback instead of waiting for the reset to |
| 90 // complete (which will happen after PipelineImpl::Stop() completes). | 90 // complete (which will happen after PipelineImpl::Stop() completes). |
| 91 gvd_loop_proxy_->PostTask(FROM_HERE, closure); | 91 gvd_loop_proxy_->PostTask(FROM_HERE, closure); |
| 92 } else { | 92 } else { |
| 93 pending_reset_cb_ = closure; | 93 pending_reset_cb_ = closure; |
| 94 } | 94 } |
| 95 | 95 |
| 96 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 96 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 97 &VideoDecodeAccelerator::Reset, vda_)); | 97 &VideoDecodeAccelerator::Reset, weak_vda_)); |
| 98 } | 98 } |
| 99 | 99 |
| 100 void GpuVideoDecoder::Stop(const base::Closure& closure) { | 100 void GpuVideoDecoder::Stop(const base::Closure& closure) { |
| 101 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 101 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 102 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 102 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 103 &GpuVideoDecoder::Stop, this, closure)); | 103 &GpuVideoDecoder::Stop, this, closure)); |
| 104 return; | 104 return; |
| 105 } | 105 } |
| 106 if (!vda_) { | 106 if (!vda_.get()) { |
| 107 closure.Run(); | 107 closure.Run(); |
| 108 return; | 108 return; |
| 109 } | 109 } |
| 110 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); |
| 110 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 111 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 111 &VideoDecodeAccelerator::Destroy, vda_)); | 112 &VideoDecodeAccelerator::Destroy, weak_vda_)); |
| 112 vda_ = NULL; | |
| 113 closure.Run(); | 113 closure.Run(); |
| 114 } | 114 } |
| 115 | 115 |
| 116 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, | 116 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, |
| 117 const PipelineStatusCB& orig_status_cb, | 117 const PipelineStatusCB& orig_status_cb, |
| 118 const StatisticsCB& statistics_cb) { | 118 const StatisticsCB& statistics_cb) { |
| 119 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 119 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 120 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 120 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 121 &GpuVideoDecoder::Initialize, | 121 &GpuVideoDecoder::Initialize, |
| 122 this, stream, orig_status_cb, statistics_cb)); | 122 this, stream, orig_status_cb, statistics_cb)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 134 | 134 |
| 135 const VideoDecoderConfig& config = stream->video_decoder_config(); | 135 const VideoDecoderConfig& config = stream->video_decoder_config(); |
| 136 // TODO(scherkus): this check should go in Pipeline prior to creating | 136 // TODO(scherkus): this check should go in Pipeline prior to creating |
| 137 // decoder objects. | 137 // decoder objects. |
| 138 if (!config.IsValidConfig()) { | 138 if (!config.IsValidConfig()) { |
| 139 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); | 139 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); |
| 140 status_cb.Run(PIPELINE_ERROR_DECODE); | 140 status_cb.Run(PIPELINE_ERROR_DECODE); |
| 141 return; | 141 return; |
| 142 } | 142 } |
| 143 | 143 |
| 144 vda_ = factories_->CreateVideoDecodeAccelerator(config.profile(), this); | 144 VideoDecodeAccelerator* vda = |
| 145 if (!vda_) { | 145 factories_->CreateVideoDecodeAccelerator(config.profile(), this); |
| 146 if (!vda) { |
| 146 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 147 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
| 147 return; | 148 return; |
| 148 } | 149 } |
| 149 | 150 |
| 150 demuxer_stream_ = stream; | 151 demuxer_stream_ = stream; |
| 151 statistics_cb_ = statistics_cb; | 152 statistics_cb_ = statistics_cb; |
| 152 | 153 |
| 153 demuxer_stream_->EnableBitstreamConverter(); | 154 demuxer_stream_->EnableBitstreamConverter(); |
| 154 | 155 |
| 155 natural_size_ = config.natural_size(); | 156 natural_size_ = config.natural_size(); |
| 156 config_frame_duration_ = GetFrameDuration(config); | 157 config_frame_duration_ = GetFrameDuration(config); |
| 157 | 158 |
| 158 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; | 159 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; |
| 159 status_cb.Run(PIPELINE_OK); | 160 vda_loop_proxy_->PostTaskAndReply( |
| 161 FROM_HERE, |
| 162 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), |
| 163 base::Bind(status_cb, PIPELINE_OK)); |
| 164 } |
| 165 |
| 166 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { |
| 167 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
| 168 vda_.reset(vda); |
| 169 weak_vda_ = vda->AsWeakPtr(); |
| 160 } | 170 } |
| 161 | 171 |
| 162 void GpuVideoDecoder::Read(const ReadCB& read_cb) { | 172 void GpuVideoDecoder::Read(const ReadCB& read_cb) { |
| 163 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 173 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 164 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 174 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 165 &GpuVideoDecoder::Read, this, read_cb)); | 175 &GpuVideoDecoder::Read, this, read_cb)); |
| 166 return; | 176 return; |
| 167 } | 177 } |
| 168 | 178 |
| 169 if (error_occured_) { | 179 if (error_occured_) { |
| 170 read_cb.Run(kDecodeError, NULL); | 180 read_cb.Run(kDecodeError, NULL); |
| 171 return; | 181 return; |
| 172 } | 182 } |
| 173 | 183 |
| 174 if (!vda_) { | 184 if (!vda_.get()) { |
| 175 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); | 185 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); |
| 176 return; | 186 return; |
| 177 } | 187 } |
| 178 | 188 |
| 179 DCHECK(pending_reset_cb_.is_null()); | 189 DCHECK(pending_reset_cb_.is_null()); |
| 180 DCHECK(pending_read_cb_.is_null()); | 190 DCHECK(pending_read_cb_.is_null()); |
| 181 pending_read_cb_ = read_cb; | 191 pending_read_cb_ = read_cb; |
| 182 | 192 |
| 183 if (!ready_video_frames_.empty()) { | 193 if (!ready_video_frames_.empty()) { |
| 184 EnqueueFrameAndTriggerFrameDelivery(NULL); | 194 EnqueueFrameAndTriggerFrameDelivery(NULL); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 211 if (!buffer) { | 221 if (!buffer) { |
| 212 if (pending_read_cb_.is_null()) | 222 if (pending_read_cb_.is_null()) |
| 213 return; | 223 return; |
| 214 | 224 |
| 215 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 225 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 216 pending_read_cb_, kOk, scoped_refptr<VideoFrame>())); | 226 pending_read_cb_, kOk, scoped_refptr<VideoFrame>())); |
| 217 pending_read_cb_.Reset(); | 227 pending_read_cb_.Reset(); |
| 218 return; | 228 return; |
| 219 } | 229 } |
| 220 | 230 |
| 221 if (!vda_) { | 231 if (!vda_.get()) { |
| 222 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 232 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 223 return; | 233 return; |
| 224 } | 234 } |
| 225 | 235 |
| 226 if (buffer->IsEndOfStream()) { | 236 if (buffer->IsEndOfStream()) { |
| 227 if (state_ == kNormal) { | 237 if (state_ == kNormal) { |
| 228 state_ = kDrainingDecoder; | 238 state_ = kDrainingDecoder; |
| 229 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 239 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 230 &VideoDecodeAccelerator::Flush, vda_)); | 240 &VideoDecodeAccelerator::Flush, weak_vda_)); |
| 231 } | 241 } |
| 232 return; | 242 return; |
| 233 } | 243 } |
| 234 | 244 |
| 235 size_t size = buffer->GetDataSize(); | 245 size_t size = buffer->GetDataSize(); |
| 236 SHMBuffer* shm_buffer = GetSHM(size); | 246 SHMBuffer* shm_buffer = GetSHM(size); |
| 237 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); | 247 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); |
| 238 BitstreamBuffer bitstream_buffer( | 248 BitstreamBuffer bitstream_buffer( |
| 239 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); | 249 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); |
| 240 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( | 250 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( |
| 241 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; | 251 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
| 242 DCHECK(inserted); | 252 DCHECK(inserted); |
| 243 RecordBufferTimeData(bitstream_buffer, *buffer); | 253 RecordBufferTimeData(bitstream_buffer, *buffer); |
| 244 | 254 |
| 245 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 255 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 246 &VideoDecodeAccelerator::Decode, vda_, bitstream_buffer)); | 256 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer)); |
| 247 } | 257 } |
| 248 | 258 |
| 249 void GpuVideoDecoder::RecordBufferTimeData( | 259 void GpuVideoDecoder::RecordBufferTimeData( |
| 250 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { | 260 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { |
| 251 base::TimeDelta duration = buffer.GetDuration(); | 261 base::TimeDelta duration = buffer.GetDuration(); |
| 252 if (duration == base::TimeDelta()) | 262 if (duration == base::TimeDelta()) |
| 253 duration = config_frame_duration_; | 263 duration = config_frame_duration_; |
| 254 input_buffer_time_data_.push_front(BufferTimeData( | 264 input_buffer_time_data_.push_front(BufferTimeData( |
| 255 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); | 265 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); |
| 256 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but | 266 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 } | 322 } |
| 313 | 323 |
| 314 std::vector<uint32> texture_ids; | 324 std::vector<uint32> texture_ids; |
| 315 decoder_texture_target_ = texture_target; | 325 decoder_texture_target_ = texture_target; |
| 316 if (!factories_->CreateTextures( | 326 if (!factories_->CreateTextures( |
| 317 count, size, &texture_ids, decoder_texture_target_)) { | 327 count, size, &texture_ids, decoder_texture_target_)) { |
| 318 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 328 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 319 return; | 329 return; |
| 320 } | 330 } |
| 321 | 331 |
| 322 if (!vda_) | 332 if (!vda_.get()) |
| 323 return; | 333 return; |
| 324 | 334 |
| 325 std::vector<PictureBuffer> picture_buffers; | 335 std::vector<PictureBuffer> picture_buffers; |
| 326 for (size_t i = 0; i < texture_ids.size(); ++i) { | 336 for (size_t i = 0; i < texture_ids.size(); ++i) { |
| 327 picture_buffers.push_back(PictureBuffer( | 337 picture_buffers.push_back(PictureBuffer( |
| 328 next_picture_buffer_id_++, size, texture_ids[i])); | 338 next_picture_buffer_id_++, size, texture_ids[i])); |
| 329 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( | 339 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( |
| 330 picture_buffers.back().id(), picture_buffers.back())).second; | 340 picture_buffers.back().id(), picture_buffers.back())).second; |
| 331 DCHECK(inserted); | 341 DCHECK(inserted); |
| 332 } | 342 } |
| 333 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 343 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 334 &VideoDecodeAccelerator::AssignPictureBuffers, vda_, picture_buffers)); | 344 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, |
| 345 picture_buffers)); |
| 335 } | 346 } |
| 336 | 347 |
| 337 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 348 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
| 338 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 349 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 339 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 350 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 340 &GpuVideoDecoder::DismissPictureBuffer, this, id)); | 351 &GpuVideoDecoder::DismissPictureBuffer, this, id)); |
| 341 return; | 352 return; |
| 342 } | 353 } |
| 343 std::map<int32, PictureBuffer>::iterator it = | 354 std::map<int32, PictureBuffer>::iterator it = |
| 344 picture_buffers_in_decoder_.find(id); | 355 picture_buffers_in_decoder_.find(id); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 pending_read_cb_.Reset(); | 413 pending_read_cb_.Reset(); |
| 403 ready_video_frames_.pop_front(); | 414 ready_video_frames_.pop_front(); |
| 404 } | 415 } |
| 405 | 416 |
| 406 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { | 417 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { |
| 407 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 418 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 408 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 419 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 409 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); | 420 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); |
| 410 return; | 421 return; |
| 411 } | 422 } |
| 412 if (!vda_) | 423 if (!vda_.get()) |
| 413 return; | 424 return; |
| 414 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 425 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 415 &VideoDecodeAccelerator::ReusePictureBuffer, vda_, picture_buffer_id)); | 426 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, |
| 427 picture_buffer_id)); |
| 416 } | 428 } |
| 417 | 429 |
| 418 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { | 430 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { |
| 419 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 431 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 420 if (available_shm_segments_.empty() || | 432 if (available_shm_segments_.empty() || |
| 421 available_shm_segments_.back()->size < min_size) { | 433 available_shm_segments_.back()->size < min_size) { |
| 422 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 434 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
| 423 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); | 435 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); |
| 424 DCHECK(shm); | 436 DCHECK(shm); |
| 425 return new SHMBuffer(shm, size_to_allocate); | 437 return new SHMBuffer(shm, size_to_allocate); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 | 472 |
| 461 if (!pending_read_cb_.is_null() && pending_reset_cb_.is_null() && | 473 if (!pending_read_cb_.is_null() && pending_reset_cb_.is_null() && |
| 462 state_ != kDrainingDecoder && | 474 state_ != kDrainingDecoder && |
| 463 bitstream_buffers_in_decoder_.empty()) { | 475 bitstream_buffers_in_decoder_.empty()) { |
| 464 DCHECK(ready_video_frames_.empty()); | 476 DCHECK(ready_video_frames_.empty()); |
| 465 EnsureDemuxOrDecode(); | 477 EnsureDemuxOrDecode(); |
| 466 } | 478 } |
| 467 } | 479 } |
| 468 | 480 |
| 469 GpuVideoDecoder::~GpuVideoDecoder() { | 481 GpuVideoDecoder::~GpuVideoDecoder() { |
| 470 DCHECK(!vda_); // Stop should have been already called. | 482 DCHECK(!vda_.get()); // Stop should have been already called. |
| 471 DCHECK(pending_read_cb_.is_null()); | 483 DCHECK(pending_read_cb_.is_null()); |
| 472 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { | 484 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
| 473 available_shm_segments_[i]->shm->Close(); | 485 available_shm_segments_[i]->shm->Close(); |
| 474 delete available_shm_segments_[i]; | 486 delete available_shm_segments_[i]; |
| 475 } | 487 } |
| 476 available_shm_segments_.clear(); | 488 available_shm_segments_.clear(); |
| 477 for (std::map<int32, BufferPair>::iterator it = | 489 for (std::map<int32, BufferPair>::iterator it = |
| 478 bitstream_buffers_in_decoder_.begin(); | 490 bitstream_buffers_in_decoder_.begin(); |
| 479 it != bitstream_buffers_in_decoder_.end(); ++it) { | 491 it != bitstream_buffers_in_decoder_.end(); ++it) { |
| 480 it->second.shm_buffer->shm->Close(); | 492 it->second.shm_buffer->shm->Close(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 503 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 515 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 504 } | 516 } |
| 505 | 517 |
| 506 void GpuVideoDecoder::NotifyResetDone() { | 518 void GpuVideoDecoder::NotifyResetDone() { |
| 507 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 519 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 508 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 520 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 509 &GpuVideoDecoder::NotifyResetDone, this)); | 521 &GpuVideoDecoder::NotifyResetDone, this)); |
| 510 return; | 522 return; |
| 511 } | 523 } |
| 512 | 524 |
| 513 if (!vda_) | 525 if (!vda_.get()) |
| 514 return; | 526 return; |
| 515 | 527 |
| 516 DCHECK(ready_video_frames_.empty()); | 528 DCHECK(ready_video_frames_.empty()); |
| 517 | 529 |
| 518 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 530 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
| 519 // delivered during the reset can find their time data. | 531 // delivered during the reset can find their time data. |
| 520 input_buffer_time_data_.clear(); | 532 input_buffer_time_data_.clear(); |
| 521 | 533 |
| 522 if (!pending_reset_cb_.is_null()) | 534 if (!pending_reset_cb_.is_null()) |
| 523 base::ResetAndReturn(&pending_reset_cb_).Run(); | 535 base::ResetAndReturn(&pending_reset_cb_).Run(); |
| 524 | 536 |
| 525 if (!pending_read_cb_.is_null()) | 537 if (!pending_read_cb_.is_null()) |
| 526 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 538 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 527 } | 539 } |
| 528 | 540 |
| 529 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 541 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
| 530 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 542 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 531 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 543 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 532 &GpuVideoDecoder::NotifyError, this, error)); | 544 &GpuVideoDecoder::NotifyError, this, error)); |
| 533 return; | 545 return; |
| 534 } | 546 } |
| 535 if (!vda_) | 547 if (!vda_.get()) |
| 536 return; | 548 return; |
| 537 vda_ = NULL; | 549 vda_loop_proxy_->DeleteSoon(FROM_HERE, vda_.release()); |
| 538 DLOG(ERROR) << "VDA Error: " << error; | 550 DLOG(ERROR) << "VDA Error: " << error; |
| 539 | 551 |
| 540 error_occured_ = true; | 552 error_occured_ = true; |
| 541 | 553 |
| 542 if (!pending_read_cb_.is_null()) { | 554 if (!pending_read_cb_.is_null()) { |
| 543 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 555 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
| 544 return; | 556 return; |
| 545 } | 557 } |
| 546 } | 558 } |
| 547 | 559 |
| 548 } // namespace media | 560 } // namespace media |
| OLD | NEW |