libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
imagedesc.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
13#include <promeki/namespace.h>
14#include <promeki/array.h>
15#include <promeki/string.h>
16#include <promeki/sharedptr.h>
17#include <promeki/size2d.h>
18#include <promeki/pixelformat.h>
19#include <promeki/metadata.h>
20#include <promeki/enums_video.h>
21
22PROMEKI_NAMESPACE_BEGIN
23
24class SdpMediaDescription;
25
47class ImageDesc {
48 PROMEKI_SHARED_FINAL(ImageDesc)
49 public:
59 static constexpr size_t MaxPlanes = 4;
60
62 using Ptr = SharedPtr<ImageDesc>;
63
65 using List = ::promeki::List<ImageDesc>;
66
68 using PtrList = ::promeki::List<Ptr>;
69
71 ImageDesc() {}
72
78 ImageDesc(const Size2Du32 &sz, const PixelFormat &pd) : _size(sz), _pixelFormat(pd) {}
79
86 ImageDesc(size_t w, size_t h, const PixelFormat &pd) : _size(Size2Du32(w, h)), _pixelFormat(pd) {}
87
127 static ImageDesc fromSdp(const SdpMediaDescription &md);
128
146 static PixelFormat::ID jpegPixelFormatFromSdp(const String &colorimetry, const String &range,
147 bool is420, bool isRgb);
148
178 SdpMediaDescription toSdp(uint8_t payloadType) const;
179
184 bool isValid() const { return _size.isValid() && _pixelFormat.isValid(); }
185
190 const PixelFormat &pixelFormat() const { return _pixelFormat; }
191
196 void setPixelFormat(const PixelFormat &pd) { _pixelFormat = pd; }
197
202 const PixelMemLayout &memLayout() const { return _pixelFormat.memLayout(); }
203
208 const ColorModel &colorModel() const { return _pixelFormat.colorModel(); }
209
214 const Size2Du32 &size() const { return _size; }
215
220 size_t width() const { return _size.width(); }
221
226 size_t height() const { return _size.height(); }
227
232 void setSize(const Size2Du32 &val) {
233 _size = val;
234 return;
235 }
236
242 void setSize(int width, int height) {
243 _size.set(width, height);
244 return;
245 }
246
262 size_t linePad() const { return _linePad[0]; }
263
269 size_t linePad(size_t plane) const { return plane < MaxPlanes ? _linePad[plane] : 0; }
270
275 void setLinePad(size_t val) {
276 for (size_t p = 0; p < MaxPlanes; ++p) _linePad[p] = static_cast<uint32_t>(val);
277 return;
278 }
279
285 void setLinePad(size_t plane, size_t val) {
286 if (plane < MaxPlanes) _linePad[plane] = static_cast<uint32_t>(val);
287 return;
288 }
289
294 size_t lineAlign() const { return _lineAlign[0]; }
295
301 size_t lineAlign(size_t plane) const { return plane < MaxPlanes ? _lineAlign[plane] : 1; }
302
307 void setLineAlign(size_t val) {
308 for (size_t p = 0; p < MaxPlanes; ++p) _lineAlign[p] = static_cast<uint32_t>(val);
309 return;
310 }
311
317 void setLineAlign(size_t plane, size_t val) {
318 if (plane < MaxPlanes) _lineAlign[plane] = static_cast<uint32_t>(val);
319 return;
320 }
321
337 bool lineFlip(size_t plane = 0) const {
338 return plane < MaxPlanes && (_lineFlipMask & (1u << plane)) != 0;
339 }
340
345 void setLineFlip(bool val) {
346 _lineFlipMask = val ? static_cast<uint8_t>((1u << MaxPlanes) - 1) : 0;
347 return;
348 }
349
355 void setLineFlip(size_t plane, bool val) {
356 if (plane >= MaxPlanes) return;
357 if (val) _lineFlipMask |= static_cast<uint8_t>(1u << plane);
358 else _lineFlipMask &= static_cast<uint8_t>(~(1u << plane));
359 return;
360 }
361
372 VideoScanMode videoScanMode() const { return _videoScanMode; }
373
378 void setVideoScanMode(const VideoScanMode &mode) {
379 _videoScanMode = mode;
380 return;
381 }
382
384 const Metadata &metadata() const { return _metadata; }
385
387 Metadata &metadata() { return _metadata; }
388
393 int planeCount() const { return _pixelFormat.planeCount(); }
394
399 String toString() const {
400 String ret = _size.toString();
401 if (_pixelFormat.isValid()) {
402 ret += ' ';
403 ret += _pixelFormat.name();
404 }
405 return ret;
406 }
407
409 operator String() const { return toString(); }
410
412 bool operator==(const ImageDesc &other) const {
413 return formatEquals(other) && _metadata == other._metadata;
414 }
415
417 bool operator!=(const ImageDesc &other) const { return !(*this == other); }
418
433 bool formatEquals(const ImageDesc &other) const {
434 return _size == other._size && _linePad == other._linePad && _lineAlign == other._lineAlign &&
435 _lineFlipMask == other._lineFlipMask && _videoScanMode == other._videoScanMode &&
436 _pixelFormat == other._pixelFormat;
437 }
438
439 private:
440 Size2Du32 _size;
441 Array<uint32_t, MaxPlanes> _linePad{}; // 0 = tightly packed
442 Array<uint32_t, MaxPlanes> _lineAlign{1, 1, 1, 1}; // 1 = no extra alignment
443 uint8_t _lineFlipMask = 0; // bit p set = plane p bottom-up
444 VideoScanMode _videoScanMode = VideoScanMode::Unknown;
445 PixelFormat _pixelFormat;
446 Metadata _metadata;
447};
448
461inline DataStream &operator<<(DataStream &stream, const ImageDesc &desc) {
462 stream.beginFrame(DataTypeImageDesc, 1);
463 stream << desc.size();
464 stream << desc.pixelFormat();
465 for (size_t p = 0; p < ImageDesc::MaxPlanes; ++p) stream << static_cast<uint32_t>(desc.linePad(p));
466 for (size_t p = 0; p < ImageDesc::MaxPlanes; ++p) stream << static_cast<uint32_t>(desc.lineAlign(p));
467 uint32_t flipMask = 0;
468 for (size_t p = 0; p < ImageDesc::MaxPlanes; ++p)
469 if (desc.lineFlip(p)) flipMask |= (1u << p);
470 stream << flipMask;
471 stream << static_cast<uint32_t>(desc.videoScanMode().value());
472 stream << desc.metadata();
473 stream.endFrame();
474 return stream;
475}
476
483inline DataStream &operator>>(DataStream &stream, ImageDesc &desc) {
484 if (!stream.readFrame(DataTypeImageDesc)) {
485 desc = ImageDesc();
486 return stream;
487 }
488 Size2Du32 size;
489 PixelFormat pd;
490 uint32_t linePad[ImageDesc::MaxPlanes] = {0};
491 uint32_t lineAlign[ImageDesc::MaxPlanes] = {0};
492 uint32_t flipMask = 0;
493 uint32_t scanValue = 0;
494 Metadata meta;
495 stream >> size >> pd;
496 for (size_t p = 0; p < ImageDesc::MaxPlanes; ++p) stream >> linePad[p];
497 for (size_t p = 0; p < ImageDesc::MaxPlanes; ++p) stream >> lineAlign[p];
498 stream >> flipMask >> scanValue >> meta;
499 if (stream.status() != DataStream::Ok) {
500 desc = ImageDesc();
501 return stream;
502 }
503 desc = ImageDesc(size, pd);
504 for (size_t p = 0; p < ImageDesc::MaxPlanes; ++p) {
505 desc.setLinePad(p, static_cast<size_t>(linePad[p]));
506 desc.setLineAlign(p, static_cast<size_t>(lineAlign[p]));
507 desc.setLineFlip(p, (flipMask & (1u << p)) != 0);
508 }
509 desc.setVideoScanMode(VideoScanMode{static_cast<int>(scanValue)});
510 desc.metadata() = std::move(meta);
511 return stream;
512}
513
514PROMEKI_NAMESPACE_END
515
516PROMEKI_FORMAT_VIA_TOSTRING(promeki::ImageDesc);
517
518#endif // PROMEKI_ENABLE_PROAV