| 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/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "media/base/demuxer_stream.h" | 10 #include "media/base/demuxer_stream.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 GpuVideoDecoder::BufferTimeData::BufferTimeData( | 36 GpuVideoDecoder::BufferTimeData::BufferTimeData( |
| 37 int32 bbid, base::TimeDelta ts, base::TimeDelta dur) | 37 int32 bbid, base::TimeDelta ts, base::TimeDelta dur) |
| 38 : bitstream_buffer_id(bbid), timestamp(ts), duration(dur) { | 38 : bitstream_buffer_id(bbid), timestamp(ts), duration(dur) { |
| 39 } | 39 } |
| 40 | 40 |
| 41 GpuVideoDecoder::BufferTimeData::~BufferTimeData() {} | 41 GpuVideoDecoder::BufferTimeData::~BufferTimeData() {} |
| 42 | 42 |
| 43 GpuVideoDecoder::GpuVideoDecoder( | 43 GpuVideoDecoder::GpuVideoDecoder( |
| 44 MessageLoop* message_loop, | 44 MessageLoop* message_loop, |
| 45 MessageLoop* vda_loop, |
| 45 const scoped_refptr<Factories>& factories) | 46 const scoped_refptr<Factories>& factories) |
| 46 : gvd_loop_proxy_(message_loop->message_loop_proxy()), | 47 : gvd_loop_proxy_(message_loop->message_loop_proxy()), |
| 47 render_loop_proxy_(base::MessageLoopProxy::current()), | 48 vda_loop_proxy_(vda_loop->message_loop_proxy()), |
| 48 factories_(factories), | 49 factories_(factories), |
| 49 state_(kNormal), | 50 state_(kNormal), |
| 50 demuxer_read_in_progress_(false), | 51 demuxer_read_in_progress_(false), |
| 51 decoder_texture_target_(0), | 52 decoder_texture_target_(0), |
| 52 next_picture_buffer_id_(0), | 53 next_picture_buffer_id_(0), |
| 53 next_bitstream_buffer_id_(0), | 54 next_bitstream_buffer_id_(0), |
| 54 shutting_down_(false) { | 55 shutting_down_(false) { |
| 55 DCHECK(gvd_loop_proxy_ && factories_); | 56 DCHECK(gvd_loop_proxy_ && factories_); |
| 56 } | 57 } |
| 57 | 58 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 74 void GpuVideoDecoder::Stop(const base::Closure& callback) { | 75 void GpuVideoDecoder::Stop(const base::Closure& callback) { |
| 75 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 76 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 76 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 77 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 77 &GpuVideoDecoder::Stop, this, callback)); | 78 &GpuVideoDecoder::Stop, this, callback)); |
| 78 return; | 79 return; |
| 79 } | 80 } |
| 80 if (!vda_) { | 81 if (!vda_) { |
| 81 callback.Run(); | 82 callback.Run(); |
| 82 return; | 83 return; |
| 83 } | 84 } |
| 84 render_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 85 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 85 &VideoDecodeAccelerator::Destroy, vda_)); | 86 &VideoDecodeAccelerator::Destroy, vda_)); |
| 86 vda_ = NULL; | 87 vda_ = NULL; |
| 87 callback.Run(); | 88 callback.Run(); |
| 88 } | 89 } |
| 89 | 90 |
| 90 void GpuVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 91 void GpuVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
| 91 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 92 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 92 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 93 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 93 &GpuVideoDecoder::Seek, this, time, cb)); | 94 &GpuVideoDecoder::Seek, this, time, cb)); |
| 94 return; | 95 return; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 // us, so we fulfill such a read here. | 130 // us, so we fulfill such a read here. |
| 130 if (!pending_read_cb_.is_null()) | 131 if (!pending_read_cb_.is_null()) |
| 131 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 132 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 132 // Immediate fire the callback instead of waiting for the reset to complete | 133 // Immediate fire the callback instead of waiting for the reset to complete |
| 133 // (which will happen after PipelineImpl::Stop() completes). | 134 // (which will happen after PipelineImpl::Stop() completes). |
| 134 callback.Run(); | 135 callback.Run(); |
| 135 } else { | 136 } else { |
| 136 pending_reset_cb_ = callback; | 137 pending_reset_cb_ = callback; |
| 137 } | 138 } |
| 138 | 139 |
| 139 render_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 140 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 140 &VideoDecodeAccelerator::Reset, vda_)); | 141 &VideoDecodeAccelerator::Reset, vda_)); |
| 141 } | 142 } |
| 142 | 143 |
| 143 void GpuVideoDecoder::Initialize(DemuxerStream* demuxer_stream, | 144 void GpuVideoDecoder::Initialize(DemuxerStream* demuxer_stream, |
| 144 const PipelineStatusCB& callback, | 145 const PipelineStatusCB& callback, |
| 145 const StatisticsCallback& stats_callback) { | 146 const StatisticsCallback& stats_callback) { |
| 146 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 147 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 147 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 148 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 148 &GpuVideoDecoder::Initialize, this, | 149 &GpuVideoDecoder::Initialize, this, |
| 149 make_scoped_refptr(demuxer_stream), callback, stats_callback)); | 150 make_scoped_refptr(demuxer_stream), callback, stats_callback)); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 } | 238 } |
| 238 | 239 |
| 239 if (!vda_) { | 240 if (!vda_) { |
| 240 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 241 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 241 return; | 242 return; |
| 242 } | 243 } |
| 243 | 244 |
| 244 if (buffer->IsEndOfStream()) { | 245 if (buffer->IsEndOfStream()) { |
| 245 if (state_ == kNormal) { | 246 if (state_ == kNormal) { |
| 246 state_ = kDrainingDecoder; | 247 state_ = kDrainingDecoder; |
| 247 render_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 248 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 248 &VideoDecodeAccelerator::Flush, vda_)); | 249 &VideoDecodeAccelerator::Flush, vda_)); |
| 249 } | 250 } |
| 250 return; | 251 return; |
| 251 } | 252 } |
| 252 | 253 |
| 253 size_t size = buffer->GetDataSize(); | 254 size_t size = buffer->GetDataSize(); |
| 254 SHMBuffer* shm_buffer = GetSHM(size); | 255 SHMBuffer* shm_buffer = GetSHM(size); |
| 255 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); | 256 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); |
| 256 BitstreamBuffer bitstream_buffer( | 257 BitstreamBuffer bitstream_buffer( |
| 257 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); | 258 next_bitstream_buffer_id_++, shm_buffer->shm->handle(), size); |
| 258 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( | 259 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( |
| 259 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; | 260 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
| 260 DCHECK(inserted); | 261 DCHECK(inserted); |
| 261 RecordBufferTimeData(bitstream_buffer, *buffer); | 262 RecordBufferTimeData(bitstream_buffer, *buffer); |
| 262 | 263 |
| 263 render_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 264 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 264 &VideoDecodeAccelerator::Decode, vda_, bitstream_buffer)); | 265 &VideoDecodeAccelerator::Decode, vda_, bitstream_buffer)); |
| 265 } | 266 } |
| 266 | 267 |
| 267 void GpuVideoDecoder::RecordBufferTimeData( | 268 void GpuVideoDecoder::RecordBufferTimeData( |
| 268 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { | 269 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { |
| 269 base::TimeDelta duration = buffer.GetDuration(); | 270 base::TimeDelta duration = buffer.GetDuration(); |
| 270 if (duration == base::TimeDelta()) | 271 if (duration == base::TimeDelta()) |
| 271 duration = config_frame_duration_; | 272 duration = config_frame_duration_; |
| 272 input_buffer_time_data_.push_front(BufferTimeData( | 273 input_buffer_time_data_.push_front(BufferTimeData( |
| 273 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); | 274 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 return; | 339 return; |
| 339 | 340 |
| 340 std::vector<PictureBuffer> picture_buffers; | 341 std::vector<PictureBuffer> picture_buffers; |
| 341 for (size_t i = 0; i < texture_ids.size(); ++i) { | 342 for (size_t i = 0; i < texture_ids.size(); ++i) { |
| 342 picture_buffers.push_back(PictureBuffer( | 343 picture_buffers.push_back(PictureBuffer( |
| 343 next_picture_buffer_id_++, size, texture_ids[i])); | 344 next_picture_buffer_id_++, size, texture_ids[i])); |
| 344 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( | 345 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( |
| 345 picture_buffers.back().id(), picture_buffers.back())).second; | 346 picture_buffers.back().id(), picture_buffers.back())).second; |
| 346 DCHECK(inserted); | 347 DCHECK(inserted); |
| 347 } | 348 } |
| 348 render_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 349 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 349 &VideoDecodeAccelerator::AssignPictureBuffers, vda_, picture_buffers)); | 350 &VideoDecodeAccelerator::AssignPictureBuffers, vda_, picture_buffers)); |
| 350 } | 351 } |
| 351 | 352 |
| 352 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 353 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
| 353 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 354 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 354 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 355 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 355 &GpuVideoDecoder::DismissPictureBuffer, this, id)); | 356 &GpuVideoDecoder::DismissPictureBuffer, this, id)); |
| 356 return; | 357 return; |
| 357 } | 358 } |
| 358 std::map<int32, PictureBuffer>::iterator it = | 359 std::map<int32, PictureBuffer>::iterator it = |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 } | 420 } |
| 420 | 421 |
| 421 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { | 422 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { |
| 422 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 423 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 423 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 424 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 424 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); | 425 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); |
| 425 return; | 426 return; |
| 426 } | 427 } |
| 427 if (!vda_) | 428 if (!vda_) |
| 428 return; | 429 return; |
| 429 render_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 430 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 430 &VideoDecodeAccelerator::ReusePictureBuffer, vda_, picture_buffer_id)); | 431 &VideoDecodeAccelerator::ReusePictureBuffer, vda_, picture_buffer_id)); |
| 431 } | 432 } |
| 432 | 433 |
| 433 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { | 434 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { |
| 434 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 435 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 435 if (available_shm_segments_.empty() || | 436 if (available_shm_segments_.empty() || |
| 436 available_shm_segments_.back()->size < min_size) { | 437 available_shm_segments_.back()->size < min_size) { |
| 437 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 438 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
| 438 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); | 439 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); |
| 439 DCHECK(shm); | 440 DCHECK(shm); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 if (!pending_read_cb_.is_null()) | 524 if (!pending_read_cb_.is_null()) |
| 524 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 525 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
| 525 } | 526 } |
| 526 | 527 |
| 527 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 528 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
| 528 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 529 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 529 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 530 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 530 &GpuVideoDecoder::NotifyError, this, error)); | 531 &GpuVideoDecoder::NotifyError, this, error)); |
| 531 return; | 532 return; |
| 532 } | 533 } |
| 534 if (!vda_) |
| 535 return; |
| 533 vda_ = NULL; | 536 vda_ = NULL; |
| 534 DLOG(ERROR) << "VDA Error: " << error; | 537 DLOG(ERROR) << "VDA Error: " << error; |
| 535 if (host()) | 538 if (host()) |
| 536 host()->SetError(PIPELINE_ERROR_DECODE); | 539 host()->SetError(PIPELINE_ERROR_DECODE); |
| 537 } | 540 } |
| 538 | 541 |
| 539 } // namespace media | 542 } // namespace media |
| OLD | NEW |