1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
media / gpu / v4l2 / v4l2_utils.h [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_V4L2_V4L2_UTILS_H_
#define MEDIA_GPU_V4L2_V4L2_UTILS_H_
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <optional>
#include <string>
#include "base/files/scoped_file.h"
#include "base/functional/callback.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/supported_video_decoder_config.h"
#include "media/base/svc_scalability_mode.h"
#include "media/base/video_codecs.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#ifndef V4L2_PIX_FMT_QC08C
#define V4L2_PIX_FMT_QC08C \
v4l2_fourcc('Q', '0', '8', 'C') /* Qualcomm 8-bit compressed */
#endif
#ifndef V4L2_PIX_FMT_INVALID
#define V4L2_PIX_FMT_INVALID v4l2_fourcc('0', '0', '0', '0')
#endif
namespace gfx {
class Size;
}
namespace media {
class VideoFrameLayout;
using IoctlAsCallback = base::RepeatingCallback<int(int, void*)>;
// Ideally this should be a decltype(mmap) (void *mmap(void *addr, size_t
// length, int prot, int flags, int fd, off_t offset)), but the types of e.g.
// V4L2Device::Mmap are wrong.
// TODO(b/279980150): correct types and argument order and use decltype.
using MmapAsCallback =
base::RepeatingCallback<void*(void*, unsigned int, int, int, unsigned int)>;
// This is the callback invoked after successfully allocating a secure buffer.
// Invocation of this is guaranteed to pass a valid FD w/ the corresponding
// secure handle.
using SecureBufferAllocatedCB =
base::OnceCallback<void(base::ScopedFD fd, uint64_t secure_handle)>;
using AllocateSecureBufferAsCallback =
base::RepeatingCallback<void(uint32_t size,
SecureBufferAllocatedCB callback)>;
// Numerical value of ioctl() OK return value;
constexpr int kIoctlOk = 0;
// These values are logged to UMA. Entries should not be renumbered and numeric
// values should never be reused. Please keep in sync with
// "MediaIoctlRequests" in src/tools/metrics/histograms/enums.xml.
enum class MediaIoctlRequests {
kMediaIocDeviceInfo = 0,
kMediaIocRequestAlloc = 1,
kMediaRequestIocQueue = 2,
kMediaRequestIocReinit = 3,
kMaxValue = kMediaRequestIocReinit,
};
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. Please keep in sync with
// "VidiocIoctlRequests" in src/tools/metrics/histograms/enums.xml.
enum class VidiocIoctlRequests {
kVidiocGFmt = 0,
kVidiocSFmt = 1,
kVidiocGSelection = 2,
kVidiocExpbuf = 3,
kVidiocReqbufs = 4,
kVidiocQuerybuf = 5,
kVidiocQbuf = 6,
kVidiocDqbuf = 7,
kVidiocStreamon = 8,
kVidiocStreamoff = 9,
kVidiocSExtCtrls = 10,
kMaxValue = kVidiocSExtCtrls,
};
// Records Media.V4L2VideoDecoder.MediaIoctlError UMA when errors happen with
// media controller API ioctl requests.
void RecordMediaIoctlUMA(MediaIoctlRequests function);
// Records Vidioc.V4L2VideoDecoder.VidiocIoctlError UMA when errors happen with
// V4L2 API ioctl requests.
void RecordVidiocIoctlErrorUMA(VidiocIoctlRequests function);
// Returns a human readable description of |memory|.
const char* V4L2MemoryToString(v4l2_memory memory);
// Returns a human readable description of |format|.
std::string V4L2FormatToString(const struct v4l2_format& format);
// Returns a human readable description of |buffer|
std::string V4L2BufferToString(const struct v4l2_buffer& buffer);
// Translates |v4l2_codec| (a Control ID, e.g. V4L2_CID_MPEG_VIDEO_VP8_PROFILE)
// and |v4l2_profile| (e.g. V4L2_MPEG_VIDEO_VP8_PROFILE_0) to a
// media::VideoCodecProfile, if those are supported by Chrome. It returns
// VIDEO_CODEC_PROFILE_UNKNOWN otherwise.
VideoCodecProfile V4L2ProfileToVideoCodecProfile(uint32_t v4l2_codec,
uint32_t v4l2_profile);
// Returns number of planes of |pix_fmt|, or 1, if this is unknown.
size_t GetNumPlanesOfV4L2PixFmt(uint32_t pix_fmt);
// Composes VideoFrameLayout based on v4l2_format.
// If error occurs, it returns std::nullopt.
std::optional<VideoFrameLayout> V4L2FormatToVideoFrameLayout(
const struct v4l2_format& format);
// Query the driver to see what scalability modes are supported for the driver.
std::vector<SVCScalabilityMode> GetSupportedScalabilityModesForV4L2Codec(
const IoctlAsCallback& ioctl_cb,
VideoCodecProfile media_profile);
// Enumerates the supported VideoCodecProfiles for a given device (accessed via
// |ioctl_cb|) and for |codec_as_pix_fmt| (e.g. V4L2_PIX_FMT_VP9). Returns an
// empty vector if |codec_as_pix_fmt| is not supported by Chrome, or the
// associated profiles cannot be enumerated or they are all unsupported
// themselves. Notably, if the device driver doesn't support enumeration of a
// supported |codec_as_pix_fmt| (i.e. VIDIOC_QUERYCTRL), a default list of
// profiles is returned (this happens for example for VP8 on Hana MTK8173, or
// for HEVC on Trogdor QC SC7180).
std::vector<VideoCodecProfile> EnumerateSupportedProfilesForV4L2Codec(
const IoctlAsCallback& ioctl_cb,
uint32_t codec_as_pix_fmt);
// Enumerates all supported pixel formats for a given device (accessed via
// |ioctl_cb|) and for |buf_type|; these will be the supported video codecs
// (e.g. V4L2_PIX_FMT_VP9) for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE.
std::vector<uint32_t> EnumerateSupportedPixFmts(const IoctlAsCallback& ioctl_cb,
v4l2_buf_type buf_type);
// Gets minimum and maximum resolution for fourcc |pixelformat|. If the driver
// doesn't support enumeration, default values are returned instead.
void GetSupportedResolution(const IoctlAsCallback& ioctl_cb,
uint32_t pixelformat,
gfx::Size* min_resolution,
gfx::Size* max_resolution);
// Translates a media::VideoCodecProfile to a supported pixel format
// (e.g. V4L2_PIX_FMT_VP9) if those are supported by Chrome. It returns
// V4L2_PIX_FMT_INVALID otherwise.
uint32_t VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
bool slice_based);
// Translates a POSIX |timeval| to Chrome's base::TimeDelta.
base::TimeDelta TimeValToTimeDelta(const struct timeval& timeval);
// Translates a Chrome |time_delta| to a POSIX struct timeval.
struct timeval TimeDeltaToTimeVal(base::TimeDelta time_delta);
// Return a set of all the codecs supported by the hardware as well as
// their capabilities
std::optional<SupportedVideoDecoderConfigs> GetSupportedV4L2DecoderConfigs();
// Queries the driver to see if it supports stateful decoding.
bool IsV4L2DecoderStateful();
// Queries whether V4L2 virtual driver (VISL) is used on VM.
bool IsVislDriver();
// Returns a readable description of |ctrls|.
std::string V4L2ControlsToString(const struct v4l2_ext_controls* ctrls);
} // namespace media
#endif // MEDIA_GPU_V4L2_V4L2_UTILS_H_