blob: dd4ae2c43bb57492e114856dfa56a951e9c97d28 [file] [log] [blame]
#pragma pattern for Advanced Professional Video (*.apv)
import std.io;
import std.mem;
#pragma endian big
/* PBU types */
enum PbuType : u8 {
FRM_PRI = 1,
FRM_NONPRI = 2,
FRM_PREVIEW = 25,
FRM_DEPTH = 26,
FRM_ALPHA = 27,
AUI = 65,
METADATA = 66,
FILLER = 67
};
fn get_0xff_ext_var(auto addr) {
u32 read = 1;
u32 var = 0;
u8 ext = std::mem::read_unsigned(addr, 1);
while (ext == 0xFF) {
var += 0xFF;
ext = std::mem::read_unsigned(addr + read, 1);
read += 1;
}
var += ext;
return var;
};
fn get_0xff_ext_var_bytes(auto addr) {
u32 read = 1;
u8 ext = std::mem::read_unsigned(addr, 1);
while (ext == 0xFF) {
ext = std::mem::read_unsigned(addr + read, 1);
read += 1;
}
return read;
};
struct PbuBase {
u32 read = 0;
str ptype_str = "";
/*
syntax code | type
--------------------------------------------------------------|-----
pbu_header(){ |
pbu_type | u(8)
group_id | u(16)
reserved_zero_8bits | u(8)
}
*/
u32 pbu_size; // originally, this syntax is part of AuccessUnit
u8 pbu_type;
u16 group_id;
u8 reserved_zero_8bits;
read += 4;
};
/*
syntax code | type
--------------------------------------------------------------|-----
frame_info(){ |
profile_idc | u(8)
level_idc | u(8)
band_idc | u(3)
reserved_zero_5bits | u(5)
frame_width | u(24)
frame_height | u(24)
chroma_format_idc | u(4)
bit_depth_minus8 | u(4)
capture_time_distance | u(8)
reserved_zero_8bits | u(8)
}
*/
bitfield FrmInfo {
profile_idc : 8;
level_idc : 8;
band_idc : 3;
reserved_zero_5bits: 5;
frame_width: 24;
frame_height: 24;
chroma_format_idc: 4;
bit_depth_minus8: 4;
capture_time_distance: 8;
reserved_zero_8bits: 8;
};
struct PbuFrm:PbuBase {
if(pbu_type == PbuType::FRM_PRI) ptype_str = "Frm(Pri)";
else if(pbu_type == PbuType::FRM_NONPRI) ptype_str = "Frm(Nonpri)";
else if(pbu_type == PbuType::FRM_PREVIEW) ptype_str = "Frm(Preview)";
else if(pbu_type == PbuType::FRM_DEPTH) ptype_str = "Frm(Depth)";
else if(pbu_type == PbuType::FRM_ALPHA) ptype_str = "Frm(Alpha)";
else ptype_str = "Frm(Unknown)";
FrmInfo finfo [[name("frame_info()")]];
read += 12; // byte size of frame_info()
u8 frameData[pbu_size - read] [[sealed]];
};
u32 metadata_payload_count = 0;
struct MetadataPayload {
str ptype_str = "";
u32 read = 0;
u32 payloadType = get_0xff_ext_var($) [[export]];
read += get_0xff_ext_var_bytes($);
$ += get_0xff_ext_var_bytes($); // update current reading point
u32 payloadSize = get_0xff_ext_var($) [[export]];
read += get_0xff_ext_var_bytes($);
$ += get_0xff_ext_var_bytes($); // update current reading point
u64 endOffset = $ + payloadSize;
if (payloadType == 4) ptype_str = "itu_t_t35";
else if (payloadType == 5) ptype_str = "mdcv";
else if (payloadType == 6) ptype_str = "cll";
else if (payloadType == 10) ptype_str = "filler";
else if (payloadType == 170) ptype_str = "user_defined";
else ptype_str = "undefined";
std::print(" metadata payload[{:d}] type = {:d}({}), size = {:d}", metadata_payload_count, payloadType, ptype_str, payloadSize);
u8 payloadData[while($ < endOffset)] [[sealed]];
metadata_payload_count += 1;
} [[name(std::format("MetadataPayload[{}]:{}", (metadata_payload_count - 1), ptype_str))]];
struct PbuMetadata:PbuBase {
u64 endOffset = 0;
ptype_str = "Metadata";
metadata_payload_count = 0; // reset number of metadata payload
u32 metadata_size; // syntax
endOffset = $ + metadata_size;
MetadataPayload pay[while($ < endOffset)] [[inline]];
};
struct PbuAui:PbuBase {
ptype_str = "aui";
u8 data[pbu_size - read] [[sealed]];
};
struct PbuFiller:PbuBase {
ptype_str = "filler";
u8 data[pbu_size - read] [[sealed]];
};
struct PbuUnknown:PbuBase {
std::warning(std::format("Unknown PBU type ({})!!!", pbu_type));
ptype_str = "unknown";
u8 data[pbu_size - read] [[sealed]];
};
u32 pbu_count = 0;
struct PBU {
u32 pbu_size = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
u8 pbu_type = std::mem::read_unsigned($ + 4, 1, std::mem::Endian::Big);
match (pbu_type) {
(PbuType::FRM_PRI) : PbuFrm Pbu [[inline]];
(PbuType::FRM_NONPRI) : PbuFrm Pbu [[inline]];
(PbuType::FRM_PREVIEW): PbuFrm Pbu [[inline]];
(PbuType::FRM_DEPTH): PbuFrm Pbu [[inline]];
(PbuType::FRM_ALPHA): PbuFrm Pbu [[inline]];
(PbuType::AUI): PbuAui Pbu [[inline]];
(PbuType::METADATA): PbuMetadata Pbu [[inline]];
(PbuType::FILLER): PbuFiller Pbu [[inline]];
(_) : PbuUnknown Pbu [[inline]];
}
std::print(" PBU[{:d}] size = {:d}, {}", pbu_count, pbu_size, Pbu.ptype_str);
pbu_count += 1;
} [[name(std::format("PBU[{}]:{}", (pbu_count - 1), Pbu.ptype_str))]];
u32 au_count = 0;
struct AccessUnit {
u64 au_end = 0;
u32 au_size; // originally this syntax is part of RawBitstream
std::print("AU[{:d}] size = {:d}", au_count, au_size);
au_end = $ + au_size;
pbu_count = 0; // reset number of PBU
PBU pbu[while($ < au_end)] [[inline]];
};
u32 raw_count = 0;
struct RawBitstream {
AccessUnit AU [[name(std::format("AU[{}]", raw_count))]];
raw_count += 1;
} [[name(std::format("Raw[{}]", (raw_count - 1)))]];
struct ApvBitstream {
RawBitstream Raw [[inline]];
}[[inline]];
ApvBitstream APV[while(!std::mem::eof())] @ 0x0 [[inline]];