From 0561794180fa7064a098d06761e1b99391521d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Grzesik?= <bgrzesik@google.com> Date: Fri, 17 Feb 2023 12:13:45 +0000 Subject: [PATCH] V4L2Device: Refactor querying capabilities This CL refactors querying capabilities. It eliminates usage of single instance of V4L2Device for multiple devices by exporting querying methods to static. Bug: 251420501 Test: adb shell dumpsys media.player Test: adb logcat Change-Id: I0d4ea16d2818a9c3cbde3ae31a99419a457cb1c1 (cherry picked from commit e4b9917003de8c330c91a1cd0a1d55a7e9828e7d) --- common/V4L2Device.cpp | 265 +++++++++--------- .../include/v4l2_codec2/common/V4L2Device.h | 76 +++-- components/V4L2DecodeInterface.cpp | 37 +-- components/V4L2Decoder.cpp | 20 +- components/V4L2EncodeInterface.cpp | 10 +- components/V4L2Encoder.cpp | 6 +- .../v4l2_codec2/components/V4L2Decoder.h | 2 - 7 files changed, 184 insertions(+), 232 deletions(-) diff --git a/common/V4L2Device.cpp b/common/V4L2Device.cpp index a58ee56..09b809a 100644 --- a/common/V4L2Device.cpp +++ b/common/V4L2Device.cpp @@ -1256,7 +1256,7 @@ std::vector<uint32_t> V4L2Device::preferredInputFormat(Type type) { } // static -uint32_t V4L2Device::C2ProfileToV4L2PixFmt(C2Config::profile_t profile, bool sliceBased) { +uint32_t V4L2Device::c2ProfileToV4L2PixFmt(C2Config::profile_t profile, bool sliceBased) { if (profile >= C2Config::PROFILE_AVC_BASELINE && profile <= C2Config::PROFILE_AVC_ENHANCED_MULTIVIEW_DEPTH_HIGH) { if (sliceBased) { @@ -1491,7 +1491,21 @@ C2Config::profile_t V4L2Device::v4L2ProfileToC2Profile(VideoCodec codec, uint32_ return C2Config::PROFILE_UNUSED; } -std::vector<C2Config::level_t> V4L2Device::v4L2PixFmtToC2Levels(uint32_t pixFmt) { +// static +uint32_t V4L2Device::videoCodecToPixFmt(VideoCodec codec) { + switch (codec) { + case VideoCodec::H264: + return V4L2_PIX_FMT_H264; + case VideoCodec::VP8: + return V4L2_PIX_FMT_VP8; + case VideoCodec::VP9: + return V4L2_PIX_FMT_VP9; + case VideoCodec::HEVC: + return V4L2_PIX_FMT_HEVC; + } +} + +std::vector<C2Config::level_t> V4L2Device::queryC2Levels(uint32_t pixFmt) { auto getSupportedLevels = [this](VideoCodec codec, std::vector<C2Config::level_t>* levels) { uint32_t queryId = 0; switch (codec) { @@ -1582,8 +1596,7 @@ std::vector<C2Config::level_t> V4L2Device::v4L2PixFmtToC2Levels(uint32_t pixFmt) return levels; } -std::vector<C2Config::profile_t> V4L2Device::v4L2PixFmtToC2Profiles(uint32_t pixFmt, - bool /*isEncoder*/) { +std::vector<C2Config::profile_t> V4L2Device::queryC2Profiles(uint32_t pixFmt) { auto getSupportedProfiles = [this](VideoCodec codec, std::vector<C2Config::profile_t>* profiles) { uint32_t queryId = 0; @@ -1744,7 +1757,7 @@ int32_t V4L2Device::h264LevelIdcToV4L2H264Level(uint8_t levelIdc) { } // static -v4l2_mpeg_video_bitrate_mode V4L2Device::C2BitrateModeToV4L2BitrateMode( +v4l2_mpeg_video_bitrate_mode V4L2Device::c2BitrateModeToV4L2BitrateMode( C2Config::bitrate_mode_t bitrateMode) { switch (bitrateMode) { case C2Config::bitrate_mode_t::BITRATE_CONST_SKIP_ALLOWED: @@ -2102,44 +2115,48 @@ std::vector<uint32_t> V4L2Device::enumerateSupportedPixelformats(v4l2_buf_type b return pixelFormats; } +// static std::vector<C2Config::level_t> V4L2Device::getSupportedDecodeLevels(VideoCodec videoCodecType) { std::vector<C2Config::level_t> supportedLevels; Type type = Type::kDecoder; - const auto& devices = getDevicesForType(type); - for (const auto& device : devices) { - if (!openDevicePath(device.first, type)) { - ALOGV("Failed opening %s", device.first.c_str()); + + for (const auto& info : getDeviceInfosForType(type)) { + scoped_refptr<V4L2Device> device = V4L2Device::create(); + if (!device->openDevicePath(info.first, type)) { + ALOGV("Failed opening %s", info.first.c_str()); continue; } - const auto& levels = enumerateSupportedDecodeLevels(videoCodecType); + const auto& levels = device->enumerateSupportedDecodeLevels(videoCodecType); supportedLevels.insert(supportedLevels.end(), levels.begin(), levels.end()); - closeDevice(); + device->closeDevice(); } return supportedLevels; } -V4L2Device::SupportedDecodeProfiles V4L2Device::getSupportedDecodeProfiles( - const std::vector<uint32_t>& pixelFormats) { - SupportedDecodeProfiles supportedProfiles; - - Type type = Type::kDecoder; - const auto& devices = getDevicesForType(type); - for (const auto& device : devices) { - if (!openDevicePath(device.first, type)) { - ALOGV("Failed opening %s", device.first.c_str()); +// static +V4L2Device::SupportedProfiles V4L2Device::getSupportedProfiles( + V4L2Device::Type type, const std::vector<uint32_t>& pixelFormats) { + SupportedProfiles supportedProfiles; + + for (const auto& info : getDeviceInfosForType(type)) { + scoped_refptr<V4L2Device> device = V4L2Device::create(); + if (!device->openDevicePath(info.first, type)) { + ALOGV("Failed opening %s", info.first.c_str()); continue; } - const auto& profiles = enumerateSupportedDecodeProfiles(pixelFormats); + const auto& profiles = device->enumerateSupportedProfiles(type, pixelFormats); supportedProfiles.insert(supportedProfiles.end(), profiles.begin(), profiles.end()); - closeDevice(); + + device->closeDevice(); } return supportedProfiles; } +// static C2Config::profile_t V4L2Device::getDefaultProfile(VideoCodec codec) { uint32_t queryId = 0; @@ -2160,42 +2177,36 @@ C2Config::profile_t V4L2Device::getDefaultProfile(VideoCodec codec) { return C2Config::PROFILE_UNUSED; } - // Call to query control which will return structure including - // index of default profile - v4l2_queryctrl queryCtrl = {}; - queryCtrl.id = queryId; - if (ioctl(VIDIOC_QUERYCTRL, &queryCtrl) != 0) { - return C2Config::PROFILE_UNUSED; - } - - v4l2_querymenu queryMenu = {}; - queryMenu.id = queryCtrl.id; - queryMenu.index = queryCtrl.default_value; - if (ioctl(VIDIOC_QUERYMENU, &queryMenu) == 0) { - return v4L2ProfileToC2Profile(codec, queryMenu.index); - } - return C2Config::PROFILE_UNUSED; -} - -V4L2Device::SupportedEncodeProfiles V4L2Device::getSupportedEncodeProfiles() { - SupportedEncodeProfiles supportedProfiles; + for (const auto& info : getDeviceInfosForType(Type::kDecoder)) { + scoped_refptr<V4L2Device> device = V4L2Device::create(); + if (!device->openDevicePath(info.first, Type::kDecoder)) { + ALOGV("Failed opening %s", info.first.c_str()); + continue; + } - Type type = Type::kEncoder; - const auto& devices = getDevicesForType(type); - for (const auto& device : devices) { - if (!openDevicePath(device.first, type)) { - ALOGV("Failed opening %s", device.first.c_str()); + // Call to query control which will return structure including + // index of default profile + v4l2_queryctrl queryCtrl = {}; + queryCtrl.id = queryId; + if (device->ioctl(VIDIOC_QUERYCTRL, &queryCtrl) != 0) { + device->closeDevice(); continue; } - const auto& profiles = enumerateSupportedEncodeProfiles(); - supportedProfiles.insert(supportedProfiles.end(), profiles.begin(), profiles.end()); - closeDevice(); - } + v4l2_querymenu queryMenu = {}; + queryMenu.id = queryCtrl.id; + queryMenu.index = queryCtrl.default_value; + if (device->ioctl(VIDIOC_QUERYMENU, &queryMenu) == 0) { + device->closeDevice(); + return v4L2ProfileToC2Profile(codec, queryMenu.index); + } - return supportedProfiles; + device->closeDevice(); + } + return C2Config::PROFILE_UNUSED; } +// static C2Config::level_t V4L2Device::getDefaultLevel(VideoCodec codec) { uint32_t queryId = 0; @@ -2215,17 +2226,29 @@ C2Config::level_t V4L2Device::getDefaultLevel(VideoCodec codec) { return C2Config::LEVEL_UNUSED; } - v4l2_queryctrl queryCtrl = {}; - queryCtrl.id = queryId; - if (ioctl(VIDIOC_QUERYCTRL, &queryCtrl) != 0) { // gets index of default profile - return C2Config::LEVEL_UNUSED; - } + for (const auto& info : getDeviceInfosForType(Type::kDecoder)) { + scoped_refptr<V4L2Device> device = V4L2Device::create(); + if (!device->openDevicePath(info.first, Type::kDecoder)) { + ALOGV("Failed opening %s", info.first.c_str()); + continue; + } + + v4l2_queryctrl queryCtrl = {}; + queryCtrl.id = queryId; + if (device->ioctl(VIDIOC_QUERYCTRL, &queryCtrl) != 0) { // gets index of default profile + device->closeDevice(); + continue; + } - v4l2_querymenu queryMenu = {}; - queryMenu.id = queryCtrl.id; - queryMenu.index = queryCtrl.default_value; - if (ioctl(VIDIOC_QUERYMENU, &queryMenu) == 0) { - return v4L2LevelToC2Level(codec, queryMenu.index); + v4l2_querymenu queryMenu = {}; + queryMenu.id = queryCtrl.id; + queryMenu.index = queryCtrl.default_value; + if (device->ioctl(VIDIOC_QUERYMENU, &queryMenu) == 0) { + device->closeDevice(); + return v4L2LevelToC2Level(codec, queryMenu.index); + } + + device->closeDevice(); } return C2Config::LEVEL_UNUSED; @@ -2240,7 +2263,7 @@ std::vector<C2Config::level_t> V4L2Device::enumerateSupportedDecodeLevels( for (uint32_t pixelFormat : supportedPixelformats) { if (isValidPixFmtForCodec(videoCodecType, pixelFormat)) { - std::vector<C2Config::level_t> levels = v4L2PixFmtToC2Levels(pixelFormat); + std::vector<C2Config::level_t> levels = queryC2Levels(pixelFormat); supportedLevels.insert(supportedLevels.end(), levels.begin(), levels.end()); } } @@ -2248,55 +2271,42 @@ std::vector<C2Config::level_t> V4L2Device::enumerateSupportedDecodeLevels( return supportedLevels; } -V4L2Device::SupportedDecodeProfiles V4L2Device::enumerateSupportedDecodeProfiles( - const std::vector<uint32_t>& pixelFormats) { - SupportedDecodeProfiles profiles; +V4L2Device::SupportedProfiles V4L2Device::enumerateSupportedProfiles( + V4L2Device::Type type, const std::vector<uint32_t>& pixelFormats) { + SupportedProfiles profiles; - const auto& supportedPixelformats = - enumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + v4l2_buf_type bufType; + switch (type) { + case Type::kDecoder: + bufType = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + break; + case Type::kEncoder: + bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + break; + } + + const auto& supportedPixelformats = enumerateSupportedPixelformats(bufType); for (uint32_t pixelFormat : supportedPixelformats) { if (std::find(pixelFormats.begin(), pixelFormats.end(), pixelFormat) == pixelFormats.end()) continue; - SupportedDecodeProfile profile; - getSupportedResolution(pixelFormat, &profile.min_resolution, &profile.max_resolution); - - const auto videoCodecProfiles = v4L2PixFmtToC2Profiles(pixelFormat, false); - - for (const auto& videoCodecProfile : videoCodecProfiles) { - profile.profile = videoCodecProfile; - profiles.push_back(profile); - - ALOGV("Found decoder profile %s, resolutions: %s %s", profileToString(profile.profile), - toString(profile.min_resolution).c_str(), - toString(profile.max_resolution).c_str()); + SupportedProfile profile; + if (type == Type::kEncoder) { + profile.max_framerate_numerator = 30; + profile.max_framerate_denominator = 1; } - } - return profiles; -} - -V4L2Device::SupportedEncodeProfiles V4L2Device::enumerateSupportedEncodeProfiles() { - SupportedEncodeProfiles profiles; - - const auto& supportedPixelformats = - enumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - - for (const auto& pixelformat : supportedPixelformats) { - SupportedEncodeProfile profile; - profile.max_framerate_numerator = 30; - profile.max_framerate_denominator = 1; - ui::Size minResolution; - getSupportedResolution(pixelformat, &minResolution, &profile.max_resolution); + getSupportedResolution(pixelFormat, &profile.min_resolution, &profile.max_resolution); - const auto videoCodecProfiles = v4L2PixFmtToC2Profiles(pixelformat, true); + const auto videoCodecProfiles = queryC2Profiles(pixelFormat); for (const auto& videoCodecProfile : videoCodecProfiles) { profile.profile = videoCodecProfile; profiles.push_back(profile); - ALOGV("Found encoder profile %s, max resolution: %s", profileToString(profile.profile), + ALOGV("Found profile %s, resolutions: %s %s", profileToString(profile.profile), + toString(profile.min_resolution).c_str(), toString(profile.max_resolution).c_str()); } } @@ -2396,70 +2406,59 @@ void V4L2Device::closeDevice() { mDeviceFd.reset(); } -void V4L2Device::enumerateDevicesForType(Type type) { +// static +const V4L2Device::DeviceInfos& V4L2Device::getDeviceInfosForType(V4L2Device::Type type) { // video input/output devices are registered as /dev/videoX in V4L2. - static const std::string kVideoDevicePattern = "/dev/video"; + static constexpr const char* kVideoDevicePattern = "/dev/video"; + static const DeviceInfos sNoDevices = {}; + static std::mutex sDeviceInfosCacheLock; + static std::map<Type, DeviceInfos> sDeviceInfosCache; + + std::lock_guard lock(sDeviceInfosCacheLock); + if (sDeviceInfosCache.find(type) != sDeviceInfosCache.end()) { + return sDeviceInfosCache[type]; + } - std::string devicePattern; v4l2_buf_type bufType; switch (type) { case Type::kDecoder: - devicePattern = kVideoDevicePattern; bufType = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; break; case Type::kEncoder: - devicePattern = kVideoDevicePattern; bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; break; default: ALOGE("Only decoder and encoder types are supported!!"); - return; + return sNoDevices; } - std::vector<std::string> candidatePaths; - - // TODO(posciak): Remove this legacy unnumbered device once all platforms are updated to use - // numbered devices. - candidatePaths.push_back(devicePattern); + DeviceInfos deviceInfos; + for (int i = 0; i < 10; ++i) { + std::string path = base::StringPrintf("%s%d", kVideoDevicePattern, i); - // We are sandboxed, so we can't query directory contents to check which devices are actually - // available. Try to open the first 16; if not present, we will just fail to open immediately. - for (int i = 0; i < 16; ++i) { - candidatePaths.push_back(base::StringPrintf("%s%d", devicePattern.c_str(), i)); - } - - Devices devices; - for (const auto& path : candidatePaths) { - if (!openDevicePath(path, type)) { + scoped_refptr<V4L2Device> device = V4L2Device::create(); + if (!device->openDevicePath(path, type)) { continue; } - const auto& supportedPixelformats = enumerateSupportedPixelformats(bufType); + const auto& supportedPixelformats = device->enumerateSupportedPixelformats(bufType); if (!supportedPixelformats.empty()) { ALOGV("Found device: %s", path.c_str()); - devices.push_back(std::make_pair(path, supportedPixelformats)); + deviceInfos.push_back(std::make_pair(path, supportedPixelformats)); } - closeDevice(); + device->closeDevice(); } - ALOG_ASSERT(mDevicesByType.count(type) == 0u); - mDevicesByType[type] = devices; -} + sDeviceInfosCache[type] = deviceInfos; -const V4L2Device::Devices& V4L2Device::getDevicesForType(Type type) { - if (mDevicesByType.count(type) == 0) enumerateDevicesForType(type); - - ALOG_ASSERT(mDevicesByType.count(type) != 0u); - return mDevicesByType[type]; + return sDeviceInfosCache[type]; } std::string V4L2Device::getDevicePathFor(Type type, uint32_t pixFmt) { - const Devices& devices = getDevicesForType(type); - - for (const auto& device : devices) { - if (std::find(device.second.begin(), device.second.end(), pixFmt) != device.second.end()) - return device.first; + for (const auto& info : getDeviceInfosForType(type)) { + if (std::find(info.second.begin(), info.second.end(), pixFmt) != info.second.end()) + return info.first; } return std::string(); diff --git a/common/include/v4l2_codec2/common/V4L2Device.h b/common/include/v4l2_codec2/common/V4L2Device.h index 534b063..7e7b941 100644 --- a/common/include/v4l2_codec2/common/V4L2Device.h +++ b/common/include/v4l2_codec2/common/V4L2Device.h @@ -342,39 +342,29 @@ private: class V4L2Device : public base::RefCountedThreadSafe<V4L2Device> { public: // Specification of an encoding profile supported by an encoder. - struct SupportedEncodeProfile { + struct SupportedProfile { C2Config::profile_t profile = C2Config::PROFILE_UNUSED; ui::Size min_resolution; ui::Size max_resolution; uint32_t max_framerate_numerator = 0; uint32_t max_framerate_denominator = 0; - }; - using SupportedEncodeProfiles = std::vector<SupportedEncodeProfile>; - - // Specification of a decoding profile supported by an decoder. - // |max_resolution| and |min_resolution| are inclusive. - struct SupportedDecodeProfile { - C2Config::profile_t profile = C2Config::PROFILE_UNUSED; - ui::Size max_resolution; - ui::Size min_resolution; bool encrypted_only = false; }; - using SupportedDecodeProfiles = std::vector<SupportedDecodeProfile>; + using SupportedProfiles = std::vector<SupportedProfile>; // Utility format conversion functions // If there is no corresponding single- or multi-planar format, returns 0. - static uint32_t C2ProfileToV4L2PixFmt(C2Config::profile_t profile, bool sliceBased); + static uint32_t c2ProfileToV4L2PixFmt(C2Config::profile_t profile, bool sliceBased); static C2Config::level_t v4L2LevelToC2Level(VideoCodec codec, uint32_t level); static C2Config::profile_t v4L2ProfileToC2Profile(VideoCodec codec, uint32_t profile); - std::vector<C2Config::level_t> v4L2PixFmtToC2Levels(uint32_t pixFmt); - std::vector<C2Config::profile_t> v4L2PixFmtToC2Profiles(uint32_t pixFmt, bool isEncoder); + static uint32_t videoCodecToPixFmt(VideoCodec codec); // Calculates the largest plane's allocation size requested by a V4L2 device. static ui::Size allocatedSizeFromV4L2Format(const struct v4l2_format& format); // Convert required H264 profile and level to V4L2 enums. static int32_t c2ProfileToV4L2H264Profile(C2Config::profile_t profile); static int32_t h264LevelIdcToV4L2H264Level(uint8_t levelIdc); - static v4l2_mpeg_video_bitrate_mode C2BitrateModeToV4L2BitrateMode( + static v4l2_mpeg_video_bitrate_mode c2BitrateModeToV4L2BitrateMode( C2Config::bitrate_mode_t bitrateMode); // Converts v4l2_memory to a string. @@ -403,6 +393,19 @@ public: enum class Type { kDecoder, kEncoder }; + // Gets supported coding formats for |type| device and |pixelFormats| + static SupportedProfiles getSupportedProfiles(Type type, + const std::vector<uint32_t>& pixelFormats); + + // Gets supported levels for all decoder devices + static std::vector<C2Config::level_t> getSupportedDecodeLevels(VideoCodec videoCodecType); + + // Get first current profile for any device + static C2Config::profile_t getDefaultProfile(VideoCodec codec); + + // Gets first current profile for any device + static C2Config::level_t getDefaultLevel(VideoCodec codec); + // Create and initialize an appropriate V4L2Device instance for the current platform, or return // nullptr if not available. static scoped_refptr<V4L2Device> create(uint32_t debugStreamId = -1); @@ -456,22 +459,17 @@ public: void getSupportedResolution(uint32_t pixelFormat, ui::Size* minResolution, ui::Size* maxResolution); - std::vector<uint32_t> enumerateSupportedPixelformats(v4l2_buf_type bufType); + // Queries supported levels for |pixFmt| pixel format + std::vector<C2Config::level_t> queryC2Levels(uint32_t pixFmt); - std::vector<C2Config::level_t> getSupportedDecodeLevels(VideoCodec videoCodecType); + // Queries supported profiles for |pixFmt| pixel format + std::vector<C2Config::profile_t> queryC2Profiles(uint32_t pixFmt); - std::vector<C2Config::level_t> enumerateSupportedDecodeLevels(VideoCodec videoCodecType); - - // Return supported profiles for decoder, including only profiles for given fourcc - // |pixelFormats|. - SupportedDecodeProfiles getSupportedDecodeProfiles(const std::vector<uint32_t>& pixelFormats); - - // Return supported profiles for encoder. - SupportedEncodeProfiles getSupportedEncodeProfiles(); - - C2Config::profile_t getDefaultProfile(VideoCodec codec); + // Queries supported pixel format for a |bufType| queue type + std::vector<uint32_t> enumerateSupportedPixelformats(v4l2_buf_type bufType); - C2Config::level_t getDefaultLevel(VideoCodec codec); + // Queries supported levels for |videoCodecType| + std::vector<C2Config::level_t> enumerateSupportedDecodeLevels(VideoCodec videoCodecType); // Start polling on this V4L2Device. |eventCallback| will be posted to the caller's sequence if // a buffer is ready to be dequeued and/or a V4L2 event has been posted. |errorCallback| will @@ -503,7 +501,10 @@ public: private: // Vector of video device node paths and corresponding pixelformats supported by each device node. - using Devices = std::vector<std::pair<std::string, std::vector<uint32_t>>>; + using DeviceInfos = std::vector<std::pair<std::string, std::vector<uint32_t>>>; + + // Enumerate all V4L2 devices on the system for |type| and return them + static const DeviceInfos& getDeviceInfosForType(V4L2Device::Type type); friend class base::RefCountedThreadSafe<V4L2Device>; V4L2Device(uint32_t debugStreamId); @@ -512,10 +513,8 @@ private: V4L2Device(const V4L2Device&) = delete; V4L2Device& operator=(const V4L2Device&) = delete; - SupportedDecodeProfiles enumerateSupportedDecodeProfiles( - const std::vector<uint32_t>& pixelFormats); - - SupportedEncodeProfiles enumerateSupportedEncodeProfiles(); + SupportedProfiles enumerateSupportedProfiles(V4L2Device::Type type, + const std::vector<uint32_t>& pixelFormats); // Open device node for |path| as a device of |type|. bool openDevicePath(const std::string& path, Type type); @@ -523,14 +522,6 @@ private: // Close the currently open device. void closeDevice(); - // Enumerate all V4L2 devices on the system for |type| and store the results under - // mDevicesByType[type]. - void enumerateDevicesForType(V4L2Device::Type type); - - // Return device information for all devices of |type| available in the system. Enumerates and - // queries devices on first run and caches the results for subsequent calls. - const Devices& getDevicesForType(V4L2Device::Type type); - // Return device node path for device of |type| supporting |pixFmt|, or an empty string if the // given combination is not supported by the system. std::string getDevicePathFor(V4L2Device::Type type, uint32_t pixFmt); @@ -541,9 +532,6 @@ private: // Identifier used for debugging purposes. uint32_t mDebugStreamId; - // Stores information for all devices available on the system for each device Type. - std::map<V4L2Device::Type, Devices> mDevicesByType; - // The actual device fd. base::ScopedFD mDeviceFd; diff --git a/components/V4L2DecodeInterface.cpp b/components/V4L2DecodeInterface.cpp index fa7f6ba..a218f13 100644 --- a/components/V4L2DecodeInterface.cpp +++ b/components/V4L2DecodeInterface.cpp @@ -132,23 +132,16 @@ V4L2DecodeInterface::V4L2DecodeInterface(const std::string& name, std::string inputMime; - scoped_refptr<V4L2Device> device = V4L2Device::create(); - if (!device) { - ALOGE("Failed to create V4L2 device"); - } - ui::Size maxSize(1, 1); std::vector<uint32_t> profiles; - if (device) { - V4L2Device::SupportedDecodeProfiles supportedProfiles = - device->getSupportedDecodeProfiles({VideoCodecToV4L2PixFmt(*mVideoCodec)}); - for (const auto& supportedProfile : supportedProfiles) { - if (isValidProfileForCodec(mVideoCodec.value(), supportedProfile.profile)) { - profiles.push_back(static_cast<uint32_t>(supportedProfile.profile)); - maxSize.setWidth(std::max(maxSize.width, supportedProfile.max_resolution.width)); - maxSize.setHeight(std::max(maxSize.height, supportedProfile.max_resolution.height)); - } + V4L2Device::SupportedProfiles supportedProfiles = V4L2Device::getSupportedProfiles( + V4L2Device::Type::kDecoder, {V4L2Device::videoCodecToPixFmt(*mVideoCodec)}); + for (const auto& supportedProfile : supportedProfiles) { + if (isValidProfileForCodec(mVideoCodec.value(), supportedProfile.profile)) { + profiles.push_back(static_cast<uint32_t>(supportedProfile.profile)); + maxSize.setWidth(std::max(maxSize.width, supportedProfile.max_resolution.width)); + maxSize.setHeight(std::max(maxSize.height, supportedProfile.max_resolution.height)); } } @@ -177,18 +170,15 @@ V4L2DecodeInterface::V4L2DecodeInterface(const std::string& name, } } - uint32_t defaultProfile = C2Config::PROFILE_UNUSED; - if (device) defaultProfile = device->getDefaultProfile(*mVideoCodec); + uint32_t defaultProfile = V4L2Device::getDefaultProfile(*mVideoCodec); if (defaultProfile == C2Config::PROFILE_UNUSED) defaultProfile = *std::min_element(profiles.begin(), profiles.end()); std::vector<unsigned int> levels; - if (device) { - std::vector<C2Config::level_t> supportedLevels = - device->getSupportedDecodeLevels(*mVideoCodec); - for (const auto& supportedLevel : supportedLevels) { - levels.push_back(static_cast<unsigned int>(supportedLevel)); - } + std::vector<C2Config::level_t> supportedLevels = + V4L2Device::getSupportedDecodeLevels(*mVideoCodec); + for (const auto& supportedLevel : supportedLevels) { + levels.push_back(static_cast<unsigned int>(supportedLevel)); } if (levels.empty()) { @@ -222,8 +212,7 @@ V4L2DecodeInterface::V4L2DecodeInterface(const std::string& name, } } - uint32_t defaultLevel = C2Config::LEVEL_UNUSED; - if (device) defaultLevel = device->getDefaultLevel(*mVideoCodec); + uint32_t defaultLevel = V4L2Device::getDefaultLevel(*mVideoCodec); if (defaultLevel == C2Config::LEVEL_UNUSED) defaultLevel = *std::min_element(levels.begin(), levels.end()); diff --git a/components/V4L2Decoder.cpp b/components/V4L2Decoder.cpp index 089e221..dfbcec1 100644 --- a/components/V4L2Decoder.cpp +++ b/components/V4L2Decoder.cpp @@ -31,19 +31,6 @@ constexpr size_t kNumExtraOutputBuffers = 4; } // namespace -uint32_t VideoCodecToV4L2PixFmt(VideoCodec codec) { - switch (codec) { - case VideoCodec::H264: - return V4L2_PIX_FMT_H264; - case VideoCodec::VP8: - return V4L2_PIX_FMT_VP8; - case VideoCodec::VP9: - return V4L2_PIX_FMT_VP9; - case VideoCodec::HEVC: - return V4L2_PIX_FMT_HEVC; - } -} - // static std::unique_ptr<VideoDecoder> V4L2Decoder::Create( uint32_t debugStreamId, const VideoCodec& codec, const size_t inputBufferSize, @@ -112,7 +99,7 @@ bool V4L2Decoder::start(const VideoCodec& codec, const size_t inputBufferSize, mDevice = V4L2Device::create(mDebugStreamId); - const uint32_t inputPixelFormat = VideoCodecToV4L2PixFmt(codec); + const uint32_t inputPixelFormat = V4L2Device::videoCodecToPixFmt(codec); if (!mDevice->open(V4L2Device::Type::kDecoder, inputPixelFormat)) { ALOGE("Failed to open device for %s", VideoCodecToString(codec)); return false; @@ -123,10 +110,7 @@ bool V4L2Decoder::start(const VideoCodec& codec, const size_t inputBufferSize, return false; } - struct v4l2_decoder_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd = V4L2_DEC_CMD_STOP; - if (mDevice->ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) { + if (!sendV4L2DecoderCmd(false)) { ALOGE("Device does not support flushing (V4L2_DEC_CMD_STOP)"); return false; } diff --git a/components/V4L2EncodeInterface.cpp b/components/V4L2EncodeInterface.cpp index 1c5b950..23a559d 100644 --- a/components/V4L2EncodeInterface.cpp +++ b/components/V4L2EncodeInterface.cpp @@ -229,13 +229,6 @@ V4L2EncodeInterface::V4L2EncodeInterface(const C2String& name, } void V4L2EncodeInterface::Initialize(const C2String& name) { - scoped_refptr<V4L2Device> device = V4L2Device::create(); - if (!device) { - ALOGE("Failed to create V4L2 device"); - mInitStatus = C2_CORRUPTED; - return; - } - auto codec = getCodecFromComponentName(name); if (!codec) { ALOGE("Invalid component name"); @@ -243,7 +236,8 @@ void V4L2EncodeInterface::Initialize(const C2String& name) { return; } - V4L2Device::SupportedEncodeProfiles supported_profiles = device->getSupportedEncodeProfiles(); + auto supported_profiles = V4L2Device::getSupportedProfiles( + V4L2Device::Type::kEncoder, {V4L2Device::videoCodecToPixFmt(codec.value())}); // Compile the list of supported profiles. // Note: unsigned int is used here, since std::vector<C2Config::profile_t> cannot convert to diff --git a/components/V4L2Encoder.cpp b/components/V4L2Encoder.cpp index 9c98324..fa09191 100644 --- a/components/V4L2Encoder.cpp +++ b/components/V4L2Encoder.cpp @@ -223,7 +223,7 @@ bool V4L2Encoder::initialize(C2Config::profile_t outputProfile, std::optional<ui // Open the V4L2 device for encoding to the requested output format. // TODO(dstaessens): Avoid conversion to VideoCodecProfile and use C2Config::profile_t directly. - uint32_t outputPixelFormat = V4L2Device::C2ProfileToV4L2PixFmt(outputProfile, false); + uint32_t outputPixelFormat = V4L2Device::c2ProfileToV4L2PixFmt(outputProfile, false); if (!outputPixelFormat) { ALOGE("Invalid output profile %s", profileToString(outputProfile)); return false; @@ -575,7 +575,7 @@ bool V4L2Encoder::configureOutputFormat(C2Config::profile_t outputProfile) { ALOG_ASSERT(!mOutputQueue->isStreaming()); ALOG_ASSERT(!isEmpty(mVisibleSize)); - auto format = mOutputQueue->setFormat(V4L2Device::C2ProfileToV4L2PixFmt(outputProfile, false), + auto format = mOutputQueue->setFormat(V4L2Device::c2ProfileToV4L2PixFmt(outputProfile, false), mVisibleSize, GetMaxOutputBufferSize(mVisibleSize)); if (!format) { ALOGE("Failed to set output format to %s", profileToString(outputProfile)); @@ -675,7 +675,7 @@ bool V4L2Encoder::configureBitrateMode(C2Config::bitrate_mode_t bitrateMode) { ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence()); v4l2_mpeg_video_bitrate_mode v4l2BitrateMode = - V4L2Device::C2BitrateModeToV4L2BitrateMode(bitrateMode); + V4L2Device::c2BitrateModeToV4L2BitrateMode(bitrateMode); if (!mDevice->setExtCtrls(V4L2_CTRL_CLASS_MPEG, {V4L2ExtCtrl(V4L2_CID_MPEG_VIDEO_BITRATE_MODE, v4l2BitrateMode)})) { // TODO(b/190336806): Our stack doesn't support bitrate mode changes yet. We default to CBR diff --git a/components/include/v4l2_codec2/components/V4L2Decoder.h b/components/include/v4l2_codec2/components/V4L2Decoder.h index 0277995..1848b1e 100644 --- a/components/include/v4l2_codec2/components/V4L2Decoder.h +++ b/components/include/v4l2_codec2/components/V4L2Decoder.h @@ -34,8 +34,6 @@ constexpr std::initializer_list<uint32_t> kSupportedOutputFourccs = { Fourcc::NV12, Fourcc::NV21, Fourcc::NM12, Fourcc::NM21, }; -uint32_t VideoCodecToV4L2PixFmt(VideoCodec codec); - class V4L2Decoder : public VideoDecoder { public: static std::unique_ptr<VideoDecoder> Create( -- GitLab