lin
2025-04-25 6a7002bcc41716f11f4ca7eb68ebd06c18fdd5e8
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
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file defines the V4L2Device interface which is used by the
// V4L2DecodeAccelerator class to delegate/pass the device specific
// handling of any of the functionalities.
// Note: ported from Chromium commit head: fb70f64
// Note: it's also merged with generic_v4l2_device.h (head: fb70f64)
 
#ifndef V4L2_DEVICE_H_
#define V4L2_DEVICE_H_
 
#include <linux/videodev2.h>
#include <map>
#include <stddef.h>
#include <stdint.h>
 
#include "base/files/scoped_file.h"
#include "base/memory/ref_counted.h"
#include "size.h"
#include "video_codecs.h"
#include "video_decode_accelerator.h"
#include "video_pixel_format.h"
 
// TODO(posciak): remove this once V4L2 headers are updated.
#define V4L2_PIX_FMT_MT21 v4l2_fourcc('M', 'T', '2', '1')
#ifndef V4L2_BUF_FLAG_LAST
#define V4L2_BUF_FLAG_LAST 0x00100000
#endif
 
namespace media {
 
// Implemented for decoder usage only.
class V4L2Device : public base::RefCountedThreadSafe<V4L2Device> {
 public:
  V4L2Device();
  ~V4L2Device();
 
  // Utility format conversion functions
  static VideoPixelFormat V4L2PixFmtToVideoPixelFormat(uint32_t format);
  static uint32_t VideoPixelFormatToV4L2PixFmt(VideoPixelFormat format);
  static uint32_t VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile);
  std::vector<VideoCodecProfile> V4L2PixFmtToVideoCodecProfiles(
      uint32_t pix_fmt,
      bool is_encoder);
 
  enum class Type {
    kDecoder,
    kEncoder,
    kImageProcessor,
    kJpegDecoder,
  };
 
  // Open a V4L2 device of |type| for use with |v4l2_pixfmt|.
  // Return true on success.
  // The device will be closed in the destructor.
  bool Open(Type type, uint32_t v4l2_pixfmt);
 
  // Parameters and return value are the same as for the standard ioctl() system
  // call.
  int Ioctl(int request, void* arg);
 
  // This method sleeps until either:
  // - SetDevicePollInterrupt() is called (on another thread),
  // - |poll_device| is true, and there is new data to be read from the device,
  //   or an event from the device has arrived; in the latter case
  //   |*event_pending| will be set to true.
  // Returns false on error, true otherwise.
  // This method should be called from a separate thread.
  bool Poll(bool poll_device, bool* event_pending);
 
  // These methods are used to interrupt the thread sleeping on Poll() and force
  // it to return regardless of device state, which is usually when the client
  // is no longer interested in what happens with the device (on cleanup,
  // client state change, etc.). When SetDevicePollInterrupt() is called, Poll()
  // will return immediately, and any subsequent calls to it will also do so
  // until ClearDevicePollInterrupt() is called.
  bool SetDevicePollInterrupt();
  bool ClearDevicePollInterrupt();
 
  // Wrappers for standard mmap/munmap system calls.
  void* Mmap(void* addr,
             unsigned int len,
             int prot,
             int flags,
             unsigned int offset);
  void Munmap(void* addr, unsigned int len);
 
  // Return a vector of dmabuf file descriptors, exported for V4L2 buffer with
  // |index|, assuming the buffer contains |num_planes| V4L2 planes and is of
  // |type|. Return an empty vector on failure.
  // The caller is responsible for closing the file descriptors after use.
  std::vector<base::ScopedFD> GetDmabufsForV4L2Buffer(
      int index,
      size_t num_planes,
      enum v4l2_buf_type type);
 
  // NOTE: The below methods to query capabilities have a side effect of
  // closing the previously-open device, if any, and should not be called after
  // Open().
  // TODO(posciak): fix this.
 
  // Get minimum and maximum resolution for fourcc |pixelformat| and store to
  // |min_resolution| and |max_resolution|.
  void GetSupportedResolution(uint32_t pixelformat,
                              Size* min_resolution,
                              Size* max_resolution);
 
  // Return supported profiles for decoder, including only profiles for given
  // fourcc |pixelformats|.
  VideoDecodeAccelerator::SupportedProfiles GetSupportedDecodeProfiles(
      const size_t num_formats,
      const uint32_t pixelformats[]);
 
 private:
  friend class base::RefCountedThreadSafe<V4L2Device>;
 
  // 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>>>;
 
  VideoDecodeAccelerator::SupportedProfiles EnumerateSupportedDecodeProfiles(
      const size_t num_formats,
      const uint32_t pixelformats[]);
 
  std::vector<uint32_t> EnumerateSupportedPixelformats(v4l2_buf_type buf_type);
 
  // Open device node for |path| as a device of |type|.
  bool OpenDevicePath(const std::string& path, Type type);
 
  // Close the currently open device.
  void CloseDevice();
 
  // Enumerate all V4L2 devices on the system for |type| and store the results
  // under devices_by_type_[type].
  void EnumerateDevicesForType(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(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(Type type, uint32_t pixfmt);
 
  // Stores information for all devices available on the system
  // for each device Type.
  std::map<Type, Devices> devices_by_type_;
 
  // The actual device fd.
  base::ScopedFD device_fd_;
 
  // eventfd fd to signal device poll thread when its poll() should be
  // interrupted.
  base::ScopedFD device_poll_interrupt_fd_;
 
  DISALLOW_COPY_AND_ASSIGN(V4L2Device);
};
 
}  //  namespace media
 
#endif  // V4L2_DEVICE_H_