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 |