OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |