Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: media/filters/gpu_video_decoder.cc

Issue 16274005: Separate DemuxerStream and VideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win64 Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | media/filters/video_decoder_selector.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
9 #include "base/cpu.h" 11 #include "base/cpu.h"
10 #include "base/message_loop.h" 12 #include "base/message_loop.h"
11 #include "base/stl_util.h" 13 #include "base/stl_util.h"
12 #include "base/task_runner_util.h" 14 #include "base/task_runner_util.h"
13 #include "media/base/bind_to_loop.h" 15 #include "media/base/bind_to_loop.h"
14 #include "media/base/decoder_buffer.h" 16 #include "media/base/decoder_buffer.h"
15 #include "media/base/demuxer_stream.h"
16 #include "media/base/pipeline.h" 17 #include "media/base/pipeline.h"
17 #include "media/base/pipeline_status.h" 18 #include "media/base/pipeline_status.h"
18 #include "media/base/video_decoder_config.h" 19 #include "media/base/video_decoder_config.h"
19 20
20 namespace media { 21 namespace media {
21 22
22 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to 23 // Proxies calls to a VideoDecodeAccelerator::Client from the calling thread to
23 // the client's thread. 24 // the client's thread.
24 // 25 //
25 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories 26 // TODO(scherkus): VDAClientProxy should hold onto GpuVideoDecoder::Factories
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns) 154 int32 bbid, base::TimeDelta ts, const gfx::Rect& vr, const gfx::Size& ns)
154 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr), 155 : bitstream_buffer_id(bbid), timestamp(ts), visible_rect(vr),
155 natural_size(ns) { 156 natural_size(ns) {
156 } 157 }
157 158
158 GpuVideoDecoder::BufferData::~BufferData() {} 159 GpuVideoDecoder::BufferData::~BufferData() {}
159 160
160 GpuVideoDecoder::GpuVideoDecoder( 161 GpuVideoDecoder::GpuVideoDecoder(
161 const scoped_refptr<base::MessageLoopProxy>& message_loop, 162 const scoped_refptr<base::MessageLoopProxy>& message_loop,
162 const scoped_refptr<Factories>& factories) 163 const scoped_refptr<Factories>& factories)
163 : demuxer_stream_(NULL), 164 : needs_bitstream_conversion_(false),
164 needs_bitstream_conversion_(false),
165 gvd_loop_proxy_(message_loop), 165 gvd_loop_proxy_(message_loop),
166 weak_factory_(this), 166 weak_factory_(this),
167 vda_loop_proxy_(factories->GetMessageLoop()), 167 vda_loop_proxy_(factories->GetMessageLoop()),
168 factories_(factories), 168 factories_(factories),
169 state_(kNormal), 169 state_(kNormal),
170 demuxer_read_in_progress_(false),
171 decoder_texture_target_(0), 170 decoder_texture_target_(0),
172 next_picture_buffer_id_(0), 171 next_picture_buffer_id_(0),
173 next_bitstream_buffer_id_(0), 172 next_bitstream_buffer_id_(0),
174 available_pictures_(0) { 173 available_pictures_(0) {
175 DCHECK(factories_.get()); 174 DCHECK(factories_.get());
176 } 175 }
177 176
178 void GpuVideoDecoder::Reset(const base::Closure& closure) { 177 void GpuVideoDecoder::Reset(const base::Closure& closure) {
178 DVLOG(3) << "Reset()";
179 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 179 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
180 180
181 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { 181 if (state_ == kDrainingDecoder && !factories_->IsAborted()) {
182 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 182 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
183 &GpuVideoDecoder::Reset, weak_this_, closure)); 183 &GpuVideoDecoder::Reset, weak_this_, closure));
184 // NOTE: if we're deferring Reset() until a Flush() completes, return 184 // NOTE: if we're deferring Reset() until a Flush() completes, return
185 // queued pictures to the VDA so they can be used to finish that Flush(). 185 // queued pictures to the VDA so they can be used to finish that Flush().
186 if (pending_read_cb_.is_null()) 186 if (pending_read_cb_.is_null())
187 ready_video_frames_.clear(); 187 ready_video_frames_.clear();
188 return; 188 return;
(...skipping 18 matching lines...) Expand all
207 } 207 }
208 208
209 void GpuVideoDecoder::Stop(const base::Closure& closure) { 209 void GpuVideoDecoder::Stop(const base::Closure& closure) {
210 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 210 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
211 if (vda_) 211 if (vda_)
212 DestroyVDA(); 212 DestroyVDA();
213 if (!pending_read_cb_.is_null()) 213 if (!pending_read_cb_.is_null())
214 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 214 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
215 if (!pending_reset_cb_.is_null()) 215 if (!pending_reset_cb_.is_null())
216 base::ResetAndReturn(&pending_reset_cb_).Run(); 216 base::ResetAndReturn(&pending_reset_cb_).Run();
217 demuxer_stream_ = NULL;
218 BindToCurrentLoop(closure).Run(); 217 BindToCurrentLoop(closure).Run();
219 } 218 }
220 219
221 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { 220 static bool IsCodedSizeSupported(const gfx::Size& coded_size) {
222 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. 221 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080.
223 // We test against 1088 to account for 16x16 macroblocks. 222 // We test against 1088 to account for 16x16 macroblocks.
224 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) 223 if (coded_size.width() <= 1920 && coded_size.height() <= 1088)
225 return true; 224 return true;
226 225
227 base::CPU cpu; 226 base::CPU cpu;
228 bool hw_large_video_support = 227 bool hw_large_video_support =
229 (cpu.vendor_name() == "GenuineIntel") && cpu.model() >= 58; 228 (cpu.vendor_name() == "GenuineIntel") && cpu.model() >= 58;
230 bool os_large_video_support = true; 229 bool os_large_video_support = true;
231 #if defined(OS_WIN) 230 #if defined(OS_WIN)
232 os_large_video_support = false; 231 os_large_video_support = false;
233 #endif 232 #endif
234 return os_large_video_support && hw_large_video_support; 233 return os_large_video_support && hw_large_video_support;
235 } 234 }
236 235
237 void GpuVideoDecoder::Initialize(DemuxerStream* stream, 236 void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config,
238 const PipelineStatusCB& orig_status_cb, 237 const PipelineStatusCB& orig_status_cb,
239 const StatisticsCB& statistics_cb) { 238 const StatisticsCB& statistics_cb) {
239 DVLOG(3) << "Initialize()";
240 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 240 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
241 DCHECK(stream); 241 DCHECK(config.IsValidConfig());
242 DCHECK(!config.is_encrypted());
242 243
243 weak_this_ = weak_factory_.GetWeakPtr(); 244 weak_this_ = weak_factory_.GetWeakPtr();
244 245
245 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( 246 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB(
246 "Media.GpuVideoDecoderInitializeStatus", 247 "Media.GpuVideoDecoderInitializeStatus",
247 BindToCurrentLoop(orig_status_cb)); 248 BindToCurrentLoop(orig_status_cb));
248 249
249 if (demuxer_stream_) { 250 if (config_.IsValidConfig()) {
250 // TODO(xhwang): Make GpuVideoDecoder reinitializable. 251 // TODO(xhwang): Make GpuVideoDecoder reinitializable.
251 // See http://crbug.com/233608 252 // See http://crbug.com/233608
252 DVLOG(1) << "GpuVideoDecoder reinitialization not supported."; 253 DVLOG(1) << "GpuVideoDecoder reinitialization not supported.";
253 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 254 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
254 return; 255 return;
255 } 256 }
256 257
257 const VideoDecoderConfig& config = stream->video_decoder_config();
258 DCHECK(config.IsValidConfig());
259 DCHECK(!config.is_encrypted());
260
261 if (!IsCodedSizeSupported(config.coded_size())) { 258 if (!IsCodedSizeSupported(config.coded_size())) {
262 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 259 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
263 return; 260 return;
264 } 261 }
265 262
266 client_proxy_ = new VDAClientProxy(this); 263 client_proxy_ = new VDAClientProxy(this);
267 VideoDecodeAccelerator* vda = factories_->CreateVideoDecodeAccelerator( 264 VideoDecodeAccelerator* vda = factories_->CreateVideoDecodeAccelerator(
268 config.profile(), client_proxy_.get()); 265 config.profile(), client_proxy_.get());
269 if (!vda) { 266 if (!vda) {
270 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 267 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
271 return; 268 return;
272 } 269 }
273 270
274 demuxer_stream_ = stream; 271 config_ = config;
275 statistics_cb_ = statistics_cb; 272 statistics_cb_ = statistics_cb;
276 needs_bitstream_conversion_ = (config.codec() == kCodecH264); 273 needs_bitstream_conversion_ = (config.codec() == kCodecH264);
277 274
278 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; 275 DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded.";
279 PostTaskAndReplyWithResult( 276 PostTaskAndReplyWithResult(
280 vda_loop_proxy_.get(), 277 vda_loop_proxy_.get(),
281 FROM_HERE, 278 FROM_HERE,
282 base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)), 279 base::Bind(&VideoDecodeAccelerator::AsWeakPtr, base::Unretained(vda)),
283 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda)); 280 base::Bind(&GpuVideoDecoder::SetVDA, weak_this_, status_cb, vda));
284 } 281 }
285 282
286 void GpuVideoDecoder::SetVDA( 283 void GpuVideoDecoder::SetVDA(
287 const PipelineStatusCB& status_cb, 284 const PipelineStatusCB& status_cb,
288 VideoDecodeAccelerator* vda, 285 VideoDecodeAccelerator* vda,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 323 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
327 &DestroyVDAWithClientProxy, client_proxy_, weak_vda_)); 324 &DestroyVDAWithClientProxy, client_proxy_, weak_vda_));
328 325
329 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); 326 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
330 client_proxy_->Detach(); 327 client_proxy_->Detach();
331 client_proxy_ = NULL; 328 client_proxy_ = NULL;
332 329
333 DestroyTextures(); 330 DestroyTextures();
334 } 331 }
335 332
336 void GpuVideoDecoder::Read(const ReadCB& read_cb) { 333 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
334 const ReadCB& read_cb) {
337 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 335 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
338 DCHECK(pending_reset_cb_.is_null()); 336 DCHECK(pending_reset_cb_.is_null());
339 DCHECK(pending_read_cb_.is_null()); 337 DCHECK(pending_read_cb_.is_null());
338
340 pending_read_cb_ = BindToCurrentLoop(read_cb); 339 pending_read_cb_ = BindToCurrentLoop(read_cb);
341 340
342 if (state_ == kError) { 341 if (state_ == kError || !vda_) {
343 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 342 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
344 return; 343 return;
345 } 344 }
346 345
347 // TODO(xhwang): It's odd that we return kOk after VDA has been released.
348 // Fix this and simplify cases.
349 if (!vda_) {
350 base::ResetAndReturn(&pending_read_cb_).Run(
351 kOk, VideoFrame::CreateEmptyFrame());
352 return;
353 }
354
355 if (!ready_video_frames_.empty()) {
356 EnqueueFrameAndTriggerFrameDelivery(NULL);
357 return;
358 }
359
360 switch (state_) { 346 switch (state_) {
361 case kDecoderDrained: 347 case kDecoderDrained:
348 if (!ready_video_frames_.empty()) {
349 EnqueueFrameAndTriggerFrameDelivery(NULL);
350 return;
351 }
362 state_ = kNormal; 352 state_ = kNormal;
363 // Fall-through. 353 // Fall-through.
364 case kNormal: 354 case kNormal:
365 EnsureDemuxOrDecode();
366 break; 355 break;
367 case kDrainingDecoder: 356 case kDrainingDecoder:
357 DCHECK(buffer->IsEndOfStream());
368 // Do nothing. Will be satisfied either by a PictureReady or 358 // Do nothing. Will be satisfied either by a PictureReady or
369 // NotifyFlushDone below. 359 // NotifyFlushDone below.
370 break; 360 return;
371 case kError: 361 case kError:
372 NOTREACHED(); 362 NOTREACHED();
373 break;
374 }
375 }
376
377 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() {
378 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
379 }
380
381 void GpuVideoDecoder::RequestBufferDecode(
382 DemuxerStream::Status status,
383 const scoped_refptr<DecoderBuffer>& buffer) {
384 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
385 DCHECK_EQ(status != DemuxerStream::kOk, !buffer.get()) << status;
386
387 demuxer_read_in_progress_ = false;
388
389 if (status == DemuxerStream::kAborted) {
390 if (pending_read_cb_.is_null())
391 return; 363 return;
392 base::ResetAndReturn(&pending_read_cb_).Run(kOk, NULL);
393 return;
394 }
395
396 // VideoFrameStream ensures no kConfigChanged is passed to VideoDecoders.
397 DCHECK_EQ(status, DemuxerStream::kOk) << status;
398
399 if (!vda_) {
400 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
401 return;
402 } 364 }
403 365
404 if (buffer->IsEndOfStream()) { 366 if (buffer->IsEndOfStream()) {
405 if (state_ == kNormal) { 367 if (state_ == kNormal) {
406 state_ = kDrainingDecoder; 368 state_ = kDrainingDecoder;
407 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 369 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
408 &VideoDecodeAccelerator::Flush, weak_vda_)); 370 &VideoDecodeAccelerator::Flush, weak_vda_));
409 } 371 }
410 return; 372 return;
411 } 373 }
412 374
413 if (!pending_reset_cb_.is_null())
414 return;
415
416 size_t size = buffer->GetDataSize(); 375 size_t size = buffer->GetDataSize();
417 SHMBuffer* shm_buffer = GetSHM(size); 376 SHMBuffer* shm_buffer = GetSHM(size);
418 if (!shm_buffer) 377 if (!shm_buffer) {
378 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
419 return; 379 return;
380 }
420 381
421 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size); 382 memcpy(shm_buffer->shm->memory(), buffer->GetData(), size);
422 BitstreamBuffer bitstream_buffer( 383 BitstreamBuffer bitstream_buffer(
423 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); 384 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size);
424 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. 385 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
425 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; 386 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
426 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( 387 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair(
427 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; 388 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
428 DCHECK(inserted); 389 DCHECK(inserted);
429 RecordBufferData(bitstream_buffer, *buffer.get()); 390 RecordBufferData(bitstream_buffer, *buffer.get());
430 391
431 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 392 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
432 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer)); 393 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer));
433 394
434 if (CanMoreDecodeWorkBeDone()) { 395 if (!ready_video_frames_.empty()) {
435 // Force post here to prevent reentrancy into DemuxerStream. 396 EnqueueFrameAndTriggerFrameDelivery(NULL);
436 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 397 return;
437 &GpuVideoDecoder::EnsureDemuxOrDecode, weak_this_));
438 } 398 }
399
400 if (CanMoreDecodeWorkBeDone())
401 base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL);
439 } 402 }
440 403
441 void GpuVideoDecoder::RecordBufferData( 404 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() {
442 const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer) { 405 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
443 input_buffer_data_.push_front(BufferData( 406 }
444 bitstream_buffer.id(), buffer.GetTimestamp(), 407
445 demuxer_stream_->video_decoder_config().visible_rect(), 408 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer,
446 demuxer_stream_->video_decoder_config().natural_size())); 409 const DecoderBuffer& buffer) {
410 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(),
411 buffer.GetTimestamp(),
412 config_.visible_rect(),
413 config_.natural_size()));
447 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but 414 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
448 // that's too small for some pathological B-frame test videos. The cost of 415 // that's too small for some pathological B-frame test videos. The cost of
449 // using too-high a value is low (192 bits per extra slot). 416 // using too-high a value is low (192 bits per extra slot).
450 static const size_t kMaxInputBufferDataSize = 128; 417 static const size_t kMaxInputBufferDataSize = 128;
451 // Pop from the back of the list, because that's the oldest and least likely 418 // Pop from the back of the list, because that's the oldest and least likely
452 // to be useful in the future data. 419 // to be useful in the future data.
453 if (input_buffer_data_.size() > kMaxInputBufferDataSize) 420 if (input_buffer_data_.size() > kMaxInputBufferDataSize)
454 input_buffer_data_.pop_back(); 421 input_buffer_data_.pop_back();
455 } 422 }
456 423
(...skipping 28 matching lines...) Expand all
485 return available_pictures_ > 0 || !ready_video_frames_.empty(); 452 return available_pictures_ > 0 || !ready_video_frames_.empty();
486 } 453 }
487 454
488 void GpuVideoDecoder::NotifyInitializeDone() { 455 void GpuVideoDecoder::NotifyInitializeDone() {
489 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; 456 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!";
490 } 457 }
491 458
492 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, 459 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
493 const gfx::Size& size, 460 const gfx::Size& size,
494 uint32 texture_target) { 461 uint32 texture_target) {
462 DVLOG(3) << "ProvidePictureBuffers(" << count << ", "
463 << size.width() << "x" << size.height() << ")";
495 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 464 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
496 465
497 std::vector<uint32> texture_ids; 466 std::vector<uint32> texture_ids;
498 std::vector<gpu::Mailbox> texture_mailboxes; 467 std::vector<gpu::Mailbox> texture_mailboxes;
499 decoder_texture_target_ = texture_target; 468 decoder_texture_target_ = texture_target;
500 // Discards the sync point returned here since PictureReady will imply that 469 // Discards the sync point returned here since PictureReady will imply that
501 // the produce has already happened, and the texture is ready for use. 470 // the produce has already happened, and the texture is ready for use.
502 if (!factories_->CreateTextures(count, 471 if (!factories_->CreateTextures(count,
503 size, 472 size,
504 &texture_ids, 473 &texture_ids,
(...skipping 18 matching lines...) Expand all
523 } 492 }
524 493
525 available_pictures_ += count; 494 available_pictures_ += count;
526 495
527 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 496 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
528 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, 497 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_,
529 picture_buffers)); 498 picture_buffers));
530 } 499 }
531 500
532 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { 501 void GpuVideoDecoder::DismissPictureBuffer(int32 id) {
502 DVLOG(3) << "DismissPictureBuffer(" << id << ")";
533 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 503 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
534 504
535 std::map<int32, PictureBuffer>::iterator it = 505 std::map<int32, PictureBuffer>::iterator it =
536 assigned_picture_buffers_.find(id); 506 assigned_picture_buffers_.find(id);
537 if (it == assigned_picture_buffers_.end()) { 507 if (it == assigned_picture_buffers_.end()) {
538 NOTREACHED() << "Missing picture buffer: " << id; 508 NOTREACHED() << "Missing picture buffer: " << id;
539 return; 509 return;
540 } 510 }
541 511
542 PictureBuffer buffer_to_dismiss = it->second; 512 PictureBuffer buffer_to_dismiss = it->second;
543 assigned_picture_buffers_.erase(it); 513 assigned_picture_buffers_.erase(it);
544 514
545 std::set<int32>::iterator at_display_it = 515 std::set<int32>::iterator at_display_it =
546 picture_buffers_at_display_.find(id); 516 picture_buffers_at_display_.find(id);
547 517
548 if (at_display_it == picture_buffers_at_display_.end()) { 518 if (at_display_it == picture_buffers_at_display_.end()) {
549 // We can delete the texture immediately as it's not being displayed. 519 // We can delete the texture immediately as it's not being displayed.
550 factories_->DeleteTexture(buffer_to_dismiss.texture_id()); 520 factories_->DeleteTexture(buffer_to_dismiss.texture_id());
551 CHECK_GT(available_pictures_, 0); 521 CHECK_GT(available_pictures_, 0);
552 --available_pictures_; 522 --available_pictures_;
553 } else { 523 } else {
554 // Texture in display. Postpone deletion until after it's returned to us. 524 // Texture in display. Postpone deletion until after it's returned to us.
555 bool inserted = dismissed_picture_buffers_.insert(std::make_pair( 525 bool inserted = dismissed_picture_buffers_.insert(std::make_pair(
556 id, buffer_to_dismiss)).second; 526 id, buffer_to_dismiss)).second;
557 DCHECK(inserted); 527 DCHECK(inserted);
558 } 528 }
559 } 529 }
560 530
561 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { 531 void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
532 DVLOG(3) << "PictureReady()";
562 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 533 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
563 534
564 std::map<int32, PictureBuffer>::iterator it = 535 std::map<int32, PictureBuffer>::iterator it =
565 assigned_picture_buffers_.find(picture.picture_buffer_id()); 536 assigned_picture_buffers_.find(picture.picture_buffer_id());
566 if (it == assigned_picture_buffers_.end()) { 537 if (it == assigned_picture_buffers_.end()) {
567 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); 538 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id();
568 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); 539 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
569 return; 540 return;
570 } 541 }
571 const PictureBuffer& pb = it->second; 542 const PictureBuffer& pb = it->second;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 589
619 if (pending_read_cb_.is_null()) 590 if (pending_read_cb_.is_null())
620 return; 591 return;
621 592
622 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); 593 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front());
623 ready_video_frames_.pop_front(); 594 ready_video_frames_.pop_front();
624 } 595 }
625 596
626 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, 597 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id,
627 uint32 sync_point) { 598 uint32 sync_point) {
599 DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")";
628 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 600 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
629 601
630 if (!vda_) 602 if (!vda_)
631 return; 603 return;
632 604
633 CHECK(!picture_buffers_at_display_.empty()); 605 CHECK(!picture_buffers_at_display_.empty());
634 606
635 size_t num_erased = picture_buffers_at_display_.erase(picture_buffer_id); 607 size_t num_erased = picture_buffers_at_display_.erase(picture_buffer_id);
636 DCHECK(num_erased); 608 DCHECK(num_erased);
637 609
638 std::map<int32, PictureBuffer>::iterator it = 610 std::map<int32, PictureBuffer>::iterator it =
639 assigned_picture_buffers_.find(picture_buffer_id); 611 assigned_picture_buffers_.find(picture_buffer_id);
640 612
641 if (it == assigned_picture_buffers_.end()) { 613 if (it == assigned_picture_buffers_.end()) {
642 // This picture was dismissed while in display, so we postponed deletion. 614 // This picture was dismissed while in display, so we postponed deletion.
643 it = dismissed_picture_buffers_.find(picture_buffer_id); 615 it = dismissed_picture_buffers_.find(picture_buffer_id);
644 DCHECK(it != dismissed_picture_buffers_.end()); 616 DCHECK(it != dismissed_picture_buffers_.end());
645 factories_->DeleteTexture(it->second.texture_id()); 617 factories_->DeleteTexture(it->second.texture_id());
646 dismissed_picture_buffers_.erase(it); 618 dismissed_picture_buffers_.erase(it);
647 return; 619 return;
648 } 620 }
649 621
650 factories_->WaitSyncPoint(sync_point); 622 factories_->WaitSyncPoint(sync_point);
651
652 ++available_pictures_; 623 ++available_pictures_;
653 624
654 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 625 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
655 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, 626 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_,
656 picture_buffer_id)); 627 picture_buffer_id));
657 } 628 }
658 629
659 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { 630 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) {
660 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 631 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
661 if (available_shm_segments_.empty() || 632 if (available_shm_segments_.empty() ||
662 available_shm_segments_.back()->size < min_size) { 633 available_shm_segments_.back()->size < min_size) {
663 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); 634 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes);
664 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate); 635 base::SharedMemory* shm = factories_->CreateSharedMemory(size_to_allocate);
665 // CreateSharedMemory() can return NULL during Shutdown. 636 // CreateSharedMemory() can return NULL during Shutdown.
666 if (!shm) 637 if (!shm)
667 return NULL; 638 return NULL;
668 return new SHMBuffer(shm, size_to_allocate); 639 return new SHMBuffer(shm, size_to_allocate);
669 } 640 }
670 SHMBuffer* ret = available_shm_segments_.back(); 641 SHMBuffer* ret = available_shm_segments_.back();
671 available_shm_segments_.pop_back(); 642 available_shm_segments_.pop_back();
672 return ret; 643 return ret;
673 } 644 }
674 645
675 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) { 646 void GpuVideoDecoder::PutSHM(SHMBuffer* shm_buffer) {
676 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 647 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
677 available_shm_segments_.push_back(shm_buffer); 648 available_shm_segments_.push_back(shm_buffer);
678 } 649 }
679 650
680 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { 651 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
652 DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")";
681 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 653 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
682 654
683 std::map<int32, BufferPair>::iterator it = 655 std::map<int32, BufferPair>::iterator it =
684 bitstream_buffers_in_decoder_.find(id); 656 bitstream_buffers_in_decoder_.find(id);
685 if (it == bitstream_buffers_in_decoder_.end()) { 657 if (it == bitstream_buffers_in_decoder_.end()) {
686 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); 658 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
687 NOTREACHED() << "Missing bitstream buffer: " << id; 659 NOTREACHED() << "Missing bitstream buffer: " << id;
688 return; 660 return;
689 } 661 }
690 662
691 PutSHM(it->second.shm_buffer); 663 PutSHM(it->second.shm_buffer);
692 const scoped_refptr<DecoderBuffer>& buffer = it->second.buffer; 664 const scoped_refptr<DecoderBuffer>& buffer = it->second.buffer;
693 if (buffer->GetDataSize()) { 665 if (buffer->GetDataSize()) {
694 PipelineStatistics statistics; 666 PipelineStatistics statistics;
695 statistics.video_bytes_decoded = buffer->GetDataSize(); 667 statistics.video_bytes_decoded = buffer->GetDataSize();
696 statistics_cb_.Run(statistics); 668 statistics_cb_.Run(statistics);
697 } 669 }
698 bitstream_buffers_in_decoder_.erase(it); 670 bitstream_buffers_in_decoder_.erase(it);
699 671
700 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && 672 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder &&
701 CanMoreDecodeWorkBeDone()) { 673 CanMoreDecodeWorkBeDone() && !pending_read_cb_.is_null()) {
702 EnsureDemuxOrDecode(); 674 base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL);
703 } 675 }
704 } 676 }
705 677
706 GpuVideoDecoder::~GpuVideoDecoder() { 678 GpuVideoDecoder::~GpuVideoDecoder() {
707 DCHECK(!vda_.get()); // Stop should have been already called. 679 DCHECK(!vda_.get()); // Stop should have been already called.
708 DCHECK(pending_read_cb_.is_null()); 680 DCHECK(pending_read_cb_.is_null());
709 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { 681 for (size_t i = 0; i < available_shm_segments_.size(); ++i) {
710 available_shm_segments_[i]->shm->Close(); 682 available_shm_segments_[i]->shm->Close();
711 delete available_shm_segments_[i]; 683 delete available_shm_segments_[i];
712 } 684 }
713 available_shm_segments_.clear(); 685 available_shm_segments_.clear();
714 for (std::map<int32, BufferPair>::iterator it = 686 for (std::map<int32, BufferPair>::iterator it =
715 bitstream_buffers_in_decoder_.begin(); 687 bitstream_buffers_in_decoder_.begin();
716 it != bitstream_buffers_in_decoder_.end(); ++it) { 688 it != bitstream_buffers_in_decoder_.end(); ++it) {
717 it->second.shm_buffer->shm->Close(); 689 it->second.shm_buffer->shm->Close();
718 } 690 }
719 bitstream_buffers_in_decoder_.clear(); 691 bitstream_buffers_in_decoder_.clear();
720 692
721 DestroyTextures(); 693 DestroyTextures();
722 } 694 }
723 695
724 void GpuVideoDecoder::EnsureDemuxOrDecode() {
725 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
726
727 // The second condition can happen during the tear-down process.
728 // GpuVideoDecoder::Stop() returns the |pending_read_cb_| immediately without
729 // waiting for the demuxer read to be returned. Therefore, this function could
730 // be called even after the decoder has been stopped.
731 if (demuxer_read_in_progress_ || !demuxer_stream_)
732 return;
733
734 demuxer_read_in_progress_ = true;
735 demuxer_stream_->Read(base::Bind(
736 &GpuVideoDecoder::RequestBufferDecode, weak_this_));
737 }
738
739 void GpuVideoDecoder::NotifyFlushDone() { 696 void GpuVideoDecoder::NotifyFlushDone() {
697 DVLOG(3) << "NotifyFlushDone()";
740 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 698 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
741 DCHECK_EQ(state_, kDrainingDecoder); 699 DCHECK_EQ(state_, kDrainingDecoder);
742 state_ = kDecoderDrained; 700 state_ = kDecoderDrained;
743 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 701 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
744 } 702 }
745 703
746 void GpuVideoDecoder::NotifyResetDone() { 704 void GpuVideoDecoder::NotifyResetDone() {
705 DVLOG(3) << "NotifyResetDone()";
747 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 706 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
748 DCHECK(ready_video_frames_.empty()); 707 DCHECK(ready_video_frames_.empty());
749 708
750 // This needs to happen after the Reset() on vda_ is done to ensure pictures 709 // This needs to happen after the Reset() on vda_ is done to ensure pictures
751 // delivered during the reset can find their time data. 710 // delivered during the reset can find their time data.
752 input_buffer_data_.clear(); 711 input_buffer_data_.clear();
753 712
754 if (!pending_reset_cb_.is_null()) 713 if (!pending_reset_cb_.is_null())
755 base::ResetAndReturn(&pending_reset_cb_).Run(); 714 base::ResetAndReturn(&pending_reset_cb_).Run();
756 715
(...skipping 11 matching lines...) Expand all
768 727
769 state_ = kError; 728 state_ = kError;
770 729
771 if (!pending_read_cb_.is_null()) { 730 if (!pending_read_cb_.is_null()) {
772 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 731 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
773 return; 732 return;
774 } 733 }
775 } 734 }
776 735
777 } // namespace media 736 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | media/filters/video_decoder_selector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698