11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
22PROMEKI_NAMESPACE_BEGIN
24class SdpMediaDescription;
48 PROMEKI_SHARED_FINAL(ImageDesc)
59 static constexpr size_t MaxPlanes = 4;
62 using Ptr = SharedPtr<ImageDesc>;
65 using List = ::promeki::List<ImageDesc>;
68 using PtrList = ::promeki::List<Ptr>;
78 ImageDesc(
const Size2Du32 &sz,
const PixelFormat &pd) : _size(sz), _pixelFormat(pd) {}
86 ImageDesc(
size_t w,
size_t h,
const PixelFormat &pd) : _size(Size2Du32(w, h)), _pixelFormat(pd) {}
127 static ImageDesc fromSdp(
const SdpMediaDescription &md);
146 static PixelFormat::ID jpegPixelFormatFromSdp(
const String &colorimetry,
const String &range,
147 bool is420,
bool isRgb);
178 SdpMediaDescription toSdp(uint8_t payloadType)
const;
184 bool isValid()
const {
return _size.isValid() && _pixelFormat.isValid(); }
190 const PixelFormat &pixelFormat()
const {
return _pixelFormat; }
196 void setPixelFormat(
const PixelFormat &pd) { _pixelFormat = pd; }
202 const PixelMemLayout &memLayout()
const {
return _pixelFormat.memLayout(); }
208 const ColorModel &colorModel()
const {
return _pixelFormat.colorModel(); }
214 const Size2Du32 &size()
const {
return _size; }
220 size_t width()
const {
return _size.width(); }
226 size_t height()
const {
return _size.height(); }
232 void setSize(
const Size2Du32 &val) {
242 void setSize(
int width,
int height) {
243 _size.set(width, height);
262 size_t linePad()
const {
return _linePad[0]; }
269 size_t linePad(
size_t plane)
const {
return plane < MaxPlanes ? _linePad[plane] : 0; }
275 void setLinePad(
size_t val) {
276 for (
size_t p = 0; p < MaxPlanes; ++p) _linePad[p] = static_cast<uint32_t>(val);
285 void setLinePad(
size_t plane,
size_t val) {
286 if (plane < MaxPlanes) _linePad[plane] =
static_cast<uint32_t
>(val);
294 size_t lineAlign()
const {
return _lineAlign[0]; }
301 size_t lineAlign(
size_t plane)
const {
return plane < MaxPlanes ? _lineAlign[plane] : 1; }
307 void setLineAlign(
size_t val) {
308 for (
size_t p = 0; p < MaxPlanes; ++p) _lineAlign[p] = static_cast<uint32_t>(val);
317 void setLineAlign(
size_t plane,
size_t val) {
318 if (plane < MaxPlanes) _lineAlign[plane] =
static_cast<uint32_t
>(val);
337 bool lineFlip(
size_t plane = 0)
const {
338 return plane < MaxPlanes && (_lineFlipMask & (1u << plane)) != 0;
345 void setLineFlip(
bool val) {
346 _lineFlipMask = val ?
static_cast<uint8_t
>((1u << MaxPlanes) - 1) : 0;
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));
372 VideoScanMode videoScanMode()
const {
return _videoScanMode; }
378 void setVideoScanMode(
const VideoScanMode &mode) {
379 _videoScanMode = mode;
384 const Metadata &metadata()
const {
return _metadata; }
387 Metadata &metadata() {
return _metadata; }
393 int planeCount()
const {
return _pixelFormat.planeCount(); }
399 String toString()
const {
400 String ret = _size.toString();
401 if (_pixelFormat.isValid()) {
403 ret += _pixelFormat.name();
409 operator String()
const {
return toString(); }
412 bool operator==(
const ImageDesc &other)
const {
413 return formatEquals(other) && _metadata == other._metadata;
417 bool operator!=(
const ImageDesc &other)
const {
return !(*
this == other); }
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;
441 Array<uint32_t, MaxPlanes> _linePad{};
442 Array<uint32_t, MaxPlanes> _lineAlign{1, 1, 1, 1};
443 uint8_t _lineFlipMask = 0;
444 VideoScanMode _videoScanMode = VideoScanMode::Unknown;
445 PixelFormat _pixelFormat;
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);
471 stream << static_cast<uint32_t>(desc.videoScanMode().value());
472 stream << desc.metadata();
483inline DataStream &operator>>(DataStream &stream, ImageDesc &desc) {
484 if (!stream.readFrame(DataTypeImageDesc)) {
490 uint32_t linePad[ImageDesc::MaxPlanes] = {0};
491 uint32_t lineAlign[ImageDesc::MaxPlanes] = {0};
492 uint32_t flipMask = 0;
493 uint32_t scanValue = 0;
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) {
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);
509 desc.setVideoScanMode(VideoScanMode{
static_cast<int>(scanValue)});
510 desc.metadata() = std::move(meta);
516PROMEKI_FORMAT_VIA_TOSTRING(promeki::ImageDesc);