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