shithub: mcfs

Download patch

ref: a41e6c0c1ed77362a80443d65e8b9541a91793b6
parent: 041e2ada566d991e41dc0f626d1d20582276a6c0
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Dec 15 10:15:06 EST 2020

ebml: move element ids elsewhere, make debugging messages more human readable

--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
 
 ## Status
 
-The code looks horrible.
+The code looks horrible(?).
 
 It's not a filesystem yet, but it can extract video streams (as IVF)
 and audio streams from MP4 and MKV.
--- a/ebml.c
+++ b/ebml.c
@@ -3,6 +3,7 @@
 #include <bio.h>
 #include <ctype.h>
 #include "common.h"
+#include "elem.h"
 
 enum
 {
@@ -72,7 +73,7 @@
 			return -1;
 		}
 		if(n == 1 && c == 0){
-			werrstr("invalid number: %02x at 0x%zx", c, Boffset(f));
+			werrstr("invalid number: %02x at %#zx", c, Boffset(f));
 			return -1;
 		}
 		v |= c;
@@ -307,7 +308,7 @@
 	duration = 0;
 	ts = 0;
 	for(isebml = 0; left != 0;){
-		if(id == 0x9b)
+		if(id == EBlockDuration)
 			te.blockdur *= timestampscale;
 		if(endtracks > 0 && left < endtracks && trackdump == Nodump){
 			/* early exit */
@@ -317,20 +318,25 @@
 
 		off = Boffset(f);
 		if((n = ebmlel(f, left, &id, &sz)) < 0){
-			werrstr("invalid ebml: %r at 0x%zx", off);
+			werrstr("invalid ebml: %r at %#zx", off);
 			goto err;
 		}
-		if(dflag > 1)
-			Bprint(&stderr, "0x%zux\t%zux\t%zd\t%zd\n", off, id, sz, left);
+		if(dflag > 1){
+			Element *el;
+			if((el = ebmlid2elem(id)) != nil)
+				Bprint(&stderr, "%#zux\t%s\t%zd\t%zd\n", off, el->name, sz, left);
+			else
+				Bprint(&stderr, "%#zux\t%#llx\t%zd\t%zd\n", off, id, sz, left);
+		}
 		left -= n;
 
-		if(id == 0x1a45dfa3){ /* EBML comes first */
+		if(id == EEBML){ /* EBML comes first */
 			if(isebml != 0){
 				werrstr("double EBML?");
 				goto err;
 			}
 			isebml++;
-		}else if(id == 0x18538067){ /* segment */
+		}else if(id == ESegment){
 			left = sz;
 			if(isebml != 1){
 				werrstr("invalid ebml");
@@ -338,15 +344,15 @@
 			}
 			isebml++; /* make sure we don't see more segments */
 			continue; /* go in */
-		}else if(id == 0x1549a966){ /* segment info */
+		}else if(id == EInfo){ /* segment info */
 			continue;
-		}else if(id == 0x1654ae6b){ /* tracks */
+		}else if(id == ETracks){
 			endtracks = left - sz; /* to skip early in case track dump not required */
 			continue;
-		}else if(id == 0x1f43b675){ /* cluster */
+		}else if(id == ECluster){
 			if(trackdump != Nodump) /* skip it entirely if no dump required */
 				continue;
-		}else if(id == 0xae){ /* track entry */
+		}else if(id == ETrackEntry){ /* track entry */
 			if(e.tracknum > 0){
 				if(trackdump == Nodump)
 					trackinfo(&out, &e);
@@ -360,11 +366,11 @@
 			memset(&e, 0, sizeof(e));
 			e.timestampscale = timestampscale;
 			continue;
-		}else if(id == 0xe0 || id == 0xe1){ /* video/audio settings */
+		}else if(id == EVideo || id == EAudio){
 			continue;
-		}else if(id == 0xa0 && trackdump != Nodump){ /* block group */
+		}else if(id == EBlockGroup && trackdump != Nodump){
 			continue;
-		}else if((id == 0xa3 || id == 0xa1) && trackdump != Nodump){ /* (simple) block */
+		}else if((id == ESimpleBlock || id == EBlock) && trackdump != Nodump){
 			if(te.tracknum == -1)
 				memmove(&te, &e, sizeof(e));
 			if((n = ebmluint(f, &track, 0)) < 0){
@@ -467,59 +473,59 @@
 				continue;
 			}
 		}else{
-				ebmlgetnumber(0x2ad7b1, timestampscale)
+				ebmlgetnumber(ETimestampScale, timestampscale)
 			else
-				ebmlgetfloat(0xb5, e.audio.samplerate)
+				ebmlgetfloat(ESamplingFrequency, e.audio.samplerate)
 			else
-				ebmlgetnumber(0x9f, e.audio.channels)
+				ebmlgetnumber(EChannels, e.audio.channels)
 			else
-				ebmlgetnumber(0x6264, e.audio.bps)
+				ebmlgetnumber(EBitDepth, e.audio.bps)
 			else
-				ebmlgetnumber(0xd7, e.tracknum)
+				ebmlgetnumber(ETrackNumber, e.tracknum)
 			else
-				ebmlgetnumber(0x83, e.tracktype)
+				ebmlgetnumber(ETrackType, e.tracktype)
 			else
-				ebmlgetstring(0x86, e.codec.name)
+				ebmlgetstring(ECodecID, e.codec.name)
 			else
-				ebmlgetbytes(0x63a2, e.codec.priv)
+				ebmlgetbytes(ECodecPrivate, e.codec.priv)
 			else
-				ebmlgetnumber(0x56aa, e.codec.delay)
+				ebmlgetnumber(ECodecDelay, e.codec.delay)
 			else
-				ebmlgetnumber(0xb0, e.video.width)
+				ebmlgetnumber(EPixelWidth, e.video.width)
 			else
-				ebmlgetnumber(0xba, e.video.height)
+				ebmlgetnumber(EPixelHeight, e.video.height)
 			else
-				ebmlgetnumber(0x54aa, e.video.crop.bottom)
+				ebmlgetnumber(EPixelCropBottom, e.video.crop.bottom)
 			else
-				ebmlgetnumber(0x54bb, e.video.crop.top)
+				ebmlgetnumber(EPixelCropTop, e.video.crop.top)
 			else
-				ebmlgetnumber(0x54cc, e.video.crop.left)
+				ebmlgetnumber(EPixelCropLeft, e.video.crop.left)
 			else
-				ebmlgetnumber(0x54dd, e.video.crop.right)
+				ebmlgetnumber(EPixelCropRight, e.video.crop.right)
 			else
-				ebmlgetnumber(0x54b0, e.video.display.width)
+				ebmlgetnumber(EDisplayWidth, e.video.display.width)
 			else
-				ebmlgetnumber(0x54ba, e.video.display.height)
+				ebmlgetnumber(EDisplayHeight, e.video.display.height)
 			else
-				ebmlgetnumber(0x54b2, e.video.display.unit)
+				ebmlgetnumber(EDisplayUnit, e.video.display.unit)
 			else
-				ebmlgetnumber(0x54b3, e.video.display.aspectmode)
+				ebmlgetnumber(EAspectRatioType, e.video.display.aspectmode)
 			else
-				ebmlgetnumber(0xe7, timestamp)
+				ebmlgetnumber(ETimestamp, timestamp)
 			else
-				ebmlgetnumber(0x23e383, e.perframe)
+				ebmlgetnumber(EDefaultDuration, e.perframe)
 			else
-				ebmlgetnumber(0x56bb, e.seekpreroll)
+				ebmlgetnumber(ESeekPreRoll, e.seekpreroll)
 			else
-				ebmlgetfloat(0x4489, duration)
+				ebmlgetfloat(EDuration, duration)
 			else
-				ebmlgetnumber(0x73c5, e.trackuid)
+				ebmlgetnumber(ETrackUID, e.trackuid)
 			else
-				ebmlgetnumber(0x75a2, te.discardpad)
+				ebmlgetnumber(EDiscardPadding, te.discardpad)
 			else
-				ebmlgetnumber(0x9b, te.blockdur)
+				ebmlgetnumber(EBlockDuration, te.blockdur)
 			else
-				ebmlgetstring(0x22b59c, e.lang)
+				ebmlgetstring(ELanguage, e.lang)
 		}
 
 		if(Bseek(f, sz, 1) < 0)
--- /dev/null
+++ b/elem.c
@@ -1,0 +1,283 @@
+#include <u.h>
+#include <libc.h>
+#include "elem.h"
+
+static Element els[] = {
+	{EChapterDisplay, "ChapterDisplay", Emaster},
+	{ETrackType, "TrackType", Eunsigned},
+	{EChapString, "ChapString", Eunicode},
+	{ECodecID, "CodecID", Esigned},
+	{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", Esigned},
+	{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},
+};
+
+Element *
+ebmlid2elem(vlong id)
+{
+	Element *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;
+}
--- /dev/null
+++ b/elem.h
@@ -1,0 +1,279 @@
+typedef struct Element Element;
+
+struct Element {
+	vlong id;
+	char *name;
+	int type;
+};
+
+enum {
+	/* ebml element value types */
+	Emaster,
+	Ebinary,
+	Efloat,
+	Eunsigned,
+	Esigned,
+	Eunicode,
+	Eascii = Eunicode,
+	Etimestamp,
+
+	/* ids */
+	EChapterDisplay = 0x80,
+	ETrackType = 0x83,
+	EChapString = 0x85,
+	ECodecID = 0x86,
+	EFlagDefault = 0x88,
+	EChapterTrackUID = 0x89,
+	ESlices = 0x8e,
+	EChapterTrack = 0x8f,
+	EChapterTimeStart = 0x91,
+	EChapterTimeEnd = 0x92,
+	ECueRefTime = 0x96,
+	ECueRefCluster = 0x97,
+	EChapterFlagHidden = 0x98,
+	EFlagInterlaced = 0x9a,
+	EBlockDuration = 0x9b,
+	EFlagLacing = 0x9c,
+	EFieldOrder = 0x9d,
+	EChannels = 0x9f,
+	EBlockGroup = 0xa0,
+	EBlock = 0xa1,
+	EBlockVirtual = 0xa2,
+	ESimpleBlock = 0xa3,
+	ECodecState = 0xa4,
+	EBlockAdditional = 0xa5,
+	EBlockMore = 0xa6,
+	EPosition = 0xa7,
+	ECodecDecodeAll = 0xaa,
+	EPrevSize = 0xab,
+	ETrackEntry = 0xae,
+	EEncryptedBlock = 0xaf,
+	EPixelWidth = 0xb0,
+	ECueDuration = 0xb2,
+	ECueTime = 0xb3,
+	ESamplingFrequency = 0xb5,
+	EChapterAtom = 0xb6,
+	ECueTrackPositions = 0xb7,
+	EFlagEnabled = 0xb9,
+	EPixelHeight = 0xba,
+	ECuePoint = 0xbb,
+	ECRC32 = 0xbf,
+	EReferenceFrame = 0xc8,
+	EReferenceOffset = 0xc9,
+	EReferenceTimestamp = 0xca,
+	EBlockAdditionID = 0xcb,
+	ELaceNumber = 0xcc,
+	EFrameNumber = 0xcd,
+	EDelay = 0xce,
+	ESliceDuration = 0xcf,
+	ETrackNumber = 0xd7,
+	ECueReference = 0xdb,
+	EVideo = 0xe0,
+	EAudio = 0xe1,
+	ETrackOperation = 0xe2,
+	ETrackCombinePlanes = 0xe3,
+	ETrackPlane = 0xe4,
+	ETrackPlaneUID = 0xe5,
+	ETrackPlaneType = 0xe6,
+	ETimestamp = 0xe7,
+	ETimeSlice = 0xe8,
+	ETrackJoinBlocks = 0xe9,
+	ECueCodecState = 0xea,
+	ECueRefCodecState = 0xeb,
+	EVoid = 0xec,
+	ETrackJoinUID = 0xed,
+	EBlockAddID = 0xee,
+	ECueRelativePosition = 0xf0,
+	ECueClusterPosition = 0xf1,
+	ECueTrack = 0xf7,
+	EReferencePriority = 0xfa,
+	EReferenceBlock = 0xfb,
+	EReferenceVirtual = 0xfd,
+	EBlockAddIDName = 0x41a4,
+	EBlockAdditionMapping = 0x41e4,
+	EBlockAddIDType = 0x41e7,
+	EBlockAddIDExtraData = 0x41ed,
+	EBlockAddIDValue = 0x41f0,
+	EContentCompAlgo = 0x4254,
+	EContentCompSettings = 0x4255,
+	EDocTypeExtension = 0x4281,
+	EDocType = 0x4282,
+	EDocTypeExtensionName = 0x4283,
+	EDocTypeExtensionVersion = 0x4284,
+	EDocTypeReadVersion = 0x4285,
+	EEBMLVersion = 0x4286,
+	EDocTypeVersion = 0x4287,
+	EEBMLMaxIDLength = 0x42f2,
+	EEBMLMaxSizeLength = 0x42f3,
+	EEBMLReadVersion = 0x42f7,
+	EChapLanguage = 0x437c,
+	EChapLanguageIETF = 0x437d,
+	EChapCountry = 0x437e,
+	ESegmentFamily = 0x4444,
+	EDateUTC = 0x4461,
+	ETagLanguage = 0x447a,
+	ETagLanguageIETF = 0x447b,
+	ETagDefault = 0x4484,
+	ETagBinary = 0x4485,
+	ETagString = 0x4487,
+	EDuration = 0x4489,
+	EChapProcessPrivate = 0x450d,
+	EChapterFlagEnabled = 0x4598,
+	ETagName = 0x45a3,
+	EEditionEntry = 0x45b9,
+	EEditionUID = 0x45bc,
+	EEditionFlagHidden = 0x45bd,
+	EEditionFlagDefault = 0x45db,
+	EEditionFlagOrdered = 0x45dd,
+	EFileData = 0x465c,
+	EFileMimeType = 0x4660,
+	EFileUsedStartTime = 0x4661,
+	EFileUsedEndTime = 0x4662,
+	EFileName = 0x466e,
+	EFileReferral = 0x4675,
+	EFileDescription = 0x467e,
+	EFileUID = 0x46ae,
+	EContentEncAlgo = 0x47e1,
+	EContentEncKeyID = 0x47e2,
+	EContentSignature = 0x47e3,
+	EContentSigKeyID = 0x47e4,
+	EContentSigAlgo = 0x47e5,
+	EContentSigHashAlgo = 0x47e6,
+	EContentAESSettings = 0x47e7,
+	EAESSettingsCipherMode = 0x47e8,
+	EMuxingApp = 0x4d80,
+	ESeek = 0x4dbb,
+	EContentEncodingOrder = 0x5031,
+	EContentEncodingScope = 0x5032,
+	EContentEncodingType = 0x5033,
+	EContentCompression = 0x5034,
+	EContentEncryption = 0x5035,
+	ECueRefNumber = 0x535f,
+	EName = 0x536e,
+	ECueBlockNumber = 0x5378,
+	ETrackOffset = 0x537f,
+	ESeekID = 0x53ab,
+	ESeekPosition = 0x53ac,
+	EStereoMode = 0x53b8,
+	EOldStereoMode = 0x53b9,
+	EAlphaMode = 0x53c0,
+	EPixelCropBottom = 0x54aa,
+	EDisplayWidth = 0x54b0,
+	EDisplayUnit = 0x54b2,
+	EAspectRatioType = 0x54b3,
+	EDisplayHeight = 0x54ba,
+	EPixelCropTop = 0x54bb,
+	EPixelCropLeft = 0x54cc,
+	EPixelCropRight = 0x54dd,
+	EFlagForced = 0x55aa,
+	EColour = 0x55b0,
+	EMatrixCoefficients = 0x55b1,
+	EBitsPerChannel = 0x55b2,
+	EChromaSubsamplingHorz = 0x55b3,
+	EChromaSubsamplingVert = 0x55b4,
+	ECbSubSamplingHorz = 0x55b5,
+	ECbSubSamplingVert = 0x55b6,
+	EChromaSitingHorz = 0x55b7,
+	EChromaSitingVert = 0x55b8,
+	ERange = 0x55b9,
+	ETransferCharacteristics = 0x55ba,
+	EPrimaries = 0x55bb,
+	EMaxCLL = 0x55bc,
+	EMaxFALL = 0x55bd,
+	EMasteringMetadata = 0x55d0,
+	EPrimaryRChromaticityX = 0x55d1,
+	EPrimaryRChromaticityY = 0x55d2,
+	EPrimaryGChromaticityX = 0x55d3,
+	EPrimaryGChromaticityY = 0x55d4,
+	EPrimaryBChromaticityX = 0x55d5,
+	EPrimaryBChromaticityY = 0x55d6,
+	EWhitePointChromaticityX = 0x55d7,
+	EWhitePointChromaticityY = 0x55d8,
+	ELuminanceMax = 0x55d9,
+	ELuminanceMin = 0x55da,
+	EMaxBlockAdditionID = 0x55ee,
+	EChapterStringUID = 0x5654,
+	ECodecDelay = 0x56aa,
+	ESeekPreRoll = 0x56bb,
+	EWritingApp = 0x5741,
+	ESilentTracks = 0x5854,
+	ESilentTrackNumber = 0x58d7,
+	EAttachedFile = 0x61a7,
+	EContentEncoding = 0x6240,
+	EBitDepth = 0x6264,
+	ECodecPrivate = 0x63a2,
+	ETargets = 0x63c0,
+	EChapterPhysicalEquiv = 0x63c3,
+	ETagChapterUID = 0x63c4,
+	ETagTrackUID = 0x63c5,
+	ETagAttachmentUID = 0x63c6,
+	ETagEditionUID = 0x63c9,
+	ETargetType = 0x63ca,
+	ETrackTranslate = 0x6624,
+	ETrackTranslateTrackID = 0x66a5,
+	ETrackTranslateCodec = 0x66bf,
+	ETrackTranslateEditionUID = 0x66fc,
+	ESimpleTag = 0x67c8,
+	ETargetTypeValue = 0x68ca,
+	EChapProcessCommand = 0x6911,
+	EChapProcessTime = 0x6922,
+	EChapterTranslate = 0x6924,
+	EChapProcessData = 0x6933,
+	EChapProcess = 0x6944,
+	EChapProcessCodecID = 0x6955,
+	EChapterTranslateID = 0x69a5,
+	EChapterTranslateCodec = 0x69bf,
+	EChapterTranslateEditionUID = 0x69fc,
+	EContentEncodings = 0x6d80,
+	EMinCache = 0x6de7,
+	EMaxCache = 0x6df8,
+	EChapterSegmentUID = 0x6e67,
+	EChapterSegmentEditionUID = 0x6ebc,
+	ETrackOverlay = 0x6fab,
+	ETag = 0x7373,
+	ESegmentFilename = 0x7384,
+	ESegmentUID = 0x73a4,
+	EChapterUID = 0x73c4,
+	ETrackUID = 0x73c5,
+	EAttachmentLink = 0x7446,
+	EBlockAdditions = 0x75a1,
+	EDiscardPadding = 0x75a2,
+	EProjection = 0x7670,
+	EProjectionType = 0x7671,
+	EProjectionPrivate = 0x7672,
+	EProjectionPoseYaw = 0x7673,
+	EProjectionPosePitch = 0x7674,
+	EProjectionPoseRoll = 0x7675,
+	EOutputSamplingFrequency = 0x78b5,
+	ETitle = 0x7ba9,
+	EChannelPositions = 0x7d7b,
+	ELanguage = 0x22b59c,
+	ELanguageIETF = 0x22b59d,
+	ETrackTimestampScale = 0x23314f,
+	EDefaultDecodedFieldDuration = 0x234e7a,
+	EFrameRate = 0x2383e3,
+	EDefaultDuration = 0x23e383,
+	ECodecName = 0x258688,
+	ECodecDownloadURL = 0x26b240,
+	ETimestampScale = 0x2ad7b1,
+	EColourSpace = 0x2eb524,
+	EGammaValue = 0x2fb523,
+	ECodecSettings = 0x3a9697,
+	ECodecInfoURL = 0x3b4040,
+	EPrevFilename = 0x3c83ab,
+	EPrevUID = 0x3cb923,
+	ENextFilename = 0x3e83bb,
+	ENextUID = 0x3eb923,
+	EChapters = 0x1043a770,
+	ESeekHead = 0x114d9b74,
+	ETags = 0x1254c367,
+	EInfo = 0x1549a966,
+	ETracks = 0x1654ae6b,
+	ESegment = 0x18538067,
+	EAttachments = 0x1941a469,
+	EEBML = 0x1a45dfa3,
+	ECues = 0x1c53bb6b,
+	ECluster = 0x1f43b675,
+};
+
+Element *ebmlid2elem(vlong id);
--- a/mkfile
+++ b/mkfile
@@ -8,6 +8,7 @@
 OFILES=\
 	crc32.$O\
 	ebml.$O\
+	elem.$O\
 	iso.$O\
 	ivf.$O\
 	main.$O\