ref: ae4f2427e78904f57323f3618f110e2a8b36a602
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] : "???"; }