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

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: Fixes for image processor. 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(output_format_fourcc_)) {
165 DVLOG(1) << "Failed to open device for profile="
166 << GetProfileName(output_profile) << ", fourcc=" << 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 convert to "
173 << VideoPixelFormatToString(device_input_format_); 188 << VideoPixelFormatToString(device_input_format_);
174 189
175 scoped_refptr<V4L2Device> device = 190 scoped_refptr<V4L2Device> device =
176 V4L2Device::Create(V4L2Device::kImageProcessor); 191 V4L2Device::Create(V4L2Device::Type::kImageProcessor);
177 image_processor_.reset(new V4L2ImageProcessor(device)); 192 image_processor_.reset(new V4L2ImageProcessor(device));
178 193
179 // Convert from input_format to device_input_format_, keeping the size 194 // 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 195 // at visible_size_ and requiring the output buffers to be of at least
181 // input_allocated_size_. Unretained is safe because |this| owns image 196 // input_allocated_size_. Unretained is safe because |this| owns image
182 // processor and there will be no callbacks after processor destroys. 197 // processor and there will be no callbacks after processor destroys.
183 if (!image_processor_->Initialize( 198 if (!image_processor_->Initialize(
184 input_format, device_input_format_, V4L2_MEMORY_USERPTR, 199 input_format, device_input_format_, V4L2_MEMORY_USERPTR,
185 V4L2_MEMORY_MMAP, visible_size_, visible_size_, visible_size_, 200 V4L2_MEMORY_MMAP, visible_size_, visible_size_, visible_size_,
186 input_allocated_size_, kImageProcBufferCount, 201 input_allocated_size_, kImageProcBufferCount,
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 } 357 }
343 358
344 // Set to kError state just in case. 359 // Set to kError state just in case.
345 encoder_state_ = kError; 360 encoder_state_ = kError;
346 361
347 delete this; 362 delete this;
348 } 363 }
349 364
350 VideoEncodeAccelerator::SupportedProfiles 365 VideoEncodeAccelerator::SupportedProfiles
351 V4L2VideoEncodeAccelerator::GetSupportedProfiles() { 366 V4L2VideoEncodeAccelerator::GetSupportedProfiles() {
352 SupportedProfiles profiles; 367 scoped_refptr<V4L2Device> device =
353 SupportedProfile profile; 368 V4L2Device::Create(V4L2Device::Type::kEncoder);
354 profile.max_framerate_numerator = 30; 369 if (!device)
355 profile.max_framerate_denominator = 1; 370 return SupportedProfiles();
356 371
357 gfx::Size min_resolution; 372 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 } 373 }
388 374
389 void V4L2VideoEncodeAccelerator::FrameProcessed(bool force_keyframe, 375 void V4L2VideoEncodeAccelerator::FrameProcessed(bool force_keyframe,
390 base::TimeDelta timestamp, 376 base::TimeDelta timestamp,
391 int output_buffer_index) { 377 int output_buffer_index) {
392 DCHECK(child_task_runner_->BelongsToCurrentThread()); 378 DCHECK(child_task_runner_->BelongsToCurrentThread());
393 DVLOG(3) << "FrameProcessed(): force_keyframe=" << force_keyframe 379 DVLOG(3) << "FrameProcessed(): force_keyframe=" << force_keyframe
394 << ", output_buffer_index=" << output_buffer_index; 380 << ", output_buffer_index=" << output_buffer_index;
395 DCHECK_GE(output_buffer_index, 0); 381 DCHECK_GE(output_buffer_index, 0);
396 DCHECK_LT(static_cast<size_t>(output_buffer_index), 382 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; 970 parms.parm.output.timeperframe.denominator = framerate;
985 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms); 971 IOCTL_OR_ERROR_RETURN(VIDIOC_S_PARM, &parms);
986 } 972 }
987 973
988 bool V4L2VideoEncodeAccelerator::SetOutputFormat( 974 bool V4L2VideoEncodeAccelerator::SetOutputFormat(
989 VideoCodecProfile output_profile) { 975 VideoCodecProfile output_profile) {
990 DCHECK(child_task_runner_->BelongsToCurrentThread()); 976 DCHECK(child_task_runner_->BelongsToCurrentThread());
991 DCHECK(!input_streamon_); 977 DCHECK(!input_streamon_);
992 DCHECK(!output_streamon_); 978 DCHECK(!output_streamon_);
993 979
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; 980 output_buffer_byte_size_ = kOutputBufferSize;
1002 981
1003 struct v4l2_format format; 982 struct v4l2_format format;
1004 memset(&format, 0, sizeof(format)); 983 memset(&format, 0, sizeof(format));
1005 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 984 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1006 format.fmt.pix_mp.width = visible_size_.width(); 985 format.fmt.pix_mp.width = visible_size_.width();
1007 format.fmt.pix_mp.height = visible_size_.height(); 986 format.fmt.pix_mp.height = visible_size_.height();
1008 format.fmt.pix_mp.pixelformat = output_format_fourcc_; 987 format.fmt.pix_mp.pixelformat = output_format_fourcc_;
1009 format.fmt.pix_mp.plane_fmt[0].sizeimage = 988 format.fmt.pix_mp.plane_fmt[0].sizeimage =
1010 base::checked_cast<__u32>(output_buffer_byte_size_); 989 base::checked_cast<__u32>(output_buffer_byte_size_);
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 } 1287 }
1309 1288
1310 return true; 1289 return true;
1311 } 1290 }
1312 1291
1313 void V4L2VideoEncodeAccelerator::DestroyInputBuffers() { 1292 void V4L2VideoEncodeAccelerator::DestroyInputBuffers() {
1314 DVLOG(3) << "DestroyInputBuffers()"; 1293 DVLOG(3) << "DestroyInputBuffers()";
1315 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1294 DCHECK(child_task_runner_->BelongsToCurrentThread());
1316 DCHECK(!input_streamon_); 1295 DCHECK(!input_streamon_);
1317 1296
1297 free_input_buffers_.clear();
1298
1299 if (input_buffer_map_.empty())
1300 return;
1301
1318 struct v4l2_requestbuffers reqbufs; 1302 struct v4l2_requestbuffers reqbufs;
1319 memset(&reqbufs, 0, sizeof(reqbufs)); 1303 memset(&reqbufs, 0, sizeof(reqbufs));
1320 reqbufs.count = 0; 1304 reqbufs.count = 0;
1321 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1305 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1322 reqbufs.memory = input_memory_type_; 1306 reqbufs.memory = input_memory_type_;
1323 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 1307 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
1324 1308
1325 input_buffer_map_.clear(); 1309 input_buffer_map_.clear();
1326 free_input_buffers_.clear();
1327 } 1310 }
1328 1311
1329 void V4L2VideoEncodeAccelerator::DestroyOutputBuffers() { 1312 void V4L2VideoEncodeAccelerator::DestroyOutputBuffers() {
1330 DVLOG(3) << "DestroyOutputBuffers()"; 1313 DVLOG(3) << "DestroyOutputBuffers()";
1331 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1314 DCHECK(child_task_runner_->BelongsToCurrentThread());
1332 DCHECK(!output_streamon_); 1315 DCHECK(!output_streamon_);
1333 1316
1317 free_output_buffers_.clear();
1318
1319 if (output_buffer_map_.empty())
1320 return;
1321
1334 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 1322 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1335 if (output_buffer_map_[i].address != NULL) 1323 if (output_buffer_map_[i].address != NULL)
1336 device_->Munmap(output_buffer_map_[i].address, 1324 device_->Munmap(output_buffer_map_[i].address,
1337 output_buffer_map_[i].length); 1325 output_buffer_map_[i].length);
1338 } 1326 }
1339 1327
1340 struct v4l2_requestbuffers reqbufs; 1328 struct v4l2_requestbuffers reqbufs;
1341 memset(&reqbufs, 0, sizeof(reqbufs)); 1329 memset(&reqbufs, 0, sizeof(reqbufs));
1342 reqbufs.count = 0; 1330 reqbufs.count = 0;
1343 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1331 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1344 reqbufs.memory = V4L2_MEMORY_MMAP; 1332 reqbufs.memory = V4L2_MEMORY_MMAP;
1345 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 1333 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
1346 1334
1347 output_buffer_map_.clear(); 1335 output_buffer_map_.clear();
1348 free_output_buffers_.clear();
1349 } 1336 }
1350 1337
1351 } // namespace media 1338 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698