libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
v4l2m2mcodec.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_V4L2
13#include <cstdint>
14#include <promeki/namespace.h>
15#include <promeki/string.h>
16#include <promeki/error.h>
17#include <promeki/result.h>
18#include <promeki/list.h>
19#include <promeki/buffer.h>
20#include <promeki/size2d.h>
21
22PROMEKI_NAMESPACE_BEGIN
23
61class V4l2M2mCodec {
62 public:
64 enum class Role {
65 Encoder,
66 Decoder,
67 };
68
70 enum class Memory {
71 Mmap,
72 Dmabuf,
73 };
74
76 struct OpenParams {
77 Role role = Role::Encoder;
87 String devPath;
88 uint32_t outputFourcc = 0;
89 uint32_t captureFourcc = 0;
90 Size2Du32 size;
91 uint32_t outputBufferCount = 6;
92 uint32_t captureBufferCount = 6;
101 Memory outputMemory = Memory::Mmap;
102 Memory captureMemory = Memory::Mmap;
111 uint32_t codedBufferSize = 0;
112
113 // Colorimetry applied to the raw queue's format
114 // (the encoder's OUTPUT) so the codec writes a
115 // matching VUI into the bitstream. Zero =
116 // DEFAULT (leave to the driver). See
117 // @ref v4l2ColorimetryFromH273.
118 uint32_t colorspace = 0;
119 uint32_t ycbcrEnc = 0;
120 uint32_t xferFunc = 0;
121 uint32_t quantization = 0;
122 };
123
125 struct OutPlane {
126 uint8_t *data = nullptr;
127 size_t capacity = 0;
128 size_t stride = 0;
129 };
130
132 struct CapturePlane {
133 const uint8_t *data = nullptr;
134 size_t size = 0;
135 size_t stride = 0;
136 };
137
138 V4l2M2mCodec();
139 ~V4l2M2mCodec();
140 V4l2M2mCodec(const V4l2M2mCodec &) = delete;
141 V4l2M2mCodec &operator=(const V4l2M2mCodec &) = delete;
142
151 static String findDevice(Role role, uint32_t outputFourcc, uint32_t captureFourcc);
152
154 Error open(const OpenParams &params);
155
157 void close();
158
160 bool isOpen() const { return _fd >= 0; }
161
163 int fd() const { return _fd; }
164
166 const String &devPath() const { return _devPath; }
167
169 const String &driverName() const { return _driver; }
170
172 uint32_t negotiatedWidth() const { return _width; }
173 uint32_t negotiatedHeight() const { return _height; }
174
176 uint32_t outputPlaneCount() const { return _outPlaneCount; }
177
179 uint32_t outputStride(uint32_t plane) const;
180
182 uint32_t negotiatedColorspace() const { return _colorspace; }
183 uint32_t negotiatedYcbcrEnc() const { return _ycbcrEnc; }
184 uint32_t negotiatedXferFunc() const { return _xferFunc; }
185 uint32_t negotiatedQuantization() const { return _quantization; }
186
200 Error setControl(uint32_t id, int32_t value, bool optional = true);
201
216 Error setControlCompound(uint32_t id, void *payload, uint32_t size, bool optional = true);
217
229 Error start();
230
232 Error stop();
233
234 // ---- Staged decoder init (Role::Decoder) ----
235 //
236 // A stateful decoder is brought up in two phases: feed coded
237 // data on the OUTPUT queue, wait for the driver to parse the
238 // stream geometry (a SOURCE_CHANGE event), then configure and
239 // stream the CAPTURE (raw) queue.
240
248 Error startOutput();
249
260 Error dequeueEvent(bool &sourceChange, bool &eos);
261
273 Error setupCapture();
274
276 bool captureConfigured() const { return _captureConfigured; }
277
279 uint32_t captureWidth() const { return _capWidth; }
280 uint32_t captureHeight() const { return _capHeight; }
281 uint32_t captureFourcc() const { return _capFourcc; }
282 uint32_t capturePlaneCount() const { return _capPlaneCount; }
284 uint32_t captureStride(uint32_t plane) const;
285
300 Error dequeueRawFrame(List<CapturePlane> &planes, int &index, int64_t &ptsUsec,
301 bool &endOfStream);
302
304 Error requeueRawFrame(int index);
305
318 Error acquireOutput(int &index, List<OutPlane> &planes);
319
329 Error submitOutput(int index, const List<size_t> &bytesused, int64_t ptsUsec);
330
349 Error queueOutputDmabuf(int fd, size_t bytesused, int64_t ptsUsec, bool &queued);
350
362 Result<int> exportBuffer(bool capture, int index);
363
380 Error dequeueCapture(Buffer &out, int64_t &ptsUsec, bool &keyframe, bool &endOfStream);
381
389 Error poll(bool &outputWritable, bool &captureReadable, int timeoutMs);
390
398 Error pollEvents(bool &outputWritable, bool &captureReadable, bool &eventPending, int timeoutMs);
399
407 Error sendStop();
408
409 private:
410 struct MappedPlane {
411 void *start = nullptr;
412 size_t length = 0;
413 };
414 struct MappedBuffer {
415 List<MappedPlane> planes;
416 bool queued = false;
417 };
418
419 Error negotiateFormats(const OpenParams &p);
420 Error allocQueue(uint32_t type, uint32_t memory, uint32_t count, List<MappedBuffer> &pool,
421 uint32_t &planeCount);
422 void unmapQueue(List<MappedBuffer> &pool);
423 Error queueAllCapture();
424 void reclaimOutput();
425 Error subscribeEvents();
426
427 int _fd = -1;
428 String _devPath;
429 String _driver;
430 Role _role = Role::Encoder;
431
432 // True for the multiplanar API (V4L2_CAP_VIDEO_M2M_MPLANE — the
433 // Xilinx VCU and Raspberry Pi); false for single-planar
434 // (V4L2_CAP_VIDEO_M2M — the kernel vicodec test driver and many
435 // simpler codecs). Selects the buffer types and the
436 // v4l2_format / v4l2_buffer layout used throughout.
437 bool _mplane = true;
438
439 uint32_t _outputType = 0; // V4L2_BUF_TYPE_VIDEO_OUTPUT[_MPLANE]
440 uint32_t _captureType = 0; // V4L2_BUF_TYPE_VIDEO_CAPTURE[_MPLANE]
441
442 uint32_t _outputMemory = 0; // V4L2_MEMORY_MMAP | V4L2_MEMORY_DMABUF
443 uint32_t _captureMemory = 0; // V4L2_MEMORY_MMAP | V4L2_MEMORY_DMABUF
444
445 // Requested pool depths (OpenParams::outputBufferCount /
446 // captureBufferCount); the driver may round these up.
447 uint32_t _outputBufferCount = 6;
448 uint32_t _captureBufferCount = 6;
449
450 uint32_t _width = 0;
451 uint32_t _height = 0;
452 uint32_t _outPlaneCount = 1;
453 uint32_t _capPlaneCount = 1;
454 uint32_t _outStride[4] = {0, 0, 0, 0};
455
456 // Negotiated CAPTURE (raw) geometry — filled by setupCapture on
457 // the decoder path.
458 uint32_t _capWidth = 0;
459 uint32_t _capHeight = 0;
460 uint32_t _capFourcc = 0;
461 uint32_t _capStride[4] = {0, 0, 0, 0};
462 uint32_t _rawFourccWanted = 0; // Desired CAPTURE raw FourCC (OpenParams::captureFourcc).
463
464 // Colorimetry negotiated on the raw queue (encoder OUTPUT).
465 uint32_t _colorspace = 0;
466 uint32_t _ycbcrEnc = 0;
467 uint32_t _xferFunc = 0;
468 uint32_t _quantization = 0;
469
470 List<MappedBuffer> _outputPool;
471 List<MappedBuffer> _capturePool;
472
473 bool _streaming = false; // OUTPUT queue streaming.
474 bool _captureConfigured = false; // CAPTURE queue set up + streaming (decoder).
475 bool _captureDrained = false; // LAST buffer seen.
476};
477
478PROMEKI_NAMESPACE_END
479
480#endif // PROMEKI_ENABLE_V4L2