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

Side by Side Diff: content/common/gpu/media/vt_video_decode_accelerator.cc

Issue 727893002: Implement a reorder queue in VTVideoDecodeAccelerator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@vt_queue_frames
Patch Set: Created 6 years, 1 month 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 <CoreVideo/CoreVideo.h> 5 #include <CoreVideo/CoreVideo.h>
6 #include <OpenGL/CGLIOSurface.h> 6 #include <OpenGL/CGLIOSurface.h>
7 #include <OpenGL/gl.h> 7 #include <OpenGL/gl.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 20 matching lines...) Expand all
31 31
32 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4). 32 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4).
33 static const int kNALUHeaderLength = 4; 33 static const int kNALUHeaderLength = 4;
34 34
35 // We request 5 picture buffers from the client, each of which has a texture ID 35 // We request 5 picture buffers from the client, each of which has a texture ID
36 // that we can bind decoded frames to. We need enough to satisfy preroll, and 36 // that we can bind decoded frames to. We need enough to satisfy preroll, and
37 // enough to avoid unnecessary stalling, but no more than that. The resource 37 // enough to avoid unnecessary stalling, but no more than that. The resource
38 // requirements are low, as we don't need the textures to be backed by storage. 38 // requirements are low, as we don't need the textures to be backed by storage.
39 static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1; 39 static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1;
40 40
41 // TODO(sandersd): Use the configured reorder window instead.
42 static const int kMinReorderQueueSize = 4;
43 static const int kMaxReorderQueueSize = 16;
44
41 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. 45 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
42 static void OutputThunk( 46 static void OutputThunk(
43 void* decompression_output_refcon, 47 void* decompression_output_refcon,
44 void* source_frame_refcon, 48 void* source_frame_refcon,
45 OSStatus status, 49 OSStatus status,
46 VTDecodeInfoFlags info_flags, 50 VTDecodeInfoFlags info_flags,
47 CVImageBufferRef image_buffer, 51 CVImageBufferRef image_buffer,
48 CMTime presentation_time_stamp, 52 CMTime presentation_time_stamp,
49 CMTime presentation_duration) { 53 CMTime presentation_duration) {
50 VTVideoDecodeAccelerator* vda = 54 VTVideoDecodeAccelerator* vda =
51 reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon); 55 reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon);
52 vda->Output(source_frame_refcon, status, image_buffer); 56 vda->Output(source_frame_refcon, status, image_buffer);
53 } 57 }
54 58
55 VTVideoDecodeAccelerator::Task::Task(TaskType type) : type(type) { 59 VTVideoDecodeAccelerator::Task::Task(TaskType type) : type(type) {
56 } 60 }
57 61
58 VTVideoDecodeAccelerator::Task::~Task() { 62 VTVideoDecodeAccelerator::Task::~Task() {
59 } 63 }
60 64
61 VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id) 65 VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id)
62 : bitstream_id(bitstream_id) { 66 : bitstream_id(bitstream_id), pic_order_cnt(0) {
63 } 67 }
64 68
65 VTVideoDecodeAccelerator::Frame::~Frame() { 69 VTVideoDecodeAccelerator::Frame::~Frame() {
66 } 70 }
67 71
72 bool VTVideoDecodeAccelerator::FrameOrder::operator()(
73 const linked_ptr<Frame>& lhs,
74 const linked_ptr<Frame>& rhs) const {
75 if (lhs->pic_order_cnt != rhs->pic_order_cnt)
76 return lhs->pic_order_cnt > rhs->pic_order_cnt;
77 // If the pic_order is the same, fallback on using the bitstream order.
78 // TODO(sandersd): Assign a sequence number in Decode().
79 return lhs->bitstream_id > rhs->bitstream_id;
80 }
81
82
68 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator( 83 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
69 CGLContextObj cgl_context, 84 CGLContextObj cgl_context,
70 const base::Callback<bool(void)>& make_context_current) 85 const base::Callback<bool(void)>& make_context_current)
71 : cgl_context_(cgl_context), 86 : cgl_context_(cgl_context),
72 make_context_current_(make_context_current), 87 make_context_current_(make_context_current),
73 client_(NULL), 88 client_(NULL),
74 state_(STATE_DECODING), 89 state_(STATE_DECODING),
75 format_(NULL), 90 format_(NULL),
76 session_(NULL), 91 session_(NULL),
92 last_sps_id_(-1),
93 last_pps_id_(-1),
77 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()), 94 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()),
78 weak_this_factory_(this), 95 weak_this_factory_(this),
79 decoder_thread_("VTDecoderThread") { 96 decoder_thread_("VTDecoderThread") {
80 DCHECK(!make_context_current_.is_null()); 97 DCHECK(!make_context_current_.is_null());
81 callback_.decompressionOutputCallback = OutputThunk; 98 callback_.decompressionOutputCallback = OutputThunk;
82 callback_.decompressionOutputRefCon = this; 99 callback_.decompressionOutputRefCon = this;
83 } 100 }
84 101
85 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { 102 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() {
86 } 103 }
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 size_t data_size = 0; 271 size_t data_size = 0;
255 std::vector<media::H264NALU> nalus; 272 std::vector<media::H264NALU> nalus;
256 parser_.SetStream(buf, size); 273 parser_.SetStream(buf, size);
257 media::H264NALU nalu; 274 media::H264NALU nalu;
258 while (true) { 275 while (true) {
259 media::H264Parser::Result result = parser_.AdvanceToNextNALU(&nalu); 276 media::H264Parser::Result result = parser_.AdvanceToNextNALU(&nalu);
260 if (result == media::H264Parser::kEOStream) 277 if (result == media::H264Parser::kEOStream)
261 break; 278 break;
262 if (result != media::H264Parser::kOk) { 279 if (result != media::H264Parser::kOk) {
263 DLOG(ERROR) << "Failed to find H.264 NALU"; 280 DLOG(ERROR) << "Failed to find H.264 NALU";
264 NotifyError(PLATFORM_FAILURE); 281 NotifyError(UNREADABLE_INPUT);
265 return; 282 return;
266 } 283 }
267 switch (nalu.nal_unit_type) { 284 switch (nalu.nal_unit_type) {
268 case media::H264NALU::kSPS: 285 case media::H264NALU::kSPS:
269 last_sps_.assign(nalu.data, nalu.data + nalu.size); 286 last_sps_.assign(nalu.data, nalu.data + nalu.size);
270 last_spsext_.clear(); 287 last_spsext_.clear();
271 config_changed = true; 288 config_changed = true;
289 if (parser_.ParseSPS(&last_sps_id_) != media::H264Parser::kOk) {
290 DLOG(ERROR) << "Could not parse SPS";
291 NotifyError(UNREADABLE_INPUT);
292 return;
293 }
272 break; 294 break;
295
273 case media::H264NALU::kSPSExt: 296 case media::H264NALU::kSPSExt:
274 // TODO(sandersd): Check that the previous NALU was an SPS. 297 // TODO(sandersd): Check that the previous NALU was an SPS.
275 last_spsext_.assign(nalu.data, nalu.data + nalu.size); 298 last_spsext_.assign(nalu.data, nalu.data + nalu.size);
276 config_changed = true; 299 config_changed = true;
277 break; 300 break;
301
278 case media::H264NALU::kPPS: 302 case media::H264NALU::kPPS:
279 last_pps_.assign(nalu.data, nalu.data + nalu.size); 303 last_pps_.assign(nalu.data, nalu.data + nalu.size);
280 config_changed = true; 304 config_changed = true;
305 if (parser_.ParsePPS(&last_pps_id_) != media::H264Parser::kOk) {
306 DLOG(ERROR) << "Could not parse PPS";
307 NotifyError(UNREADABLE_INPUT);
308 return;
309 }
281 break; 310 break;
311
282 case media::H264NALU::kSliceDataA: 312 case media::H264NALU::kSliceDataA:
283 case media::H264NALU::kSliceDataB: 313 case media::H264NALU::kSliceDataB:
284 case media::H264NALU::kSliceDataC: 314 case media::H264NALU::kSliceDataC:
285 DLOG(ERROR) << "Coded slide data partitions not implemented."; 315 DLOG(ERROR) << "Coded slide data partitions not implemented.";
286 NotifyError(PLATFORM_FAILURE); 316 NotifyError(PLATFORM_FAILURE);
287 return; 317 return;
318
319 case media::H264NALU::kNonIDRSlice:
320 // TODO(sandersd): Check that there has been an SPS or IDR slice since
321 // the last reset.
288 case media::H264NALU::kIDRSlice: 322 case media::H264NALU::kIDRSlice:
289 case media::H264NALU::kNonIDRSlice: 323 {
290 // TODO(sandersd): Compute pic_order_count. 324 // TODO(sandersd): Make sure this only happens once per frame.
325 DCHECK_EQ(frame->pic_order_cnt, 0);
326
327 media::H264SliceHeader slice_hdr;
328 result = parser_.ParseSliceHeader(nalu, &slice_hdr);
329 if (result != media::H264Parser::kOk) {
330 DLOG(ERROR) << "Could not parse slice header";
331 NotifyError(UNREADABLE_INPUT);
332 return;
333 }
334
335 // TODO(sandersd): Keep a cache of recent SPS/PPS units instead of
336 // only the most recent ones.
337 DCHECK_EQ(slice_hdr.pic_parameter_set_id, last_pps_id_);
338 const media::H264PPS* pps =
339 parser_.GetPPS(slice_hdr.pic_parameter_set_id);
340 if (!pps) {
341 DLOG(ERROR) << "Mising PPS referenced by slice";
342 NotifyError(UNREADABLE_INPUT);
343 return false;
344 }
345
346 DCHECK_EQ(pps->seq_parameter_set_id, last_sps_id_);
347 const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
348 if (!sps) {
349 DLOG(ERROR) << "Mising SPS referenced by PPS";
350 NotifyError(UNREADABLE_INPUT);
351 return false;
352 }
353
354 // TODO(sandersd): Compute pic_order_cnt.
355 DCHECK(!slice_hdr.field_pic_flag);
356 frame->pic_order_cnt = 0;
357 }
291 default: 358 default:
292 nalus.push_back(nalu); 359 nalus.push_back(nalu);
293 data_size += kNALUHeaderLength + nalu.size; 360 data_size += kNALUHeaderLength + nalu.size;
294 break; 361 break;
295 } 362 }
296 } 363 }
297 364
298 // Initialize VideoToolbox. 365 // Initialize VideoToolbox.
299 // TODO(sandersd): Instead of assuming that the last SPS and PPS units are 366 // TODO(sandersd): Instead of assuming that the last SPS and PPS units are
300 // always the correct ones, maintain a cache of recent SPS and PPS units and 367 // always the correct ones, maintain a cache of recent SPS and PPS units and
(...skipping 19 matching lines...) Expand all
320 return; 387 return;
321 } 388 }
322 389
323 // If the session is not configured by this point, fail. 390 // If the session is not configured by this point, fail.
324 if (!session_) { 391 if (!session_) {
325 DLOG(ERROR) << "Image slice without configuration"; 392 DLOG(ERROR) << "Image slice without configuration";
326 NotifyError(INVALID_ARGUMENT); 393 NotifyError(INVALID_ARGUMENT);
327 return; 394 return;
328 } 395 }
329 396
397 // Update the frame metadata with configuration data.
398 frame->coded_size = coded_size_;
399
330 // Create a memory-backed CMBlockBuffer for the translated data. 400 // Create a memory-backed CMBlockBuffer for the translated data.
331 // TODO(sandersd): Pool of memory blocks. 401 // TODO(sandersd): Pool of memory blocks.
332 base::ScopedCFTypeRef<CMBlockBufferRef> data; 402 base::ScopedCFTypeRef<CMBlockBufferRef> data;
333 OSStatus status = CMBlockBufferCreateWithMemoryBlock( 403 OSStatus status = CMBlockBufferCreateWithMemoryBlock(
334 kCFAllocatorDefault, 404 kCFAllocatorDefault,
335 NULL, // &memory_block 405 NULL, // &memory_block
336 data_size, // block_length 406 data_size, // block_length
337 kCFAllocatorDefault, // block_allocator 407 kCFAllocatorDefault, // block_allocator
338 NULL, // &custom_block_source 408 NULL, // &custom_block_source
339 0, // offset_to_data 409 0, // offset_to_data
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 0, // num_sample_timing_entries 448 0, // num_sample_timing_entries
379 NULL, // &sample_timing_array 449 NULL, // &sample_timing_array
380 0, // num_sample_size_entries 450 0, // num_sample_size_entries
381 NULL, // &sample_size_array 451 NULL, // &sample_size_array
382 sample.InitializeInto()); 452 sample.InitializeInto());
383 if (status) { 453 if (status) {
384 NOTIFY_STATUS("CMSampleBufferCreate()", status); 454 NOTIFY_STATUS("CMSampleBufferCreate()", status);
385 return; 455 return;
386 } 456 }
387 457
388 // Update the frame data.
389 frame->coded_size = coded_size_;
390
391 // Send the frame for decoding. 458 // Send the frame for decoding.
392 // Asynchronous Decompression allows for parallel submission of frames 459 // Asynchronous Decompression allows for parallel submission of frames
393 // (without it, DecodeFrame() does not return until the frame has been 460 // (without it, DecodeFrame() does not return until the frame has been
394 // decoded). We don't enable Temporal Processing so that frames are always 461 // decoded). We don't enable Temporal Processing so that frames are always
395 // returned in decode order; this makes it easier to avoid deadlock. 462 // returned in decode order; this makes it easier to avoid deadlock.
396 VTDecodeFrameFlags decode_flags = 463 VTDecodeFrameFlags decode_flags =
397 kVTDecodeFrame_EnableAsynchronousDecompression; 464 kVTDecodeFrame_EnableAsynchronousDecompression;
398 status = VTDecompressionSessionDecodeFrame( 465 status = VTDecompressionSessionDecodeFrame(
399 session_, 466 session_,
400 sample, // sample_buffer 467 sample, // sample_buffer
(...skipping 24 matching lines...) Expand all
425 weak_this_factory_.GetWeakPtr(), frame)); 492 weak_this_factory_.GetWeakPtr(), frame));
426 } 493 }
427 } 494 }
428 495
429 void VTVideoDecodeAccelerator::DecodeDone(Frame* frame) { 496 void VTVideoDecodeAccelerator::DecodeDone(Frame* frame) {
430 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 497 DCHECK(gpu_thread_checker_.CalledOnValidThread());
431 DCHECK_EQ(frame->bitstream_id, pending_frames_.front()->bitstream_id); 498 DCHECK_EQ(frame->bitstream_id, pending_frames_.front()->bitstream_id);
432 Task task(TASK_FRAME); 499 Task task(TASK_FRAME);
433 task.frame = pending_frames_.front(); 500 task.frame = pending_frames_.front();
434 pending_frames_.pop(); 501 pending_frames_.pop();
435 pending_tasks_.push(task); 502 task_queue_.push(task);
436 ProcessTasks(); 503 ProcessWorkQueues();
437 } 504 }
438 505
439 void VTVideoDecodeAccelerator::FlushTask(TaskType type) { 506 void VTVideoDecodeAccelerator::FlushTask(TaskType type) {
440 DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread()); 507 DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
441 FinishDelayedFrames(); 508 FinishDelayedFrames();
442 509
443 // Always queue a task, even if FinishDelayedFrames() fails, so that 510 // Always queue a task, even if FinishDelayedFrames() fails, so that
444 // destruction always completes. 511 // destruction always completes.
445 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( 512 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
446 &VTVideoDecodeAccelerator::FlushDone, 513 &VTVideoDecodeAccelerator::FlushDone,
447 weak_this_factory_.GetWeakPtr(), type)); 514 weak_this_factory_.GetWeakPtr(), type));
448 } 515 }
449 516
450 void VTVideoDecodeAccelerator::FlushDone(TaskType type) { 517 void VTVideoDecodeAccelerator::FlushDone(TaskType type) {
451 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 518 DCHECK(gpu_thread_checker_.CalledOnValidThread());
452 pending_tasks_.push(Task(type)); 519 task_queue_.push(Task(type));
453 ProcessTasks(); 520 ProcessWorkQueues();
454 } 521 }
455 522
456 void VTVideoDecodeAccelerator::Decode(const media::BitstreamBuffer& bitstream) { 523 void VTVideoDecodeAccelerator::Decode(const media::BitstreamBuffer& bitstream) {
457 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 524 DCHECK(gpu_thread_checker_.CalledOnValidThread());
458 DCHECK_EQ(assigned_bitstream_ids_.count(bitstream.id()), 0u); 525 DCHECK_EQ(assigned_bitstream_ids_.count(bitstream.id()), 0u);
459 assigned_bitstream_ids_.insert(bitstream.id()); 526 assigned_bitstream_ids_.insert(bitstream.id());
460 Frame* frame = new Frame(bitstream.id()); 527 Frame* frame = new Frame(bitstream.id());
461 pending_frames_.push(make_linked_ptr(frame)); 528 pending_frames_.push(make_linked_ptr(frame));
462 decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind( 529 decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
463 &VTVideoDecodeAccelerator::DecodeTask, base::Unretained(this), 530 &VTVideoDecodeAccelerator::DecodeTask, base::Unretained(this),
464 bitstream, frame)); 531 bitstream, frame));
465 } 532 }
466 533
467 void VTVideoDecodeAccelerator::AssignPictureBuffers( 534 void VTVideoDecodeAccelerator::AssignPictureBuffers(
468 const std::vector<media::PictureBuffer>& pictures) { 535 const std::vector<media::PictureBuffer>& pictures) {
469 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 536 DCHECK(gpu_thread_checker_.CalledOnValidThread());
470 537
471 for (const media::PictureBuffer& picture : pictures) { 538 for (const media::PictureBuffer& picture : pictures) {
472 DCHECK(!texture_ids_.count(picture.id())); 539 DCHECK(!texture_ids_.count(picture.id()));
473 assigned_picture_ids_.insert(picture.id()); 540 assigned_picture_ids_.insert(picture.id());
474 available_picture_ids_.push_back(picture.id()); 541 available_picture_ids_.push_back(picture.id());
475 texture_ids_[picture.id()] = picture.texture_id(); 542 texture_ids_[picture.id()] = picture.texture_id();
476 } 543 }
477 544
478 // Pictures are not marked as uncleared until after this method returns, and 545 // Pictures are not marked as uncleared until after this method returns, and
479 // they will be broken if they are used before that happens. So, schedule 546 // they will be broken if they are used before that happens. So, schedule
480 // future work after that happens. 547 // future work after that happens.
481 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( 548 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
482 &VTVideoDecodeAccelerator::ProcessTasks, 549 &VTVideoDecodeAccelerator::ProcessWorkQueues,
483 weak_this_factory_.GetWeakPtr())); 550 weak_this_factory_.GetWeakPtr()));
484 } 551 }
485 552
486 void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) { 553 void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) {
487 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 554 DCHECK(gpu_thread_checker_.CalledOnValidThread());
488 DCHECK_EQ(CFGetRetainCount(picture_bindings_[picture_id]), 1); 555 DCHECK_EQ(CFGetRetainCount(picture_bindings_[picture_id]), 1);
489 picture_bindings_.erase(picture_id); 556 picture_bindings_.erase(picture_id);
490 if (assigned_picture_ids_.count(picture_id) != 0) { 557 if (assigned_picture_ids_.count(picture_id) != 0) {
491 available_picture_ids_.push_back(picture_id); 558 available_picture_ids_.push_back(picture_id);
492 ProcessTasks(); 559 ProcessWorkQueues();
493 } else { 560 } else {
494 client_->DismissPictureBuffer(picture_id); 561 client_->DismissPictureBuffer(picture_id);
495 } 562 }
496 } 563 }
497 564
498 void VTVideoDecodeAccelerator::ProcessTasks() { 565 void VTVideoDecodeAccelerator::ProcessWorkQueues() {
499 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 566 DCHECK(gpu_thread_checker_.CalledOnValidThread());
567 switch (state_) {
568 case STATE_DECODING:
569 // TODO(sandersd): Batch where possible.
570 while (ProcessReorderQueue() || ProcessTaskQueue());
DaleCurtis 2014/11/14 21:11:45 Is this something that could block for a long time
sandersd (OOO until July 31) 2014/11/14 21:28:52 This would be worth investigating. I do expect thi
DaleCurtis 2014/11/14 21:41:54 More important than the length is the time taken.
571 return;
500 572
501 while (!pending_tasks_.empty()) { 573 case STATE_ERROR:
502 const Task& task = pending_tasks_.front(); 574 // Do nothing until Destroy() is called.
575 return;
503 576
504 switch (state_) { 577 case STATE_DESTROYING:
505 case STATE_DECODING: 578 // Drop tasks until we are ready to destruct.
506 if (!ProcessTask(task)) 579 while (!task_queue_.empty()) {
507 return; 580 if (task_queue_.front().type == TASK_DESTROY) {
508 pending_tasks_.pop();
509 break;
510
511 case STATE_ERROR:
512 // Do nothing until Destroy() is called.
513 return;
514
515 case STATE_DESTROYING:
516 // Discard tasks until destruction is complete.
517 if (task.type == TASK_DESTROY) {
518 delete this; 581 delete this;
519 return; 582 return;
520 } 583 }
521 pending_tasks_.pop(); 584 task_queue_.pop();
522 break; 585 }
523 } 586 return;
524 } 587 }
525 } 588 }
526 589
527 bool VTVideoDecodeAccelerator::ProcessTask(const Task& task) { 590 bool VTVideoDecodeAccelerator::ProcessTaskQueue() {
528 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 591 DCHECK(gpu_thread_checker_.CalledOnValidThread());
529 DCHECK_EQ(state_, STATE_DECODING); 592 DCHECK_EQ(state_, STATE_DECODING);
530 593
594 if (task_queue_.empty())
595 return false;
596
597 const Task& task = task_queue_.front();
531 switch (task.type) { 598 switch (task.type) {
532 case TASK_FRAME: 599 case TASK_FRAME:
533 return ProcessFrame(*task.frame); 600 // TODO(sandersd): Signal IDR explicitly (not using pic_order_cnt == 0).
601 if (reorder_queue_.size() < kMaxReorderQueueSize &&
602 (task.frame->pic_order_cnt != 0 || reorder_queue_.empty())) {
603 assigned_bitstream_ids_.erase(task.frame->bitstream_id);
604 client_->NotifyEndOfBitstreamBuffer(task.frame->bitstream_id);
605 reorder_queue_.push(task.frame);
606 task_queue_.pop();
607 return true;
608 }
609 return false;
534 610
535 case TASK_FLUSH: 611 case TASK_FLUSH:
536 DCHECK_EQ(task.type, pending_flush_tasks_.front()); 612 DCHECK_EQ(task.type, pending_flush_tasks_.front());
537 pending_flush_tasks_.pop(); 613 if (reorder_queue_.size() == 0) {
538 client_->NotifyFlushDone(); 614 pending_flush_tasks_.pop();
539 return true; 615 client_->NotifyFlushDone();
616 task_queue_.pop();
617 return true;
618 }
619 return false;
540 620
541 case TASK_RESET: 621 case TASK_RESET:
542 DCHECK_EQ(task.type, pending_flush_tasks_.front()); 622 DCHECK_EQ(task.type, pending_flush_tasks_.front());
543 pending_flush_tasks_.pop(); 623 if (reorder_queue_.size() == 0) {
544 client_->NotifyResetDone(); 624 pending_flush_tasks_.pop();
545 return true; 625 client_->NotifyResetDone();
626 task_queue_.pop();
627 return true;
628 }
629 return false;
546 630
547 case TASK_DESTROY: 631 case TASK_DESTROY:
548 NOTREACHED() << "Can't destroy while in STATE_DECODING."; 632 NOTREACHED() << "Can't destroy while in STATE_DECODING.";
549 NotifyError(ILLEGAL_STATE); 633 NotifyError(ILLEGAL_STATE);
550 return false; 634 return false;
551 } 635 }
552 } 636 }
553 637
638 bool VTVideoDecodeAccelerator::ProcessReorderQueue() {
639 DCHECK(gpu_thread_checker_.CalledOnValidThread());
640 DCHECK_EQ(state_, STATE_DECODING);
641
642 if (reorder_queue_.empty())
643 return false;
644
645 // If the next task is a flush (because there is a pending flush or becuase
646 // the next frame is an IDR), then we don't need a full reorder buffer to send
647 // the next frame.
648 bool flushing = !task_queue_.empty() &&
649 (task_queue_.front().type != TASK_FRAME ||
650 task_queue_.front().frame->pic_order_cnt == 0);
651 if (flushing || reorder_queue_.size() >= kMinReorderQueueSize) {
652 if (ProcessFrame(*reorder_queue_.top())) {
653 reorder_queue_.pop();
654 return true;
655 }
656 }
657
658 return false;
659 }
660
554 bool VTVideoDecodeAccelerator::ProcessFrame(const Frame& frame) { 661 bool VTVideoDecodeAccelerator::ProcessFrame(const Frame& frame) {
555 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 662 DCHECK(gpu_thread_checker_.CalledOnValidThread());
556 DCHECK_EQ(state_, STATE_DECODING); 663 DCHECK_EQ(state_, STATE_DECODING);
664
557 // If the next pending flush is for a reset, then the frame will be dropped. 665 // If the next pending flush is for a reset, then the frame will be dropped.
558 bool resetting = !pending_flush_tasks_.empty() && 666 bool resetting = !pending_flush_tasks_.empty() &&
559 pending_flush_tasks_.front() == TASK_RESET; 667 pending_flush_tasks_.front() == TASK_RESET;
668
560 if (!resetting && frame.image.get()) { 669 if (!resetting && frame.image.get()) {
561 // If the |coded_size| has changed, request new picture buffers and then 670 // If the |coded_size| has changed, request new picture buffers and then
562 // wait for them. 671 // wait for them.
563 // TODO(sandersd): If GpuVideoDecoder didn't specifically check the size of 672 // TODO(sandersd): If GpuVideoDecoder didn't specifically check the size of
564 // textures, this would be unnecessary, as the size is actually a property 673 // textures, this would be unnecessary, as the size is actually a property
565 // of the texture binding, not the texture. We rebind every frame, so the 674 // of the texture binding, not the texture. We rebind every frame, so the
566 // size passed to ProvidePictureBuffers() is meaningless. 675 // size passed to ProvidePictureBuffers() is meaningless.
567 if (picture_size_ != frame.coded_size) { 676 if (picture_size_ != frame.coded_size) {
568 // Dismiss current pictures. 677 // Dismiss current pictures.
569 for (int32_t picture_id : assigned_picture_ids_) 678 for (int32_t picture_id : assigned_picture_ids_)
570 client_->DismissPictureBuffer(picture_id); 679 client_->DismissPictureBuffer(picture_id);
571 assigned_picture_ids_.clear(); 680 assigned_picture_ids_.clear();
572 available_picture_ids_.clear(); 681 available_picture_ids_.clear();
573 682
574 // Request new pictures. 683 // Request new pictures.
575 picture_size_ = frame.coded_size; 684 picture_size_ = frame.coded_size;
576 client_->ProvidePictureBuffers( 685 client_->ProvidePictureBuffers(
577 kNumPictureBuffers, coded_size_, GL_TEXTURE_RECTANGLE_ARB); 686 kNumPictureBuffers, coded_size_, GL_TEXTURE_RECTANGLE_ARB);
578 return false; 687 return false;
579 } 688 }
580 if (!SendFrame(frame)) 689 if (!SendFrame(frame))
581 return false; 690 return false;
582 } 691 }
583 assigned_bitstream_ids_.erase(frame.bitstream_id); 692
584 client_->NotifyEndOfBitstreamBuffer(frame.bitstream_id);
585 return true; 693 return true;
586 } 694 }
587 695
588 bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) { 696 bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
589 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 697 DCHECK(gpu_thread_checker_.CalledOnValidThread());
590 DCHECK_EQ(state_, STATE_DECODING); 698 DCHECK_EQ(state_, STATE_DECODING);
591 699
592 if (available_picture_ids_.empty()) 700 if (available_picture_ids_.empty())
593 return false; 701 return false;
594 702
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 748
641 void VTVideoDecodeAccelerator::QueueFlush(TaskType type) { 749 void VTVideoDecodeAccelerator::QueueFlush(TaskType type) {
642 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 750 DCHECK(gpu_thread_checker_.CalledOnValidThread());
643 pending_flush_tasks_.push(type); 751 pending_flush_tasks_.push(type);
644 decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind( 752 decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
645 &VTVideoDecodeAccelerator::FlushTask, base::Unretained(this), 753 &VTVideoDecodeAccelerator::FlushTask, base::Unretained(this),
646 type)); 754 type));
647 755
648 // If this is a new flush request, see if we can make progress. 756 // If this is a new flush request, see if we can make progress.
649 if (pending_flush_tasks_.size() == 1) 757 if (pending_flush_tasks_.size() == 1)
650 ProcessTasks(); 758 ProcessWorkQueues();
651 } 759 }
652 760
653 void VTVideoDecodeAccelerator::Flush() { 761 void VTVideoDecodeAccelerator::Flush() {
654 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 762 DCHECK(gpu_thread_checker_.CalledOnValidThread());
655 QueueFlush(TASK_FLUSH); 763 QueueFlush(TASK_FLUSH);
656 } 764 }
657 765
658 void VTVideoDecodeAccelerator::Reset() { 766 void VTVideoDecodeAccelerator::Reset() {
659 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 767 DCHECK(gpu_thread_checker_.CalledOnValidThread());
660 QueueFlush(TASK_RESET); 768 QueueFlush(TASK_RESET);
661 } 769 }
662 770
663 void VTVideoDecodeAccelerator::Destroy() { 771 void VTVideoDecodeAccelerator::Destroy() {
664 DCHECK(gpu_thread_checker_.CalledOnValidThread()); 772 DCHECK(gpu_thread_checker_.CalledOnValidThread());
773 // TODO(sandersd): Make sure the decoder won't try to read the buffers again
774 // before discarding them.
665 for (int32_t bitstream_id : assigned_bitstream_ids_) 775 for (int32_t bitstream_id : assigned_bitstream_ids_)
666 client_->NotifyEndOfBitstreamBuffer(bitstream_id); 776 client_->NotifyEndOfBitstreamBuffer(bitstream_id);
667 assigned_bitstream_ids_.clear(); 777 assigned_bitstream_ids_.clear();
668 state_ = STATE_DESTROYING; 778 state_ = STATE_DESTROYING;
669 QueueFlush(TASK_DESTROY); 779 QueueFlush(TASK_DESTROY);
670 } 780 }
671 781
672 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { 782 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() {
673 return false; 783 return false;
674 } 784 }
675 785
676 } // namespace content 786 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698