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(Type type) : type_(type) {} |
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(Type type) { |
24 DVLOG(3) << __PRETTY_FUNCTION__; | 24 DVLOG(3) << __PRETTY_FUNCTION__; |
25 | 25 |
26 scoped_refptr<GenericV4L2Device> generic_device(new GenericV4L2Device(type)); | |
27 if (generic_device->Initialize()) | |
28 return generic_device; | |
29 | |
30 #if defined(ARCH_CPU_ARMEL) | 26 #if defined(ARCH_CPU_ARMEL) |
31 scoped_refptr<TegraV4L2Device> tegra_device(new TegraV4L2Device(type)); | 27 scoped_refptr<TegraV4L2Device> tegra_device(new TegraV4L2Device(type)); |
32 if (tegra_device->Initialize()) | 28 if (tegra_device->Initialize()) |
33 return tegra_device; | 29 return tegra_device; |
34 #endif | 30 #endif |
35 | 31 |
32 scoped_refptr<GenericV4L2Device> generic_device(new GenericV4L2Device(type)); | |
33 if (generic_device->Initialize()) | |
34 return generic_device; | |
35 | |
36 DVLOG(1) << "Failed to create V4L2Device"; | 36 DVLOG(1) << "Failed to create V4L2Device"; |
37 return scoped_refptr<V4L2Device>(); | 37 return scoped_refptr<V4L2Device>(); |
38 } | 38 } |
39 | 39 |
40 // static | 40 // static |
41 VideoPixelFormat V4L2Device::V4L2PixFmtToVideoPixelFormat(uint32_t pix_fmt) { | 41 VideoPixelFormat V4L2Device::V4L2PixFmtToVideoPixelFormat(uint32_t pix_fmt) { |
42 switch (pix_fmt) { | 42 switch (pix_fmt) { |
43 case V4L2_PIX_FMT_NV12: | 43 case V4L2_PIX_FMT_NV12: |
44 case V4L2_PIX_FMT_NV12M: | 44 case V4L2_PIX_FMT_NV12M: |
45 return PIXEL_FORMAT_NV12; | 45 return PIXEL_FORMAT_NV12; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 return V4L2_PIX_FMT_VP9_FRAME; | 102 return V4L2_PIX_FMT_VP9_FRAME; |
103 else | 103 else |
104 return V4L2_PIX_FMT_VP9; | 104 return V4L2_PIX_FMT_VP9; |
105 } else { | 105 } else { |
106 LOG(FATAL) << "Add more cases as needed"; | 106 LOG(FATAL) << "Add more cases as needed"; |
107 return 0; | 107 return 0; |
108 } | 108 } |
109 } | 109 } |
110 | 110 |
111 // static | 111 // static |
112 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles( | |
113 uint32_t pix_fmt, | |
114 bool is_encoder) { | |
115 VideoCodecProfile min_profile, max_profile; | |
116 std::vector<VideoCodecProfile> profiles; | |
117 | |
118 switch (pix_fmt) { | |
119 case V4L2_PIX_FMT_H264: | |
120 case V4L2_PIX_FMT_H264_SLICE: | |
121 if (is_encoder) { | |
122 // TODO(posciak): need to query the device for supported H.264 profiles, | |
123 // for now choose Main as a sensible default. | |
124 min_profile = H264PROFILE_MAIN; | |
125 max_profile = H264PROFILE_MAIN; | |
126 } else { | |
127 min_profile = H264PROFILE_MIN; | |
128 max_profile = H264PROFILE_MAX; | |
129 } | |
130 break; | |
131 | |
132 case V4L2_PIX_FMT_VP8: | |
133 case V4L2_PIX_FMT_VP8_FRAME: | |
134 min_profile = VP8PROFILE_MIN; | |
135 max_profile = VP8PROFILE_MAX; | |
136 break; | |
137 | |
138 case V4L2_PIX_FMT_VP9: | |
139 case V4L2_PIX_FMT_VP9_FRAME: | |
140 min_profile = VP9PROFILE_MIN; | |
141 max_profile = VP9PROFILE_MAX; | |
142 break; | |
143 | |
144 default: | |
145 NOTREACHED() << "Unhandled pixelformat " << std::hex << pix_fmt; | |
kcwu
2016/10/06 10:40:00
add "0x" string
Pawel Osciak
2016/10/07 08:30:23
Done.
| |
146 return profiles; | |
147 } | |
148 | |
149 for (int profile = min_profile; profile <= max_profile; ++profile) | |
150 profiles.push_back(static_cast<VideoCodecProfile>(profile)); | |
151 | |
152 return profiles; | |
153 } | |
154 | |
155 // static | |
112 uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) { | 156 uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) { |
113 switch (format) { | 157 switch (format) { |
114 case V4L2_PIX_FMT_NV12: | 158 case V4L2_PIX_FMT_NV12: |
115 case V4L2_PIX_FMT_NV12M: | 159 case V4L2_PIX_FMT_NV12M: |
116 return DRM_FORMAT_NV12; | 160 return DRM_FORMAT_NV12; |
117 | 161 |
118 case V4L2_PIX_FMT_YUV420: | 162 case V4L2_PIX_FMT_YUV420: |
119 case V4L2_PIX_FMT_YUV420M: | 163 case V4L2_PIX_FMT_YUV420M: |
120 return DRM_FORMAT_YUV420; | 164 return DRM_FORMAT_YUV420; |
121 | 165 |
122 case V4L2_PIX_FMT_YVU420: | 166 case V4L2_PIX_FMT_YVU420: |
123 return DRM_FORMAT_YVU420; | 167 return DRM_FORMAT_YVU420; |
124 | 168 |
125 case V4L2_PIX_FMT_RGB32: | 169 case V4L2_PIX_FMT_RGB32: |
126 return DRM_FORMAT_ARGB8888; | 170 return DRM_FORMAT_ARGB8888; |
127 | 171 |
172 case V4L2_PIX_FMT_MT21: | |
173 return DRM_FORMAT_MT21; | |
174 | |
128 default: | 175 default: |
129 DVLOG(1) << "Add more cases as needed"; | 176 DVLOG(1) << "Unrecognized format " << std::hex << format; |
kcwu
2016/10/06 10:39:59
"0x"
Pawel Osciak
2016/10/07 08:30:23
Done.
| |
130 return 0; | 177 return 0; |
131 } | 178 } |
132 } | 179 } |
133 | 180 |
134 // static | 181 // static |
135 gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { | 182 gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { |
136 gfx::Size coded_size; | 183 gfx::Size coded_size; |
137 gfx::Size visible_size; | 184 gfx::Size visible_size; |
138 VideoPixelFormat frame_format = PIXEL_FORMAT_UNKNOWN; | 185 VideoPixelFormat frame_format = PIXEL_FORMAT_UNKNOWN; |
139 size_t bytesperline = 0; | 186 size_t bytesperline = 0; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 << ", fall back to " << max_resolution->ToString(); | 299 << ", fall back to " << max_resolution->ToString(); |
253 } | 300 } |
254 if (min_resolution->IsEmpty()) { | 301 if (min_resolution->IsEmpty()) { |
255 min_resolution->SetSize(16, 16); | 302 min_resolution->SetSize(16, 16); |
256 LOG(ERROR) << "GetSupportedResolution failed to get minimum resolution for " | 303 LOG(ERROR) << "GetSupportedResolution failed to get minimum resolution for " |
257 << "fourcc " << std::hex << pixelformat | 304 << "fourcc " << std::hex << pixelformat |
258 << ", fall back to " << min_resolution->ToString(); | 305 << ", fall back to " << min_resolution->ToString(); |
259 } | 306 } |
260 } | 307 } |
261 | 308 |
262 VideoDecodeAccelerator::SupportedProfiles | 309 std::vector<uint32_t> V4L2Device::EnumerateSupportedPixelformats( |
263 V4L2Device::GetSupportedDecodeProfiles(const size_t num_formats, | 310 v4l2_buf_type buf_type) { |
264 const uint32_t pixelformats[]) { | 311 std::vector<uint32_t> pixelformats; |
265 DCHECK_EQ(type_, kDecoder); | 312 |
266 VideoDecodeAccelerator::SupportedProfiles profiles; | |
267 VideoDecodeAccelerator::SupportedProfile profile; | |
268 v4l2_fmtdesc fmtdesc; | 313 v4l2_fmtdesc fmtdesc; |
269 memset(&fmtdesc, 0, sizeof(fmtdesc)); | 314 memset(&fmtdesc, 0, sizeof(fmtdesc)); |
270 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 315 fmtdesc.type = buf_type; |
271 | 316 |
272 for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { | 317 for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { |
273 if (std::find(pixelformats, pixelformats + num_formats, | 318 DVLOG(1) << "Found " << std::hex << fmtdesc.pixelformat << " " |
274 fmtdesc.pixelformat) == pixelformats + num_formats) | 319 << fmtdesc.description; |
320 pixelformats.push_back(fmtdesc.pixelformat); | |
321 } | |
322 | |
323 return pixelformats; | |
324 } | |
325 | |
326 VideoDecodeAccelerator::SupportedProfiles | |
327 V4L2Device::EnumerateSupportedDecodeProfiles(const size_t num_formats, | |
328 const uint32_t pixelformats[]) { | |
329 DCHECK_EQ(type_, Type::kDecoder); | |
330 VideoDecodeAccelerator::SupportedProfiles profiles; | |
331 | |
332 const auto& supported_pixelformats = | |
333 EnumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); | |
334 | |
335 for (uint32_t pixelformat : supported_pixelformats) { | |
336 if (std::find(pixelformats, pixelformats + num_formats, pixelformat) == | |
337 pixelformats + num_formats) | |
275 continue; | 338 continue; |
276 int min_profile, max_profile; | 339 |
277 switch (fmtdesc.pixelformat) { | 340 VideoDecodeAccelerator::SupportedProfile profile; |
278 case V4L2_PIX_FMT_H264: | 341 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); | 342 &profile.max_resolution); |
300 for (int media_profile = min_profile; media_profile <= max_profile; | 343 |
301 ++media_profile) { | 344 const auto video_codec_profiles = |
302 profile.profile = static_cast<VideoCodecProfile>(media_profile); | 345 V4L2PixFmtToVideoCodecProfiles(pixelformat, false); |
346 | |
347 for (const auto& video_codec_profile : video_codec_profiles) { | |
348 profile.profile = video_codec_profile; | |
303 profiles.push_back(profile); | 349 profiles.push_back(profile); |
350 | |
351 DVLOG(1) << "Found decoder profile " << GetProfileName(profile.profile) | |
352 << ", resolutions: " << profile.min_resolution.ToString() << " " | |
353 << profile.max_resolution.ToString(); | |
304 } | 354 } |
305 } | 355 } |
356 | |
306 return profiles; | 357 return profiles; |
307 } | 358 } |
308 | 359 |
309 bool V4L2Device::SupportsDecodeProfileForV4L2PixelFormats( | 360 VideoEncodeAccelerator::SupportedProfiles |
310 VideoCodecProfile profile, | 361 V4L2Device::EnumerateSupportedEncodeProfiles() { |
kcwu
2016/10/06 10:39:59
DCHECK_EQ(type_, Type::kEncode);
Pawel Osciak
2016/10/07 08:30:24
Done.
| |
311 const size_t num_formats, | 362 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 | 363 |
318 // Try to find requested profile among the returned supported_profiles. | 364 const auto& supported_pixelformats = |
319 const auto iter = std::find_if( | 365 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 | 366 |
325 return iter != supported_profiles.end(); | 367 for (const auto& pixelformat : supported_pixelformats) { |
368 VideoEncodeAccelerator::SupportedProfile profile; | |
369 profile.max_framerate_numerator = 30; | |
370 profile.max_framerate_denominator = 1; | |
371 gfx::Size min_resolution; | |
372 GetSupportedResolution(pixelformat, &min_resolution, | |
373 &profile.max_resolution); | |
374 | |
375 const auto video_codec_profiles = | |
376 V4L2PixFmtToVideoCodecProfiles(pixelformat, true); | |
377 | |
378 for (const auto& video_codec_profile : video_codec_profiles) { | |
379 profile.profile = video_codec_profile; | |
380 profiles.push_back(profile); | |
381 | |
382 DVLOG(1) << "Found encoder profile " << GetProfileName(profile.profile) | |
383 << ", max resolution: " << profile.max_resolution.ToString(); | |
384 } | |
385 } | |
386 | |
387 return profiles; | |
326 } | 388 } |
327 | 389 |
328 } // namespace media | 390 } // namespace media |
OLD | NEW |