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

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

Issue 1541353002: Add offset support to BitstreamBuffer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase over crrev.com/1645873002 Created 4 years, 10 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
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 <dlfcn.h> 5 #include <dlfcn.h>
6 #include <errno.h> 6 #include <errno.h>
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <linux/videodev2.h> 8 #include <linux/videodev2.h>
9 #include <poll.h> 9 #include <poll.h>
10 #include <string.h> 10 #include <string.h>
11 #include <sys/eventfd.h> 11 #include <sys/eventfd.h>
12 #include <sys/ioctl.h> 12 #include <sys/ioctl.h>
13 #include <sys/mman.h> 13 #include <sys/mman.h>
14 14
15 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/memory/shared_memory.h"
19 #include "base/message_loop/message_loop.h" 18 #include "base/message_loop/message_loop.h"
20 #include "base/numerics/safe_conversions.h" 19 #include "base/numerics/safe_conversions.h"
21 #include "base/thread_task_runner_handle.h" 20 #include "base/thread_task_runner_handle.h"
22 #include "base/trace_event/trace_event.h" 21 #include "base/trace_event/trace_event.h"
23 #include "build/build_config.h" 22 #include "build/build_config.h"
23 #include "content/common/gpu/media/shared_memory_region.h"
24 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" 24 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h"
25 #include "media/base/media_switches.h" 25 #include "media/base/media_switches.h"
26 #include "media/filters/h264_parser.h" 26 #include "media/filters/h264_parser.h"
27 #include "ui/gfx/geometry/rect.h" 27 #include "ui/gfx/geometry/rect.h"
28 #include "ui/gl/scoped_binders.h" 28 #include "ui/gl/scoped_binders.h"
29 29
30 #define NOTIFY_ERROR(x) \ 30 #define NOTIFY_ERROR(x) \
31 do { \ 31 do { \
32 LOG(ERROR) << "Setting error state:" << x; \ 32 LOG(ERROR) << "Setting error state:" << x; \
33 SetErrorState(x); \ 33 SetErrorState(x); \
(...skipping 24 matching lines...) Expand all
58 58
59 // static 59 // static
60 const uint32_t V4L2VideoDecodeAccelerator::supported_input_fourccs_[] = { 60 const uint32_t V4L2VideoDecodeAccelerator::supported_input_fourccs_[] = {
61 V4L2_PIX_FMT_H264, V4L2_PIX_FMT_VP8, V4L2_PIX_FMT_VP9, 61 V4L2_PIX_FMT_H264, V4L2_PIX_FMT_VP8, V4L2_PIX_FMT_VP9,
62 }; 62 };
63 63
64 struct V4L2VideoDecodeAccelerator::BitstreamBufferRef { 64 struct V4L2VideoDecodeAccelerator::BitstreamBufferRef {
65 BitstreamBufferRef( 65 BitstreamBufferRef(
66 base::WeakPtr<Client>& client, 66 base::WeakPtr<Client>& client,
67 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, 67 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
68 base::SharedMemory* shm, 68 SharedMemoryRegion* shm,
dcheng 2016/03/01 01:48:43 scoped_ptr<SharedMemoryRegion> to have the compile
Owen Lin 2016/03/02 02:50:53 Done.
69 size_t size,
70 int32_t input_id); 69 int32_t input_id);
71 ~BitstreamBufferRef(); 70 ~BitstreamBufferRef();
72 const base::WeakPtr<Client> client; 71 const base::WeakPtr<Client> client;
73 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; 72 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner;
74 const scoped_ptr<base::SharedMemory> shm; 73 const scoped_ptr<SharedMemoryRegion> shm;
75 const size_t size;
76 size_t bytes_used; 74 size_t bytes_used;
77 const int32_t input_id; 75 const int32_t input_id;
78 }; 76 };
79 77
80 struct V4L2VideoDecodeAccelerator::EGLSyncKHRRef { 78 struct V4L2VideoDecodeAccelerator::EGLSyncKHRRef {
81 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); 79 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync);
82 ~EGLSyncKHRRef(); 80 ~EGLSyncKHRRef();
83 EGLDisplay const egl_display; 81 EGLDisplay const egl_display;
84 EGLSyncKHR egl_sync; 82 EGLSyncKHR egl_sync;
85 }; 83 };
86 84
87 struct V4L2VideoDecodeAccelerator::PictureRecord { 85 struct V4L2VideoDecodeAccelerator::PictureRecord {
88 PictureRecord(bool cleared, const media::Picture& picture); 86 PictureRecord(bool cleared, const media::Picture& picture);
89 ~PictureRecord(); 87 ~PictureRecord();
90 bool cleared; // Whether the texture is cleared and safe to render from. 88 bool cleared; // Whether the texture is cleared and safe to render from.
91 media::Picture picture; // The decoded picture. 89 media::Picture picture; // The decoded picture.
92 }; 90 };
93 91
94 V4L2VideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( 92 V4L2VideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef(
95 base::WeakPtr<Client>& client, 93 base::WeakPtr<Client>& client,
96 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, 94 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
97 base::SharedMemory* shm, 95 SharedMemoryRegion* shm,
98 size_t size,
99 int32_t input_id) 96 int32_t input_id)
100 : client(client), 97 : client(client),
101 client_task_runner(client_task_runner), 98 client_task_runner(client_task_runner),
102 shm(shm), 99 shm(shm),
103 size(size),
104 bytes_used(0), 100 bytes_used(0),
105 input_id(input_id) {} 101 input_id(input_id) {}
106 102
107 V4L2VideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { 103 V4L2VideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() {
108 if (input_id >= 0) { 104 if (input_id >= 0) {
109 client_task_runner->PostTask( 105 client_task_runner->PostTask(
110 FROM_HERE, 106 FROM_HERE,
111 base::Bind(&Client::NotifyEndOfBitstreamBuffer, client, input_id)); 107 base::Bind(&Client::NotifyEndOfBitstreamBuffer, client, input_id));
112 } 108 }
113 } 109 }
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 void V4L2VideoDecodeAccelerator::DecodeTask( 471 void V4L2VideoDecodeAccelerator::DecodeTask(
476 const media::BitstreamBuffer& bitstream_buffer) { 472 const media::BitstreamBuffer& bitstream_buffer) {
477 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); 473 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id();
478 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 474 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
479 DCHECK_NE(decoder_state_, kUninitialized); 475 DCHECK_NE(decoder_state_, kUninitialized);
480 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", 476 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id",
481 bitstream_buffer.id()); 477 bitstream_buffer.id());
482 478
483 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( 479 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef(
484 io_client_, io_task_runner_, 480 io_client_, io_task_runner_,
485 new base::SharedMemory(bitstream_buffer.handle(), true), 481 new SharedMemoryRegion(bitstream_buffer, true), bitstream_buffer.id()));
486 bitstream_buffer.size(), bitstream_buffer.id())); 482 if (!bitstream_record->shm->Map()) {
487 if (!bitstream_record->shm->Map(bitstream_buffer.size())) {
488 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; 483 LOG(ERROR) << "Decode(): could not map bitstream_buffer";
489 NOTIFY_ERROR(UNREADABLE_INPUT); 484 NOTIFY_ERROR(UNREADABLE_INPUT);
490 return; 485 return;
491 } 486 }
492 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); 487 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory();
493 488
494 if (decoder_state_ == kResetting || decoder_flushing_) { 489 if (decoder_state_ == kResetting || decoder_flushing_) {
495 // In the case that we're resetting or flushing, we need to delay decoding 490 // In the case that we're resetting or flushing, we need to delay decoding
496 // the BitstreamBuffers that come after the Reset() or Flush() call. When 491 // the BitstreamBuffers that come after the Reset() or Flush() call. When
497 // we're here, we know that this DecodeTask() was scheduled by a Decode() 492 // we're here, we know that this DecodeTask() was scheduled by a Decode()
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 } 531 }
537 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front(); 532 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front();
538 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) { 533 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) {
539 // We're asked to delay decoding on this and subsequent buffers. 534 // We're asked to delay decoding on this and subsequent buffers.
540 return; 535 return;
541 } 536 }
542 537
543 // Setup to use the next buffer. 538 // Setup to use the next buffer.
544 decoder_current_bitstream_buffer_.reset(buffer_ref.release()); 539 decoder_current_bitstream_buffer_.reset(buffer_ref.release());
545 decoder_input_queue_.pop(); 540 decoder_input_queue_.pop();
546 DVLOG(3) << "DecodeBufferTask(): reading input_id=" 541 const auto& shm = decoder_current_bitstream_buffer_->shm;
547 << decoder_current_bitstream_buffer_->input_id 542 if (shm) {
548 << ", addr=" << (decoder_current_bitstream_buffer_->shm ? 543 DVLOG(3) << "DecodeBufferTask(): reading input_id="
549 decoder_current_bitstream_buffer_->shm->memory() : 544 << decoder_current_bitstream_buffer_->input_id
550 NULL) 545 << ", addr=" << shm->memory() << ", size=" << shm->size();
551 << ", size=" << decoder_current_bitstream_buffer_->size; 546 } else {
547 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId);
548 DVLOG(3) << "DecodeBufferTask(): reading input_id=kFlushBufferId";
549 }
552 } 550 }
553 bool schedule_task = false; 551 bool schedule_task = false;
554 const size_t size = decoder_current_bitstream_buffer_->size;
555 size_t decoded_size = 0; 552 size_t decoded_size = 0;
556 if (size == 0) { 553 const auto& shm = decoder_current_bitstream_buffer_->shm;
557 const int32_t input_id = decoder_current_bitstream_buffer_->input_id; 554 if (!shm) {
558 if (input_id >= 0) { 555 // This is a dummy buffer, queued to flush the pipe. Flush.
559 // This is a buffer queued from the client that has zero size. Skip. 556 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId);
557 // Enqueue a buffer guaranteed to be empty. To do that, we flush the
558 // current input, enqueue no data to the next frame, then flush that down.
559 schedule_task = true;
560 if (decoder_current_input_buffer_ != -1 &&
561 input_buffer_map_[decoder_current_input_buffer_].input_id !=
562 kFlushBufferId)
563 schedule_task = FlushInputFrame();
564
565 if (schedule_task && AppendToInputFrame(NULL, 0) && FlushInputFrame()) {
566 DVLOG(2) << "DecodeBufferTask(): enqueued flush buffer";
567 decoder_partial_frame_pending_ = false;
560 schedule_task = true; 568 schedule_task = true;
561 } else { 569 } else {
562 // This is a buffer of zero size, queued to flush the pipe. Flush. 570 // If we failed to enqueue the empty buffer (due to pipeline
563 DCHECK_EQ(decoder_current_bitstream_buffer_->shm.get(), 571 // backpressure), don't advance the bitstream buffer queue, and don't
564 static_cast<base::SharedMemory*>(NULL)); 572 // schedule the next task. This bitstream buffer queue entry will get
565 // Enqueue a buffer guaranteed to be empty. To do that, we flush the 573 // reprocessed when the pipeline frees up.
566 // current input, enqueue no data to the next frame, then flush that down. 574 schedule_task = false;
567 schedule_task = true;
568 if (decoder_current_input_buffer_ != -1 &&
569 input_buffer_map_[decoder_current_input_buffer_].input_id !=
570 kFlushBufferId)
571 schedule_task = FlushInputFrame();
572
573 if (schedule_task && AppendToInputFrame(NULL, 0) && FlushInputFrame()) {
574 DVLOG(2) << "DecodeBufferTask(): enqueued flush buffer";
575 decoder_partial_frame_pending_ = false;
576 schedule_task = true;
577 } else {
578 // If we failed to enqueue the empty buffer (due to pipeline
579 // backpressure), don't advance the bitstream buffer queue, and don't
580 // schedule the next task. This bitstream buffer queue entry will get
581 // reprocessed when the pipeline frees up.
582 schedule_task = false;
583 }
584 } 575 }
576 } else if (shm->size() == 0) {
577 // This is a buffer queued from the client that has zero size. Skip.
578 schedule_task = true;
585 } else { 579 } else {
586 // This is a buffer queued from the client, with actual contents. Decode. 580 // This is a buffer queued from the client, with actual contents. Decode.
587 const uint8_t* const data = 581 const uint8_t* const data =
588 reinterpret_cast<const uint8_t*>( 582 reinterpret_cast<const uint8_t*>(shm->memory()) +
589 decoder_current_bitstream_buffer_->shm->memory()) +
590 decoder_current_bitstream_buffer_->bytes_used; 583 decoder_current_bitstream_buffer_->bytes_used;
591 const size_t data_size = 584 const size_t data_size =
592 decoder_current_bitstream_buffer_->size - 585 shm->size() - decoder_current_bitstream_buffer_->bytes_used;
593 decoder_current_bitstream_buffer_->bytes_used;
594 if (!AdvanceFrameFragment(data, data_size, &decoded_size)) { 586 if (!AdvanceFrameFragment(data, data_size, &decoded_size)) {
595 NOTIFY_ERROR(UNREADABLE_INPUT); 587 NOTIFY_ERROR(UNREADABLE_INPUT);
596 return; 588 return;
597 } 589 }
598 // AdvanceFrameFragment should not return a size larger than the buffer 590 // AdvanceFrameFragment should not return a size larger than the buffer
599 // size, even on invalid data. 591 // size, even on invalid data.
600 CHECK_LE(decoded_size, data_size); 592 CHECK_LE(decoded_size, data_size);
601 593
602 switch (decoder_state_) { 594 switch (decoder_state_) {
603 case kInitialized: 595 case kInitialized:
604 case kAfterReset: 596 case kAfterReset:
605 schedule_task = DecodeBufferInitial(data, decoded_size, &decoded_size); 597 schedule_task = DecodeBufferInitial(data, decoded_size, &decoded_size);
606 break; 598 break;
607 case kDecoding: 599 case kDecoding:
608 schedule_task = DecodeBufferContinue(data, decoded_size); 600 schedule_task = DecodeBufferContinue(data, decoded_size);
609 break; 601 break;
610 default: 602 default:
611 NOTIFY_ERROR(ILLEGAL_STATE); 603 NOTIFY_ERROR(ILLEGAL_STATE);
612 return; 604 return;
613 } 605 }
614 } 606 }
615 if (decoder_state_ == kError) { 607 if (decoder_state_ == kError) {
616 // Failed during decode. 608 // Failed during decode.
617 return; 609 return;
618 } 610 }
619 611
620 if (schedule_task) { 612 if (schedule_task) {
621 decoder_current_bitstream_buffer_->bytes_used += decoded_size; 613 decoder_current_bitstream_buffer_->bytes_used += decoded_size;
622 if (decoder_current_bitstream_buffer_->bytes_used == 614 if ((shm ? shm->size() : 0) ==
623 decoder_current_bitstream_buffer_->size) { 615 decoder_current_bitstream_buffer_->bytes_used) {
624 // Our current bitstream buffer is done; return it. 616 // Our current bitstream buffer is done; return it.
625 int32_t input_id = decoder_current_bitstream_buffer_->input_id; 617 int32_t input_id = decoder_current_bitstream_buffer_->input_id;
626 DVLOG(3) << "DecodeBufferTask(): finished input_id=" << input_id; 618 DVLOG(3) << "DecodeBufferTask(): finished input_id=" << input_id;
627 // BitstreamBufferRef destructor calls NotifyEndOfBitstreamBuffer(). 619 // BitstreamBufferRef destructor calls NotifyEndOfBitstreamBuffer().
628 decoder_current_bitstream_buffer_.reset(); 620 decoder_current_bitstream_buffer_.reset();
629 } 621 }
630 ScheduleDecodeBufferTaskIfNeeded(); 622 ScheduleDecodeBufferTaskIfNeeded();
631 } 623 }
632 } 624 }
633 625
(...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 DVLOG(2) << "FlushTask(): early out: kError state"; 1261 DVLOG(2) << "FlushTask(): early out: kError state";
1270 return; 1262 return;
1271 } 1263 }
1272 1264
1273 // We don't support stacked flushing. 1265 // We don't support stacked flushing.
1274 DCHECK(!decoder_flushing_); 1266 DCHECK(!decoder_flushing_);
1275 1267
1276 // Queue up an empty buffer -- this triggers the flush. 1268 // Queue up an empty buffer -- this triggers the flush.
1277 decoder_input_queue_.push( 1269 decoder_input_queue_.push(
1278 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( 1270 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef(
1279 io_client_, io_task_runner_, NULL, 0, kFlushBufferId))); 1271 io_client_, io_task_runner_, nullptr, kFlushBufferId)));
1280 decoder_flushing_ = true; 1272 decoder_flushing_ = true;
1281 SendPictureReady(); // Send all pending PictureReady. 1273 SendPictureReady(); // Send all pending PictureReady.
1282 1274
1283 ScheduleDecodeBufferTaskIfNeeded(); 1275 ScheduleDecodeBufferTaskIfNeeded();
1284 } 1276 }
1285 1277
1286 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { 1278 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
1287 if (!decoder_flushing_) 1279 if (!decoder_flushing_)
1288 return; 1280 return;
1289 1281
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after
2033 2025
2034 void V4L2VideoDecodeAccelerator::PictureCleared() { 2026 void V4L2VideoDecodeAccelerator::PictureCleared() {
2035 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; 2027 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
2036 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 2028 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2037 DCHECK_GT(picture_clearing_count_, 0); 2029 DCHECK_GT(picture_clearing_count_, 0);
2038 picture_clearing_count_--; 2030 picture_clearing_count_--;
2039 SendPictureReady(); 2031 SendPictureReady();
2040 } 2032 }
2041 2033
2042 } // namespace content 2034 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698