• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <linux/videodev2.h>
20 #include <iostream>
21 #include "common/libs/fs/shared_fd.h"
22 #include "common/libs/utils/result.h"
23 #include "utils/Timers.h"
24 #include "vsock_connection.h"
25 
26 namespace cuttlefish {
27 
28 // VsockFrameSource accepts WebRTC YUV camera stream data
29 // over vsock, converts it to v4l2 format BGRX32, and then
30 // writes the result to a v4l2 device.  This allows for creation
31 // of v4l2 devices in guest VMs, and streaming to them
32 // from Cuttlefish's WebRTC UI via any connected camera.
33 class VsockFrameSource {
34  public:
35   // Starts a Frame Source streaming session targeting a
36   // specific v4l2 device
37   static Result<std::unique_ptr<VsockFrameSource>> Start(
38       const std::string& v4l2_device_path);
39 
40   ~VsockFrameSource();
41 
42   // Stops a thread managing the stream if running, and closes the v4l2 device.
43   void Stop();
44 
45   // Returns true if there is a camera stream currently running
46   bool Running();
47 
48   // This is a blocking method, that runs while connection is valid.
49   // It receives frames from a vsock socket, formats the data stream and
50   // sends it to a v4l2 output device.
51   void VsockReadLoop();
52 
53   // Starts a Thread which invokes VsockReadLoop(). This allows the calling
54   // thread to perform other operations while this frame source is sending data.
55   Result<void> VsockReadLoopThreaded();
56 
57  private:
58   // The v4l2 device path to receive camera frames, ie /dev/video0
59   std::string v4l2_device_path_;
60   std::unique_ptr<cuttlefish::VsockConnection> connection_;
61   std::thread reader_thread_;
62   std::atomic<bool> running_;
63   std::mutex frame_mutex_;
64   std::mutex settings_mutex_;
65   std::atomic<nsecs_t> timestamp_;
66   std::condition_variable yuv_frame_updated_;
67 
68   // File handle of v4l2 device to be written to
69   SharedFD fd_v4l2_device_;
70 
71   // Following frame_* values will be set after successful connection.
72   // Host process sends a message which conveys the camera dimensions
73   // to this guest instance over the vsock connection.
74   int frame_width_ = 0;
75   int frame_height_ = 0;
76   int frame_rate_ = 0;
77   int frame_size_ = 0;
78 
79   // Currently this class only supports writing to v4l2 devices
80   // via this format.
81   int format_ = V4L2_PIX_FMT_BGRX32;
82 
83   // Verifies that given data is a video frame. Used to
84   // distinguish control messages.
85   bool FramesizeMatches(const std::vector<char>& data);
86 
87   // Determines if a vsock packet contains special data
88   // that is not camera frame.
89   bool IsBlob(const std::vector<char>& blob);
90 
91   // Sends message to Host process communicating an event in the
92   // camera connection state. ie - when to start or stop streaming.
93   bool WriteJsonEventMessage(const std::string& message);
94 
95   // After connect, this is called to retrieve camera dimensions
96   // and properties needed to initialize the v4l2 device and allocate
97   // buffers necessary for streaming.
98   Result<bool> ReadSettingsFromJson(const Json::Value& json);
99 
100   // Established the vsock connection
101   bool Connect();
102 
103   // Called once every frame to write a frame buffer to the v4l2
104   // output device.
105   void WriteFrame(const std::vector<char>& frame, std::vector<char>& rgb_frame);
106 
107  protected:
108   VsockFrameSource() = default;
109 };
110 
111 }  // End namespace cuttlefish