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" |
(...skipping 20 matching lines...) Expand all Loading... |
31 scoped_refptr<TegraV4L2Device> tegra_device(new TegraV4L2Device(type)); | 31 scoped_refptr<TegraV4L2Device> tegra_device(new TegraV4L2Device(type)); |
32 if (tegra_device->Initialize()) | 32 if (tegra_device->Initialize()) |
33 return tegra_device; | 33 return tegra_device; |
34 #endif | 34 #endif |
35 | 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 media::VideoPixelFormat V4L2Device::V4L2PixFmtToVideoPixelFormat( | 41 VideoPixelFormat V4L2Device::V4L2PixFmtToVideoPixelFormat(uint32_t pix_fmt) { |
42 uint32_t pix_fmt) { | |
43 switch (pix_fmt) { | 42 switch (pix_fmt) { |
44 case V4L2_PIX_FMT_NV12: | 43 case V4L2_PIX_FMT_NV12: |
45 case V4L2_PIX_FMT_NV12M: | 44 case V4L2_PIX_FMT_NV12M: |
46 return media::PIXEL_FORMAT_NV12; | 45 return PIXEL_FORMAT_NV12; |
47 | 46 |
48 case V4L2_PIX_FMT_MT21: | 47 case V4L2_PIX_FMT_MT21: |
49 return media::PIXEL_FORMAT_MT21; | 48 return PIXEL_FORMAT_MT21; |
50 | 49 |
51 case V4L2_PIX_FMT_YUV420: | 50 case V4L2_PIX_FMT_YUV420: |
52 case V4L2_PIX_FMT_YUV420M: | 51 case V4L2_PIX_FMT_YUV420M: |
53 return media::PIXEL_FORMAT_I420; | 52 return PIXEL_FORMAT_I420; |
54 | 53 |
55 case V4L2_PIX_FMT_RGB32: | 54 case V4L2_PIX_FMT_RGB32: |
56 return media::PIXEL_FORMAT_ARGB; | 55 return PIXEL_FORMAT_ARGB; |
57 | 56 |
58 default: | 57 default: |
59 LOG(FATAL) << "Add more cases as needed"; | 58 LOG(FATAL) << "Add more cases as needed"; |
60 return media::PIXEL_FORMAT_UNKNOWN; | 59 return PIXEL_FORMAT_UNKNOWN; |
61 } | 60 } |
62 } | 61 } |
63 | 62 |
64 // static | 63 // static |
65 uint32_t V4L2Device::VideoPixelFormatToV4L2PixFmt( | 64 uint32_t V4L2Device::VideoPixelFormatToV4L2PixFmt(VideoPixelFormat format) { |
66 media::VideoPixelFormat format) { | |
67 switch (format) { | 65 switch (format) { |
68 case media::PIXEL_FORMAT_NV12: | 66 case PIXEL_FORMAT_NV12: |
69 return V4L2_PIX_FMT_NV12M; | 67 return V4L2_PIX_FMT_NV12M; |
70 | 68 |
71 case media::PIXEL_FORMAT_MT21: | 69 case PIXEL_FORMAT_MT21: |
72 return V4L2_PIX_FMT_MT21; | 70 return V4L2_PIX_FMT_MT21; |
73 | 71 |
74 case media::PIXEL_FORMAT_I420: | 72 case PIXEL_FORMAT_I420: |
75 return V4L2_PIX_FMT_YUV420M; | 73 return V4L2_PIX_FMT_YUV420M; |
76 | 74 |
77 default: | 75 default: |
78 LOG(FATAL) << "Add more cases as needed"; | 76 LOG(FATAL) << "Add more cases as needed"; |
79 return 0; | 77 return 0; |
80 } | 78 } |
81 } | 79 } |
82 | 80 |
83 // static | 81 // static |
84 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt( | 82 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, |
85 media::VideoCodecProfile profile, | 83 bool slice_based) { |
86 bool slice_based) { | 84 if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) { |
87 if (profile >= media::H264PROFILE_MIN && profile <= media::H264PROFILE_MAX) { | |
88 if (slice_based) | 85 if (slice_based) |
89 return V4L2_PIX_FMT_H264_SLICE; | 86 return V4L2_PIX_FMT_H264_SLICE; |
90 else | 87 else |
91 return V4L2_PIX_FMT_H264; | 88 return V4L2_PIX_FMT_H264; |
92 } else if (profile >= media::VP8PROFILE_MIN && | 89 } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) { |
93 profile <= media::VP8PROFILE_MAX) { | |
94 if (slice_based) | 90 if (slice_based) |
95 return V4L2_PIX_FMT_VP8_FRAME; | 91 return V4L2_PIX_FMT_VP8_FRAME; |
96 else | 92 else |
97 return V4L2_PIX_FMT_VP8; | 93 return V4L2_PIX_FMT_VP8; |
98 } else if (profile >= media::VP9PROFILE_MIN && | 94 } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) { |
99 profile <= media::VP9PROFILE_MAX) { | |
100 return V4L2_PIX_FMT_VP9; | 95 return V4L2_PIX_FMT_VP9; |
101 } else { | 96 } else { |
102 LOG(FATAL) << "Add more cases as needed"; | 97 LOG(FATAL) << "Add more cases as needed"; |
103 return 0; | 98 return 0; |
104 } | 99 } |
105 } | 100 } |
106 | 101 |
107 // static | 102 // static |
108 uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) { | 103 uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) { |
109 switch (format) { | 104 switch (format) { |
(...skipping 11 matching lines...) Expand all Loading... |
121 default: | 116 default: |
122 DVLOG(1) << "Add more cases as needed"; | 117 DVLOG(1) << "Add more cases as needed"; |
123 return 0; | 118 return 0; |
124 } | 119 } |
125 } | 120 } |
126 | 121 |
127 // static | 122 // static |
128 gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { | 123 gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) { |
129 gfx::Size coded_size; | 124 gfx::Size coded_size; |
130 gfx::Size visible_size; | 125 gfx::Size visible_size; |
131 media::VideoPixelFormat frame_format = media::PIXEL_FORMAT_UNKNOWN; | 126 VideoPixelFormat frame_format = PIXEL_FORMAT_UNKNOWN; |
132 size_t bytesperline = 0; | 127 size_t bytesperline = 0; |
133 // Total bytes in the frame. | 128 // Total bytes in the frame. |
134 size_t sizeimage = 0; | 129 size_t sizeimage = 0; |
135 | 130 |
136 if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) { | 131 if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) { |
137 DCHECK_GT(format.fmt.pix_mp.num_planes, 0); | 132 DCHECK_GT(format.fmt.pix_mp.num_planes, 0); |
138 bytesperline = | 133 bytesperline = |
139 base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[0].bytesperline); | 134 base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[0].bytesperline); |
140 for (size_t i = 0; i < format.fmt.pix_mp.num_planes; ++i) { | 135 for (size_t i = 0; i < format.fmt.pix_mp.num_planes; ++i) { |
141 sizeimage += | 136 sizeimage += |
(...skipping 17 matching lines...) Expand all Loading... |
159 // provides bpl for the first component in the plane. So we can't depend on it | 154 // provides bpl for the first component in the plane. So we can't depend on it |
160 // for calculating height, because bpl may vary within one physical plane | 155 // for calculating height, because bpl may vary within one physical plane |
161 // buffer. For example, YUV420 contains 3 components in one physical plane, | 156 // buffer. For example, YUV420 contains 3 components in one physical plane, |
162 // with Y at 8 bits per pixel, and Cb/Cr at 4 bits per pixel per component, | 157 // with Y at 8 bits per pixel, and Cb/Cr at 4 bits per pixel per component, |
163 // but we only get 8 pits per pixel from bytesperline in physical plane 0. | 158 // but we only get 8 pits per pixel from bytesperline in physical plane 0. |
164 // So we need to get total frame bpp from elsewhere to calculate coded height. | 159 // So we need to get total frame bpp from elsewhere to calculate coded height. |
165 | 160 |
166 // We need bits per pixel for one component only to calculate | 161 // We need bits per pixel for one component only to calculate |
167 // coded_width from bytesperline. | 162 // coded_width from bytesperline. |
168 int plane_horiz_bits_per_pixel = | 163 int plane_horiz_bits_per_pixel = |
169 media::VideoFrame::PlaneHorizontalBitsPerPixel(frame_format, 0); | 164 VideoFrame::PlaneHorizontalBitsPerPixel(frame_format, 0); |
170 | 165 |
171 // Adding up bpp for each component will give us total bpp for all components. | 166 // Adding up bpp for each component will give us total bpp for all components. |
172 int total_bpp = 0; | 167 int total_bpp = 0; |
173 for (size_t i = 0; i < media::VideoFrame::NumPlanes(frame_format); ++i) | 168 for (size_t i = 0; i < VideoFrame::NumPlanes(frame_format); ++i) |
174 total_bpp += media::VideoFrame::PlaneBitsPerPixel(frame_format, i); | 169 total_bpp += VideoFrame::PlaneBitsPerPixel(frame_format, i); |
175 | 170 |
176 if (sizeimage == 0 || bytesperline == 0 || plane_horiz_bits_per_pixel == 0 || | 171 if (sizeimage == 0 || bytesperline == 0 || plane_horiz_bits_per_pixel == 0 || |
177 total_bpp == 0 || (bytesperline * 8) % plane_horiz_bits_per_pixel != 0) { | 172 total_bpp == 0 || (bytesperline * 8) % plane_horiz_bits_per_pixel != 0) { |
178 LOG(ERROR) << "Invalid format provided"; | 173 LOG(ERROR) << "Invalid format provided"; |
179 return coded_size; | 174 return coded_size; |
180 } | 175 } |
181 | 176 |
182 // Coded width can be calculated by taking the first component's bytesperline, | 177 // Coded width can be calculated by taking the first component's bytesperline, |
183 // which in V4L2 always applies to the first component in physical plane | 178 // which in V4L2 always applies to the first component in physical plane |
184 // buffer. | 179 // buffer. |
185 int coded_width = bytesperline * 8 / plane_horiz_bits_per_pixel; | 180 int coded_width = bytesperline * 8 / plane_horiz_bits_per_pixel; |
186 // Sizeimage is coded_width * coded_height * total_bpp. | 181 // Sizeimage is coded_width * coded_height * total_bpp. |
187 int coded_height = sizeimage * 8 / coded_width / total_bpp; | 182 int coded_height = sizeimage * 8 / coded_width / total_bpp; |
188 | 183 |
189 coded_size.SetSize(coded_width, coded_height); | 184 coded_size.SetSize(coded_width, coded_height); |
190 // It's possible the driver gave us a slightly larger sizeimage than what | 185 // It's possible the driver gave us a slightly larger sizeimage than what |
191 // would be calculated from coded size. This is technically not allowed, but | 186 // would be calculated from coded size. This is technically not allowed, but |
192 // some drivers (Exynos) like to have some additional alignment that is not a | 187 // some drivers (Exynos) like to have some additional alignment that is not a |
193 // multiple of bytesperline. The best thing we can do is to compensate by | 188 // multiple of bytesperline. The best thing we can do is to compensate by |
194 // aligning to next full row. | 189 // aligning to next full row. |
195 if (sizeimage > media::VideoFrame::AllocationSize(frame_format, coded_size)) | 190 if (sizeimage > VideoFrame::AllocationSize(frame_format, coded_size)) |
196 coded_size.SetSize(coded_width, coded_height + 1); | 191 coded_size.SetSize(coded_width, coded_height + 1); |
197 DVLOG(3) << "coded_size=" << coded_size.ToString(); | 192 DVLOG(3) << "coded_size=" << coded_size.ToString(); |
198 | 193 |
199 // Sanity checks. Calculated coded size has to contain given visible size | 194 // Sanity checks. Calculated coded size has to contain given visible size |
200 // and fulfill buffer byte size requirements. | 195 // and fulfill buffer byte size requirements. |
201 DCHECK(gfx::Rect(coded_size).Contains(gfx::Rect(visible_size))); | 196 DCHECK(gfx::Rect(coded_size).Contains(gfx::Rect(visible_size))); |
202 DCHECK_LE(sizeimage, | 197 DCHECK_LE(sizeimage, VideoFrame::AllocationSize(frame_format, coded_size)); |
203 media::VideoFrame::AllocationSize(frame_format, coded_size)); | |
204 | 198 |
205 return coded_size; | 199 return coded_size; |
206 } | 200 } |
207 | 201 |
208 void V4L2Device::GetSupportedResolution(uint32_t pixelformat, | 202 void V4L2Device::GetSupportedResolution(uint32_t pixelformat, |
209 gfx::Size* min_resolution, | 203 gfx::Size* min_resolution, |
210 gfx::Size* max_resolution) { | 204 gfx::Size* max_resolution) { |
211 max_resolution->SetSize(0, 0); | 205 max_resolution->SetSize(0, 0); |
212 min_resolution->SetSize(0, 0); | 206 min_resolution->SetSize(0, 0); |
213 v4l2_frmsizeenum frame_size; | 207 v4l2_frmsizeenum frame_size; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 << ", fall back to " << max_resolution->ToString(); | 240 << ", fall back to " << max_resolution->ToString(); |
247 } | 241 } |
248 if (min_resolution->IsEmpty()) { | 242 if (min_resolution->IsEmpty()) { |
249 min_resolution->SetSize(16, 16); | 243 min_resolution->SetSize(16, 16); |
250 LOG(ERROR) << "GetSupportedResolution failed to get minimum resolution for " | 244 LOG(ERROR) << "GetSupportedResolution failed to get minimum resolution for " |
251 << "fourcc " << std::hex << pixelformat | 245 << "fourcc " << std::hex << pixelformat |
252 << ", fall back to " << min_resolution->ToString(); | 246 << ", fall back to " << min_resolution->ToString(); |
253 } | 247 } |
254 } | 248 } |
255 | 249 |
256 media::VideoDecodeAccelerator::SupportedProfiles | 250 VideoDecodeAccelerator::SupportedProfiles |
257 V4L2Device::GetSupportedDecodeProfiles(const size_t num_formats, | 251 V4L2Device::GetSupportedDecodeProfiles(const size_t num_formats, |
258 const uint32_t pixelformats[]) { | 252 const uint32_t pixelformats[]) { |
259 DCHECK_EQ(type_, kDecoder); | 253 DCHECK_EQ(type_, kDecoder); |
260 media::VideoDecodeAccelerator::SupportedProfiles profiles; | 254 VideoDecodeAccelerator::SupportedProfiles profiles; |
261 media::VideoDecodeAccelerator::SupportedProfile profile; | 255 VideoDecodeAccelerator::SupportedProfile profile; |
262 v4l2_fmtdesc fmtdesc; | 256 v4l2_fmtdesc fmtdesc; |
263 memset(&fmtdesc, 0, sizeof(fmtdesc)); | 257 memset(&fmtdesc, 0, sizeof(fmtdesc)); |
264 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 258 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
265 | 259 |
266 for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { | 260 for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { |
267 if (std::find(pixelformats, pixelformats + num_formats, | 261 if (std::find(pixelformats, pixelformats + num_formats, |
268 fmtdesc.pixelformat) == pixelformats + num_formats) | 262 fmtdesc.pixelformat) == pixelformats + num_formats) |
269 continue; | 263 continue; |
270 int min_profile, max_profile; | 264 int min_profile, max_profile; |
271 switch (fmtdesc.pixelformat) { | 265 switch (fmtdesc.pixelformat) { |
272 case V4L2_PIX_FMT_H264: | 266 case V4L2_PIX_FMT_H264: |
273 case V4L2_PIX_FMT_H264_SLICE: | 267 case V4L2_PIX_FMT_H264_SLICE: |
274 min_profile = media::H264PROFILE_MIN; | 268 min_profile = H264PROFILE_MIN; |
275 max_profile = media::H264PROFILE_MAX; | 269 max_profile = H264PROFILE_MAX; |
276 break; | 270 break; |
277 case V4L2_PIX_FMT_VP8: | 271 case V4L2_PIX_FMT_VP8: |
278 case V4L2_PIX_FMT_VP8_FRAME: | 272 case V4L2_PIX_FMT_VP8_FRAME: |
279 min_profile = media::VP8PROFILE_MIN; | 273 min_profile = VP8PROFILE_MIN; |
280 max_profile = media::VP8PROFILE_MAX; | 274 max_profile = VP8PROFILE_MAX; |
281 break; | 275 break; |
282 case V4L2_PIX_FMT_VP9: | 276 case V4L2_PIX_FMT_VP9: |
283 min_profile = media::VP9PROFILE_MIN; | 277 min_profile = VP9PROFILE_MIN; |
284 max_profile = media::VP9PROFILE_MAX; | 278 max_profile = VP9PROFILE_MAX; |
285 break; | 279 break; |
286 default: | 280 default: |
287 NOTREACHED() << "Unhandled pixelformat " << std::hex | 281 NOTREACHED() << "Unhandled pixelformat " << std::hex |
288 << fmtdesc.pixelformat; | 282 << fmtdesc.pixelformat; |
289 return profiles; | 283 return profiles; |
290 } | 284 } |
291 GetSupportedResolution(fmtdesc.pixelformat, &profile.min_resolution, | 285 GetSupportedResolution(fmtdesc.pixelformat, &profile.min_resolution, |
292 &profile.max_resolution); | 286 &profile.max_resolution); |
293 for (int media_profile = min_profile; media_profile <= max_profile; | 287 for (int media_profile = min_profile; media_profile <= max_profile; |
294 ++media_profile) { | 288 ++media_profile) { |
295 profile.profile = static_cast<media::VideoCodecProfile>(media_profile); | 289 profile.profile = static_cast<VideoCodecProfile>(media_profile); |
296 profiles.push_back(profile); | 290 profiles.push_back(profile); |
297 } | 291 } |
298 } | 292 } |
299 return profiles; | 293 return profiles; |
300 } | 294 } |
301 | 295 |
302 bool V4L2Device::SupportsDecodeProfileForV4L2PixelFormats( | 296 bool V4L2Device::SupportsDecodeProfileForV4L2PixelFormats( |
303 media::VideoCodecProfile profile, | 297 VideoCodecProfile profile, |
304 const size_t num_formats, | 298 const size_t num_formats, |
305 const uint32_t pixelformats[]) { | 299 const uint32_t pixelformats[]) { |
306 // Get all supported profiles by this device, taking into account only fourccs | 300 // Get all supported profiles by this device, taking into account only fourccs |
307 // in pixelformats. | 301 // in pixelformats. |
308 const auto supported_profiles = | 302 const auto supported_profiles = |
309 GetSupportedDecodeProfiles(num_formats, pixelformats); | 303 GetSupportedDecodeProfiles(num_formats, pixelformats); |
310 | 304 |
311 // Try to find requested profile among the returned supported_profiles. | 305 // Try to find requested profile among the returned supported_profiles. |
312 const auto iter = std::find_if( | 306 const auto iter = std::find_if( |
313 supported_profiles.begin(), supported_profiles.end(), | 307 supported_profiles.begin(), supported_profiles.end(), |
314 [profile](const media::VideoDecodeAccelerator::SupportedProfile& p) { | 308 [profile](const VideoDecodeAccelerator::SupportedProfile& p) { |
315 return profile == p.profile; | 309 return profile == p.profile; |
316 }); | 310 }); |
317 | 311 |
318 return iter != supported_profiles.end(); | 312 return iter != supported_profiles.end(); |
319 } | 313 } |
320 | 314 |
321 } // namespace media | 315 } // namespace media |
OLD | NEW |