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

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

Issue 833063003: Add accelerated video decoder interface, VP8 and H.264 implementations and hook up to V4L2SVDA. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed all comments. Created 5 years, 11 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 <fcntl.h> 5 #include <fcntl.h>
6 #include <linux/videodev2.h> 6 #include <linux/videodev2.h>
7 #include <poll.h> 7 #include <poll.h>
8 #include <sys/eventfd.h> 8 #include <sys/eventfd.h>
9 #include <sys/ioctl.h> 9 #include <sys/ioctl.h>
10 #include <sys/mman.h> 10 #include <sys/mman.h>
11 11
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
15 #include "base/message_loop/message_loop_proxy.h" 15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/numerics/safe_conversions.h" 16 #include "base/numerics/safe_conversions.h"
17 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" 17 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
18 #include "content/public/common/content_switches.h" 18 #include "content/public/common/content_switches.h"
19 #include "media/base/bitstream_buffer.h" 19 #include "media/base/bitstream_buffer.h"
20 20
21 #define NOTIFY_ERROR(x) \ 21 #define NOTIFY_ERROR(x) \
22 do { \ 22 do { \
23 SetEncoderState(kError); \ 23 LOG(ERROR) << "Setting error state:" << x; \
24 LOG(ERROR) << "calling NotifyError(): " << x; \ 24 SetErrorState(x); \
25 NotifyError(x); \
26 } while (0) 25 } while (0)
27 26
28 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \ 27 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \
29 do { \ 28 do { \
30 if (device_->Ioctl(type, arg) != 0) { \ 29 if (device_->Ioctl(type, arg) != 0) { \
31 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ 30 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
32 NOTIFY_ERROR(kPlatformFailureError); \ 31 NOTIFY_ERROR(kPlatformFailureError); \
33 return value; \ 32 return value; \
34 } \ 33 } \
35 } while (0) 34 } while (0)
(...skipping 27 matching lines...) Expand all
63 } 62 }
64 63
65 V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord() 64 V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord()
66 : at_device(false), address(NULL), length(0) { 65 : at_device(false), address(NULL), length(0) {
67 } 66 }
68 67
69 V4L2VideoEncodeAccelerator::OutputRecord::~OutputRecord() { 68 V4L2VideoEncodeAccelerator::OutputRecord::~OutputRecord() {
70 } 69 }
71 70
72 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator( 71 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator(
73 scoped_ptr<V4L2Device> device) 72 scoped_refptr<V4L2Device> device)
74 : child_message_loop_proxy_(base::MessageLoopProxy::current()), 73 : child_message_loop_proxy_(base::MessageLoopProxy::current()),
75 output_buffer_byte_size_(0), 74 output_buffer_byte_size_(0),
76 device_input_format_(media::VideoFrame::UNKNOWN), 75 device_input_format_(media::VideoFrame::UNKNOWN),
77 input_planes_count_(0), 76 input_planes_count_(0),
78 output_format_fourcc_(0), 77 output_format_fourcc_(0),
79 encoder_state_(kUninitialized), 78 encoder_state_(kUninitialized),
80 stream_header_size_(0), 79 stream_header_size_(0),
81 device_(device.Pass()), 80 device_(device),
82 input_streamon_(false), 81 input_streamon_(false),
83 input_buffer_queued_count_(0), 82 input_buffer_queued_count_(0),
84 input_memory_type_(V4L2_MEMORY_USERPTR), 83 input_memory_type_(V4L2_MEMORY_USERPTR),
85 output_streamon_(false), 84 output_streamon_(false),
86 output_buffer_queued_count_(0), 85 output_buffer_queued_count_(0),
87 encoder_thread_("V4L2EncoderThread"), 86 encoder_thread_("V4L2EncoderThread"),
88 device_poll_thread_("V4L2EncoderDevicePollThread"), 87 device_poll_thread_("V4L2EncoderDevicePollThread"),
89 weak_this_ptr_factory_(this) { 88 weak_this_ptr_factory_(this) {
90 weak_this_ = weak_this_ptr_factory_.GetWeakPtr(); 89 weak_this_ = weak_this_ptr_factory_.GetWeakPtr();
91 } 90 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 131
133 if (!SetFormats(input_format, output_profile)) { 132 if (!SetFormats(input_format, output_profile)) {
134 LOG(ERROR) << "Failed setting up formats"; 133 LOG(ERROR) << "Failed setting up formats";
135 return false; 134 return false;
136 } 135 }
137 136
138 if (input_format != device_input_format_) { 137 if (input_format != device_input_format_) {
139 DVLOG(1) << "Input format not supported by the HW, will convert to " 138 DVLOG(1) << "Input format not supported by the HW, will convert to "
140 << media::VideoFrame::FormatToString(device_input_format_); 139 << media::VideoFrame::FormatToString(device_input_format_);
141 140
142 scoped_ptr<V4L2Device> device = 141 scoped_refptr<V4L2Device> device =
143 V4L2Device::Create(V4L2Device::kImageProcessor); 142 V4L2Device::Create(V4L2Device::kImageProcessor);
144 image_processor_.reset(new V4L2ImageProcessor(device.Pass())); 143 image_processor_.reset(new V4L2ImageProcessor(device));
145 144
146 // Convert from input_format to device_input_format_, keeping the size 145 // Convert from input_format to device_input_format_, keeping the size
147 // at visible_size_ and requiring the output buffers to be of at least 146 // at visible_size_ and requiring the output buffers to be of at least
148 // input_allocated_size_. 147 // input_allocated_size_.
149 if (!image_processor_->Initialize( 148 if (!image_processor_->Initialize(
150 input_format, 149 input_format,
151 device_input_format_, 150 device_input_format_,
152 visible_size_, 151 visible_size_,
153 visible_size_, 152 visible_size_,
154 input_allocated_size_, 153 input_allocated_size_,
(...skipping 10 matching lines...) Expand all
165 if (!CreateOutputBuffers()) 164 if (!CreateOutputBuffers())
166 return false; 165 return false;
167 166
168 if (!encoder_thread_.Start()) { 167 if (!encoder_thread_.Start()) {
169 LOG(ERROR) << "Initialize(): encoder thread failed to start"; 168 LOG(ERROR) << "Initialize(): encoder thread failed to start";
170 return false; 169 return false;
171 } 170 }
172 171
173 RequestEncodingParametersChange(initial_bitrate, kInitialFramerate); 172 RequestEncodingParametersChange(initial_bitrate, kInitialFramerate);
174 173
175 SetEncoderState(kInitialized); 174 encoder_state_ = kInitialized;
176 175
177 child_message_loop_proxy_->PostTask( 176 child_message_loop_proxy_->PostTask(
178 FROM_HERE, 177 FROM_HERE,
179 base::Bind(&Client::RequireBitstreamBuffers, 178 base::Bind(&Client::RequireBitstreamBuffers,
180 client_, 179 client_,
181 kInputBufferCount, 180 kInputBufferCount,
182 image_processor_.get() ? 181 image_processor_.get() ?
183 image_processor_->input_allocated_size() : 182 image_processor_->input_allocated_size() :
184 input_allocated_size_, 183 input_allocated_size_,
185 output_buffer_byte_size_)); 184 output_buffer_byte_size_));
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 base::Unretained(this))); 273 base::Unretained(this)));
275 // DestroyTask() will put the encoder into kError state and cause all tasks 274 // DestroyTask() will put the encoder into kError state and cause all tasks
276 // to no-op. 275 // to no-op.
277 encoder_thread_.Stop(); 276 encoder_thread_.Stop();
278 } else { 277 } else {
279 // Otherwise, call the destroy task directly. 278 // Otherwise, call the destroy task directly.
280 DestroyTask(); 279 DestroyTask();
281 } 280 }
282 281
283 // Set to kError state just in case. 282 // Set to kError state just in case.
284 SetEncoderState(kError); 283 encoder_state_ = kError;
285 284
286 delete this; 285 delete this;
287 } 286 }
288 287
289 std::vector<media::VideoEncodeAccelerator::SupportedProfile> 288 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
290 V4L2VideoEncodeAccelerator::GetSupportedProfiles() { 289 V4L2VideoEncodeAccelerator::GetSupportedProfiles() {
291 std::vector<SupportedProfile> profiles; 290 std::vector<SupportedProfile> profiles;
292 SupportedProfile profile; 291 SupportedProfile profile;
293 profile.max_resolution.SetSize(1920, 1088); 292 profile.max_resolution.SetSize(1920, 1088);
294 profile.max_framerate_numerator = 30; 293 profile.max_framerate_numerator = 30;
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 &V4L2VideoEncodeAccelerator::NotifyError, weak_this_, error)); 775 &V4L2VideoEncodeAccelerator::NotifyError, weak_this_, error));
777 return; 776 return;
778 } 777 }
779 778
780 if (client_) { 779 if (client_) {
781 client_->NotifyError(error); 780 client_->NotifyError(error);
782 client_ptr_factory_.reset(); 781 client_ptr_factory_.reset();
783 } 782 }
784 } 783 }
785 784
786 void V4L2VideoEncodeAccelerator::SetEncoderState(State state) { 785 void V4L2VideoEncodeAccelerator::SetErrorState(Error error) {
787 DVLOG(3) << "SetEncoderState(): state=" << state;
788
789 // We can touch encoder_state_ only if this is the encoder thread or the 786 // We can touch encoder_state_ only if this is the encoder thread or the
790 // encoder thread isn't running. 787 // encoder thread isn't running.
791 if (encoder_thread_.message_loop() != NULL && 788 if (encoder_thread_.message_loop() != NULL &&
792 encoder_thread_.message_loop() != base::MessageLoop::current()) { 789 encoder_thread_.message_loop() != base::MessageLoop::current()) {
793 encoder_thread_.message_loop()->PostTask( 790 encoder_thread_.message_loop()->PostTask(
794 FROM_HERE, 791 FROM_HERE, base::Bind(&V4L2VideoEncodeAccelerator::SetErrorState,
795 base::Bind(&V4L2VideoEncodeAccelerator::SetEncoderState, 792 base::Unretained(this), error));
796 base::Unretained(this), 793 return;
797 state));
798 } else {
799 encoder_state_ = state;
800 } 794 }
795
796 // Post NotifyError only if we are already initialized, as the API does
797 // not allow doing so before that.
798 if (encoder_state_ != kError && encoder_state_ != kUninitialized)
799 NotifyError(error);
800
801 encoder_state_ = kError;
801 } 802 }
802 803
803 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask( 804 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask(
804 uint32 bitrate, 805 uint32 bitrate,
805 uint32 framerate) { 806 uint32 framerate) {
806 DVLOG(3) << "RequestEncodingParametersChangeTask(): bitrate=" << bitrate 807 DVLOG(3) << "RequestEncodingParametersChangeTask(): bitrate=" << bitrate
807 << ", framerate=" << framerate; 808 << ", framerate=" << framerate;
808 DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current()); 809 DCHECK_EQ(encoder_thread_.message_loop(), base::MessageLoop::current());
809 810
810 if (bitrate < 1) 811 if (bitrate < 1)
(...skipping 23 matching lines...) Expand all
834 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms); 835 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms);
835 } 836 }
836 837
837 bool V4L2VideoEncodeAccelerator::SetOutputFormat( 838 bool V4L2VideoEncodeAccelerator::SetOutputFormat(
838 media::VideoCodecProfile output_profile) { 839 media::VideoCodecProfile output_profile) {
839 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); 840 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
840 DCHECK(!input_streamon_); 841 DCHECK(!input_streamon_);
841 DCHECK(!output_streamon_); 842 DCHECK(!output_streamon_);
842 843
843 output_format_fourcc_ = 844 output_format_fourcc_ =
844 V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile); 845 V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile, false);
845 if (!output_format_fourcc_) { 846 if (!output_format_fourcc_) {
846 LOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile; 847 LOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile;
847 return false; 848 return false;
848 } 849 }
849 850
850 output_buffer_byte_size_ = kOutputBufferSize; 851 output_buffer_byte_size_ = kOutputBufferSize;
851 852
852 struct v4l2_format format; 853 struct v4l2_format format;
853 memset(&format, 0, sizeof(format)); 854 memset(&format, 0, sizeof(format));
854 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 855 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 reqbufs.count = 0; 1145 reqbufs.count = 0;
1145 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1146 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1146 reqbufs.memory = V4L2_MEMORY_MMAP; 1147 reqbufs.memory = V4L2_MEMORY_MMAP;
1147 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 1148 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
1148 1149
1149 output_buffer_map_.clear(); 1150 output_buffer_map_.clear();
1150 free_output_buffers_.clear(); 1151 free_output_buffers_.clear();
1151 } 1152 }
1152 1153
1153 } // namespace content 1154 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698