/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include namespace android { namespace webcam { typedef std::vector Events; using android::base::unique_fd; class EpollW { public: Status init(); Status add(int fd, uint32_t events); Status modify(int fd, uint32_t events); Status remove(int fd); Events waitForEvents(); private: unique_fd mEpollFd; }; struct ConfigFrame { uint32_t index = 0; uint32_t width = 0; uint32_t height = 0; std::vector intervals; }; struct ConfigFormat { uint32_t formatIndex = 0; uint32_t fcc; std::vector frames; }; struct ConfigEndPoint { uint32_t streamingInterval = 0; uint32_t streamingMaxPacketSize = 0; uint32_t streamingMaxBurst = 0; }; struct ConfigStreaming { ConfigEndPoint ep; std::vector formats; uint32_t interfaceNumber = 0; }; struct UVCProperties { std::string videoNode; std::string udc; ConfigStreaming streaming; uint32_t controlInterfaceNumber = 0; }; // This struct has the information needed to uniquely identify a 'chosen' format : the format index // which indexes into the format list advertised by the UVC V4L2 node, the frame index which indexes // the frame size in the frame size list per format, and finally the frame interval for the // particular format and size chosen. struct FormatTriplet { // Note: These are '1' indexed. uint8_t formatIndex = 1; uint8_t frameSizeIndex = 1; uint32_t frameInterval = 0; FormatTriplet(uint8_t formatIndex, uint8_t frameSizeIndex, uint32_t frameInterval) : formatIndex(formatIndex), frameSizeIndex(frameSizeIndex), frameInterval(frameInterval) {} }; // This class manages all things related to UVC event handling. class UVCProvider : public std::enable_shared_from_this { public: static std::string getVideoNode(); UVCProvider() = default; ~UVCProvider(); Status init(); // Start listening for UVC events Status startService(); void stopService(); int encodeImage(AHardwareBuffer* hardwareBuffer, long timestamp); void watchStreamEvent(); private: // Created after a UVC_SETUP event has been received and processed by UVCProvider // This class manages stream related events UVC_STREAMON / STREAMOFF and queries by the host // for probing and committing controls. class UVCDevice : public BufferCreatorAndDestroyer { public: explicit UVCDevice(std::weak_ptr parent); ~UVCDevice() override = default; void closeUVCFd(); [[nodiscard]] bool isInited() const; int getUVCFd() { return mUVCFd.get(); } void processSetupEvent(const struct usb_ctrlrequest* request, struct uvc_request_data* response); void processSetupControlEvent(const struct usb_ctrlrequest* request, struct uvc_request_data* response); void processSetupStreamingEvent(const struct usb_ctrlrequest* request, struct uvc_request_data* response); void processSetupClassEvent(const struct usb_ctrlrequest* request, struct uvc_request_data* response); void processDataEvent(const struct uvc_request_data*); void processStreamOnEvent(); void processStreamOffEvent(); void processStreamEvent(); Status encodeImage(AHardwareBuffer* buffer, long timestamp); // BufferCreatorAndDestroyer overrides Status allocateAndMapBuffers( std::shared_ptr* consumerBuffer, std::vector>* producerBuffers) override; void destroyBuffers(std::shared_ptr& consumerBuffer, std::vector>& producerBuffers) override; private: std::shared_ptr parseUvcProperties(); std::vector getFormats(); void getFrameIntervals(ConfigFrame* frame, ConfigFormat* format); void getFormatFrames(ConfigFormat* format); Status openV4L2DeviceAndSubscribe(const std::string& videoNode); void setStreamingControl(struct uvc_streaming_control* streamingControl, const FormatTriplet* req); void commitControls(); std::shared_ptr mapBuffer(uint32_t i); static Status unmapBuffer(std::shared_ptr& buffer); Status getFrameAndQueueBufferToGadgetDriver(bool firstBuffer = false); struct uvc_streaming_control mProbe {}; struct uvc_streaming_control mCommit {}; uint8_t mCurrentControlState = UVC_VS_CONTROL_UNDEFINED; std::weak_ptr mParent; std::shared_ptr mUVCProperties; std::shared_ptr mBufferManager; std::shared_ptr mFrameProvider; unique_fd mUVCFd; // Path to /dev/video*, this is the node we open up and poll the fd for uvc / v4l2 events. std::string mVideoNode; struct v4l2_format mV4l2Format {}; uint32_t mFps = 0; bool mInited = false; }; void stopAndWaitForUVCListenerThread(); void startUVCListenerThread(); void ListenToUVCFds(); void processUVCEvent(); std::shared_ptr mUVCDevice; std::thread mUVCListenerThread; volatile bool mListenToUVCFds = true; EpollW mEpollW; }; } // namespace webcam } // namespace android