ref: 2c5718f371ce2b84ebd513310184351becc7be53
dir: /ebml.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "ebml.h"
static Elspec els[] = {
{EChapterDisplay, "ChapterDisplay", Emaster},
{ETrackType, "TrackType", Eunsigned},
{EChapString, "ChapString", Eunicode},
{ECodecID, "CodecID", Eascii},
{EFlagDefault, "FlagDefault", Eunsigned},
{EChapterTrackUID, "ChapterTrackUID", Eunsigned},
{ESlices, "Slices", Emaster},
{EChapterTrack, "ChapterTrack", Emaster},
{EChapterTimeStart, "ChapterTimeStart", Eunsigned},
{EChapterTimeEnd, "ChapterTimeEnd", Eunsigned},
{ECueRefTime, "CueRefTime", Eunsigned},
{ECueRefCluster, "CueRefCluster", Eunsigned},
{EChapterFlagHidden, "ChapterFlagHidden", Eunsigned},
{EFlagInterlaced, "FlagInterlaced", Eunsigned},
{EBlockDuration, "BlockDuration", Eunsigned},
{EFlagLacing, "FlagLacing", Eunsigned},
{EFieldOrder, "FieldOrder", Eunsigned},
{EChannels, "Channels", Eunsigned},
{EBlockGroup, "BlockGroup", Emaster},
{EBlock, "Block", Ebinary},
{EBlockVirtual, "BlockVirtual", Ebinary},
{ESimpleBlock, "SimpleBlock", Ebinary},
{ECodecState, "CodecState", Ebinary},
{EBlockAdditional, "BlockAdditional", Ebinary},
{EBlockMore, "BlockMore", Emaster},
{EPosition, "Position", Eunsigned},
{ECodecDecodeAll, "CodecDecodeAll", Eunsigned},
{EPrevSize, "PrevSize", Eunsigned},
{ETrackEntry, "TrackEntry", Emaster},
{EEncryptedBlock, "EncryptedBlock", Ebinary},
{EPixelWidth, "PixelWidth", Eunsigned},
{ECueDuration, "CueDuration", Eunsigned},
{ECueTime, "CueTime", Eunsigned},
{ESamplingFrequency, "SamplingFrequency", Efloat},
{EChapterAtom, "ChapterAtom", Emaster},
{ECueTrackPositions, "CueTrackPositions", Emaster},
{EFlagEnabled, "FlagEnabled", Eunsigned},
{EPixelHeight, "PixelHeight", Eunsigned},
{ECuePoint, "CuePoint", Emaster},
{ECRC32, "CRC-32", Ebinary},
{EReferenceFrame, "ReferenceFrame", Emaster},
{EReferenceOffset, "ReferenceOffset", Eunsigned},
{EReferenceTimestamp, "ReferenceTimestamp", Eunsigned},
{EBlockAdditionID, "BlockAdditionID", Eunsigned},
{ELaceNumber, "LaceNumber", Eunsigned},
{EFrameNumber, "FrameNumber", Eunsigned},
{EDelay, "Delay", Eunsigned},
{ESliceDuration, "SliceDuration", Eunsigned},
{ETrackNumber, "TrackNumber", Eunsigned},
{ECueReference, "CueReference", Emaster},
{EVideo, "Video", Emaster},
{EAudio, "Audio", Emaster},
{ETrackOperation, "TrackOperation", Emaster},
{ETrackCombinePlanes, "TrackCombinePlanes", Emaster},
{ETrackPlane, "TrackPlane", Emaster},
{ETrackPlaneUID, "TrackPlaneUID", Eunsigned},
{ETrackPlaneType, "TrackPlaneType", Eunsigned},
{ETimestamp, "Timestamp", Eunsigned},
{ETimeSlice, "TimeSlice", Emaster},
{ETrackJoinBlocks, "TrackJoinBlocks", Emaster},
{ECueCodecState, "CueCodecState", Eunsigned},
{ECueRefCodecState, "CueRefCodecState", Eunsigned},
{EVoid, "Void", Ebinary},
{ETrackJoinUID, "TrackJoinUID", Eunsigned},
{EBlockAddID, "BlockAddID", Eunsigned},
{ECueRelativePosition, "CueRelativePosition", Eunsigned},
{ECueClusterPosition, "CueClusterPosition", Eunsigned},
{ECueTrack, "CueTrack", Eunsigned},
{EReferencePriority, "ReferencePriority", Eunsigned},
{EReferenceBlock, "ReferenceBlock", Esigned},
{EReferenceVirtual, "ReferenceVirtual", Esigned},
{EBlockAddIDName, "BlockAddIDName", Eascii},
{EBlockAdditionMapping, "BlockAdditionMapping", Emaster},
{EBlockAddIDType, "BlockAddIDType", Eunsigned},
{EBlockAddIDExtraData, "BlockAddIDExtraData", Ebinary},
{EBlockAddIDValue, "BlockAddIDValue", Eunsigned},
{EContentCompAlgo, "ContentCompAlgo", Eunsigned},
{EContentCompSettings, "ContentCompSettings", Ebinary},
{EDocTypeExtension, "DocTypeExtension", Emaster},
{EDocType, "DocType", Eascii},
{EDocTypeExtensionName, "DocTypeExtensionName", Eascii},
{EDocTypeExtensionVersion, "DocTypeExtensionVersion", Eunsigned},
{EDocTypeReadVersion, "DocTypeReadVersion", Eunsigned},
{EEBMLVersion, "EBMLVersion", Eunsigned},
{EDocTypeVersion, "DocTypeVersion", Eunsigned},
{EEBMLMaxIDLength, "EBMLMaxIDLength", Eunsigned},
{EEBMLMaxSizeLength, "EBMLMaxSizeLength", Eunsigned},
{EEBMLReadVersion, "EBMLReadVersion", Eunsigned},
{EChapLanguage, "ChapLanguage", Eascii},
{EChapLanguageIETF, "ChapLanguageIETF", Eascii},
{EChapCountry, "ChapCountry", Eascii},
{ESegmentFamily, "SegmentFamily", Ebinary},
{EDateUTC, "DateUTC", Etimestamp},
{ETagLanguage, "TagLanguage", Eascii},
{ETagLanguageIETF, "TagLanguageIETF", Eascii},
{ETagDefault, "TagDefault", Eunsigned},
{ETagBinary, "TagBinary", Ebinary},
{ETagString, "TagString", Eunicode},
{EDuration, "Duration", Efloat},
{EChapProcessPrivate, "ChapProcessPrivate", Ebinary},
{EChapterFlagEnabled, "ChapterFlagEnabled", Eunsigned},
{ETagName, "TagName", Eunicode},
{EEditionEntry, "EditionEntry", Emaster},
{EEditionUID, "EditionUID", Eunsigned},
{EEditionFlagHidden, "EditionFlagHidden", Eunsigned},
{EEditionFlagDefault, "EditionFlagDefault", Eunsigned},
{EEditionFlagOrdered, "EditionFlagOrdered", Eunsigned},
{EFileData, "FileData", Ebinary},
{EFileMimeType, "FileMimeType", Eascii},
{EFileUsedStartTime, "FileUsedStartTime", Eunsigned},
{EFileUsedEndTime, "FileUsedEndTime", Eunsigned},
{EFileName, "FileName", Eunicode},
{EFileReferral, "FileReferral", Ebinary},
{EFileDescription, "FileDescription", Eunicode},
{EFileUID, "FileUID", Eunsigned},
{EContentEncAlgo, "ContentEncAlgo", Eunsigned},
{EContentEncKeyID, "ContentEncKeyID", Ebinary},
{EContentSignature, "ContentSignature", Ebinary},
{EContentSigKeyID, "ContentSigKeyID", Ebinary},
{EContentSigAlgo, "ContentSigAlgo", Eunsigned},
{EContentSigHashAlgo, "ContentSigHashAlgo", Eunsigned},
{EContentAESSettings, "ContentAESSettings", Emaster},
{EAESSettingsCipherMode, "AESSettingsCipherMode", Eunsigned},
{EMuxingApp, "MuxingApp", Eunicode},
{ESeek, "Seek", Emaster},
{EContentEncodingOrder, "ContentEncodingOrder", Eunsigned},
{EContentEncodingScope, "ContentEncodingScope", Eunsigned},
{EContentEncodingType, "ContentEncodingType", Eunsigned},
{EContentCompression, "ContentCompression", Emaster},
{EContentEncryption, "ContentEncryption", Emaster},
{ECueRefNumber, "CueRefNumber", Eunsigned},
{EName, "Name", Eunicode},
{ECueBlockNumber, "CueBlockNumber", Eunsigned},
{ETrackOffset, "TrackOffset", Esigned},
{ESeekID, "SeekID", Ebinary},
{ESeekPosition, "SeekPosition", Eunsigned},
{EStereoMode, "StereoMode", Eunsigned},
{EOldStereoMode, "OldStereoMode", Eunsigned},
{EAlphaMode, "AlphaMode", Eunsigned},
{EPixelCropBottom, "PixelCropBottom", Eunsigned},
{EDisplayWidth, "DisplayWidth", Eunsigned},
{EDisplayUnit, "DisplayUnit", Eunsigned},
{EAspectRatioType, "AspectRatioType", Eunsigned},
{EDisplayHeight, "DisplayHeight", Eunsigned},
{EPixelCropTop, "PixelCropTop", Eunsigned},
{EPixelCropLeft, "PixelCropLeft", Eunsigned},
{EPixelCropRight, "PixelCropRight", Eunsigned},
{EFlagForced, "FlagForced", Eunsigned},
{EColour, "Colour", Emaster},
{EMatrixCoefficients, "MatrixCoefficients", Eunsigned},
{EBitsPerChannel, "BitsPerChannel", Eunsigned},
{EChromaSubsamplingHorz, "ChromaSubsamplingHorz", Eunsigned},
{EChromaSubsamplingVert, "ChromaSubsamplingVert", Eunsigned},
{ECbSubSamplingHorz, "CbSubSamplingHorz", Eunsigned},
{ECbSubSamplingVert, "CbSubSamplingVert", Eunsigned},
{EChromaSitingHorz, "ChromaSitingHorz", Eunsigned},
{EChromaSitingVert, "ChromaSitingVert", Eunsigned},
{ERange, "Range", Eunsigned},
{ETransferCharacteristics, "TransferCharacteristics", Eunsigned},
{EPrimaries, "Primaries", Eunsigned},
{EMaxCLL, "MaxCLL", Eunsigned},
{EMaxFALL, "MaxFALL", Eunsigned},
{EMasteringMetadata, "MasteringMetadata", Emaster},
{EPrimaryRChromaticityX, "PrimaryRChromaticityX", Efloat},
{EPrimaryRChromaticityY, "PrimaryRChromaticityY", Efloat},
{EPrimaryGChromaticityX, "PrimaryGChromaticityX", Efloat},
{EPrimaryGChromaticityY, "PrimaryGChromaticityY", Efloat},
{EPrimaryBChromaticityX, "PrimaryBChromaticityX", Efloat},
{EPrimaryBChromaticityY, "PrimaryBChromaticityY", Efloat},
{EWhitePointChromaticityX, "WhitePointChromaticityX", Efloat},
{EWhitePointChromaticityY, "WhitePointChromaticityY", Efloat},
{ELuminanceMax, "LuminanceMax", Efloat},
{ELuminanceMin, "LuminanceMin", Efloat},
{EMaxBlockAdditionID, "MaxBlockAdditionID", Eunsigned},
{EChapterStringUID, "ChapterStringUID", Eunicode},
{ECodecDelay, "CodecDelay", Eunsigned},
{ESeekPreRoll, "SeekPreRoll", Eunsigned},
{EWritingApp, "WritingApp", Eunicode},
{ESilentTracks, "SilentTracks", Emaster},
{ESilentTrackNumber, "SilentTrackNumber", Eunsigned},
{EAttachedFile, "AttachedFile", Emaster},
{EContentEncoding, "ContentEncoding", Emaster},
{EBitDepth, "BitDepth", Eunsigned},
{ECodecPrivate, "CodecPrivate", Ebinary},
{ETargets, "Targets", Emaster},
{EChapterPhysicalEquiv, "ChapterPhysicalEquiv", Eunsigned},
{ETagChapterUID, "TagChapterUID", Eunsigned},
{ETagTrackUID, "TagTrackUID", Eunsigned},
{ETagAttachmentUID, "TagAttachmentUID", Eunsigned},
{ETagEditionUID, "TagEditionUID", Eunsigned},
{ETargetType, "TargetType", Eascii},
{ETrackTranslate, "TrackTranslate", Emaster},
{ETrackTranslateTrackID, "TrackTranslateTrackID", Ebinary},
{ETrackTranslateCodec, "TrackTranslateCodec", Eunsigned},
{ETrackTranslateEditionUID, "TrackTranslateEditionUID", Eunsigned},
{ESimpleTag, "SimpleTag", Emaster},
{ETargetTypeValue, "TargetTypeValue", Eunsigned},
{EChapProcessCommand, "ChapProcessCommand", Emaster},
{EChapProcessTime, "ChapProcessTime", Eunsigned},
{EChapterTranslate, "ChapterTranslate", Emaster},
{EChapProcessData, "ChapProcessData", Ebinary},
{EChapProcess, "ChapProcess", Emaster},
{EChapProcessCodecID, "ChapProcessCodecID", Eunsigned},
{EChapterTranslateID, "ChapterTranslateID", Ebinary},
{EChapterTranslateCodec, "ChapterTranslateCodec", Eunsigned},
{EChapterTranslateEditionUID, "ChapterTranslateEditionUID", Eunsigned},
{EContentEncodings, "ContentEncodings", Emaster},
{EMinCache, "MinCache", Eunsigned},
{EMaxCache, "MaxCache", Eunsigned},
{EChapterSegmentUID, "ChapterSegmentUID", Ebinary},
{EChapterSegmentEditionUID, "ChapterSegmentEditionUID", Eunsigned},
{ETrackOverlay, "TrackOverlay", Eunsigned},
{ETag, "Tag", Emaster},
{ESegmentFilename, "SegmentFilename", Eunicode},
{ESegmentUID, "SegmentUID", Ebinary},
{EChapterUID, "ChapterUID", Eunsigned},
{ETrackUID, "TrackUID", Eunsigned},
{EAttachmentLink, "AttachmentLink", Eunsigned},
{EBlockAdditions, "BlockAdditions", Emaster},
{EDiscardPadding, "DiscardPadding", Esigned},
{EProjection, "Projection", Emaster},
{EProjectionType, "ProjectionType", Eunsigned},
{EProjectionPrivate, "ProjectionPrivate", Ebinary},
{EProjectionPoseYaw, "ProjectionPoseYaw", Efloat},
{EProjectionPosePitch, "ProjectionPosePitch", Efloat},
{EProjectionPoseRoll, "ProjectionPoseRoll", Efloat},
{EOutputSamplingFrequency, "OutputSamplingFrequency", Efloat},
{ETitle, "Title", Eunicode},
{EChannelPositions, "ChannelPositions", Ebinary},
{ELanguage, "Language", Eascii},
{ELanguageIETF, "LanguageIETF", Eascii},
{ETrackTimestampScale, "TrackTimestampScale", Efloat},
{EDefaultDecodedFieldDuration, "DefaultDecodedFieldDuration", Eunsigned},
{EFrameRate, "FrameRate", Efloat},
{EDefaultDuration, "DefaultDuration", Eunsigned},
{ECodecName, "CodecName", Eunicode},
{ECodecDownloadURL, "CodecDownloadURL", Eascii},
{ETimestampScale, "TimestampScale", Eunsigned},
{EColourSpace, "ColourSpace", Ebinary},
{EGammaValue, "GammaValue", Efloat},
{ECodecSettings, "CodecSettings", Eunicode},
{ECodecInfoURL, "CodecInfoURL", Eascii},
{EPrevFilename, "PrevFilename", Eunicode},
{EPrevUID, "PrevUID", Ebinary},
{ENextFilename, "NextFilename", Eunicode},
{ENextUID, "NextUID", Ebinary},
{EChapters, "Chapters", Emaster},
{ESeekHead, "SeekHead", Emaster},
{ETags, "Tags", Emaster},
{EInfo, "Info", Emaster},
{ETracks, "Tracks", Emaster},
{ESegment, "Segment", Emaster},
{EAttachments, "Attachments", Emaster},
{EEBML, "EBML", Emaster},
{ECues, "Cues", Emaster},
{ECluster, "Cluster", Emaster},
};
static Elspec *
elspec(vlong id)
{
Elspec *p, *t;
int m, n;
n = nelem(els);
t = els;
while(n > 1){
m = n/2;
p = t + m;
if(id >= p->id) {
t = p;
n = n-m;
} else
n = m;
}
return id == t->id ? t : nil;
}
int
ebmluintb(u8int *b, vlong sz, vlong *out)
{
uvlong v, m;
int c, n;
*out = 0;
for(n = 1, m = 0x80, v = 0; n <= 8; v <<= 8, m <<= 7, n++){
if(n-1 >= sz){
werrstr("eof");
return -1;
}
c = b[n-1];
if(n == 1 && c == 0){
werrstr("invalid number: %02x", c);
return -1;
}
v |= c;
if(v & m){
*out = v & ~m;
return n;
}
v &= ~m;
}
werrstr("number overflow");
return -1;
}
int
ebmlsintb(u8int *b, vlong sz, vlong *out)
{
int n;
if((n = ebmluintb(b, sz, out)) < 0)
return -1;
*out -= (1 << n*7-1) - 1;
return n;
}
static int
_ebmluint(Biobuf *f, vlong *out, vlong sz, int isid)
{
uvlong v, m;
int c, n, i;
*out = 0;
for(i = 0, n = 1, m = 0x80, v = 0; i < sz && n <= 8; v <<= 8, m <<= 7, n++){
if((c = Bgetc(f)) < 0){
werrstr("eof");
return -1;
}
if(n == 1 && c == 0){
werrstr("invalid number: %02x at %#llux", c, Boffset(f));
return -1;
}
v |= c;
if(v & m){
*out = isid ? v : (v & ~m);
if(!isid && *out == (1<<(7*n))-1) /* unknown size */
*out = -1;
return n;
}
if(!isid)
v &= ~m;
}
if(i >= sz)
werrstr("ebmluint: short read");
else
werrstr("ebmluint: overflow");
return -1;
}
int
ebmluint(Biobuf *f, vlong sz, vlong *out)
{
return _ebmluint(f, out, sz, 0);
}
int
ebmlid(Biobuf *f, vlong sz, vlong *out)
{
return _ebmluint(f, out, sz, 1);
}
int
ebmlsint(Biobuf *f, vlong sz, vlong *out)
{
int n;
if((n = ebmluint(f, sz, out)) < 0)
return -1;
*out -= (1 << n*7-1) - 1;
return n;
}
int
ebmlfloat(Biobuf *f, vlong sz, double *out)
{
u32int u;
union {
uchar b[8];
u32int u[2];
float f;
double d;
}x;
if(sz != 4 && sz != 8){
werrstr("invalid float size %lld", sz);
return -1;
}
if(Bread(f, x.b, sz) != sz)
return -1;
if(sz == 4){
x.u[0] = (x.u[0]&0xff000000)>>24 | (x.u[0]&0x00ff0000)>>8 | (x.u[0]&0x0000ff00)<<8 | (x.u[0]&0x000000ff)<<24;
*out = x.f;
}else if(sz == 8){
u = (x.u[0]&0xff000000)>>24 | (x.u[0]&0x00ff0000)>>8 | (x.u[0]&0x0000ff00)<<8 | (x.u[0]&0x000000ff)<<24;
x.u[0] = (x.u[1]&0xff000000)>>24 | (x.u[1]&0x00ff0000)>>8 | (x.u[1]&0x0000ff00)<<8 | (x.u[1]&0x000000ff)<<24;
x.u[1] = u;
*out = x.d;
}
return 0;
}
vlong
ebmlel(Biobuf *f, vlong sz, Elspec *el, vlong *esz)
{
vlong x, n, r;
Elspec *s;
if(Bgetc(f) < 0)
return 0;
Bungetc(f);
r = ebmlid(f, sz, &x);
n = r;
if(r >= sz || r < 0){
werrstr("id: %r");
return -1;
}
if((s = elspec(x)) != nil){
*el = *s;
el->id = x;
r = ebmluint(f, sz-n, &x);
n += r;
if(n >= sz || r < 0 || sz-n < x){
werrstr("sz: (sz=%lld n=%lld r=%lld x=%lld): %r", sz, n, r, x);
return -1;
}
*esz = x;
}else{ /* skip invalid elements */
while(--n > 0)
Bungetc(f);
el->id = x;
el->type = -1;
*esz = 0;
return 0;
}
return n;
}
vlong
ebmlrawuint(Biobuf *f, vlong sz, vlong *dst)
{
vlong i;
int c;
*dst = 0;
for(i = 0; i < sz; i++){
*dst <<= 8;
if((c = Bgetc(f)) < 0){
werrstr("eof");
return -1;
}
*dst |= c;
}
return 0;
}
vlong
ebmlrawsint(Biobuf *f, vlong sz, vlong *dst)
{
vlong i, x;
int c;
x = 0;
for(i = 0; i < sz; i++){
x <<= 8;
if((c = Bgetc(f)) < 0){
werrstr("eof");
return -1;
}
x |= c;
}
if(x & (0x80ULL<<(i-1)))
*dst = -(~x + 1);
else
*dst = x;
return 0;
}
char *
ebmltracktype(int t)
{
static char *types[] = {
[Etrackvideo] = "video",
[Etrackaudio] = "audio",
[Etrackcomplex] = "complex",
[Etracklogo] = "logo",
[Etracksubtitles] = "subtitle",
[Etrackbuttons] = "buttons",
[Etrackcontrol] = "control",
[Etrackmetadata] = "metadata",
};
return t < nelem(types) ? types[t] : "???";
}