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
|
// 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_
|