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 25 matching lines...) Expand all Loading... |
36 // Size of shared-memory segments we allocate. Since we reuse them we let them | 36 // Size of shared-memory segments we allocate. Since we reuse them we let them |
37 // be on the beefy side. | 37 // be on the beefy side. |
38 static const size_t kSharedMemorySegmentBytes = 100 << 10; | 38 static const size_t kSharedMemorySegmentBytes = 100 << 10; |
39 | 39 |
40 GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s) | 40 GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s) |
41 : shm(m), size(s) { | 41 : shm(m), size(s) { |
42 } | 42 } |
43 | 43 |
44 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} | 44 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} |
45 | 45 |
46 GpuVideoDecoder::PendingDecoderBuffer::PendingDecoderBuffer( | 46 GpuVideoDecoder::BufferPair::BufferPair( |
47 SHMBuffer* s, | 47 SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b) |
48 const scoped_refptr<DecoderBuffer>& b, | 48 : shm_buffer(s), buffer(b) { |
49 const DecodeCB& done_cb) | |
50 : shm_buffer(s), buffer(b), done_cb(done_cb) { | |
51 } | 49 } |
52 | 50 |
53 GpuVideoDecoder::PendingDecoderBuffer::~PendingDecoderBuffer() {} | 51 GpuVideoDecoder::BufferPair::~BufferPair() {} |
54 | 52 |
55 GpuVideoDecoder::BufferData::BufferData( | 53 GpuVideoDecoder::BufferData::BufferData( |
56 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns) | 54 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns) |
57 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), | 55 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), |
58 natural_size(ns) { | 56 natural_size(ns) { |
59 } | 57 } |
60 | 58 |
61 GpuVideoDecoder::BufferData::~BufferData() {} | 59 GpuVideoDecoder::BufferData::~BufferData() {} |
62 | 60 |
63 GpuVideoDecoder::GpuVideoDecoder( | 61 GpuVideoDecoder::GpuVideoDecoder( |
(...skipping 13 matching lines...) Expand all Loading... |
77 | 75 |
78 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 76 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
79 DVLOG(3) << "Reset()"; | 77 DVLOG(3) << "Reset()"; |
80 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 78 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
81 | 79 |
82 if (state_ == kDrainingDecoder) { | 80 if (state_ == kDrainingDecoder) { |
83 base::MessageLoop::current()->PostTask( | 81 base::MessageLoop::current()->PostTask( |
84 FROM_HERE, | 82 FROM_HERE, |
85 base::Bind( | 83 base::Bind( |
86 &GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure)); | 84 &GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure)); |
| 85 // NOTE: if we're deferring Reset() until a Flush() completes, return |
| 86 // queued pictures to the VDA so they can be used to finish that Flush(). |
| 87 if (pending_decode_cb_.is_null()) |
| 88 ready_video_frames_.clear(); |
87 return; | 89 return; |
88 } | 90 } |
89 | 91 |
| 92 // Throw away any already-decoded, not-yet-delivered frames. |
| 93 ready_video_frames_.clear(); |
| 94 |
90 if (!vda_) { | 95 if (!vda_) { |
91 base::MessageLoop::current()->PostTask(FROM_HERE, closure); | 96 base::MessageLoop::current()->PostTask(FROM_HERE, closure); |
92 return; | 97 return; |
93 } | 98 } |
94 | 99 |
| 100 if (!pending_decode_cb_.is_null()) |
| 101 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
| 102 |
95 DCHECK(pending_reset_cb_.is_null()); | 103 DCHECK(pending_reset_cb_.is_null()); |
96 pending_reset_cb_ = BindToCurrentLoop(closure); | 104 pending_reset_cb_ = BindToCurrentLoop(closure); |
97 | 105 |
98 vda_->Reset(); | 106 vda_->Reset(); |
99 } | 107 } |
100 | 108 |
101 void GpuVideoDecoder::Stop() { | 109 void GpuVideoDecoder::Stop() { |
102 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 110 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
103 if (vda_) | 111 if (vda_) |
104 DestroyVDA(); | 112 DestroyVDA(); |
105 DCHECK(bitstream_buffers_in_decoder_.empty()); | 113 if (!pending_decode_cb_.is_null()) |
| 114 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
106 if (!pending_reset_cb_.is_null()) | 115 if (!pending_reset_cb_.is_null()) |
107 base::ResetAndReturn(&pending_reset_cb_).Run(); | 116 base::ResetAndReturn(&pending_reset_cb_).Run(); |
108 } | 117 } |
109 | 118 |
110 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { | 119 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { |
111 #if defined(OS_WIN) | 120 #if defined(OS_WIN) |
112 // Windows Media Foundation H.264 decoding does not support decoding videos | 121 // Windows Media Foundation H.264 decoding does not support decoding videos |
113 // with any dimension smaller than 48 pixels: | 122 // with any dimension smaller than 48 pixels: |
114 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815 | 123 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815 |
115 if (coded_size.width() < 48 || coded_size.height() < 48) | 124 if (coded_size.width() < 48 || coded_size.height() < 48) |
(...skipping 26 matching lines...) Expand all Loading... |
142 static void ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB( | 151 static void ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB( |
143 const PipelineStatusCB& cb, | 152 const PipelineStatusCB& cb, |
144 PipelineStatus status) { | 153 PipelineStatus status) { |
145 UMA_HISTOGRAM_ENUMERATION( | 154 UMA_HISTOGRAM_ENUMERATION( |
146 "Media.GpuVideoDecoderInitializeStatus", status, PIPELINE_STATUS_MAX + 1); | 155 "Media.GpuVideoDecoderInitializeStatus", status, PIPELINE_STATUS_MAX + 1); |
147 cb.Run(status); | 156 cb.Run(status); |
148 } | 157 } |
149 | 158 |
150 void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, | 159 void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, |
151 bool live_mode, | 160 bool live_mode, |
152 const PipelineStatusCB& orig_status_cb, | 161 const PipelineStatusCB& orig_status_cb) { |
153 const OutputCB& output_cb) { | |
154 DVLOG(3) << "Initialize()"; | 162 DVLOG(3) << "Initialize()"; |
155 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 163 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
156 DCHECK(config.IsValidConfig()); | 164 DCHECK(config.IsValidConfig()); |
157 DCHECK(!config.is_encrypted()); | 165 DCHECK(!config.is_encrypted()); |
158 | 166 |
159 PipelineStatusCB status_cb = | 167 PipelineStatusCB status_cb = |
160 base::Bind(&ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB, | 168 base::Bind(&ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB, |
161 BindToCurrentLoop(orig_status_cb)); | 169 BindToCurrentLoop(orig_status_cb)); |
162 | 170 |
163 bool previously_initialized = config_.IsValidConfig(); | 171 bool previously_initialized = config_.IsValidConfig(); |
164 DVLOG(1) << "(Re)initializing GVD with config: " | 172 DVLOG(1) << "(Re)initializing GVD with config: " |
165 << config.AsHumanReadableString(); | 173 << config.AsHumanReadableString(); |
166 | 174 |
167 // TODO(posciak): destroy and create a new VDA on codec/profile change | 175 // TODO(posciak): destroy and create a new VDA on codec/profile change |
168 // (http://crbug.com/260224). | 176 // (http://crbug.com/260224). |
169 if (previously_initialized && (config_.profile() != config.profile())) { | 177 if (previously_initialized && (config_.profile() != config.profile())) { |
170 DVLOG(1) << "Codec or profile changed, cannot reinitialize."; | 178 DVLOG(1) << "Codec or profile changed, cannot reinitialize."; |
171 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 179 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
172 return; | 180 return; |
173 } | 181 } |
174 | 182 |
175 if (!IsCodedSizeSupported(config.coded_size())) { | 183 if (!IsCodedSizeSupported(config.coded_size())) { |
176 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 184 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
177 return; | 185 return; |
178 } | 186 } |
179 | 187 |
180 config_ = config; | 188 config_ = config; |
181 needs_bitstream_conversion_ = (config.codec() == kCodecH264); | 189 needs_bitstream_conversion_ = (config.codec() == kCodecH264); |
182 output_cb_ = BindToCurrentLoop(output_cb); | |
183 | 190 |
184 if (previously_initialized) { | 191 if (previously_initialized) { |
185 // Reinitialization with a different config (but same codec and profile). | 192 // Reinitialization with a different config (but same codec and profile). |
186 // VDA should handle it by detecting this in-stream by itself, | 193 // VDA should handle it by detecting this in-stream by itself, |
187 // no need to notify it. | 194 // no need to notify it. |
188 status_cb.Run(PIPELINE_OK); | 195 status_cb.Run(PIPELINE_OK); |
189 return; | 196 return; |
190 } | 197 } |
191 | 198 |
192 vda_ = factories_->CreateVideoDecodeAccelerator().Pass(); | 199 vda_ = factories_->CreateVideoDecodeAccelerator().Pass(); |
(...skipping 30 matching lines...) Expand all Loading... |
223 ++it) { | 230 ++it) { |
224 assigned_picture_buffers_.erase(it->first); | 231 assigned_picture_buffers_.erase(it->first); |
225 } | 232 } |
226 DestroyPictureBuffers(&assigned_picture_buffers_); | 233 DestroyPictureBuffers(&assigned_picture_buffers_); |
227 } | 234 } |
228 | 235 |
229 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 236 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
230 const DecodeCB& decode_cb) { | 237 const DecodeCB& decode_cb) { |
231 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 238 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
232 DCHECK(pending_reset_cb_.is_null()); | 239 DCHECK(pending_reset_cb_.is_null()); |
| 240 DCHECK(pending_decode_cb_.is_null()); |
233 | 241 |
234 DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb); | 242 pending_decode_cb_ = BindToCurrentLoop(decode_cb); |
235 | 243 |
236 if (state_ == kError || !vda_) { | 244 if (state_ == kError || !vda_) { |
237 bound_decode_cb.Run(kDecodeError); | 245 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
238 return; | 246 return; |
239 } | 247 } |
240 | 248 |
241 switch (state_) { | 249 switch (state_) { |
242 case kDecoderDrained: | 250 case kDecoderDrained: |
| 251 if (!ready_video_frames_.empty()) { |
| 252 EnqueueFrameAndTriggerFrameDelivery(NULL); |
| 253 return; |
| 254 } |
243 state_ = kNormal; | 255 state_ = kNormal; |
244 // Fall-through. | 256 // Fall-through. |
245 case kNormal: | 257 case kNormal: |
246 break; | 258 break; |
247 case kDrainingDecoder: | 259 case kDrainingDecoder: |
| 260 DCHECK(buffer->end_of_stream()); |
| 261 // Do nothing. Will be satisfied either by a PictureReady or |
| 262 // NotifyFlushDone below. |
| 263 return; |
248 case kError: | 264 case kError: |
249 NOTREACHED(); | 265 NOTREACHED(); |
250 return; | 266 return; |
251 } | 267 } |
252 | 268 |
253 DCHECK_EQ(state_, kNormal); | |
254 | |
255 if (buffer->end_of_stream()) { | 269 if (buffer->end_of_stream()) { |
256 state_ = kDrainingDecoder; | 270 if (state_ == kNormal) { |
257 eos_decode_cb_ = bound_decode_cb; | 271 state_ = kDrainingDecoder; |
258 vda_->Flush(); | 272 vda_->Flush(); |
| 273 // If we have ready frames, go ahead and process them to ensure that the |
| 274 // Flush operation does not block in the VDA due to lack of picture |
| 275 // buffers. |
| 276 if (!ready_video_frames_.empty()) |
| 277 EnqueueFrameAndTriggerFrameDelivery(NULL); |
| 278 } |
259 return; | 279 return; |
260 } | 280 } |
261 | 281 |
262 size_t size = buffer->data_size(); | 282 size_t size = buffer->data_size(); |
263 SHMBuffer* shm_buffer = GetSHM(size); | 283 SHMBuffer* shm_buffer = GetSHM(size); |
264 if (!shm_buffer) { | 284 if (!shm_buffer) { |
265 bound_decode_cb.Run(kDecodeError); | 285 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
266 return; | 286 return; |
267 } | 287 } |
268 | 288 |
269 memcpy(shm_buffer->shm->memory(), buffer->data(), size); | 289 memcpy(shm_buffer->shm->memory(), buffer->data(), size); |
270 BitstreamBuffer bitstream_buffer( | 290 BitstreamBuffer bitstream_buffer( |
271 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); | 291 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); |
272 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. | 292 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. |
273 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; | 293 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; |
274 DCHECK(!ContainsKey(bitstream_buffers_in_decoder_, bitstream_buffer.id())); | 294 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( |
275 bitstream_buffers_in_decoder_.insert( | 295 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
276 std::make_pair(bitstream_buffer.id(), | 296 DCHECK(inserted); |
277 PendingDecoderBuffer(shm_buffer, buffer, decode_cb))); | |
278 DCHECK_LE(static_cast<int>(bitstream_buffers_in_decoder_.size()), | |
279 kMaxInFlightDecodes); | |
280 RecordBufferData(bitstream_buffer, *buffer.get()); | 297 RecordBufferData(bitstream_buffer, *buffer.get()); |
281 | 298 |
282 vda_->Decode(bitstream_buffer); | 299 vda_->Decode(bitstream_buffer); |
| 300 |
| 301 if (!ready_video_frames_.empty()) { |
| 302 EnqueueFrameAndTriggerFrameDelivery(NULL); |
| 303 return; |
| 304 } |
| 305 |
| 306 if (CanMoreDecodeWorkBeDone()) |
| 307 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); |
| 308 } |
| 309 |
| 310 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { |
| 311 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; |
283 } | 312 } |
284 | 313 |
285 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, | 314 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, |
286 const DecoderBuffer& buffer) { | 315 const DecoderBuffer& buffer) { |
287 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), | 316 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), |
288 buffer.timestamp(), | 317 buffer.timestamp(), |
289 config_.visible_rect(), | 318 config_.visible_rect(), |
290 config_.natural_size())); | 319 config_.natural_size())); |
291 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but | 320 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but |
292 // that's too small for some pathological B-frame test videos. The cost of | 321 // that's too small for some pathological B-frame test videos. The cost of |
(...skipping 23 matching lines...) Expand all Loading... |
316 | 345 |
317 bool GpuVideoDecoder::NeedsBitstreamConversion() const { | 346 bool GpuVideoDecoder::NeedsBitstreamConversion() const { |
318 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 347 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
319 return needs_bitstream_conversion_; | 348 return needs_bitstream_conversion_; |
320 } | 349 } |
321 | 350 |
322 bool GpuVideoDecoder::CanReadWithoutStalling() const { | 351 bool GpuVideoDecoder::CanReadWithoutStalling() const { |
323 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 352 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
324 return | 353 return |
325 next_picture_buffer_id_ == 0 || // Decode() will ProvidePictureBuffers(). | 354 next_picture_buffer_id_ == 0 || // Decode() will ProvidePictureBuffers(). |
326 available_pictures_ > 0; | 355 available_pictures_ > 0 || !ready_video_frames_.empty(); |
327 } | |
328 | |
329 int GpuVideoDecoder::GetMaxDecodeRequests() const { | |
330 return kMaxInFlightDecodes; | |
331 } | 356 } |
332 | 357 |
333 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, | 358 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, |
334 const gfx::Size& size, | 359 const gfx::Size& size, |
335 uint32 texture_target) { | 360 uint32 texture_target) { |
336 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " | 361 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " |
337 << size.width() << "x" << size.height() << ")"; | 362 << size.width() << "x" << size.height() << ")"; |
338 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 363 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
339 | 364 |
340 std::vector<uint32> texture_ids; | 365 std::vector<uint32> texture_ids; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 timestamp, | 478 timestamp, |
454 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect))); | 479 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect))); |
455 CHECK_GT(available_pictures_, 0); | 480 CHECK_GT(available_pictures_, 0); |
456 --available_pictures_; | 481 --available_pictures_; |
457 bool inserted = | 482 bool inserted = |
458 picture_buffers_at_display_.insert(std::make_pair( | 483 picture_buffers_at_display_.insert(std::make_pair( |
459 picture.picture_buffer_id(), | 484 picture.picture_buffer_id(), |
460 pb.texture_id())).second; | 485 pb.texture_id())).second; |
461 DCHECK(inserted); | 486 DCHECK(inserted); |
462 | 487 |
463 DeliverFrame(frame); | 488 EnqueueFrameAndTriggerFrameDelivery(frame); |
464 } | 489 } |
465 | 490 |
466 void GpuVideoDecoder::DeliverFrame( | 491 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
467 const scoped_refptr<VideoFrame>& frame) { | 492 const scoped_refptr<VideoFrame>& frame) { |
468 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 493 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
469 | 494 |
470 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the | 495 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the |
471 // floor and return. | 496 // floor and return. |
472 if (!pending_reset_cb_.is_null()) | 497 if (!pending_reset_cb_.is_null()) |
473 return; | 498 return; |
474 | 499 |
475 output_cb_.Run(frame); | 500 if (frame.get()) |
| 501 ready_video_frames_.push_back(frame); |
| 502 else |
| 503 DCHECK(!ready_video_frames_.empty()); |
| 504 |
| 505 if (pending_decode_cb_.is_null()) |
| 506 return; |
| 507 |
| 508 base::ResetAndReturn(&pending_decode_cb_) |
| 509 .Run(kOk, ready_video_frames_.front()); |
| 510 ready_video_frames_.pop_front(); |
476 } | 511 } |
477 | 512 |
478 // static | 513 // static |
479 void GpuVideoDecoder::ReleaseMailbox( | 514 void GpuVideoDecoder::ReleaseMailbox( |
480 base::WeakPtr<GpuVideoDecoder> decoder, | 515 base::WeakPtr<GpuVideoDecoder> decoder, |
481 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, | 516 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
482 int64 picture_buffer_id, | 517 int64 picture_buffer_id, |
483 uint32 texture_id, | 518 uint32 texture_id, |
484 const std::vector<uint32>& release_sync_points) { | 519 const std::vector<uint32>& release_sync_points) { |
485 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); | 520 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 | 573 |
539 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { | 574 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { |
540 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 575 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
541 available_shm_segments_.push_back(shm_buffer); | 576 available_shm_segments_.push_back(shm_buffer); |
542 } | 577 } |
543 | 578 |
544 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { | 579 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
545 DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")"; | 580 DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")"; |
546 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 581 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
547 | 582 |
548 std::map<int32, PendingDecoderBuffer>::iterator it = | 583 std::map<int32, BufferPair>::iterator it = |
549 bitstream_buffers_in_decoder_.find(id); | 584 bitstream_buffers_in_decoder_.find(id); |
550 if (it == bitstream_buffers_in_decoder_.end()) { | 585 if (it == bitstream_buffers_in_decoder_.end()) { |
551 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 586 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
552 NOTREACHED() << "Missing bitstream buffer: " << id; | 587 NOTREACHED() << "Missing bitstream buffer: " << id; |
553 return; | 588 return; |
554 } | 589 } |
555 | 590 |
556 PutSHM(it->second.shm_buffer); | 591 PutSHM(it->second.shm_buffer); |
557 it->second.done_cb.Run(state_ == kError ? kDecodeError : kOk); | |
558 bitstream_buffers_in_decoder_.erase(it); | 592 bitstream_buffers_in_decoder_.erase(it); |
| 593 |
| 594 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && |
| 595 CanMoreDecodeWorkBeDone() && !pending_decode_cb_.is_null()) { |
| 596 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); |
| 597 } |
559 } | 598 } |
560 | 599 |
561 GpuVideoDecoder::~GpuVideoDecoder() { | 600 GpuVideoDecoder::~GpuVideoDecoder() { |
562 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 601 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
563 // Stop should have been already called. | 602 // Stop should have been already called. |
564 DCHECK(!vda_.get() && assigned_picture_buffers_.empty()); | 603 DCHECK(!vda_.get() && assigned_picture_buffers_.empty()); |
565 DCHECK(bitstream_buffers_in_decoder_.empty()); | 604 DCHECK(pending_decode_cb_.is_null()); |
566 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { | 605 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
567 available_shm_segments_[i]->shm->Close(); | 606 available_shm_segments_[i]->shm->Close(); |
568 delete available_shm_segments_[i]; | 607 delete available_shm_segments_[i]; |
569 } | 608 } |
570 available_shm_segments_.clear(); | 609 available_shm_segments_.clear(); |
571 for (std::map<int32, PendingDecoderBuffer>::iterator it = | 610 for (std::map<int32, BufferPair>::iterator it = |
572 bitstream_buffers_in_decoder_.begin(); | 611 bitstream_buffers_in_decoder_.begin(); |
573 it != bitstream_buffers_in_decoder_.end(); ++it) { | 612 it != bitstream_buffers_in_decoder_.end(); ++it) { |
574 it->second.shm_buffer->shm->Close(); | 613 it->second.shm_buffer->shm->Close(); |
575 } | 614 } |
576 bitstream_buffers_in_decoder_.clear(); | 615 bitstream_buffers_in_decoder_.clear(); |
577 } | 616 } |
578 | 617 |
579 void GpuVideoDecoder::NotifyFlushDone() { | 618 void GpuVideoDecoder::NotifyFlushDone() { |
580 DVLOG(3) << "NotifyFlushDone()"; | 619 DVLOG(3) << "NotifyFlushDone()"; |
581 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 620 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
582 DCHECK_EQ(state_, kDrainingDecoder); | 621 DCHECK_EQ(state_, kDrainingDecoder); |
583 state_ = kDecoderDrained; | 622 state_ = kDecoderDrained; |
584 DeliverFrame(VideoFrame::CreateEOSFrame()); | 623 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
585 base::ResetAndReturn(&eos_decode_cb_).Run(kOk); | |
586 } | 624 } |
587 | 625 |
588 void GpuVideoDecoder::NotifyResetDone() { | 626 void GpuVideoDecoder::NotifyResetDone() { |
589 DVLOG(3) << "NotifyResetDone()"; | 627 DVLOG(3) << "NotifyResetDone()"; |
590 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 628 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
591 DCHECK(bitstream_buffers_in_decoder_.empty()); | 629 DCHECK(ready_video_frames_.empty()); |
592 | 630 |
593 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 631 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
594 // delivered during the reset can find their time data. | 632 // delivered during the reset can find their time data. |
595 input_buffer_data_.clear(); | 633 input_buffer_data_.clear(); |
596 | 634 |
597 if (!pending_reset_cb_.is_null()) | 635 if (!pending_reset_cb_.is_null()) |
598 base::ResetAndReturn(&pending_reset_cb_).Run(); | 636 base::ResetAndReturn(&pending_reset_cb_).Run(); |
| 637 |
| 638 if (!pending_decode_cb_.is_null()) |
| 639 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
599 } | 640 } |
600 | 641 |
601 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 642 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
602 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 643 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
603 if (!vda_) | 644 if (!vda_) |
604 return; | 645 return; |
605 | 646 |
| 647 DLOG(ERROR) << "VDA Error: " << error; |
| 648 DestroyVDA(); |
| 649 |
606 state_ = kError; | 650 state_ = kError; |
607 | 651 |
608 DLOG(ERROR) << "VDA Error: " << error; | 652 if (!pending_decode_cb_.is_null()) { |
609 DestroyVDA(); | 653 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
| 654 return; |
| 655 } |
610 } | 656 } |
611 | 657 |
612 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 658 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
613 const { | 659 const { |
614 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 660 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
615 } | 661 } |
616 | 662 |
617 } // namespace media | 663 } // namespace media |
OLD | NEW |