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

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

Issue 2398883002: Add support for multiple V4L2 video devices of the same type. (Closed)
Patch Set: comments addressed Created 4 years, 2 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 "media/gpu/v4l2_video_encode_accelerator.h" 5 #include "media/gpu/v4l2_video_encode_accelerator.h"
6 6
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>
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 << ", initial_bitrate=" << initial_bitrate; 146 << ", initial_bitrate=" << initial_bitrate;
147 147
148 visible_size_ = input_visible_size; 148 visible_size_ = input_visible_size;
149 149
150 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); 150 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
151 client_ = client_ptr_factory_->GetWeakPtr(); 151 client_ = client_ptr_factory_->GetWeakPtr();
152 152
153 DCHECK(child_task_runner_->BelongsToCurrentThread()); 153 DCHECK(child_task_runner_->BelongsToCurrentThread());
154 DCHECK_EQ(encoder_state_, kUninitialized); 154 DCHECK_EQ(encoder_state_, kUninitialized);
155 155
156 output_format_fourcc_ =
157 V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile, false);
158 if (!output_format_fourcc_) {
159 LOG(ERROR) << "Initialize(): invalid output_profile="
160 << GetProfileName(output_profile);
161 return false;
162 }
163
164 if (!device_->Open(V4L2Device::Type::kEncoder, output_format_fourcc_)) {
165 DVLOG(1) << "Failed to open device for profile="
166 << GetProfileName(output_profile) << ", fourcc=0x" << std::hex
167 << output_format_fourcc_;
168 return false;
169 }
170
156 struct v4l2_capability caps; 171 struct v4l2_capability caps;
157 memset(&caps, 0, sizeof(caps)); 172 memset(&caps, 0, sizeof(caps));
158 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 173 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
159 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); 174 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
160 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { 175 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
161 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " 176 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
162 << "caps check failed: 0x" << std::hex << caps.capabilities; 177 << "caps check failed: 0x" << std::hex << caps.capabilities;
163 return false; 178 return false;
164 } 179 }
165 180
166 if (!SetFormats(input_format, output_profile)) { 181 if (!SetFormats(input_format, output_profile)) {
167 DLOG(ERROR) << "Failed setting up formats"; 182 DLOG(ERROR) << "Failed setting up formats";
168 return false; 183 return false;
169 } 184 }
170 185
171 if (input_format != device_input_format_) { 186 if (input_format != device_input_format_) {
172 DVLOG(1) << "Input format not supported by the HW, will convert to " 187 DVLOG(1) << "Input format not supported by the HW, will try to convert to "
173 << VideoPixelFormatToString(device_input_format_); 188 << VideoPixelFormatToString(device_input_format_);
174 189
175 scoped_refptr<V4L2Device> device = 190 if (!V4L2ImageProcessor::IsSupported()) {
176 V4L2Device::Create(V4L2Device::kImageProcessor); 191 DVLOG(1) << "Image processor not available";
192 return false;
193 }
194
195 scoped_refptr<V4L2Device> device = V4L2Device::Create();
177 image_processor_.reset(new V4L2ImageProcessor(device)); 196 image_processor_.reset(new V4L2ImageProcessor(device));
178 197
179 // Convert from input_format to device_input_format_, keeping the size 198 // Convert from input_format to device_input_format_, keeping the size
180 // at visible_size_ and requiring the output buffers to be of at least 199 // at visible_size_ and requiring the output buffers to be of at least
181 // input_allocated_size_. Unretained is safe because |this| owns image 200 // input_allocated_size_. Unretained is safe because |this| owns image
182 // processor and there will be no callbacks after processor destroys. 201 // processor and there will be no callbacks after processor destroys.
183 if (!image_processor_->Initialize( 202 if (!image_processor_->Initialize(
184 input_format, device_input_format_, V4L2_MEMORY_USERPTR, 203 input_format, device_input_format_, V4L2_MEMORY_USERPTR,
185 V4L2_MEMORY_MMAP, visible_size_, visible_size_, visible_size_, 204 V4L2_MEMORY_MMAP, visible_size_, visible_size_, visible_size_,
186 input_allocated_size_, kImageProcBufferCount, 205 input_allocated_size_, kImageProcBufferCount,
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 } 361 }
343 362
344 // Set to kError state just in case. 363 // Set to kError state just in case.
345 encoder_state_ = kError; 364 encoder_state_ = kError;
346 365
347 delete this; 366 delete this;
348 } 367 }
349 368
350 VideoEncodeAccelerator::SupportedProfiles 369 VideoEncodeAccelerator::SupportedProfiles
351 V4L2VideoEncodeAccelerator::GetSupportedProfiles() { 370 V4L2VideoEncodeAccelerator::GetSupportedProfiles() {
352 SupportedProfiles profiles; 371 scoped_refptr<V4L2Device> device = V4L2Device::Create();
353 SupportedProfile profile; 372 if (!device)
354 profile.max_framerate_numerator = 30; 373 return SupportedProfiles();
355 profile.max_framerate_denominator = 1;
356 374
357 gfx::Size min_resolution; 375 return device->GetSupportedEncodeProfiles();
358 v4l2_fmtdesc fmtdesc;
359 memset(&fmtdesc, 0, sizeof(fmtdesc));
360 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
361 for (; device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
362 device_->GetSupportedResolution(fmtdesc.pixelformat, &min_resolution,
363 &profile.max_resolution);
364 switch (fmtdesc.pixelformat) {
365 case V4L2_PIX_FMT_H264:
366 profile.profile = H264PROFILE_MAIN;
367 profiles.push_back(profile);
368 break;
369 case V4L2_PIX_FMT_VP8:
370 profile.profile = VP8PROFILE_ANY;
371 profiles.push_back(profile);
372 break;
373 case V4L2_PIX_FMT_VP9:
374 profile.profile = VP9PROFILE_PROFILE0;
375 profiles.push_back(profile);
376 profile.profile = VP9PROFILE_PROFILE1;
377 profiles.push_back(profile);
378 profile.profile = VP9PROFILE_PROFILE2;
379 profiles.push_back(profile);
380 profile.profile = VP9PROFILE_PROFILE3;
381 profiles.push_back(profile);
382 break;
383 }
384 }
385
386 return profiles;
387 } 376 }
388 377
389 void V4L2VideoEncodeAccelerator::FrameProcessed(bool force_keyframe, 378 void V4L2VideoEncodeAccelerator::FrameProcessed(bool force_keyframe,
390 base::TimeDelta timestamp, 379 base::TimeDelta timestamp,
391 int output_buffer_index) { 380 int output_buffer_index) {
392 DCHECK(child_task_runner_->BelongsToCurrentThread()); 381 DCHECK(child_task_runner_->BelongsToCurrentThread());
393 DVLOG(3) << "FrameProcessed(): force_keyframe=" << force_keyframe 382 DVLOG(3) << "FrameProcessed(): force_keyframe=" << force_keyframe
394 << ", output_buffer_index=" << output_buffer_index; 383 << ", output_buffer_index=" << output_buffer_index;
395 DCHECK_GE(output_buffer_index, 0); 384 DCHECK_GE(output_buffer_index, 0);
396 DCHECK_LT(static_cast<size_t>(output_buffer_index), 385 DCHECK_LT(static_cast<size_t>(output_buffer_index),
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 parms.parm.output.timeperframe.denominator = framerate; 973 parms.parm.output.timeperframe.denominator = framerate;
985 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms); 974 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms);
986 } 975 }
987 976
988 bool V4L2VideoEncodeAccelerator::SetOutputFormat( 977 bool V4L2VideoEncodeAccelerator::SetOutputFormat(
989 VideoCodecProfile output_profile) { 978 VideoCodecProfile output_profile) {
990 DCHECK(child_task_runner_->BelongsToCurrentThread()); 979 DCHECK(child_task_runner_->BelongsToCurrentThread());
991 DCHECK(!input_streamon_); 980 DCHECK(!input_streamon_);
992 DCHECK(!output_streamon_); 981 DCHECK(!output_streamon_);
993 982
994 output_format_fourcc_ =
995 V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile, false);
996 if (!output_format_fourcc_) {
997 LOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile;
998 return false;
999 }
1000
1001 output_buffer_byte_size_ = kOutputBufferSize; 983 output_buffer_byte_size_ = kOutputBufferSize;
1002 984
1003 struct v4l2_format format; 985 struct v4l2_format format;
1004 memset(&format, 0, sizeof(format)); 986 memset(&format, 0, sizeof(format));
1005 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 987 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1006 format.fmt.pix_mp.width = visible_size_.width(); 988 format.fmt.pix_mp.width = visible_size_.width();
1007 format.fmt.pix_mp.height = visible_size_.height(); 989 format.fmt.pix_mp.height = visible_size_.height();
1008 format.fmt.pix_mp.pixelformat = output_format_fourcc_; 990 format.fmt.pix_mp.pixelformat = output_format_fourcc_;
1009 format.fmt.pix_mp.plane_fmt[0].sizeimage = 991 format.fmt.pix_mp.plane_fmt[0].sizeimage =
1010 base::checked_cast<__u32>(output_buffer_byte_size_); 992 base::checked_cast<__u32>(output_buffer_byte_size_);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 // First see if we the device can use the provided input_format directly. 1024 // First see if we the device can use the provided input_format directly.
1043 struct v4l2_format format; 1025 struct v4l2_format format;
1044 memset(&format, 0, sizeof(format)); 1026 memset(&format, 0, sizeof(format));
1045 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1027 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1046 format.fmt.pix_mp.width = visible_size_.width(); 1028 format.fmt.pix_mp.width = visible_size_.width();
1047 format.fmt.pix_mp.height = visible_size_.height(); 1029 format.fmt.pix_mp.height = visible_size_.height();
1048 format.fmt.pix_mp.pixelformat = input_format_fourcc; 1030 format.fmt.pix_mp.pixelformat = input_format_fourcc;
1049 format.fmt.pix_mp.num_planes = input_planes_count; 1031 format.fmt.pix_mp.num_planes = input_planes_count;
1050 if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) { 1032 if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) {
1051 // Error or format unsupported by device, try to negotiate a fallback. 1033 // Error or format unsupported by device, try to negotiate a fallback.
1052 input_format_fourcc = device_->PreferredInputFormat(); 1034 input_format_fourcc =
1035 device_->PreferredInputFormat(V4L2Device::Type::kEncoder);
1053 input_format = 1036 input_format =
1054 V4L2Device::V4L2PixFmtToVideoPixelFormat(input_format_fourcc); 1037 V4L2Device::V4L2PixFmtToVideoPixelFormat(input_format_fourcc);
1055 if (input_format == PIXEL_FORMAT_UNKNOWN) { 1038 if (input_format == PIXEL_FORMAT_UNKNOWN) {
1056 LOG(ERROR) << "Unsupported input format" << input_format_fourcc; 1039 LOG(ERROR) << "Unsupported input format" << input_format_fourcc;
1057 return false; 1040 return false;
1058 } 1041 }
1059 1042
1060 input_planes_count = VideoFrame::NumPlanes(input_format); 1043 input_planes_count = VideoFrame::NumPlanes(input_format);
1061 DCHECK_LE(input_planes_count, static_cast<size_t>(VIDEO_MAX_PLANES)); 1044 DCHECK_LE(input_planes_count, static_cast<size_t>(VIDEO_MAX_PLANES));
1062 1045
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 } 1291 }
1309 1292
1310 return true; 1293 return true;
1311 } 1294 }
1312 1295
1313 void V4L2VideoEncodeAccelerator::DestroyInputBuffers() { 1296 void V4L2VideoEncodeAccelerator::DestroyInputBuffers() {
1314 DVLOG(3) << "DestroyInputBuffers()"; 1297 DVLOG(3) << "DestroyInputBuffers()";
1315 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1298 DCHECK(child_task_runner_->BelongsToCurrentThread());
1316 DCHECK(!input_streamon_); 1299 DCHECK(!input_streamon_);
1317 1300
1301 free_input_buffers_.clear();
1302
1303 if (input_buffer_map_.empty())
1304 return;
1305
1318 struct v4l2_requestbuffers reqbufs; 1306 struct v4l2_requestbuffers reqbufs;
1319 memset(&reqbufs, 0, sizeof(reqbufs)); 1307 memset(&reqbufs, 0, sizeof(reqbufs));
1320 reqbufs.count = 0; 1308 reqbufs.count = 0;
1321 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1309 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1322 reqbufs.memory = input_memory_type_; 1310 reqbufs.memory = input_memory_type_;
1323 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 1311 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
1324 1312
1325 input_buffer_map_.clear(); 1313 input_buffer_map_.clear();
1326 free_input_buffers_.clear();
1327 } 1314 }
1328 1315
1329 void V4L2VideoEncodeAccelerator::DestroyOutputBuffers() { 1316 void V4L2VideoEncodeAccelerator::DestroyOutputBuffers() {
1330 DVLOG(3) << "DestroyOutputBuffers()"; 1317 DVLOG(3) << "DestroyOutputBuffers()";
1331 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1318 DCHECK(child_task_runner_->BelongsToCurrentThread());
1332 DCHECK(!output_streamon_); 1319 DCHECK(!output_streamon_);
1333 1320
1321 free_output_buffers_.clear();
1322
1323 if (output_buffer_map_.empty())
1324 return;
1325
1334 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 1326 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1335 if (output_buffer_map_[i].address != NULL) 1327 if (output_buffer_map_[i].address != NULL)
1336 device_->Munmap(output_buffer_map_[i].address, 1328 device_->Munmap(output_buffer_map_[i].address,
1337 output_buffer_map_[i].length); 1329 output_buffer_map_[i].length);
1338 } 1330 }
1339 1331
1340 struct v4l2_requestbuffers reqbufs; 1332 struct v4l2_requestbuffers reqbufs;
1341 memset(&reqbufs, 0, sizeof(reqbufs)); 1333 memset(&reqbufs, 0, sizeof(reqbufs));
1342 reqbufs.count = 0; 1334 reqbufs.count = 0;
1343 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1335 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1344 reqbufs.memory = V4L2_MEMORY_MMAP; 1336 reqbufs.memory = V4L2_MEMORY_MMAP;
1345 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 1337 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
1346 1338
1347 output_buffer_map_.clear(); 1339 output_buffer_map_.clear();
1348 free_output_buffers_.clear();
1349 } 1340 }
1350 1341
1351 } // namespace media 1342 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698