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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), | 49 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), |
50 natural_size(ns) { | 50 natural_size(ns) { |
51 } | 51 } |
52 | 52 |
53 GpuVideoDecoder::BufferData::~BufferData() {} | 53 GpuVideoDecoder::BufferData::~BufferData() {} |
54 | 54 |
55 GpuVideoDecoder::GpuVideoDecoder( | 55 GpuVideoDecoder::GpuVideoDecoder( |
56 const scoped_refptr<GpuVideoAcceleratorFactories>& factories, | 56 const scoped_refptr<GpuVideoAcceleratorFactories>& factories, |
57 const scoped_refptr<MediaLog>& media_log) | 57 const scoped_refptr<MediaLog>& media_log) |
58 : needs_bitstream_conversion_(false), | 58 : needs_bitstream_conversion_(false), |
59 gvd_loop_proxy_(factories->GetMessageLoop()), | 59 gvd_task_runner_(factories->GetTaskRunner()), |
60 weak_factory_(this), | 60 weak_factory_(this), |
61 factories_(factories), | 61 factories_(factories), |
62 state_(kNormal), | 62 state_(kNormal), |
63 media_log_(media_log), | 63 media_log_(media_log), |
64 decoder_texture_target_(0), | 64 decoder_texture_target_(0), |
65 next_picture_buffer_id_(0), | 65 next_picture_buffer_id_(0), |
66 next_bitstream_buffer_id_(0), | 66 next_bitstream_buffer_id_(0), |
67 available_pictures_(0) { | 67 available_pictures_(0) { |
68 DCHECK(factories_.get()); | 68 DCHECK(factories_.get()); |
69 } | 69 } |
70 | 70 |
71 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 71 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
72 DVLOG(3) << "Reset()"; | 72 DVLOG(3) << "Reset()"; |
73 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 73 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
74 | 74 |
75 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { | 75 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { |
76 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 76 gvd_task_runner_->PostTask(FROM_HERE, base::Bind( |
77 &GpuVideoDecoder::Reset, weak_this_, closure)); | 77 &GpuVideoDecoder::Reset, weak_this_, closure)); |
78 // NOTE: if we're deferring Reset() until a Flush() completes, return | 78 // NOTE: if we're deferring Reset() until a Flush() completes, return |
79 // queued pictures to the VDA so they can be used to finish that Flush(). | 79 // queued pictures to the VDA so they can be used to finish that Flush(). |
80 if (pending_decode_cb_.is_null()) | 80 if (pending_decode_cb_.is_null()) |
81 ready_video_frames_.clear(); | 81 ready_video_frames_.clear(); |
82 return; | 82 return; |
83 } | 83 } |
84 | 84 |
85 // Throw away any already-decoded, not-yet-delivered frames. | 85 // Throw away any already-decoded, not-yet-delivered frames. |
86 ready_video_frames_.clear(); | 86 ready_video_frames_.clear(); |
87 | 87 |
88 if (!vda_) { | 88 if (!vda_) { |
89 gvd_loop_proxy_->PostTask(FROM_HERE, closure); | 89 gvd_task_runner_->PostTask(FROM_HERE, closure); |
90 return; | 90 return; |
91 } | 91 } |
92 | 92 |
93 if (!pending_decode_cb_.is_null()) | 93 if (!pending_decode_cb_.is_null()) |
94 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 94 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
95 | 95 |
96 DCHECK(pending_reset_cb_.is_null()); | 96 DCHECK(pending_reset_cb_.is_null()); |
97 pending_reset_cb_ = BindToCurrentLoop(closure); | 97 pending_reset_cb_ = BindToCurrentLoop(closure); |
98 | 98 |
99 vda_->Reset(); | 99 vda_->Reset(); |
100 } | 100 } |
101 | 101 |
102 void GpuVideoDecoder::Stop(const base::Closure& closure) { | 102 void GpuVideoDecoder::Stop(const base::Closure& closure) { |
103 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 103 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
104 if (vda_) | 104 if (vda_) |
105 DestroyVDA(); | 105 DestroyVDA(); |
106 if (!pending_decode_cb_.is_null()) | 106 if (!pending_decode_cb_.is_null()) |
107 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 107 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
108 if (!pending_reset_cb_.is_null()) | 108 if (!pending_reset_cb_.is_null()) |
109 base::ResetAndReturn(&pending_reset_cb_).Run(); | 109 base::ResetAndReturn(&pending_reset_cb_).Run(); |
110 BindToCurrentLoop(closure).Run(); | 110 BindToCurrentLoop(closure).Run(); |
111 } | 111 } |
112 | 112 |
113 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { | 113 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { |
114 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. | 114 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. |
115 // We test against 1088 to account for 16x16 macroblocks. | 115 // We test against 1088 to account for 16x16 macroblocks. |
116 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) | 116 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) |
117 return true; | 117 return true; |
118 | 118 |
119 base::CPU cpu; | 119 base::CPU cpu; |
120 bool hw_large_video_support = | 120 bool hw_large_video_support = |
121 (cpu.vendor_name() == "GenuineIntel") && cpu.model() >= 58; | 121 (cpu.vendor_name() == "GenuineIntel") && cpu.model() >= 58; |
122 bool os_large_video_support = true; | 122 bool os_large_video_support = true; |
123 #if defined(OS_WIN) | 123 #if defined(OS_WIN) |
124 os_large_video_support = false; | 124 os_large_video_support = false; |
125 #endif | 125 #endif |
126 return os_large_video_support && hw_large_video_support; | 126 return os_large_video_support && hw_large_video_support; |
127 } | 127 } |
128 | 128 |
129 void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, | 129 void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, |
130 const PipelineStatusCB& orig_status_cb) { | 130 const PipelineStatusCB& orig_status_cb) { |
131 DVLOG(3) << "Initialize()"; | 131 DVLOG(3) << "Initialize()"; |
132 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 132 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
133 DCHECK(config.IsValidConfig()); | 133 DCHECK(config.IsValidConfig()); |
134 DCHECK(!config.is_encrypted()); | 134 DCHECK(!config.is_encrypted()); |
135 | 135 |
136 weak_this_ = weak_factory_.GetWeakPtr(); | 136 weak_this_ = weak_factory_.GetWeakPtr(); |
137 | 137 |
138 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( | 138 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( |
139 "Media.GpuVideoDecoderInitializeStatus", | 139 "Media.GpuVideoDecoderInitializeStatus", |
140 BindToCurrentLoop(orig_status_cb)); | 140 BindToCurrentLoop(orig_status_cb)); |
141 | 141 |
142 bool previously_initialized = config_.IsValidConfig(); | 142 bool previously_initialized = config_.IsValidConfig(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 182 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
183 return; | 183 return; |
184 } | 184 } |
185 | 185 |
186 DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded."; | 186 DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded."; |
187 media_log_->SetStringProperty("video_decoder", "gpu"); | 187 media_log_->SetStringProperty("video_decoder", "gpu"); |
188 status_cb.Run(PIPELINE_OK); | 188 status_cb.Run(PIPELINE_OK); |
189 } | 189 } |
190 | 190 |
191 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { | 191 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { |
192 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 192 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
193 for (PictureBufferMap::iterator it = buffers->begin(); it != buffers->end(); | 193 for (PictureBufferMap::iterator it = buffers->begin(); it != buffers->end(); |
194 ++it) { | 194 ++it) { |
195 factories_->DeleteTexture(it->second.texture_id()); | 195 factories_->DeleteTexture(it->second.texture_id()); |
196 } | 196 } |
197 | 197 |
198 buffers->clear(); | 198 buffers->clear(); |
199 } | 199 } |
200 | 200 |
201 void GpuVideoDecoder::DestroyVDA() { | 201 void GpuVideoDecoder::DestroyVDA() { |
202 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 202 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
203 | 203 |
204 if (vda_) | 204 if (vda_) |
205 vda_.release()->Destroy(); | 205 vda_.release()->Destroy(); |
206 | 206 |
207 DestroyPictureBuffers(&assigned_picture_buffers_); | 207 DestroyPictureBuffers(&assigned_picture_buffers_); |
208 // Not destroying PictureBuffers in |dismissed_picture_buffers_| yet, since | 208 // Not destroying PictureBuffers in |dismissed_picture_buffers_| yet, since |
209 // their textures may still be in use by the user of this GpuVideoDecoder. | 209 // their textures may still be in use by the user of this GpuVideoDecoder. |
210 } | 210 } |
211 | 211 |
212 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 212 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
213 const DecodeCB& decode_cb) { | 213 const DecodeCB& decode_cb) { |
214 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 214 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
215 DCHECK(pending_reset_cb_.is_null()); | 215 DCHECK(pending_reset_cb_.is_null()); |
216 DCHECK(pending_decode_cb_.is_null()); | 216 DCHECK(pending_decode_cb_.is_null()); |
217 | 217 |
218 pending_decode_cb_ = BindToCurrentLoop(decode_cb); | 218 pending_decode_cb_ = BindToCurrentLoop(decode_cb); |
219 | 219 |
220 if (state_ == kError || !vda_) { | 220 if (state_ == kError || !vda_) { |
221 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); | 221 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
222 return; | 222 return; |
223 } | 223 } |
224 | 224 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 continue; | 313 continue; |
314 *timestamp = it->timestamp; | 314 *timestamp = it->timestamp; |
315 *visible_rect = it->visible_rect; | 315 *visible_rect = it->visible_rect; |
316 *natural_size = it->natural_size; | 316 *natural_size = it->natural_size; |
317 return; | 317 return; |
318 } | 318 } |
319 NOTREACHED() << "Missing bitstreambuffer id: " << id; | 319 NOTREACHED() << "Missing bitstreambuffer id: " << id; |
320 } | 320 } |
321 | 321 |
322 bool GpuVideoDecoder::HasAlpha() const { | 322 bool GpuVideoDecoder::HasAlpha() const { |
323 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 323 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
324 return true; | 324 return true; |
325 } | 325 } |
326 | 326 |
327 bool GpuVideoDecoder::NeedsBitstreamConversion() const { | 327 bool GpuVideoDecoder::NeedsBitstreamConversion() const { |
328 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 328 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
329 return needs_bitstream_conversion_; | 329 return needs_bitstream_conversion_; |
330 } | 330 } |
331 | 331 |
332 bool GpuVideoDecoder::CanReadWithoutStalling() const { | 332 bool GpuVideoDecoder::CanReadWithoutStalling() const { |
333 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 333 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
334 return available_pictures_ > 0 || !ready_video_frames_.empty(); | 334 return available_pictures_ > 0 || !ready_video_frames_.empty(); |
335 } | 335 } |
336 | 336 |
337 void GpuVideoDecoder::NotifyInitializeDone() { | 337 void GpuVideoDecoder::NotifyInitializeDone() { |
338 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; | 338 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; |
339 } | 339 } |
340 | 340 |
341 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, | 341 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, |
342 const gfx::Size& size, | 342 const gfx::Size& size, |
343 uint32 texture_target) { | 343 uint32 texture_target) { |
344 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " | 344 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " |
345 << size.width() << "x" << size.height() << ")"; | 345 << size.width() << "x" << size.height() << ")"; |
346 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 346 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
347 | 347 |
348 std::vector<uint32> texture_ids; | 348 std::vector<uint32> texture_ids; |
349 std::vector<gpu::Mailbox> texture_mailboxes; | 349 std::vector<gpu::Mailbox> texture_mailboxes; |
350 decoder_texture_target_ = texture_target; | 350 decoder_texture_target_ = texture_target; |
351 // Discards the sync point returned here since PictureReady will imply that | 351 // Discards the sync point returned here since PictureReady will imply that |
352 // the produce has already happened, and the texture is ready for use. | 352 // the produce has already happened, and the texture is ready for use. |
353 if (!factories_->CreateTextures(count, | 353 if (!factories_->CreateTextures(count, |
354 size, | 354 size, |
355 &texture_ids, | 355 &texture_ids, |
356 &texture_mailboxes, | 356 &texture_mailboxes, |
(...skipping 16 matching lines...) Expand all Loading... |
373 DCHECK(inserted); | 373 DCHECK(inserted); |
374 } | 374 } |
375 | 375 |
376 available_pictures_ += count; | 376 available_pictures_ += count; |
377 | 377 |
378 vda_->AssignPictureBuffers(picture_buffers); | 378 vda_->AssignPictureBuffers(picture_buffers); |
379 } | 379 } |
380 | 380 |
381 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 381 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
382 DVLOG(3) << "DismissPictureBuffer(" << id << ")"; | 382 DVLOG(3) << "DismissPictureBuffer(" << id << ")"; |
383 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 383 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
384 | 384 |
385 PictureBufferMap::iterator it = assigned_picture_buffers_.find(id); | 385 PictureBufferMap::iterator it = assigned_picture_buffers_.find(id); |
386 if (it == assigned_picture_buffers_.end()) { | 386 if (it == assigned_picture_buffers_.end()) { |
387 NOTREACHED() << "Missing picture buffer: " << id; | 387 NOTREACHED() << "Missing picture buffer: " << id; |
388 return; | 388 return; |
389 } | 389 } |
390 | 390 |
391 PictureBuffer buffer_to_dismiss = it->second; | 391 PictureBuffer buffer_to_dismiss = it->second; |
392 assigned_picture_buffers_.erase(it); | 392 assigned_picture_buffers_.erase(it); |
393 | 393 |
394 std::set<int32>::iterator at_display_it = | 394 std::set<int32>::iterator at_display_it = |
395 picture_buffers_at_display_.find(id); | 395 picture_buffers_at_display_.find(id); |
396 | 396 |
397 if (at_display_it == picture_buffers_at_display_.end()) { | 397 if (at_display_it == picture_buffers_at_display_.end()) { |
398 // We can delete the texture immediately as it's not being displayed. | 398 // We can delete the texture immediately as it's not being displayed. |
399 factories_->DeleteTexture(buffer_to_dismiss.texture_id()); | 399 factories_->DeleteTexture(buffer_to_dismiss.texture_id()); |
400 CHECK_GT(available_pictures_, 0); | 400 CHECK_GT(available_pictures_, 0); |
401 --available_pictures_; | 401 --available_pictures_; |
402 } else { | 402 } else { |
403 // Texture in display. Postpone deletion until after it's returned to us. | 403 // Texture in display. Postpone deletion until after it's returned to us. |
404 bool inserted = dismissed_picture_buffers_.insert(std::make_pair( | 404 bool inserted = dismissed_picture_buffers_.insert(std::make_pair( |
405 id, buffer_to_dismiss)).second; | 405 id, buffer_to_dismiss)).second; |
406 DCHECK(inserted); | 406 DCHECK(inserted); |
407 } | 407 } |
408 } | 408 } |
409 | 409 |
410 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { | 410 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { |
411 DVLOG(3) << "PictureReady()"; | 411 DVLOG(3) << "PictureReady()"; |
412 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 412 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
413 | 413 |
414 PictureBufferMap::iterator it = | 414 PictureBufferMap::iterator it = |
415 assigned_picture_buffers_.find(picture.picture_buffer_id()); | 415 assigned_picture_buffers_.find(picture.picture_buffer_id()); |
416 if (it == assigned_picture_buffers_.end()) { | 416 if (it == assigned_picture_buffers_.end()) { |
417 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); | 417 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); |
418 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 418 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
419 return; | 419 return; |
420 } | 420 } |
421 const PictureBuffer& pb = it->second; | 421 const PictureBuffer& pb = it->second; |
422 | 422 |
(...skipping 26 matching lines...) Expand all Loading... |
449 --available_pictures_; | 449 --available_pictures_; |
450 bool inserted = | 450 bool inserted = |
451 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; | 451 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; |
452 DCHECK(inserted); | 452 DCHECK(inserted); |
453 | 453 |
454 EnqueueFrameAndTriggerFrameDelivery(frame); | 454 EnqueueFrameAndTriggerFrameDelivery(frame); |
455 } | 455 } |
456 | 456 |
457 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 457 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
458 const scoped_refptr<VideoFrame>& frame) { | 458 const scoped_refptr<VideoFrame>& frame) { |
459 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 459 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
460 | 460 |
461 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the | 461 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the |
462 // floor and return. | 462 // floor and return. |
463 if (!pending_reset_cb_.is_null()) | 463 if (!pending_reset_cb_.is_null()) |
464 return; | 464 return; |
465 | 465 |
466 if (frame.get()) | 466 if (frame.get()) |
467 ready_video_frames_.push_back(frame); | 467 ready_video_frames_.push_back(frame); |
468 else | 468 else |
469 DCHECK(!ready_video_frames_.empty()); | 469 DCHECK(!ready_video_frames_.empty()); |
470 | 470 |
471 if (pending_decode_cb_.is_null()) | 471 if (pending_decode_cb_.is_null()) |
472 return; | 472 return; |
473 | 473 |
474 base::ResetAndReturn(&pending_decode_cb_) | 474 base::ResetAndReturn(&pending_decode_cb_) |
475 .Run(kOk, ready_video_frames_.front()); | 475 .Run(kOk, ready_video_frames_.front()); |
476 ready_video_frames_.pop_front(); | 476 ready_video_frames_.pop_front(); |
477 } | 477 } |
478 | 478 |
479 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, | 479 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, |
480 uint32 sync_point) { | 480 uint32 sync_point) { |
481 DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")"; | 481 DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")"; |
482 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 482 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
483 | 483 |
484 if (!vda_) | 484 if (!vda_) |
485 return; | 485 return; |
486 | 486 |
487 CHECK(!picture_buffers_at_display_.empty()); | 487 CHECK(!picture_buffers_at_display_.empty()); |
488 | 488 |
489 size_t num_erased = picture_buffers_at_display_.erase(picture_buffer_id); | 489 size_t num_erased = picture_buffers_at_display_.erase(picture_buffer_id); |
490 DCHECK(num_erased); | 490 DCHECK(num_erased); |
491 | 491 |
492 PictureBufferMap::iterator it = | 492 PictureBufferMap::iterator it = |
493 assigned_picture_buffers_.find(picture_buffer_id); | 493 assigned_picture_buffers_.find(picture_buffer_id); |
494 | 494 |
495 if (it == assigned_picture_buffers_.end()) { | 495 if (it == assigned_picture_buffers_.end()) { |
496 // This picture was dismissed while in display, so we postponed deletion. | 496 // This picture was dismissed while in display, so we postponed deletion. |
497 it = dismissed_picture_buffers_.find(picture_buffer_id); | 497 it = dismissed_picture_buffers_.find(picture_buffer_id); |
498 DCHECK(it != dismissed_picture_buffers_.end()); | 498 DCHECK(it != dismissed_picture_buffers_.end()); |
499 factories_->DeleteTexture(it->second.texture_id()); | 499 factories_->DeleteTexture(it->second.texture_id()); |
500 dismissed_picture_buffers_.erase(it); | 500 dismissed_picture_buffers_.erase(it); |
501 return; | 501 return; |
502 } | 502 } |
503 | 503 |
504 factories_->WaitSyncPoint(sync_point); | 504 factories_->WaitSyncPoint(sync_point); |
505 ++available_pictures_; | 505 ++available_pictures_; |
506 | 506 |
507 vda_->ReusePictureBuffer(picture_buffer_id); | 507 vda_->ReusePictureBuffer(picture_buffer_id); |
508 } | 508 } |
509 | 509 |
510 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { | 510 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { |
511 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 511 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
512 if (available_shm_segments_.empty() || | 512 if (available_shm_segments_.empty() || |
513 available_shm_segments_.back()->size < min_size) { | 513 available_shm_segments_.back()->size < min_size) { |
514 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 514 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
515 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); | 515 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); |
516 // CreateSharedMemory() can return NULL during Shutdown. | 516 // CreateSharedMemory() can return NULL during Shutdown. |
517 if (!shm) | 517 if (!shm) |
518 return NULL; | 518 return NULL; |
519 return new SHMBuffer(shm, size_to_allocate); | 519 return new SHMBuffer(shm, size_to_allocate); |
520 } | 520 } |
521 SHMBuffer* ret = available_shm_segments_.back(); | 521 SHMBuffer* ret = available_shm_segments_.back(); |
522 available_shm_segments_.pop_back(); | 522 available_shm_segments_.pop_back(); |
523 return ret; | 523 return ret; |
524 } | 524 } |
525 | 525 |
526 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { | 526 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { |
527 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 527 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
528 available_shm_segments_.push_back(shm_buffer); | 528 available_shm_segments_.push_back(shm_buffer); |
529 } | 529 } |
530 | 530 |
531 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { | 531 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
532 DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")"; | 532 DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")"; |
533 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 533 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
534 | 534 |
535 std::map<int32, BufferPair>::iterator it = | 535 std::map<int32, BufferPair>::iterator it = |
536 bitstream_buffers_in_decoder_.find(id); | 536 bitstream_buffers_in_decoder_.find(id); |
537 if (it == bitstream_buffers_in_decoder_.end()) { | 537 if (it == bitstream_buffers_in_decoder_.end()) { |
538 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 538 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
539 NOTREACHED() << "Missing bitstream buffer: " << id; | 539 NOTREACHED() << "Missing bitstream buffer: " << id; |
540 return; | 540 return; |
541 } | 541 } |
542 | 542 |
543 PutSHM(it->second.shm_buffer); | 543 PutSHM(it->second.shm_buffer); |
544 bitstream_buffers_in_decoder_.erase(it); | 544 bitstream_buffers_in_decoder_.erase(it); |
545 | 545 |
546 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && | 546 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && |
547 CanMoreDecodeWorkBeDone() && !pending_decode_cb_.is_null()) { | 547 CanMoreDecodeWorkBeDone() && !pending_decode_cb_.is_null()) { |
548 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); | 548 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); |
549 } | 549 } |
550 } | 550 } |
551 | 551 |
552 GpuVideoDecoder::~GpuVideoDecoder() { | 552 GpuVideoDecoder::~GpuVideoDecoder() { |
553 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 553 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
554 DCHECK(!vda_.get()); // Stop should have been already called. | 554 DCHECK(!vda_.get()); // Stop should have been already called. |
555 DCHECK(pending_decode_cb_.is_null()); | 555 DCHECK(pending_decode_cb_.is_null()); |
556 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { | 556 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
557 available_shm_segments_[i]->shm->Close(); | 557 available_shm_segments_[i]->shm->Close(); |
558 delete available_shm_segments_[i]; | 558 delete available_shm_segments_[i]; |
559 } | 559 } |
560 available_shm_segments_.clear(); | 560 available_shm_segments_.clear(); |
561 for (std::map<int32, BufferPair>::iterator it = | 561 for (std::map<int32, BufferPair>::iterator it = |
562 bitstream_buffers_in_decoder_.begin(); | 562 bitstream_buffers_in_decoder_.begin(); |
563 it != bitstream_buffers_in_decoder_.end(); ++it) { | 563 it != bitstream_buffers_in_decoder_.end(); ++it) { |
564 it->second.shm_buffer->shm->Close(); | 564 it->second.shm_buffer->shm->Close(); |
565 } | 565 } |
566 bitstream_buffers_in_decoder_.clear(); | 566 bitstream_buffers_in_decoder_.clear(); |
567 | 567 |
568 DestroyPictureBuffers(&assigned_picture_buffers_); | 568 DestroyPictureBuffers(&assigned_picture_buffers_); |
569 DestroyPictureBuffers(&dismissed_picture_buffers_); | 569 DestroyPictureBuffers(&dismissed_picture_buffers_); |
570 } | 570 } |
571 | 571 |
572 void GpuVideoDecoder::NotifyFlushDone() { | 572 void GpuVideoDecoder::NotifyFlushDone() { |
573 DVLOG(3) << "NotifyFlushDone()"; | 573 DVLOG(3) << "NotifyFlushDone()"; |
574 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 574 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
575 DCHECK_EQ(state_, kDrainingDecoder); | 575 DCHECK_EQ(state_, kDrainingDecoder); |
576 state_ = kDecoderDrained; | 576 state_ = kDecoderDrained; |
577 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 577 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
578 } | 578 } |
579 | 579 |
580 void GpuVideoDecoder::NotifyResetDone() { | 580 void GpuVideoDecoder::NotifyResetDone() { |
581 DVLOG(3) << "NotifyResetDone()"; | 581 DVLOG(3) << "NotifyResetDone()"; |
582 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 582 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
583 DCHECK(ready_video_frames_.empty()); | 583 DCHECK(ready_video_frames_.empty()); |
584 | 584 |
585 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 585 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
586 // delivered during the reset can find their time data. | 586 // delivered during the reset can find their time data. |
587 input_buffer_data_.clear(); | 587 input_buffer_data_.clear(); |
588 | 588 |
589 if (!pending_reset_cb_.is_null()) | 589 if (!pending_reset_cb_.is_null()) |
590 base::ResetAndReturn(&pending_reset_cb_).Run(); | 590 base::ResetAndReturn(&pending_reset_cb_).Run(); |
591 | 591 |
592 if (!pending_decode_cb_.is_null()) | 592 if (!pending_decode_cb_.is_null()) |
593 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 593 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
594 } | 594 } |
595 | 595 |
596 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 596 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
597 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 597 DCHECK(gvd_task_runner_->BelongsToCurrentThread()); |
598 if (!vda_) | 598 if (!vda_) |
599 return; | 599 return; |
600 | 600 |
601 DLOG(ERROR) << "VDA Error: " << error; | 601 DLOG(ERROR) << "VDA Error: " << error; |
602 DestroyVDA(); | 602 DestroyVDA(); |
603 | 603 |
604 state_ = kError; | 604 state_ = kError; |
605 | 605 |
606 if (!pending_decode_cb_.is_null()) { | 606 if (!pending_decode_cb_.is_null()) { |
607 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); | 607 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
608 return; | 608 return; |
609 } | 609 } |
610 } | 610 } |
611 | 611 |
612 } // namespace media | 612 } // namespace media |
OLD | NEW |