ref: ace30eb522ce18622b465e550c6926d895101cb0
parent: aad9511a85b15ced2fde315c693ce12a05f1f315
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Tue Dec 15 16:41:48 EST 2020
move stuff around to make the code better
--- /dev/null
+++ b/aac.c
@@ -1,0 +1,24 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "common.h"
+#include "packet.h"
+
+int
+aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
+{
+ int i;
+
+ USED(ts);
+ if(ctx->codec.priv.sz > 0 && Bwrite(out, ctx->codec.priv.data, ctx->codec.priv.sz) != ctx->codec.priv.sz)
+ goto err;
+ for(i = 0; i < np; i++, p++){
+ if(Bwrite(out, p->data, p->sz) != p->sz)
+ goto err;
+ }
+
+ return 0;
+err:
+ werrstr("aacpacket: %r");
+ return -1;
+}
--- a/common.h
+++ b/common.h
@@ -16,64 +16,8 @@
FmtMp3 = 0x006d7033u,
};
-typedef struct Ebml Ebml;
-typedef struct Packet Packet;
-typedef struct Packetctx Packetctx;
-typedef int (*packet_f)(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
+#define min(a,b) ((a)<=(b)?(a):(b))
-struct Packet {
- uchar *data;
- int sz;
-};
-
-struct Packetctx {
- uvlong frid;
- uvlong duration;
- uvlong seekpreroll;
- vlong discardpad;
- vlong blockdur;
- struct {
- char name[16];
- vlong delay;
- struct {
- uchar *data;
- int sz;
- }priv;
- }codec;
- u32int trackuid;
- u32int fmt;
-
- struct {
- int width, height;
- struct {
- int left, right, top, bottom;
- }crop;
- struct {
- int width, height;
- int unit;
- int aspectmode;
- }display;
- }video;
- struct {
- float samplerate;
- int channels;
- int bps;
- }audio;
-};
-
-struct Ebml {
- Packetctx;
-
- packet_f fpacket;
-
- vlong timestampscale;
- vlong perframe;
- int tracknum;
- int tracktype;
- vlong codecdelay;
- char lang[8];
-};
-
extern Biobuf stderr, out;
extern int dflag, trackdump;
@@ -84,77 +28,6 @@
int srttsfmt(Fmt *f);
int isorun(Biobuf *f);
-int ebmlrun(Biobuf *f);
+int matroskarun(Biobuf *f);
u32int crc32(u32int init, u8int *d, ulong len);
-
-int ivfpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
-int oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
-int srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
-
-int ebmlint(Biobuf *f, vlong *out, int isid);
-vlong ebmlel(Biobuf *f, vlong sz, vlong *id, vlong *esz);
-vlong ebmlrawint(Biobuf *f, vlong sz, vlong *dst);
-
-#define ebmlgetnumber(expid, dest) \
- if(id == expid){ \
- vlong x; \
- if(ebmlrawint(f, sz, &x) < 0) \
- return -1; \
- dest = x; \
- left -= sz; \
- continue; \
- }
-
-#define ebmlgetstring(expid, dest) \
- if(id == expid){ \
- n = min(sizeof(dest)-1, sz); \
- if(Bread(f, dest, n) != n) \
- return -1; \
- dest[n] = 0; \
- if(n != sz) \
- Bseek(f, sz-n, 1); \
- left -= sz; \
- continue; \
- }
-
-#define ebmlgetbytes(expid, dest) \
- if(id == expid){ \
- dest.data = malloc(sz); \
- if(Bread(f, dest.data, sz) != sz) \
- return -1; \
- dest.sz = sz; \
- left -= sz; \
- continue; \
- }
-
-#define ebmlgetfloat(expid, dest) \
- if(id == expid){ \
- u32int u; \
- union { \
- uchar b[8]; \
- u32int u[2]; \
- float f; \
- double d; \
- }x; \
- if(sz == 4){ \
- if(Bread(f, x.b, 4) != 4) \
- return -1; \
- x.u[0] = (x.u[0]&0xff000000)>>24 | (x.u[0]&0x00ff0000)>>8 | (x.u[0]&0x0000ff00)<<8 | (x.u[0]&0x000000ff)<<24; \
- dest = x.f; \
- }else if(sz == 8){ \
- if(Bread(f, x.b, 8) != 8) \
- return -1; \
- 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; \
- dest = x.d; \
- }else{ \
- werrstr("invalid float size"); \
- break; \
- } \
- left -= sz; \
- continue; \
- }
-
-#define min(a,b) ((a)<=(b)?(a):(b))
--- a/ebml.c
+++ b/ebml.c
@@ -3,23 +3,288 @@
#include <bio.h>
#include <ctype.h>
#include "common.h"
-#include "elem.h"
+#include "ebml.h"
-enum
-{
- Trackvideo = 1,
- Trackaudio = 2,
- Trackcomplex = 3,
- Tracklogo = 16,
- Tracksubtitles = 17,
- Trackbuttons = 18,
- Trackcontrol = 32,
- Trackmetadata = 33,
+static Elspec 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},
};
-static Packet packets[256];
-static vlong stack[32];
+Elspec *
+ebmlelspec(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, int sz, vlong *out)
{
@@ -61,8 +326,8 @@
return n;
}
-int
-ebmluint(Biobuf *f, vlong *out, int isid)
+static int
+_ebmluint(Biobuf *f, vlong *out, int isid)
{
uvlong v, m;
int c, n;
@@ -91,11 +356,23 @@
}
int
+ebmluint(Biobuf *f, vlong *out)
+{
+ return _ebmluint(f, out, 0);
+}
+
+int
+ebmlid(Biobuf *f, vlong *out)
+{
+ return _ebmluint(f, out, 1);
+}
+
+int
ebmlsint(Biobuf *f, vlong *out)
{
int n;
- if((n = ebmluint(f, out, 0)) < 0)
+ if((n = ebmluint(f, out)) < 0)
return -1;
*out -= (1 << n*7-1) - 1;
@@ -107,15 +384,13 @@
{
vlong x, n, r;
- if(sz < 2)
- return -1;
n = 0;
- if((n += (r = ebmluint(f, &x, 1))) >= sz || r < 0){
+ if((n += (r = ebmlid(f, &x))) >= sz || r < 0){
werrstr("id: %r");
return -1;
}
*id = x;
- if((n += (r = ebmluint(f, &x, 0))) >= sz || r < 0 || sz-n < x){
+ if((n += (r = ebmluint(f, &x))) >= sz || r < 0 || sz-n < x){
werrstr("sz: (sz=%zd n=%zd r=%zd x=%zd): %r", sz, n, r, x);
return -1;
}
@@ -143,413 +418,19 @@
return 0;
}
-static char *
-format(Ebml *e)
+char *
+ebmltracktype(int t)
{
- static char t[16];
- char *s;
- int n;
-
- if(e->tracktype == Tracksubtitles){
- if(strcmp(e->codec.name, "S_TEXT/UTF8") == 0)
- return "srt";
- }else if(e->tracktype == Trackaudio){
- if(strcmp(e->codec.name, "A_MPEG/L3") == 0)
- return "mp3";
- }else if(e->tracktype == Trackvideo){
- if(strcmp(e->codec.name, "V_MPEG4/ISO/AVC") == 0)
- return "h264";
- }
-
- n = snprint(t, sizeof(t), "%s", e->codec.name+2);
- for(n -= 1; n >= 0; n--)
- t[n] = tolower(t[n]);
- if((s = strchr(t, '/')) != nil)
- *s = 0;
-
- return t;
-}
-
-static int
-asispacket(Biobuf *out, Packetctx *, Packet *p, int np, uvlong)
-{
- int i;
-
- for(i = 0; i < np; i++, p++)
- Bwrite(out, p->data, p->sz);
-
- return 0;
-}
-
-static int
-initctx(Ebml *e, double duration)
-{
- char *c;
-
- e->duration = duration;
- e->duration *= e->timestampscale;
- c = format(e);
- if(e->tracktype == Trackvideo){
- if(strcmp(c, "vp9") == 0)
- e->fmt = FmtVp09;
- else if(strcmp(c, "vp8") == 0)
- e->fmt = FmtVp08;
- else if(strcmp(c, "h264") == 0)
- e->fmt = FmtAvc1;
- else
- goto err;
- e->fpacket = ivfpacket;
- return 0;
- }else if(e->tracktype == Trackaudio){
- if(strcmp(c, "vorbis") == 0){
- e->fmt = FmtVorbis;
- e->fpacket = oggpacket;
- }else if(strcmp(c, "opus") == 0){
- e->fmt = FmtOpus;
- e->fpacket = oggpacket;
- }else if(strcmp(c, "mp3") == 0){
- e->fmt = FmtMp3;
- e->fpacket = asispacket;
- }else if(strcmp(c, "aac") == 0){
- e->fmt = FmtMp4a;
- e->fpacket = asispacket;
- }else
- goto err;
- return 0;
- }else if(e->tracktype == Tracksubtitles){
- if(strcmp(c, "srt") == 0){
- e->fmt = FmtSrt;
- e->fpacket = srtpacket;
- }else
- goto err;
- return 0;
- }
-
-err:
- werrstr("don't know how to remux %s (track type %d)", e->codec.name, e->tracktype);
-
- return -1;
-}
-
-static char *
-tracktype(Ebml *e)
-{
static char *types[] = {
- [Trackvideo] = "video",
- [Trackaudio] = "audio",
- [Trackcomplex] = "complex",
- [Tracklogo] = "logo",
- [Tracksubtitles] = "subtitle",
- [Trackbuttons] = "buttons",
- [Trackcontrol] = "control",
- [Trackmetadata] = "metadata",
+ [Etrackvideo] = "video",
+ [Etrackaudio] = "audio",
+ [Etrackcomplex] = "complex",
+ [Etracklogo] = "logo",
+ [Etracksubtitles] = "subtitle",
+ [Etrackbuttons] = "buttons",
+ [Etrackcontrol] = "control",
+ [Etrackmetadata] = "metadata",
};
- char *t;
- t = e->tracktype < nelem(types) ? types[e->tracktype] : "???";
- if(t == nil)
- t = "???";
-
- return t;
-}
-
-static void
-trackinfo(Biobuf *o, Ebml *e)
-{
- char *t;
-
- if(dflag){
- Bprint(o, "per frame: %zd\n", e->perframe);
- Bprint(o, "track number: %d\n", e->tracknum);
- Bprint(o, "track type: %d\n", e->tracktype);
- Bprint(o, "codec name: %s\n", e->codec.name);
- Bprint(o, "codec priv data: %d bytes [%.*H]\n", e->codec.priv.sz, e->codec.priv.sz, e->codec.priv.data);
- Bprint(o, "codec delay: %zdns\n", e->codec.delay);
- if(e->tracktype == Trackvideo){
- Bprint(o, "video: %dx%d [%d,%d,%d,%d]\n", e->video.width, e->video.height, e->video.crop.left, e->video.crop.top, e->video.crop.right, e->video.crop.bottom);
- Bprint(o, "display: %dx%d unit=%d aspectmode=%d\n", e->video.display.width, e->video.display.height, e->video.display.unit, e->video.display.aspectmode);
- }else if(e->tracktype == Trackaudio){
- Bprint(o, "audio: samplerate=%g, channels=%d, bps=%d\n", e->audio.samplerate, e->audio.channels, e->audio.bps);
- }
- Bprint(o, "seek pre-roll: %zd\n", e->seekpreroll);
- }
-
- t = tracktype(e);
- Bprint(o, "%d\t%s\t%s\t", e->tracknum, t, format(e));
- if(e->tracktype == 1)
- Bprint(o, "%d\t%d", e->video.width, e->video.height);
- else if(e->tracktype == 2)
- Bprint(o, "%d\t%d", e->audio.channels, (int)e->audio.samplerate);
- else if(e->tracktype == 17)
- Bprint(o, "%s", e->lang);
- else
- Bprint(o, "???");
- Bprint(o, "\n");
-}
-
-int
-ebmlrun(Biobuf *f)
-{
- int isebml, npackets, i, sti;
- vlong left, id, n, sz, bufsz, track, off, packetsz, x, endtracks;
- uvlong ts, timestamp, timestampscale;
- uchar *buf;
- double duration;
- Ebml e, te;
- Element *el;
-
- buf = nil;
- bufsz = 0;
- track = -1;
- timestamp = 0;
- left = (1ULL<<63)-1;
- endtracks = -1;
- te.tracknum = -1;
- timestampscale = 1000000;
- e.tracknum = -1;
- duration = 0;
- ts = 0;
- sti = 0;
- for(isebml = 0; left != 0;){
- if(id == EBlockDuration)
- te.blockdur *= timestampscale;
- if(endtracks > 0 && left < endtracks && trackdump == Nodump){
- /* early exit */
- left = 0;
- break;
- }
-
- off = Boffset(f);
- if((n = ebmlel(f, left, &id, &sz)) < 0){
- werrstr("invalid ebml: %r at %#zx", off);
- goto err;
- }
- while(sti > 0 && off >= stack[sti-1])
- sti--;
- left -= n;
- if(dflag > 1){
- if((el = ebmlid2elem(id)) != nil){
- for(i = 0; i < sti; i++)
- Bputc(&stderr, '\t');
- Bprint(&stderr, "%s\n", el->name);
- if(el->type == Emaster && sti < nelem(stack))
- stack[sti++] = off+n+sz;
- }
- else
- Bprint(&stderr, "%#llx\n", id);
- }
-
- if(id == EEBML){ /* EBML comes first */
- if(isebml != 0){
- werrstr("double EBML?");
- goto err;
- }
- isebml++;
- }else if(id == ESegment){
- left = sz;
- if(isebml != 1){
- werrstr("invalid ebml");
- goto err;
- }
- isebml++; /* make sure we don't see more segments */
- continue; /* go in */
- }else if(id == EInfo){ /* segment info */
- continue;
- }else if(id == ETracks){
- endtracks = left - sz; /* to skip early in case track dump not required */
- continue;
- }else if(id == ECluster){
- if(trackdump != Nodump) /* skip it entirely if no dump required */
- continue;
- }else if(id == ETrackEntry){ /* track entry */
- if(e.tracknum > 0){
- if(trackdump == Nodump)
- trackinfo(&out, &e);
- else if(trackdump == Dumpvideo && e.tracktype == Trackvideo)
- trackdump = e.tracknum;
- else if(trackdump == Dumpaudio && e.tracktype == Trackaudio)
- trackdump = e.tracknum;
- }
- if(e.tracknum == trackdump)
- memmove(&te, &e, sizeof(e));
- memset(&e, 0, sizeof(e));
- e.timestampscale = timestampscale;
- continue;
- }else if(id == EVideo || id == EAudio){
- continue;
- }else if(id == EBlockGroup && trackdump != Nodump){
- continue;
- }else if((id == ESimpleBlock || id == EBlock) && trackdump != Nodump){
- if(te.tracknum == -1)
- memmove(&te, &e, sizeof(e));
- if((n = ebmluint(f, &track, 0)) < 0){
- werrstr("block: %r");
- goto err;
- }
- left -= n;
- sz -= n;
- if(trackdump == Dumpvideo && e.tracktype == Trackvideo)
- trackdump = te.tracknum;
- else if(trackdump == Dumpaudio && e.tracktype == Trackaudio)
- trackdump = te.tracknum;
- if(track == trackdump && track == te.tracknum){
- if(te.fpacket == nil && initctx(&te, duration) != 0){
- werrstr("packet: %r");
- goto err;
- }
-
- if(bufsz < sz){
- buf = realloc(buf, sz);
- bufsz = sz;
- }
- if(Bread(f, buf, sz) != sz){
- werrstr("short read");
- goto err;
- }
- left -= sz;
- sz -= 3;
- npackets = buf[3]+1;
- switch((buf[2] >> 1) & 3){ /* lacing */
- case 0: /* none */
- packets[0].data = buf+3;
- packets[0].sz = sz;
- npackets = 1;
- break;
- case 1: /* xiph */
- sz--;
- off = 4;
- for(i = 0; i < npackets-1; i++){
- packets[i].sz = 0;
- do{
- packets[i].sz += buf[off];
- }while(buf[off++] == 0xff);
- }
- for(i = 0; i < npackets-1; i++){
- packets[i].data = buf+off;
- off += packets[i].sz;
- sz -= packets[i].sz;
- }
- packets[i].data = buf+off;
- packets[i].sz = sz;
- break;
- case 2: /* fixed-size */
- sz--;
- if((sz % npackets) != 0){
- werrstr("invalid number of frames with fixed-size lacing");
- goto err;
- }
- packets[0].sz = sz / npackets;
- for(i = 0; i < npackets; i++){
- packets[i].data = buf+4 + i*packets[0].sz;
- packets[i].sz = packets[0].sz;
- sz -= packets[0].sz;
- }
- break;
- case 3: /* ebml */
- sz--;
- packetsz = 0;
- off = 4;
- for(i = 0; i < npackets-1; i++){
- if((n = (i == 0 ? ebmluintb : ebmlsintb)(buf+off, sz, &x)) < 0)
- goto err;
- packetsz += x;
- if(packetsz < 0){
- werrstr("invalid frame size %zd", packetsz);
- goto err;
- }
- packets[i].sz = packetsz;
- off += n;
- sz -= n;
- }
- for(i = 0; i < npackets-1; i++){
- if(packets[i].sz > sz){
- werrstr("frame %d/%d out of bounds: %d > %zd", i, npackets-1, packets[i].sz, sz);
- goto err;
- }
- packets[i].data = buf+off;
- off += packets[i].sz;
- sz -= packets[i].sz;
- }
- packets[i].data = buf+off;
- packets[i].sz = sz;
- break;
- }
-
- if(te.fpacket(&out, &te, packets, npackets, ts) != 0)
- goto err;
- /* ns timestamp */
- ts = (timestamp + (s16int)(buf[0]<<8 | buf[1])) * timestampscale - te.codec.delay;
- continue;
- }
- }else{
- ebmlgetnumber(ETimestampScale, timestampscale)
- else
- ebmlgetfloat(ESamplingFrequency, e.audio.samplerate)
- else
- ebmlgetnumber(EChannels, e.audio.channels)
- else
- ebmlgetnumber(EBitDepth, e.audio.bps)
- else
- ebmlgetnumber(ETrackNumber, e.tracknum)
- else
- ebmlgetnumber(ETrackType, e.tracktype)
- else
- ebmlgetstring(ECodecID, e.codec.name)
- else
- ebmlgetbytes(ECodecPrivate, e.codec.priv)
- else
- ebmlgetnumber(ECodecDelay, e.codec.delay)
- else
- ebmlgetnumber(EPixelWidth, e.video.width)
- else
- ebmlgetnumber(EPixelHeight, e.video.height)
- else
- ebmlgetnumber(EPixelCropBottom, e.video.crop.bottom)
- else
- ebmlgetnumber(EPixelCropTop, e.video.crop.top)
- else
- ebmlgetnumber(EPixelCropLeft, e.video.crop.left)
- else
- ebmlgetnumber(EPixelCropRight, e.video.crop.right)
- else
- ebmlgetnumber(EDisplayWidth, e.video.display.width)
- else
- ebmlgetnumber(EDisplayHeight, e.video.display.height)
- else
- ebmlgetnumber(EDisplayUnit, e.video.display.unit)
- else
- ebmlgetnumber(EAspectRatioType, e.video.display.aspectmode)
- else
- ebmlgetnumber(ETimestamp, timestamp)
- else
- ebmlgetnumber(EDefaultDuration, e.perframe)
- else
- ebmlgetnumber(ESeekPreRoll, e.seekpreroll)
- else
- ebmlgetfloat(EDuration, duration)
- else
- ebmlgetnumber(ETrackUID, e.trackuid)
- else
- ebmlgetnumber(EDiscardPadding, te.discardpad)
- else
- ebmlgetnumber(EBlockDuration, te.blockdur)
- else
- ebmlgetstring(ELanguage, e.lang)
- }
-
- if(Bseek(f, sz, 1) < 0)
- return -1;
- left -= sz;
- }
-
- if(isebml == 2 && left == 0){
- if(e.tracknum > 0){
- if(trackdump == Nodump)
- trackinfo(&out, &e);
- }
- return 0;
- }
-
-err:
- return -1;
+ return t < nelem(types) ? types[t] : "???";
}
--- /dev/null
+++ b/ebml.h
@@ -1,0 +1,296 @@
+typedef struct Elspec Elspec;
+
+struct Elspec {
+ vlong id;
+ char *name;
+ int type;
+};
+
+enum {
+ /* ebml element value types */
+ Emaster,
+ Ebinary,
+ Efloat,
+ Eunsigned,
+ Esigned,
+ Eunicode,
+ Eascii = Eunicode,
+ Etimestamp,
+
+ /* known track types */
+ Etrackvideo = 1,
+ Etrackaudio = 2,
+ Etrackcomplex = 3,
+ Etracklogo = 16,
+ Etracksubtitles = 17,
+ Etrackbuttons = 18,
+ Etrackcontrol = 32,
+ Etrackmetadata = 33,
+
+ /* 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,
+};
+
+int ebmluintb(u8int *b, int sz, vlong *out);
+int ebmlsintb(u8int *b, int sz, vlong *out);
+int ebmluint(Biobuf *f, vlong *out);
+int ebmlid(Biobuf *f, vlong *out);
+vlong ebmlel(Biobuf *f, vlong sz, vlong *id, vlong *esz);
+vlong ebmlrawint(Biobuf *f, vlong sz, vlong *dst);
+char *ebmltracktype(int t);
+Elspec *ebmlelspec(vlong id);
--- a/elem.c
+++ /dev/null
@@ -1,283 +1,0 @@
-#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;
-}
--- a/elem.h
+++ /dev/null
@@ -1,279 +1,0 @@
-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/ivf.c
+++ b/ivf.c
@@ -2,6 +2,7 @@
#include <libc.h>
#include <bio.h>
#include "common.h"
+#include "packet.h"
enum {
Timedenum = 1000ULL,
--- a/main.c
+++ b/main.c
@@ -76,9 +76,9 @@
Bprint(&stderr, "seek back failed: %r\n");
status = "seek failed";
}else if(memcmp(d, "\x1a\x45\xdf\xa3", 4) == 0){
- if(ebmlrun(&f) != 0){
- Bprint(&stderr, "embl: %r\n");
- status = "ebml failed";
+ if(matroskarun(&f) != 0){
+ Bprint(&stderr, "matroska: %r\n");
+ status = "matroska failed";
}
}else if(isorun(&f) != 0){
Bprint(&stderr, "iso: %r\n");
--- /dev/null
+++ b/matroska.c
@@ -1,0 +1,445 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "common.h"
+#include "ebml.h"
+#include "packet.h"
+
+typedef struct Ebml Ebml;
+
+struct Ebml {
+ Packetctx;
+
+ packet_f fpacket;
+
+ vlong timestampscale;
+ vlong perframe;
+ int tracknum;
+ int tracktype;
+ vlong codecdelay;
+ char lang[8];
+};
+
+static Packet packets[256];
+static vlong stack[32];
+
+#define ebmlgetnumber(expid, dest) \
+ if(id == expid){ \
+ vlong x; \
+ if(ebmlrawint(f, sz, &x) < 0) \
+ return -1; \
+ dest = x; \
+ left -= sz; \
+ continue; \
+ }
+
+#define ebmlgetstring(expid, dest) \
+ if(id == expid){ \
+ n = min(sizeof(dest)-1, sz); \
+ if(Bread(f, dest, n) != n) \
+ return -1; \
+ dest[n] = 0; \
+ if(n != sz) \
+ Bseek(f, sz-n, 1); \
+ left -= sz; \
+ continue; \
+ }
+
+#define ebmlgetbytes(expid, dest) \
+ if(id == expid){ \
+ dest.data = malloc(sz); \
+ if(Bread(f, dest.data, sz) != sz) \
+ return -1; \
+ dest.sz = sz; \
+ left -= sz; \
+ continue; \
+ }
+
+#define ebmlgetfloat(expid, dest) \
+ if(id == expid){ \
+ u32int u; \
+ union { \
+ uchar b[8]; \
+ u32int u[2]; \
+ float f; \
+ double d; \
+ }x; \
+ if(sz == 4){ \
+ if(Bread(f, x.b, 4) != 4) \
+ return -1; \
+ x.u[0] = (x.u[0]&0xff000000)>>24 | (x.u[0]&0x00ff0000)>>8 | (x.u[0]&0x0000ff00)<<8 | (x.u[0]&0x000000ff)<<24; \
+ dest = x.f; \
+ }else if(sz == 8){ \
+ if(Bread(f, x.b, 8) != 8) \
+ return -1; \
+ 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; \
+ dest = x.d; \
+ }else{ \
+ werrstr("invalid float size"); \
+ break; \
+ } \
+ left -= sz; \
+ continue; \
+ }
+
+static char *
+format(Ebml *e)
+{
+ static char t[16];
+ char *s;
+ int n;
+
+ if(e->tracktype == Etracksubtitles){
+ if(strcmp(e->codec.name, "S_TEXT/UTF8") == 0)
+ return "srt";
+ }else if(e->tracktype == Etrackaudio){
+ if(strcmp(e->codec.name, "A_MPEG/L3") == 0)
+ return "mp3";
+ }else if(e->tracktype == Etrackvideo){
+ if(strcmp(e->codec.name, "V_MPEG4/ISO/AVC") == 0)
+ return "h264";
+ }
+
+ n = snprint(t, sizeof(t), "%s", e->codec.name+2);
+ for(n -= 1; n >= 0; n--)
+ t[n] = tolower(t[n]);
+ if((s = strchr(t, '/')) != nil)
+ *s = 0;
+
+ return t;
+}
+
+static int
+asispacket(Biobuf *out, Packetctx *, Packet *p, int np, uvlong)
+{
+ int i;
+
+ for(i = 0; i < np; i++, p++)
+ Bwrite(out, p->data, p->sz);
+
+ return 0;
+}
+
+static int
+initctx(Ebml *e, double duration)
+{
+ char *c;
+
+ e->duration = duration;
+ e->duration *= e->timestampscale;
+ c = format(e);
+ if(e->tracktype == Etrackvideo){
+ if(strcmp(c, "vp9") == 0)
+ e->fmt = FmtVp09;
+ else if(strcmp(c, "vp8") == 0)
+ e->fmt = FmtVp08;
+ else if(strcmp(c, "h264") == 0)
+ e->fmt = FmtAvc1;
+ else
+ goto err;
+ e->fpacket = ivfpacket;
+ return 0;
+ }else if(e->tracktype == Etrackaudio){
+ if(strcmp(c, "vorbis") == 0){
+ e->fmt = FmtVorbis;
+ e->fpacket = oggpacket;
+ }else if(strcmp(c, "opus") == 0){
+ e->fmt = FmtOpus;
+ e->fpacket = oggpacket;
+ }else if(strcmp(c, "mp3") == 0){
+ e->fmt = FmtMp3;
+ e->fpacket = asispacket;
+ }else if(strcmp(c, "aac") == 0){
+ e->fmt = FmtMp4a;
+ e->fpacket = aacpacket;
+ }else
+ goto err;
+ return 0;
+ }else if(e->tracktype == Etracksubtitles){
+ if(strcmp(c, "srt") == 0){
+ e->fmt = FmtSrt;
+ e->fpacket = srtpacket;
+ }else
+ goto err;
+ return 0;
+ }
+
+err:
+ werrstr("don't know how to remux %s (track type %d)", e->codec.name, e->tracktype);
+
+ return -1;
+}
+
+static void
+trackinfo(Biobuf *o, Ebml *e)
+{
+ char *t;
+
+ t = ebmltracktype(e->tracktype);
+ Bprint(o, "%d\t%s\t%s\t", e->tracknum, t, format(e));
+ if(e->tracktype == Etrackvideo)
+ Bprint(o, "%d\t%d", e->video.width, e->video.height);
+ else if(e->tracktype == Etrackaudio)
+ Bprint(o, "%d\t%d", e->audio.channels, (int)e->audio.samplerate);
+ else if(e->tracktype == Etracksubtitles)
+ Bprint(o, "%s", e->lang);
+ else
+ Bprint(o, "???");
+ Bprint(o, "\n");
+}
+
+int
+matroskarun(Biobuf *f)
+{
+ int isebml, npackets, i, sti, skipdata;
+ vlong left, id, n, sz, bufsz, track, off, packetsz, x, endtracks;
+ uvlong ts, timestamp, timestampscale;
+ uchar *buf;
+ double duration;
+ Ebml e, te;
+ Elspec *el;
+
+ buf = nil;
+ bufsz = 0;
+ track = -1;
+ timestamp = 0;
+ left = (1ULL<<63)-1;
+ endtracks = -1;
+ te.tracknum = -1;
+ timestampscale = 1000000;
+ e.tracknum = -1;
+ duration = 0;
+ ts = 0;
+ sti = 0;
+ skipdata = trackdump == Nodump && dflag < 2;
+ for(isebml = 0; left != 0;){
+ if(id == EBlockDuration)
+ te.blockdur *= timestampscale;
+ if(endtracks > 0 && left < endtracks && skipdata){
+ /* early exit */
+ left = 0;
+ break;
+ }
+
+ off = Boffset(f);
+ if((n = ebmlel(f, left, &id, &sz)) < 0){
+ werrstr("invalid ebml: %r at %#zx (size %zd)", off, sz);
+ goto err;
+ }
+ if(n == 0) /* eof */
+ break;
+ while(sti > 0 && off >= stack[sti-1])
+ sti--;
+ left -= n;
+ if(dflag > 1){
+ if((el = ebmlelspec(id)) != nil){
+ for(i = 0; i < sti; i++)
+ Bputc(&stderr, '\t');
+ Bprint(&stderr, "%s\n", el->name);
+ if(el->type == Emaster && sti < nelem(stack))
+ stack[sti++] = off+n+sz;
+ }
+ else
+ Bprint(&stderr, "%#llx\n", id);
+ }
+
+ if(id == EEBML){ /* EBML comes first */
+ if(isebml != 0){
+ werrstr("double EBML?");
+ goto err;
+ }
+ isebml++;
+ }else if(id == ESegment){
+ left = sz;
+ if(isebml != 1){
+ werrstr("invalid ebml");
+ goto err;
+ }
+ isebml++; /* make sure we don't see more segments */
+ continue; /* go in */
+ }else if(id == EInfo){ /* segment info */
+ continue;
+ }else if(id == ETracks){
+ endtracks = left - sz; /* to skip early in case track dump not required */
+ continue;
+ }else if(id == ECluster){
+ if(!skipdata) /* skip it entirely if no dump required */
+ continue;
+ }else if(id == ETrackEntry){ /* track entry */
+ if(e.tracknum > 0){
+ if(trackdump == Nodump)
+ trackinfo(&out, &e);
+ else if(trackdump == Dumpvideo && e.tracktype == Etrackvideo)
+ trackdump = e.tracknum;
+ else if(trackdump == Dumpaudio && e.tracktype == Etrackaudio)
+ trackdump = e.tracknum;
+ }
+ if(e.tracknum == trackdump)
+ memmove(&te, &e, sizeof(e));
+ memset(&e, 0, sizeof(e));
+ e.timestampscale = timestampscale;
+ continue;
+ }else if(id == EVideo || id == EAudio){
+ continue;
+ }else if(id == EBlockGroup && !skipdata){
+ continue;
+ }else if((id == ESimpleBlock || id == EBlock) && !skipdata){
+ if(te.tracknum == -1)
+ memmove(&te, &e, sizeof(e));
+ if((n = ebmluint(f, &track)) < 0){
+ werrstr("block: %r");
+ goto err;
+ }
+ left -= n;
+ sz -= n;
+ if(trackdump == Dumpvideo && e.tracktype == Etrackvideo)
+ trackdump = te.tracknum;
+ else if(trackdump == Dumpaudio && e.tracktype == Etrackaudio)
+ trackdump = te.tracknum;
+ if(track == trackdump && track == te.tracknum){
+ if(te.fpacket == nil && initctx(&te, duration) != 0){
+ werrstr("packet: %r");
+ goto err;
+ }
+
+ if(bufsz < sz){
+ buf = realloc(buf, sz);
+ bufsz = sz;
+ }
+ if(Bread(f, buf, sz) != sz){
+ werrstr("short read");
+ goto err;
+ }
+ left -= sz;
+ sz -= 3;
+ npackets = buf[3]+1;
+ switch((buf[2] >> 1) & 3){ /* lacing */
+ case 0: /* none */
+ packets[0].data = buf+3;
+ packets[0].sz = sz;
+ npackets = 1;
+ break;
+ case 1: /* xiph */
+ sz--;
+ off = 4;
+ for(i = 0; i < npackets-1; i++){
+ packets[i].sz = 0;
+ do{
+ packets[i].sz += buf[off];
+ }while(buf[off++] == 0xff);
+ }
+ for(i = 0; i < npackets-1; i++){
+ packets[i].data = buf+off;
+ off += packets[i].sz;
+ sz -= packets[i].sz;
+ }
+ packets[i].data = buf+off;
+ packets[i].sz = sz;
+ break;
+ case 2: /* fixed-size */
+ sz--;
+ if((sz % npackets) != 0){
+ werrstr("invalid number of frames with fixed-size lacing");
+ goto err;
+ }
+ packets[0].sz = sz / npackets;
+ for(i = 0; i < npackets; i++){
+ packets[i].data = buf+4 + i*packets[0].sz;
+ packets[i].sz = packets[0].sz;
+ sz -= packets[0].sz;
+ }
+ break;
+ case 3: /* ebml */
+ sz--;
+ packetsz = 0;
+ off = 4;
+ for(i = 0; i < npackets-1; i++){
+ if((n = (i == 0 ? ebmluintb : ebmlsintb)(buf+off, sz, &x)) < 0)
+ goto err;
+ packetsz += x;
+ if(packetsz < 0){
+ werrstr("invalid frame size %zd", packetsz);
+ goto err;
+ }
+ packets[i].sz = packetsz;
+ off += n;
+ sz -= n;
+ }
+ for(i = 0; i < npackets-1; i++){
+ if(packets[i].sz > sz){
+ werrstr("frame %d/%d out of bounds: %d > %zd", i, npackets-1, packets[i].sz, sz);
+ goto err;
+ }
+ packets[i].data = buf+off;
+ off += packets[i].sz;
+ sz -= packets[i].sz;
+ }
+ packets[i].data = buf+off;
+ packets[i].sz = sz;
+ break;
+ }
+
+ if(te.fpacket(&out, &te, packets, npackets, ts) != 0)
+ goto err;
+ /* ns timestamp */
+ ts = (timestamp + (s16int)(buf[0]<<8 | buf[1])) * timestampscale - te.codec.delay;
+ continue;
+ }
+ }else{
+ ebmlgetnumber(ETimestampScale, timestampscale)
+ else
+ ebmlgetfloat(ESamplingFrequency, e.audio.samplerate)
+ else
+ ebmlgetnumber(EChannels, e.audio.channels)
+ else
+ ebmlgetnumber(EBitDepth, e.audio.bps)
+ else
+ ebmlgetnumber(ETrackNumber, e.tracknum)
+ else
+ ebmlgetnumber(ETrackType, e.tracktype)
+ else
+ ebmlgetstring(ECodecID, e.codec.name)
+ else
+ ebmlgetbytes(ECodecPrivate, e.codec.priv)
+ else
+ ebmlgetnumber(ECodecDelay, e.codec.delay)
+ else
+ ebmlgetnumber(EPixelWidth, e.video.width)
+ else
+ ebmlgetnumber(EPixelHeight, e.video.height)
+ else
+ ebmlgetnumber(ETimestamp, timestamp)
+ else
+ ebmlgetnumber(EDefaultDuration, e.perframe)
+ else
+ ebmlgetnumber(ESeekPreRoll, e.seekpreroll)
+ else
+ ebmlgetfloat(EDuration, duration)
+ else
+ ebmlgetnumber(ETrackUID, e.trackuid)
+ else
+ ebmlgetnumber(EDiscardPadding, te.discardpad)
+ else
+ ebmlgetnumber(EBlockDuration, te.blockdur)
+ else
+ ebmlgetstring(ELanguage, e.lang)
+ }
+
+ if(Bseek(f, sz, 1) < 0)
+ return -1;
+ left -= sz;
+ }
+
+ if(isebml == 2 && left == 0){
+ if(e.tracknum > 0){
+ if(trackdump == Nodump)
+ trackinfo(&out, &e);
+ }
+ return 0;
+ }
+
+err:
+ return -1;
+}
--- a/mkfile
+++ b/mkfile
@@ -6,17 +6,19 @@
BIN=/$objtype/bin
OFILES=\
+ aac.$O\
crc32.$O\
ebml.$O\
- elem.$O\
iso.$O\
ivf.$O\
main.$O\
+ matroska.$O\
ogg.$O\
srt.$O\
HFILES=\
common.h\
+ ebml.h\
default:V: all
--- a/ogg.c
+++ b/ogg.c
@@ -2,6 +2,7 @@
#include <libc.h>
#include <bio.h>
#include "common.h"
+#include "packet.h"
static int
packet(Biobuf *out, Packetctx *ctx, int htype, Packet *p, int np, uvlong granule)
--- /dev/null
+++ b/packet.h
@@ -1,0 +1,42 @@
+typedef struct Packet Packet;
+typedef struct Packetctx Packetctx;
+
+typedef int (*packet_f)(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
+
+struct Packet {
+ uchar *data;
+ int sz;
+};
+
+struct Packetctx {
+ uvlong frid;
+ uvlong duration;
+ uvlong seekpreroll;
+ vlong discardpad;
+ vlong blockdur;
+ struct {
+ char name[16];
+ vlong delay;
+ struct {
+ uchar *data;
+ int sz;
+ }priv;
+ }codec;
+ u32int trackuid;
+ u32int fmt;
+
+ struct {
+ int width;
+ int height;
+ }video;
+ struct {
+ float samplerate;
+ int channels;
+ int bps;
+ }audio;
+};
+
+int aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
+int ivfpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
+int oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
+int srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
--- a/srt.c
+++ b/srt.c
@@ -2,6 +2,7 @@
#include <libc.h>
#include <bio.h>
#include "common.h"
+#include "packet.h"
enum {
Timedenum = 1000ULL,