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

Side by Side Diff: media/gpu/v4l2_device.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 <libdrm/drm_fourcc.h> 5 #include <libdrm/drm_fourcc.h>
6 #include <linux/videodev2.h> 6 #include <linux/videodev2.h>
7 #include <string.h> 7 #include <string.h>
8 8
9 #include "base/numerics/safe_conversions.h" 9 #include "base/numerics/safe_conversions.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
11 #include "media/gpu/generic_v4l2_device.h" 11 #include "media/gpu/generic_v4l2_device.h"
12 #if defined(ARCH_CPU_ARMEL) 12 #if defined(ARCH_CPU_ARMEL)
13 #include "media/gpu/tegra_v4l2_device.h" 13 #include "media/gpu/tegra_v4l2_device.h"
14 #endif 14 #endif
15 15
16 namespace media { 16 namespace media {
17 17
18 V4L2Device::V4L2Device(Type type) : type_(type) {} 18 V4L2Device::V4L2Device() {}
19 19
20 V4L2Device::~V4L2Device() {} 20 V4L2Device::~V4L2Device() {}
21 21
22 // static 22 // static
23 scoped_refptr<V4L2Device> V4L2Device::Create(Type type) { 23 scoped_refptr<V4L2Device> V4L2Device::Create() {
24 DVLOG(3) << __PRETTY_FUNCTION__; 24 DVLOG(3) << __PRETTY_FUNCTION__;
25 25
26 scoped_refptr<GenericV4L2Device> generic_device(new GenericV4L2Device(type)); 26 scoped_refptr<V4L2Device> device;
27 if (generic_device->Initialize())
28 return generic_device;
29 27
30 #if defined(ARCH_CPU_ARMEL) 28 #if defined(ARCH_CPU_ARMEL)
31 scoped_refptr<TegraV4L2Device> tegra_device(new TegraV4L2Device(type)); 29 device = new TegraV4L2Device();
32 if (tegra_device->Initialize()) 30 if (device->Initialize())
33 return tegra_device; 31 return device;
34 #endif 32 #endif
35 33
36 DVLOG(1) << "Failed to create V4L2Device"; 34 device = new GenericV4L2Device();
37 return scoped_refptr<V4L2Device>(); 35 if (device->Initialize())
36 return device;
37
38 DVLOG(1) << "Failed to create a V4L2Device";
39 return nullptr;
38 } 40 }
39 41
40 // static 42 // static
41 VideoPixelFormat V4L2Device::V4L2PixFmtToVideoPixelFormat(uint32_t pix_fmt) { 43 VideoPixelFormat V4L2Device::V4L2PixFmtToVideoPixelFormat(uint32_t pix_fmt) {
42 switch (pix_fmt) { 44 switch (pix_fmt) {
43 case V4L2_PIX_FMT_NV12: 45 case V4L2_PIX_FMT_NV12:
44 case V4L2_PIX_FMT_NV12M: 46 case V4L2_PIX_FMT_NV12M:
45 return PIXEL_FORMAT_NV12; 47 return PIXEL_FORMAT_NV12;
46 48
47 case V4L2_PIX_FMT_MT21: 49 case V4L2_PIX_FMT_MT21:
48 return PIXEL_FORMAT_MT21; 50 return PIXEL_FORMAT_MT21;
49 51
50 case V4L2_PIX_FMT_YUV420: 52 case V4L2_PIX_FMT_YUV420:
51 case V4L2_PIX_FMT_YUV420M: 53 case V4L2_PIX_FMT_YUV420M:
52 return PIXEL_FORMAT_I420; 54 return PIXEL_FORMAT_I420;
53 55
54 case V4L2_PIX_FMT_YVU420: 56 case V4L2_PIX_FMT_YVU420:
55 return PIXEL_FORMAT_YV12; 57 return PIXEL_FORMAT_YV12;
56 58
57 case V4L2_PIX_FMT_RGB32: 59 case V4L2_PIX_FMT_RGB32:
58 return PIXEL_FORMAT_ARGB; 60 return PIXEL_FORMAT_ARGB;
59 61
60 default: 62 default:
61 LOG(FATAL) << "Add more cases as needed"; 63 DVLOG(1) << "Add more cases as needed";
62 return PIXEL_FORMAT_UNKNOWN; 64 return PIXEL_FORMAT_UNKNOWN;
63 } 65 }
64 } 66 }
65 67
66 // static 68 // static
67 uint32_t V4L2Device::VideoPixelFormatToV4L2PixFmt(VideoPixelFormat format) { 69 uint32_t V4L2Device::VideoPixelFormatToV4L2PixFmt(VideoPixelFormat format) {
68 switch (format) { 70 switch (format) {
69 case PIXEL_FORMAT_NV12: 71 case PIXEL_FORMAT_NV12:
70 return V4L2_PIX_FMT_NV12M; 72 return V4L2_PIX_FMT_NV12M;
71 73
(...skipping 30 matching lines...) Expand all
102 return V4L2_PIX_FMT_VP9_FRAME; 104 return V4L2_PIX_FMT_VP9_FRAME;
103 else 105 else
104 return V4L2_PIX_FMT_VP9; 106 return V4L2_PIX_FMT_VP9;
105 } else { 107 } else {
106 LOG(FATAL) << "Add more cases as needed"; 108 LOG(FATAL) << "Add more cases as needed";
107 return 0; 109 return 0;
108 } 110 }
109 } 111 }
110 112
111 // static 113 // static
114 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
115 uint32_t pix_fmt,
116 bool is_encoder) {
117 VideoCodecProfile min_profile, max_profile;
118 std::vector<VideoCodecProfile> profiles;
119
120 switch (pix_fmt) {
121 case V4L2_PIX_FMT_H264:
122 case V4L2_PIX_FMT_H264_SLICE:
123 if (is_encoder) {
124 // TODO(posciak): need to query the device for supported H.264 profiles,
125 // for now choose Main as a sensible default.
126 min_profile = H264PROFILE_MAIN;
127 max_profile = H264PROFILE_MAIN;
128 } else {
129 min_profile = H264PROFILE_MIN;
130 max_profile = H264PROFILE_MAX;
131 }
132 break;
133
134 case V4L2_PIX_FMT_VP8:
135 case V4L2_PIX_FMT_VP8_FRAME:
136 min_profile = VP8PROFILE_MIN;
137 max_profile = VP8PROFILE_MAX;
138 break;
139
140 case V4L2_PIX_FMT_VP9:
141 case V4L2_PIX_FMT_VP9_FRAME:
142 min_profile = VP9PROFILE_MIN;
143 max_profile = VP9PROFILE_MAX;
144 break;
145
146 default:
147 DVLOG(1) << "Unhandled pixelformat " << std::hex << "0x" << pix_fmt;
148 return profiles;
149 }
150
151 for (int profile = min_profile; profile <= max_profile; ++profile)
152 profiles.push_back(static_cast<VideoCodecProfile>(profile));
153
154 return profiles;
155 }
156
157 // static
112 uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) { 158 uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) {
113 switch (format) { 159 switch (format) {
114 case V4L2_PIX_FMT_NV12: 160 case V4L2_PIX_FMT_NV12:
115 case V4L2_PIX_FMT_NV12M: 161 case V4L2_PIX_FMT_NV12M:
116 return DRM_FORMAT_NV12; 162 return DRM_FORMAT_NV12;
117 163
118 case V4L2_PIX_FMT_YUV420: 164 case V4L2_PIX_FMT_YUV420:
119 case V4L2_PIX_FMT_YUV420M: 165 case V4L2_PIX_FMT_YUV420M:
120 return DRM_FORMAT_YUV420; 166 return DRM_FORMAT_YUV420;
121 167
122 case V4L2_PIX_FMT_YVU420: 168 case V4L2_PIX_FMT_YVU420:
123 return DRM_FORMAT_YVU420; 169 return DRM_FORMAT_YVU420;
124 170
125 case V4L2_PIX_FMT_RGB32: 171 case V4L2_PIX_FMT_RGB32:
126 return DRM_FORMAT_ARGB8888; 172 return DRM_FORMAT_ARGB8888;
127 173
174 case V4L2_PIX_FMT_MT21:
175 return DRM_FORMAT_MT21;
176
128 default: 177 default:
129 DVLOG(1) << "Add more cases as needed"; 178 DVLOG(1) << "Unrecognized format " << std::hex << "0x" << format;
130 return 0; 179 return 0;
131 } 180 }
132 } 181 }
133 182
134 // static 183 // static
135 gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { 184 gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) {
136 gfx::Size coded_size; 185 gfx::Size coded_size;
137 gfx::Size visible_size; 186 gfx::Size visible_size;
138 VideoPixelFormat frame_format = PIXEL_FORMAT_UNKNOWN; 187 VideoPixelFormat frame_format = PIXEL_FORMAT_UNKNOWN;
139 size_t bytesperline = 0; 188 size_t bytesperline = 0;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 << ", fall back to " << max_resolution->ToString(); 301 << ", fall back to " << max_resolution->ToString();
253 } 302 }
254 if (min_resolution->IsEmpty()) { 303 if (min_resolution->IsEmpty()) {
255 min_resolution->SetSize(16, 16); 304 min_resolution->SetSize(16, 16);
256 LOG(ERROR) << "GetSupportedResolution failed to get minimum resolution for " 305 LOG(ERROR) << "GetSupportedResolution failed to get minimum resolution for "
257 << "fourcc " << std::hex << pixelformat 306 << "fourcc " << std::hex << pixelformat
258 << ", fall back to " << min_resolution->ToString(); 307 << ", fall back to " << min_resolution->ToString();
259 } 308 }
260 } 309 }
261 310
262 VideoDecodeAccelerator::SupportedProfiles 311 std::vector<uint32_t> V4L2Device::EnumerateSupportedPixelformats(
263 V4L2Device::GetSupportedDecodeProfiles(const size_t num_formats, 312 v4l2_buf_type buf_type) {
264 const uint32_t pixelformats[]) { 313 std::vector<uint32_t> pixelformats;
265 DCHECK_EQ(type_, kDecoder); 314
266 VideoDecodeAccelerator::SupportedProfiles profiles;
267 VideoDecodeAccelerator::SupportedProfile profile;
268 v4l2_fmtdesc fmtdesc; 315 v4l2_fmtdesc fmtdesc;
269 memset(&fmtdesc, 0, sizeof(fmtdesc)); 316 memset(&fmtdesc, 0, sizeof(fmtdesc));
270 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 317 fmtdesc.type = buf_type;
271 318
272 for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { 319 for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
273 if (std::find(pixelformats, pixelformats + num_formats, 320 DVLOG(1) << "Found " << fmtdesc.description << std::hex << " (0x"
274 fmtdesc.pixelformat) == pixelformats + num_formats) 321 << fmtdesc.pixelformat << ")";
322 pixelformats.push_back(fmtdesc.pixelformat);
323 }
324
325 return pixelformats;
326 }
327
328 VideoDecodeAccelerator::SupportedProfiles
329 V4L2Device::EnumerateSupportedDecodeProfiles(const size_t num_formats,
330 const uint32_t pixelformats[]) {
331 VideoDecodeAccelerator::SupportedProfiles profiles;
332
333 const auto& supported_pixelformats =
334 EnumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
335
336 for (uint32_t pixelformat : supported_pixelformats) {
337 if (std::find(pixelformats, pixelformats + num_formats, pixelformat) ==
338 pixelformats + num_formats)
275 continue; 339 continue;
276 int min_profile, max_profile; 340
277 switch (fmtdesc.pixelformat) { 341 VideoDecodeAccelerator::SupportedProfile profile;
278 case V4L2_PIX_FMT_H264: 342 GetSupportedResolution(pixelformat, &profile.min_resolution,
279 case V4L2_PIX_FMT_H264_SLICE:
280 min_profile = H264PROFILE_MIN;
281 max_profile = H264PROFILE_MAX;
282 break;
283 case V4L2_PIX_FMT_VP8:
284 case V4L2_PIX_FMT_VP8_FRAME:
285 min_profile = VP8PROFILE_MIN;
286 max_profile = VP8PROFILE_MAX;
287 break;
288 case V4L2_PIX_FMT_VP9:
289 case V4L2_PIX_FMT_VP9_FRAME:
290 min_profile = VP9PROFILE_MIN;
291 max_profile = VP9PROFILE_MAX;
292 break;
293 default:
294 NOTREACHED() << "Unhandled pixelformat " << std::hex
295 << fmtdesc.pixelformat;
296 return profiles;
297 }
298 GetSupportedResolution(fmtdesc.pixelformat, &profile.min_resolution,
299 &profile.max_resolution); 343 &profile.max_resolution);
300 for (int media_profile = min_profile; media_profile <= max_profile; 344
301 ++media_profile) { 345 const auto video_codec_profiles =
302 profile.profile = static_cast<VideoCodecProfile>(media_profile); 346 V4L2PixFmtToVideoCodecProfiles(pixelformat, false);
347
348 for (const auto& video_codec_profile : video_codec_profiles) {
349 profile.profile = video_codec_profile;
303 profiles.push_back(profile); 350 profiles.push_back(profile);
351
352 DVLOG(1) << "Found decoder profile " << GetProfileName(profile.profile)
353 << ", resolutions: " << profile.min_resolution.ToString() << " "
354 << profile.max_resolution.ToString();
304 } 355 }
305 } 356 }
357
306 return profiles; 358 return profiles;
307 } 359 }
308 360
309 bool V4L2Device::SupportsDecodeProfileForV4L2PixelFormats( 361 VideoEncodeAccelerator::SupportedProfiles
310 VideoCodecProfile profile, 362 V4L2Device::EnumerateSupportedEncodeProfiles() {
311 const size_t num_formats, 363 VideoEncodeAccelerator::SupportedProfiles profiles;
312 const uint32_t pixelformats[]) {
313 // Get all supported profiles by this device, taking into account only fourccs
314 // in pixelformats.
315 const auto supported_profiles =
316 GetSupportedDecodeProfiles(num_formats, pixelformats);
317 364
318 // Try to find requested profile among the returned supported_profiles. 365 const auto& supported_pixelformats =
319 const auto iter = std::find_if( 366 EnumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
320 supported_profiles.begin(), supported_profiles.end(),
321 [profile](const VideoDecodeAccelerator::SupportedProfile& p) {
322 return profile == p.profile;
323 });
324 367
325 return iter != supported_profiles.end(); 368 for (const auto& pixelformat : supported_pixelformats) {
369 VideoEncodeAccelerator::SupportedProfile profile;
370 profile.max_framerate_numerator = 30;
371 profile.max_framerate_denominator = 1;
372 gfx::Size min_resolution;
373 GetSupportedResolution(pixelformat, &min_resolution,
374 &profile.max_resolution);
375
376 const auto video_codec_profiles =
377 V4L2PixFmtToVideoCodecProfiles(pixelformat, true);
378
379 for (const auto& video_codec_profile : video_codec_profiles) {
380 profile.profile = video_codec_profile;
381 profiles.push_back(profile);
382
383 DVLOG(1) << "Found encoder profile " << GetProfileName(profile.profile)
384 << ", max resolution: " << profile.max_resolution.ToString();
385 }
386 }
387
388 return profiles;
326 } 389 }
327 390
328 } // namespace media 391 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698