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/synchronization/waitable_event.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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 vda_loop_proxy_->PostTaskAndReply( |
165 FROM_HERE, | 169 FROM_HERE, |
166 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), | 170 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, vda), |
167 base::Bind(status_cb, PIPELINE_OK)); | 171 base::Bind(status_cb, PIPELINE_OK)); |
168 } | 172 } |
169 | 173 |
170 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { | 174 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { |
171 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 175 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
172 DCHECK(!vda_.get()); | 176 DCHECK(!vda_.get()); |
173 vda_.reset(vda); | 177 vda_.reset(vda); |
174 weak_vda_ = vda->AsWeakPtr(); | 178 weak_vda_ = vda->AsWeakPtr(); |
175 } | 179 } |
176 | 180 |
177 void GpuVideoDecoder::DestroyTextures() { | 181 void GpuVideoDecoder::DestroyTextures() { |
178 for (std::map<int32, PictureBuffer>::iterator it = | 182 for (std::map<int32, PictureBuffer>::iterator it = |
179 picture_buffers_in_decoder_.begin(); | 183 picture_buffers_in_decoder_.begin(); |
180 it != picture_buffers_in_decoder_.end(); ++it) { | 184 it != picture_buffers_in_decoder_.end(); ++it) { |
181 factories_->DeleteTexture(it->second.texture_id()); | 185 factories_->DeleteTexture(it->second.texture_id()); |
182 } | 186 } |
183 picture_buffers_in_decoder_.clear(); | 187 picture_buffers_in_decoder_.clear(); |
184 } | 188 } |
185 | 189 |
190 static void DestroyAndSignal( | |
191 base::WeakPtr<VideoDecodeAccelerator> weak_vda, | |
192 base::WaitableEvent* event) { | |
193 // XXX: how else would weak_vda be null? | |
scherkus (not reviewing)
2013/03/22 00:04:20
FYI
xhwang
2013/03/22 01:00:32
Defer this part to fischman :)
Ami GONE FROM CHROMIUM
2013/03/22 23:48:01
VDA unfortunately SupportsWeakPtr, so others can i
| |
194 if (weak_vda) | |
195 weak_vda->Destroy(); | |
196 event->Signal(); | |
197 } | |
198 | |
186 void GpuVideoDecoder::DestroyVDA() { | 199 void GpuVideoDecoder::DestroyVDA() { |
187 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 200 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
188 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); | 201 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); |
189 // Tricky: |this| needs to stay alive until after VDA::Destroy is actually | 202 |
190 // called, not just posted, so we take an artificial ref to |this| and release | 203 // Wait until VideoDecodeAccelerator::Destroy() completes. |
scherkus (not reviewing)
2013/03/22 00:04:20
fischman: http://blog.operationreality.org/wp-cont
| |
191 // it as |reply| after VDA::Destroy() returns. | 204 base::WaitableEvent event(false, false); |
192 AddRef(); | 205 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
193 vda_loop_proxy_->PostTaskAndReply( | 206 &DestroyAndSignal, weak_vda_, &event)); |
194 FROM_HERE, | 207 event.Wait(); |
Ami GONE FROM CHROMIUM
2013/03/22 23:48:01
This looks like a deadlock: Stop() calls this func
| |
195 base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_), | |
196 base::Bind(&GpuVideoDecoder::Release, this)); | |
197 | 208 |
198 DestroyTextures(); | 209 DestroyTextures(); |
199 } | 210 } |
200 | 211 |
201 void GpuVideoDecoder::Read(const ReadCB& read_cb) { | 212 void GpuVideoDecoder::Read(const ReadCB& read_cb) { |
202 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 213 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
203 DCHECK(pending_reset_cb_.is_null()); | 214 DCHECK(pending_reset_cb_.is_null()); |
204 DCHECK(pending_read_cb_.is_null()); | 215 DCHECK(pending_read_cb_.is_null()); |
205 pending_read_cb_ = BindToCurrentLoop(read_cb); | 216 pending_read_cb_ = BindToCurrentLoop(read_cb); |
206 | 217 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; | 249 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; |
239 } | 250 } |
240 | 251 |
241 void GpuVideoDecoder::RequestBufferDecode( | 252 void GpuVideoDecoder::RequestBufferDecode( |
242 DemuxerStream::Status status, | 253 DemuxerStream::Status status, |
243 const scoped_refptr<DecoderBuffer>& buffer) { | 254 const scoped_refptr<DecoderBuffer>& buffer) { |
244 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; | 255 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; |
245 | 256 |
246 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 257 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
247 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 258 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
248 &GpuVideoDecoder::RequestBufferDecode, this, status, buffer)); | 259 &GpuVideoDecoder::RequestBufferDecode, weak_this_, status, buffer)); |
249 return; | 260 return; |
250 } | 261 } |
251 demuxer_read_in_progress_ = false; | 262 demuxer_read_in_progress_ = false; |
252 | 263 |
253 if (status != DemuxerStream::kOk) { | 264 if (status != DemuxerStream::kOk) { |
254 if (pending_read_cb_.is_null()) | 265 if (pending_read_cb_.is_null()) |
255 return; | 266 return; |
256 | 267 |
257 // TODO(acolwell): Add support for reinitializing the decoder when | 268 // TODO(acolwell): Add support for reinitializing the decoder when |
258 // |status| == kConfigChanged. For now we just trigger a decode error. | 269 // |status| == kConfigChanged. For now we just trigger a decode error. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
344 | 355 |
345 void GpuVideoDecoder::NotifyInitializeDone() { | 356 void GpuVideoDecoder::NotifyInitializeDone() { |
346 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; | 357 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; |
347 } | 358 } |
348 | 359 |
349 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, | 360 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, |
350 const gfx::Size& size, | 361 const gfx::Size& size, |
351 uint32 texture_target) { | 362 uint32 texture_target) { |
352 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 363 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
353 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 364 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
354 &GpuVideoDecoder::ProvidePictureBuffers, this, count, size, | 365 &GpuVideoDecoder::ProvidePictureBuffers, weak_this_, count, size, |
355 texture_target)); | 366 texture_target)); |
356 return; | 367 return; |
357 } | 368 } |
358 | 369 |
359 std::vector<uint32> texture_ids; | 370 std::vector<uint32> texture_ids; |
360 decoder_texture_target_ = texture_target; | 371 decoder_texture_target_ = texture_target; |
361 if (!factories_->CreateTextures( | 372 if (!factories_->CreateTextures( |
362 count, size, &texture_ids, decoder_texture_target_)) { | 373 count, size, &texture_ids, decoder_texture_target_)) { |
363 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 374 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
364 return; | 375 return; |
(...skipping 14 matching lines...) Expand all Loading... | |
379 DCHECK(inserted); | 390 DCHECK(inserted); |
380 } | 391 } |
381 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 392 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
382 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, | 393 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, |
383 picture_buffers)); | 394 picture_buffers)); |
384 } | 395 } |
385 | 396 |
386 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 397 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
387 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 398 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
388 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 399 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
389 &GpuVideoDecoder::DismissPictureBuffer, this, id)); | 400 &GpuVideoDecoder::DismissPictureBuffer, weak_this_, id)); |
390 return; | 401 return; |
391 } | 402 } |
392 std::map<int32, PictureBuffer>::iterator it = | 403 std::map<int32, PictureBuffer>::iterator it = |
393 picture_buffers_in_decoder_.find(id); | 404 picture_buffers_in_decoder_.find(id); |
394 if (it == picture_buffers_in_decoder_.end()) { | 405 if (it == picture_buffers_in_decoder_.end()) { |
395 NOTREACHED() << "Missing picture buffer: " << id; | 406 NOTREACHED() << "Missing picture buffer: " << id; |
396 return; | 407 return; |
397 } | 408 } |
398 factories_->DeleteTexture(it->second.texture_id()); | 409 factories_->DeleteTexture(it->second.texture_id()); |
399 picture_buffers_in_decoder_.erase(it); | 410 picture_buffers_in_decoder_.erase(it); |
400 } | 411 } |
401 | 412 |
402 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { | 413 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { |
403 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 414 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
404 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 415 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
405 &GpuVideoDecoder::PictureReady, this, picture)); | 416 &GpuVideoDecoder::PictureReady, weak_this_, picture)); |
406 return; | 417 return; |
407 } | 418 } |
408 std::map<int32, PictureBuffer>::iterator it = | 419 std::map<int32, PictureBuffer>::iterator it = |
409 picture_buffers_in_decoder_.find(picture.picture_buffer_id()); | 420 picture_buffers_in_decoder_.find(picture.picture_buffer_id()); |
410 if (it == picture_buffers_in_decoder_.end()) { | 421 if (it == picture_buffers_in_decoder_.end()) { |
411 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); | 422 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); |
412 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 423 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
413 return; | 424 return; |
414 } | 425 } |
415 const PictureBuffer& pb = it->second; | 426 const PictureBuffer& pb = it->second; |
416 | 427 |
417 // Update frame's timestamp. | 428 // Update frame's timestamp. |
418 base::TimeDelta timestamp; | 429 base::TimeDelta timestamp; |
419 gfx::Rect visible_rect; | 430 gfx::Rect visible_rect; |
420 gfx::Size natural_size; | 431 gfx::Size natural_size; |
421 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, | 432 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, |
422 &natural_size); | 433 &natural_size); |
423 DCHECK(decoder_texture_target_); | 434 DCHECK(decoder_texture_target_); |
424 scoped_refptr<VideoFrame> frame( | 435 scoped_refptr<VideoFrame> frame( |
425 VideoFrame::WrapNativeTexture( | 436 VideoFrame::WrapNativeTexture( |
426 pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect, | 437 pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect, |
427 natural_size, timestamp, | 438 natural_size, timestamp, |
428 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), | 439 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), |
429 decoder_texture_target_, | 440 decoder_texture_target_, |
430 gfx::Size(visible_rect.width(), visible_rect.height())), | 441 gfx::Size(visible_rect.width(), visible_rect.height())), |
431 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, | 442 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, weak_this_, |
432 picture.picture_buffer_id()))); | 443 picture.picture_buffer_id()))); |
433 CHECK_GT(available_pictures_, 0); | 444 CHECK_GT(available_pictures_, 0); |
434 available_pictures_--; | 445 available_pictures_--; |
435 | 446 |
436 EnqueueFrameAndTriggerFrameDelivery(frame); | 447 EnqueueFrameAndTriggerFrameDelivery(frame); |
437 } | 448 } |
438 | 449 |
439 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 450 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
440 const scoped_refptr<VideoFrame>& frame) { | 451 const scoped_refptr<VideoFrame>& frame) { |
441 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 452 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
(...skipping 11 matching lines...) Expand all Loading... | |
453 if (pending_read_cb_.is_null()) | 464 if (pending_read_cb_.is_null()) |
454 return; | 465 return; |
455 | 466 |
456 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); | 467 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); |
457 ready_video_frames_.pop_front(); | 468 ready_video_frames_.pop_front(); |
458 } | 469 } |
459 | 470 |
460 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { | 471 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { |
461 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 472 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
462 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 473 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
463 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); | 474 &GpuVideoDecoder::ReusePictureBuffer, weak_this_, picture_buffer_id)); |
464 return; | 475 return; |
465 } | 476 } |
466 CHECK_GE(available_pictures_, 0); | 477 CHECK_GE(available_pictures_, 0); |
467 available_pictures_++; | 478 available_pictures_++; |
468 | 479 |
469 if (!vda_.get()) | 480 if (!vda_.get()) |
470 return; | 481 return; |
471 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 482 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
472 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, | 483 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, |
473 picture_buffer_id)); | 484 picture_buffer_id)); |
(...skipping 14 matching lines...) Expand all Loading... | |
488 } | 499 } |
489 | 500 |
490 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { | 501 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { |
491 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 502 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
492 available_shm_segments_.push_back(shm_buffer); | 503 available_shm_segments_.push_back(shm_buffer); |
493 } | 504 } |
494 | 505 |
495 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { | 506 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
496 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 507 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
497 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 508 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
498 &GpuVideoDecoder::NotifyEndOfBitstreamBuffer, this, id)); | 509 &GpuVideoDecoder::NotifyEndOfBitstreamBuffer, weak_this_, id)); |
499 return; | 510 return; |
500 } | 511 } |
501 | 512 |
502 std::map<int32, BufferPair>::iterator it = | 513 std::map<int32, BufferPair>::iterator it = |
503 bitstream_buffers_in_decoder_.find(id); | 514 bitstream_buffers_in_decoder_.find(id); |
504 if (it == bitstream_buffers_in_decoder_.end()) { | 515 if (it == bitstream_buffers_in_decoder_.end()) { |
505 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 516 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
506 NOTREACHED() << "Missing bitstream buffer: " << id; | 517 NOTREACHED() << "Missing bitstream buffer: " << id; |
507 return; | 518 return; |
508 } | 519 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
540 DestroyTextures(); | 551 DestroyTextures(); |
541 } | 552 } |
542 | 553 |
543 void GpuVideoDecoder::EnsureDemuxOrDecode() { | 554 void GpuVideoDecoder::EnsureDemuxOrDecode() { |
544 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 555 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
545 if (demuxer_read_in_progress_) | 556 if (demuxer_read_in_progress_) |
546 return; | 557 return; |
547 demuxer_read_in_progress_ = true; | 558 demuxer_read_in_progress_ = true; |
548 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 559 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
549 &DemuxerStream::Read, demuxer_stream_.get(), | 560 &DemuxerStream::Read, demuxer_stream_.get(), |
550 base::Bind(&GpuVideoDecoder::RequestBufferDecode, this))); | 561 base::Bind(&GpuVideoDecoder::RequestBufferDecode, weak_this_))); |
551 } | 562 } |
552 | 563 |
553 void GpuVideoDecoder::NotifyFlushDone() { | 564 void GpuVideoDecoder::NotifyFlushDone() { |
554 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 565 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
555 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 566 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
556 &GpuVideoDecoder::NotifyFlushDone, this)); | 567 &GpuVideoDecoder::NotifyFlushDone, weak_this_)); |
557 return; | 568 return; |
558 } | 569 } |
559 DCHECK_EQ(state_, kDrainingDecoder); | 570 DCHECK_EQ(state_, kDrainingDecoder); |
560 state_ = kDecoderDrained; | 571 state_ = kDecoderDrained; |
561 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 572 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
562 } | 573 } |
563 | 574 |
564 void GpuVideoDecoder::NotifyResetDone() { | 575 void GpuVideoDecoder::NotifyResetDone() { |
565 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 576 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
566 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 577 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
567 &GpuVideoDecoder::NotifyResetDone, this)); | 578 &GpuVideoDecoder::NotifyResetDone, weak_this_)); |
568 return; | 579 return; |
569 } | 580 } |
570 | 581 |
571 if (!vda_.get()) | 582 if (!vda_.get()) |
572 return; | 583 return; |
573 | 584 |
574 DCHECK(ready_video_frames_.empty()); | 585 DCHECK(ready_video_frames_.empty()); |
575 | 586 |
576 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 587 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
577 // delivered during the reset can find their time data. | 588 // delivered during the reset can find their time data. |
578 input_buffer_data_.clear(); | 589 input_buffer_data_.clear(); |
579 | 590 |
580 if (!pending_reset_cb_.is_null()) | 591 if (!pending_reset_cb_.is_null()) |
581 base::ResetAndReturn(&pending_reset_cb_).Run(); | 592 base::ResetAndReturn(&pending_reset_cb_).Run(); |
582 | 593 |
583 if (!pending_read_cb_.is_null()) | 594 if (!pending_read_cb_.is_null()) |
584 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 595 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
585 } | 596 } |
586 | 597 |
587 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 598 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
588 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 599 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
589 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 600 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
590 &GpuVideoDecoder::NotifyError, this, error)); | 601 &GpuVideoDecoder::NotifyError, weak_this_, error)); |
591 return; | 602 return; |
592 } | 603 } |
593 if (!vda_.get()) | 604 if (!vda_.get()) |
594 return; | 605 return; |
595 | 606 |
596 DLOG(ERROR) << "VDA Error: " << error; | 607 DLOG(ERROR) << "VDA Error: " << error; |
597 DestroyVDA(); | 608 DestroyVDA(); |
598 | 609 |
599 error_occured_ = true; | 610 error_occured_ = true; |
600 | 611 |
601 if (!pending_read_cb_.is_null()) { | 612 if (!pending_read_cb_.is_null()) { |
602 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 613 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
603 return; | 614 return; |
604 } | 615 } |
605 } | 616 } |
606 | 617 |
607 } // namespace media | 618 } // namespace media |
OLD | NEW |