aboutsummaryrefslogtreecommitdiff
path: root/ebml/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-01-14 11:36:57 +0100
committermetamuffin <metamuffin@disroot.org>2023-01-14 11:36:57 +0100
commit6c023ddeaa0894813fc74038af7568c2d867c052 (patch)
tree3d323c62fa8a6c2a7827d15061843fce8a7418f0 /ebml/src
parent855a8896175ee45a3376775203fa20e629d809b3 (diff)
downloadjellything-6c023ddeaa0894813fc74038af7568c2d867c052.tar
jellything-6c023ddeaa0894813fc74038af7568c2d867c052.tar.bz2
jellything-6c023ddeaa0894813fc74038af7568c2d867c052.tar.zst
parsing should work
Diffstat (limited to 'ebml/src')
-rw-r--r--ebml/src/bin/experiment.rs4
-rw-r--r--ebml/src/lib.rs45
-rw-r--r--ebml/src/matroska.rs439
-rw-r--r--ebml/src/read.rs86
4 files changed, 341 insertions, 233 deletions
diff --git a/ebml/src/bin/experiment.rs b/ebml/src/bin/experiment.rs
index 13b6895..c510bb5 100644
--- a/ebml/src/bin/experiment.rs
+++ b/ebml/src/bin/experiment.rs
@@ -6,7 +6,7 @@ fn main() {
let f = File::open(std::env::args().skip(1).next().unwrap()).unwrap();
let mut r = EbmlReader::new(BufReader::new(f));
- loop {
- println!("{:?}", r.read_tag());
+ for tag in r {
+ println!("{:?}", tag);
}
}
diff --git a/ebml/src/lib.rs b/ebml/src/lib.rs
index 7445bbc..22af473 100644
--- a/ebml/src/lib.rs
+++ b/ebml/src/lib.rs
@@ -16,13 +16,6 @@ pub trait ValueFromBuf: Sized {
impl ValueFromBuf for u64 {
fn from_buf(buf: &[u8]) -> anyhow::Result<Self> {
- // if buf.len() != 8 {
- // bail!("u64 is not 64 bits long")
- // }
- // Ok((buf[0] as u64) << 24
- // | (buf[1] as u64) << 16
- // | (buf[2] as u64) << 8
- // | (buf[3] as u64) << 0)
if buf.len() > 8 {
bail!("u64 too big")
}
@@ -34,6 +27,34 @@ impl ValueFromBuf for u64 {
Ok(val)
}
}
+impl ValueFromBuf for i64 {
+ fn from_buf(buf: &[u8]) -> anyhow::Result<Self> {
+ if buf.len() > 8 {
+ bail!("i64 too big")
+ }
+ Ok(if buf[0] > 127 {
+ if buf.len() == 8 {
+ i64::from_be_bytes(buf.try_into().unwrap())
+ } else {
+ -((1 << (buf.len() * 8)) - (u64::from_buf(buf)? as i64))
+ }
+ } else {
+ u64::from_buf(buf)? as i64
+ })
+ }
+}
+impl ValueFromBuf for f64 {
+ fn from_buf(buf: &[u8]) -> anyhow::Result<Self> {
+ Ok(if buf.len() == 4 {
+ f32::from_be_bytes(buf.try_into().unwrap()) as f64
+ } else if buf.len() == 8 {
+ f64::from_be_bytes(buf.try_into().unwrap())
+ } else {
+ bail!("float is not 4 or 8 bytes long");
+ })
+ }
+}
+
impl ValueFromBuf for Vec<u8> {
fn from_buf(buf: &[u8]) -> anyhow::Result<Self> {
Ok(buf.to_vec())
@@ -44,3 +65,13 @@ impl ValueFromBuf for String {
Ok(String::from_utf8(Vec::from(buf))?)
}
}
+impl ValueFromBuf for Master {
+ /// this has an internal usage, where buf has len of 1, when an end should be constructed
+ fn from_buf(buf: &[u8]) -> anyhow::Result<Self> {
+ Ok(match buf.len() {
+ 0 => Master::Start,
+ 1 => Master::End,
+ _ => unreachable!(),
+ })
+ }
+}
diff --git a/ebml/src/matroska.rs b/ebml/src/matroska.rs
index c9198bb..9678e80 100644
--- a/ebml/src/matroska.rs
+++ b/ebml/src/matroska.rs
@@ -31,6 +31,7 @@ define_ebml! {
FileUsedStartTime[0x4661]: Uint,
},
},
+
Chapters[0x1043A770]: {
EditionEntry[0x45B9]: {
ChapPterAtom[0xB6]: {
@@ -69,259 +70,259 @@ define_ebml! {
},
Cluster[0x1F43B675]: {
- #[id=0xA0] BlockGroup: {
- #[id=0xA1] Block(Binary),
- #[id=0x75A1] BlockAdditions: {
- #[id=0xA6] BlockMore: {
- #[id=0xEE] BlockAddID(Uint),
- #[id=0xA5] BlockAdditional(Binary),
+ BlockGroup[0xA0]: {
+ Block[0xA1]: Binary,
+ BlockAdditions[0x75A1]: {
+ BlockMore[0xA6]: {
+ BlockAddID[0xEE]: Uint,
+ BlockAdditional[0xA5]: Binary,
},
},
- #[id=0x9B] BlockDuration(Uint),
- #[id=0xA2] BlockVirtual(Binary),
- #[id=0xA4] CodecState(Binary),
- #[id=0x75A2] DiscardPadding(Integer),
- #[id=0xFB] ReferenceBlock(Integer),
- #[id=0xC8] ReferenceFrame: {
- #[id=0xC9] ReferenceOffset(Uint),
- #[id=0xCA] ReferenceTimestamp(Uint),
+ BlockDuration[0x9B]: Uint,
+ BlockVirtual[0xA2]: Binary,
+ CodecState[0xA4]: Binary,
+ DiscardPadding[0x75A2]: Int,
+ ReferenceBlock[0xFB]: Int,
+ ReferenceFrame[0xC8]: {
+ ReferenceOffset[0xC9]: Uint,
+ ReferenceTimestamp[0xCA]: Uint,
},
- #[id=0xFA] ReferencePriority(Uint),
- #[id=0xFD] ReferenceVirtual(Integer),
- #[id=0x8E] Slices: {
- #[id=0xE8] TimeSlice: {
- #[id=0xCB] BlockAdditionID(Uint),
- #[id=0xCE] Delay(Uint),
- #[id=0xCD] FrameNumber(Uint),
- #[id=0xCC] LaceNumber(Uint),
- #[id=0xCF] SliceDuration(Uint),
+ ReferencePriority[0xFA]: Uint,
+ ReferenceVirtual[0xFD]: Int,
+ Slices[0x8E]: {
+ TimeSlice[0xE8]: {
+ BlockAdditionID[0xCB]: Uint,
+ Delay[0xCE]: Uint,
+ FrameNumber[0xCD]: Uint,
+ LaceNumber[0xCC]: Uint,
+ SliceDuration[0xCF]: Uint,
},
},
},
- #[id=0xAF] EncryptedBlock(Binary),
- #[id=0xA7] Position(Uint),
- #[id=0xAB] PrevSize(Uint),
- #[id=0x5854] SilentTracks: {
- #[id=0x58D7] SilentTrackNumber(Uint),
+ EncryptedBlock[0xAF]: Binary,
+ Position[0xA7]: Uint,
+ PrevSize[0xAB]: Uint,
+ SilentTracks[0x5854]: {
+ SilentTrackNumber[0x58D7]: Uint,
},
- #[id=0xA3] SimpleBlock(Binary),
- #[id=0xE7] Timestamp(Uint),
- }
+ SimpleBlock[0xA3]: Binary,
+ Timestamp[0xE7]: Uint,
+ },
- #[id=0x1C53BB6B] Cues: {
- #[id=0xBB] CuePoint: {
- #[id=0xB3] CueTime(Uint),
- #[id=0xB7] CueTrackPositions: {
- #[id=0x5378] CueBlockNumber(Uint),
- #[id=0xF1] CueClusterPosition(Uint),
- #[id=0xEA] CueCodecState(Uint),
- #[id=0xB2] CueDuration(Uint),
- #[id=0xDB] CueReference: {
- #[id=0x97] CueRefCluster(Uint),
- #[id=0xEB] CueRefCodecState(Uint),
- #[id=0x535F] CueRefNumber(Uint),
- #[id=0x96] CueRefTime(Uint),
+ Cues[0x1C53BB6B]: {
+ CuePoint[0xBB]: {
+ CueTime[0xB3]: Uint,
+ CueTrackPositions[0xB7]: {
+ CueBlockNumber[0x5378]: Uint,
+ CueClusterPosition[0xF1]: Uint,
+ CueCodecState[0xEA]: Uint,
+ CueDuration[0xB2]: Uint,
+ CueReference[0xDB]: {
+ CueRefCluster[0x97]: Uint,
+ CueRefCodecState[0xEB]: Uint,
+ CueRefNumber[0x535F]: Uint,
+ CueRefTime[0x96]: Uint,
},
- #[id=0xF0] CueRelativePosition(Uint),
- #[id=0xF7] CueTrack(Uint),
+ CueRelativePosition[0xF0]: Uint,
+ CueTrack[0xF7]: Uint,
},
},
},
- #[id=0x1549A966] Info: {
- #[id=0x6924] ChapterTranslate: {
- #[id=0x69BF] ChapterTranslateCodec(Uint),
- #[id=0x69FC] ChapterTranslateEditionUID(Uint),
- #[id=0x69A5] ChapterTranslateID(Binary),
- }
- #[id=0x4461] DateUTC(Integer),
- #[id=0x4489] Duration(Float),
- #[id=0x4D80] MuxingApp(Utf8),
- #[id=0x3E83BB] NextFilename(Utf8),
- #[id=0x3EB923] NextUID(Binary),
- #[id=0x3C83AB] PrevFilename(Utf8),
- #[id=0x3CB923] PrevUID(Binary),
- #[id=0x4444] SegmentFamily(Binary),
- #[id=0x7384] SegmentFilename(Utf8),
- #[id=0x73A4] SegmentUID(Binary),
- #[id=0x2AD7B1] TimestampScale(Uint),
- #[id=0x7BA9] Title(Utf8),
- #[id=0x5741] WritingApp(Utf8),
+ Info[0x1549A966]: {
+ ChapterTranslate[0x6924]: {
+ ChapterTranslateCodec[0x69BF]: Uint,
+ ChapterTranslateEditionUID[0x69FC]: Uint,
+ ChapterTranslateID[0x69A5]: Binary,
+ },
+ DateUTC[0x4461]: Int,
+ Duration[0x4489]: Float,
+ MuxingApp[0x4D80]: Utf8,
+ NextFilename[0x3E83BB]: Utf8,
+ NextUID[0x3EB923]: Binary,
+ PrevFilename[0x3C83AB]: Utf8,
+ PrevUID[0x3CB923]: Binary,
+ SegmentFamily[0x4444]: Binary,
+ SegmentFilename[0x7384]: Utf8,
+ SegmentUID[0x73A4]: Binary,
+ TimestampScale[0x2AD7B1]: Uint,
+ Title[0x7BA9]: Utf8,
+ WritingApp[0x5741]: Utf8,
},
- #[id=0x114D9B74] SeekHead: {
- #[id=0x4DBB] Seek: {
- #[id=0x53AB] SeekID(Binary),
- #[id=0x53AC] SeekPosition(Uint),
+ SeekHead[0x114D9B74]: {
+ Seek[0x4DBB]: {
+ SeekID[0x53AB]: Binary,
+ SeekPosition[0x53AC]: Uint,
},
},
- #[id=0x1254C367] Tags: {
- #[id=0x7373] Tag: {
- #[id=0x67C8] SimpleTag: {
- #[id=0x4485] TagBinary(Binary),
- #[id=0x4484] TagDefault(Uint),
- #[id=0x44B4] TagDefaultBogus(Uint),
- #[id=0x447A] TagLanguage(Utf8),
- #[id=0x447B] TagLanguageIETF(Utf8),
- #[id=0x45A3] TagName(Utf8),
- #[id=0x4487] TagString(Utf8),
+ Tags[0x1254C367]: {
+ Tag[0x7373]: {
+ SimpleTag[0x67C8]: {
+ TagBinary[0x4485]: Binary,
+ TagDefault[0x4484]: Uint,
+ TagDefaultBogus[0x44B4]: Uint,
+ TagLanguage[0x447A]: Utf8,
+ TagLanguageIETF[0x447B]: Utf8,
+ TagName[0x45A3]: Utf8,
+ TagString[0x4487]: Utf8,
},
- #[id=0x63C0] Targets: {
- #[id=0x63C6] TagAttachmentUID(Uint),
- #[id=0x63C4] TagChapterUID(Uint),
- #[id=0x63C9] TagEditionUID(Uint),
- #[id=0x63C5] TagTrackUID(Uint),
- #[id=0x63CA] TargetType(Utf8),
- #[id=0x68CA] TargetTypeValue(Uint),
+ Targets[0x63C0]: {
+ TagAttachmentUID[0x63C6]: Uint,
+ TagChapterUID[0x63C4]: Uint,
+ TagEditionUID[0x63C9]: Uint,
+ TagTrackUID[0x63C5]: Uint,
+ TargetType[0x63CA]: Utf8,
+ TargetTypeValue[0x68CA]: Uint,
},
},
},
- #[id=0x1654AE6B] Tracks: {
- #[id=0xAE] TrackEntry: {
- #[id=0x7446] AttachmentLink(Uint),
- #[id=0xE1] Audio: {
- #[id=0x6264] BitDepth(Uint),
- #[id=0x7D7B] ChannelPositions(Binary),
- #[id=0x9F] Channels(Uint),
- #[id=0x78B5] OutputSamplingFrequency(Float),
- #[id=0xB5] SamplingFrequency(Float),
- }
- #[id=0x41E4] BlockAdditionMapping: {
- #[id=0x41ED] BlockAddIDExtraData(Binary),
- #[id=0x41A4] BlockAddIDName(Utf8),
- #[id=0x41E7] BlockAddIDType(Uint),
- #[id=0x41F0] BlockAddIDValue(Uint),
- }
- #[id=0xAA] CodecDecodeAll(Uint),
- #[id=0x56AA] CodecDelay(Uint),
- #[id=0x26B240] CodecDownloadURL(Utf8),
- #[id=0x86] CodecID(Utf8),
- #[id=0x3B4040] CodecInfoURL(Utf8),
- #[id=0x258688] CodecName(Utf8),
- #[id=0x63A2] CodecPrivate(Binary),
- #[id=0x3A9697] CodecSettings(Utf8),
- #[id=0x6D80] ContentEncodings: {
- #[id=0x6240] ContentEncoding: {
- #[id=0x5034] ContentCompression: {
- #[id=0x4254] ContentCompAlgo(Uint),
- #[id=0x4255] ContentCompSettings(Binary),
+ Tracks[0x1654AE6B]: {
+ TrackEntry[0xAE]: {
+ AttachmentLink[0x7446]: Uint,
+ Audio[0xE1]: {
+ BitDepth[0x6264]: Uint,
+ ChannelPositions[0x7D7B]: Binary,
+ Channels[0x9F]: Uint,
+ OutputSamplingFrequency[0x78B5]: Float,
+ SamplingFrequency[0xB5]: Float,
+ },
+ BlockAdditionMapping[0x41E4]: {
+ BlockAddIDExtraData[0x41ED]: Binary,
+ BlockAddIDName[0x41A4]: Utf8,
+ BlockAddIDType[0x41E7]: Uint,
+ BlockAddIDValue[0x41F0]: Uint,
+ },
+ CodecDecodeAll[0xAA]: Uint,
+ CodecDelay[0x56AA]: Uint,
+ CodecDownloadURL[0x26B240]: Utf8,
+ CodecID[0x86]: Utf8,
+ CodecInfoURL[0x3B4040]: Utf8,
+ CodecName[0x258688]: Utf8,
+ CodecPrivate[0x63A2]: Binary,
+ CodecSettings[0x3A9697]: Utf8,
+ ContentEncodings[0x6D80]: {
+ ContentEncoding[0x6240]: {
+ ContentCompression[0x5034]: {
+ ContentCompAlgo[0x4254]: Uint,
+ ContentCompSettings[0x4255]: Binary,
},
- #[id=0x5031] ContentEncodingOrder(Uint),
- #[id=0x5032] ContentEncodingScope(Uint),
- #[id=0x5033] ContentEncodingType(Uint),
- #[id=0x5035] ContentEncryption: {
- #[id=0x47E7] ContentEncAESSettings: {
- #[id=0x47E8] AESSettingsCipherMode(Uint),
- }
- #[id=0x47E1] ContentEncAlgo(Uint),
- #[id=0x47E2] ContentEncKeyID(Binary),
- #[id=0x47E5] ContentSigAlgo(Uint),
- #[id=0x47E6] ContentSigHashAlgo(Uint),
- #[id=0x47E4] ContentSigKeyID(Binary),
- #[id=0x47E3] ContentSignature(Binary),
+ ContentEncodingOrder[0x5031]: Uint,
+ ContentEncodingScope[0x5032]: Uint,
+ ContentEncodingType[0x5033]: Uint,
+ ContentEncryption[0x5035]: {
+ ContentEncAESSettings[0x47E7]: {
+ AESSettingsCipherMode[0x47E8]: Uint,
+ },
+ ContentEncAlgo[0x47E1]: Uint,
+ ContentEncKeyID[0x47E2]: Binary,
+ ContentSigAlgo[0x47E5]: Uint,
+ ContentSigHashAlgo[0x47E6]: Uint,
+ ContentSigKeyID[0x47E4]: Binary,
+ ContentSignature[0x47E3]: Binary,
},
},
},
- #[id=0x234E7A] DefaultDecodedFieldDuration(Uint),
- #[id=0x23E383] DefaultDuration(Uint),
- #[id=0x55AF] FlagCommentary(Uint),
- #[id=0x88] FlagDefault(Uint),
- #[id=0xB9] FlagEnabled(Uint),
- #[id=0x55AA] FlagForced(Uint),
- #[id=0x55AB] FlagHearingImpaired(Uint),
- #[id=0x9C] FlagLacing(Uint),
- #[id=0x55AE] FlagOriginal(Uint),
- #[id=0x55AD] FlagTextDescriptions(Uint),
- #[id=0x55AC] FlagVisualImpaired(Uint),
- #[id=0x22B59C] Language(Utf8),
- #[id=0x22B59D] LanguageIETF(Utf8),
- #[id=0x55EE] MaxBlockAdditionID(Uint),
- #[id=0x6DF8] MaxCache(Uint),
- #[id=0x6DE7] MinCache(Uint),
- #[id=0x536E] Name(Utf8),
- #[id=0x56BB] SeekPreRoll(Uint),
- #[id=0xD7] TrackNumber(Uint),
- #[id=0x537F] TrackOffset(Integer),
- #[id=0xE2] TrackOperation: {
- #[id=0xE3] TrackCombinePlanes: {
- #[id=0xE4] TrackPlane: {
- #[id=0xE6] TrackPlaneType(Uint),
- #[id=0xE5] TrackPlaneUID(Uint),
+ DefaultDecodedFieldDuration[0x234E7A]: Uint,
+ DefaultDuration[0x23E383]: Uint,
+ FlagCommentary[0x55AF]: Uint,
+ FlagDefault[0x88]: Uint,
+ FlagEnabled[0xB9]: Uint,
+ FlagForced[0x55AA]: Uint,
+ FlagHearingImpaired[0x55AB]: Uint,
+ FlagLacing[0x9C]: Uint,
+ FlagOriginal[0x55AE]: Uint,
+ FlagTextDescriptions[0x55AD]: Uint,
+ FlagVisualImpaired[0x55AC]: Uint,
+ Language[0x22B59C]: Utf8,
+ LanguageIETF[0x22B59D]: Utf8,
+ MaxBlockAdditionID[0x55EE]: Uint,
+ MaxCache[0x6DF8]: Uint,
+ MinCache[0x6DE7]: Uint,
+ Name[0x536E]: Utf8,
+ SeekPreRoll[0x56BB]: Uint,
+ TrackNumber[0xD7]: Uint,
+ TrackOffset[0x537F]: Int,
+ TrackOperation[0xE2]: {
+ TrackCombinePlanes[0xE3]: {
+ TrackPlane[0xE4]: {
+ TrackPlaneType[0xE6]: Uint,
+ TrackPlaneUID[0xE5]: Uint,
},
},
- #[id=0xE9] TrackJoinBlocks: {
- #[id=0xED] TrackJoinUID(Uint),
+ TrackJoinBlocks[0xE9]: {
+ TrackJoinUID[0xED]: Uint,
},
- }
- #[id=0x6FAB] TrackOverlay(Uint),
- #[id=0x23314F] TrackTimestampScale(Float),
- #[id=0x6624] TrackTranslate: {
- #[id=0x66BF] TrackTranslateCodec(Uint),
- #[id=0x66FC] TrackTranslateEditionUID(Uint),
- #[id=0x66A5] TrackTranslateTrackID(Binary),
},
- #[id=0x83] TrackType(Uint),
- #[id=0x73C5] TrackUID(Uint),
- #[id=0xC4] TrickMasterTrackSegmentUID(Binary),
- #[id=0xC7] TrickMasterTrackUID(Uint),
- #[id=0xC6] TrickTrackFlag(Uint),
- #[id=0xC1] TrickTrackSegmentUID(Binary),
- #[id=0xC0] TrickTrackUID(Uint),
- #[id=0xE0] Video: {
- #[id=0x53C0] AlphaMode(Uint),
- #[id=0x54B3] AspectRatioType(Uint),
- #[id=0x55B0] Colour: {
- #[id=0x55B2] BitsPerChannel(Uint),
- #[id=0x55B5] CbSubsamplingHorz(Uint),
- #[id=0x55B6] CbSubsamplingVert(Uint),
- #[id=0x55B7] ChromaSitingHorz(Uint),
- #[id=0x55B8] ChromaSitingVert(Uint),
- #[id=0x55B3] ChromaSubsamplingHorz(Uint),
- #[id=0x55B4] ChromaSubsamplingVert(Uint),
- #[id=0x55D0] MasteringMetadata: {
- #[id=0x55D9] LuminanceMax(Float),
- #[id=0x55DA] LuminanceMin(Float),
- #[id=0x55D5] PrimaryBChromaticityX(Float),
- #[id=0x55D6] PrimaryBChromaticityY(Float),
- #[id=0x55D3] PrimaryGChromaticityX(Float),
- #[id=0x55D4] PrimaryGChromaticityY(Float),
- #[id=0x55D1] PrimaryRChromaticityX(Float),
- #[id=0x55D2] PrimaryRChromaticityY(Float),
- #[id=0x55D7] WhitePointChromaticityX(Float),
- #[id=0x55D8] WhitePointChromaticityY(Float),
+ TrackOverlay[0x6FAB]: Uint,
+ TrackTimestampScale[0x23314F]: Float,
+ TrackTranslate[0x6624]: {
+ TrackTranslateCodec[0x66BF]: Uint,
+ TrackTranslateEditionUID[0x66FC]: Uint,
+ TrackTranslateTrackID[0x66A5]: Binary,
+ },
+ TrackType[0x83]: Uint,
+ TrackUID[0x73C5]: Uint,
+ TrickMasterTrackSegmentUID[0xC4]: Binary,
+ TrickMasterTrackUID[0xC7]: Uint,
+ TrickTrackFlag[0xC6]: Uint,
+ TrickTrackSegmentUID[0xC1]: Binary,
+ TrickTrackUID[0xC0]: Uint,
+ Video[0xE0]: {
+ AlphaMode[0x53C0]: Uint,
+ AspectRatioType[0x54B3]: Uint,
+ Colour[0x55B0]: {
+ BitsPerChannel[0x55B2]: Uint,
+ CbSubsamplingHorz[0x55B5]: Uint,
+ CbSubsamplingVert[0x55B6]: Uint,
+ ChromaSitingHorz[0x55B7]: Uint,
+ ChromaSitingVert[0x55B8]: Uint,
+ ChromaSubsamplingHorz[0x55B3]: Uint,
+ ChromaSubsamplingVert[0x55B4]: Uint,
+ MasteringMetadata[0x55D0]: {
+ LuminanceMax[0x55D9]: Float,
+ LuminanceMin[0x55DA]: Float,
+ PrimaryBChromaticityX[0x55D5]: Float,
+ PrimaryBChromaticityY[0x55D6]: Float,
+ PrimaryGChromaticityX[0x55D3]: Float,
+ PrimaryGChromaticityY[0x55D4]: Float,
+ PrimaryRChromaticityX[0x55D1]: Float,
+ PrimaryRChromaticityY[0x55D2]: Float,
+ WhitePointChromaticityX[0x55D7]: Float,
+ WhitePointChromaticityY[0x55D8]: Float,
},
- #[id=0x55B1] MatrixCoefficients(Uint),
- #[id=0x55BC] MaxCLL(Uint),
- #[id=0x55BD] MaxFALL(Uint),
- #[id=0x55BB] Primaries(Uint),
- #[id=0x55B9] Range(Uint),
- #[id=0x55BA] TransferCharacteristics(Uint),
+ MatrixCoefficients[0x55B1]: Uint,
+ MaxCLL[0x55BC]: Uint,
+ MaxFALL[0x55BD]: Uint,
+ Primaries[0x55BB]: Uint,
+ Range[0x55B9]: Uint,
+ TransferCharacteristics[0x55BA]: Uint,
},
- #[id=0x54BA] DisplayHeight(Uint),
- #[id=0x54B2] DisplayUnit(Uint),
- #[id=0x54B0] DisplayWidth(Uint),
- #[id=0x9D] FieldOrder(Uint),
- #[id=0x9A] FlagInterlaced(Uint),
- #[id=0x2383E3] FrameRate(Float),
- #[id=0x2FB523] GammaValue(Float),
- #[id=0x53B9] OldStereoMode(Uint),
- #[id=0x54AA] PixelCropBottom(Uint),
- #[id=0x54CC] PixelCropLeft(Uint),
- #[id=0x54DD] PixelCropRight(Uint),
- #[id=0x54BB] PixelCropTop(Uint),
- #[id=0xBA] PixelHeight(Uint),
- #[id=0xB0] PixelWidth(Uint),
- #[id=0x7670] Projection: {
- #[id=0x7674] ProjectionPosePitch(Float),
- #[id=0x7675] ProjectionPoseRoll(Float),
- #[id=0x7673] ProjectionPoseYaw(Float),
- #[id=0x7672] ProjectionPrivate(Binary),
- #[id=0x7671] ProjectionType(Uint),
+ DisplayHeight[0x54BA]: Uint,
+ DisplayUnit[0x54B2]: Uint,
+ DisplayWidth[0x54B0]: Uint,
+ FieldOrder[0x9D]: Uint,
+ FlagInterlaced[0x9A]: Uint,
+ FrameRate[0x2383E3]: Float,
+ GammaValue[0x2FB523]: Float,
+ OldStereoMode[0x53B9]: Uint,
+ PixelCropBottom[0x54AA]: Uint,
+ PixelCropLeft[0x54CC]: Uint,
+ PixelCropRight[0x54DD]: Uint,
+ PixelCropTop[0x54BB]: Uint,
+ PixelHeight[0xBA]: Uint,
+ PixelWidth[0xB0]: Uint,
+ Projection[0x7670]: {
+ ProjectionPosePitch[0x7674]: Float,
+ ProjectionPoseRoll[0x7675]: Float,
+ ProjectionPoseYaw[0x7673]: Float,
+ ProjectionPrivate[0x7672]: Binary,
+ ProjectionType[0x7671]: Uint,
},
- #[id=0x53B8] StereoMode(Uint),
- #[id=0x2EB524] UncompressedFourCC(Binary),
+ StereoMode[0x53B8]: Uint,
+ UncompressedFourCC[0x2EB524]: Binary,
},
},
},
diff --git a/ebml/src/read.rs b/ebml/src/read.rs
index 23b4e21..3e02e18 100644
--- a/ebml/src/read.rs
+++ b/ebml/src/read.rs
@@ -1,13 +1,25 @@
use anyhow::{bail, Result};
-use std::io::{Read, Seek};
+use log::warn;
+use std::{
+ collections::VecDeque,
+ io::{Read, Seek},
+};
use crate::matroska::MatroskaTag;
trait ReadAndSeek: Read + Seek {}
impl<T: Read + Seek> ReadAndSeek for T {}
+#[derive(Debug, Clone, Copy)]
+pub struct StackTag {
+ end: Option<usize>,
+ id: u64,
+}
+
pub struct EbmlReader {
inner: Box<dyn ReadAndSeek>,
+ stack: Vec<StackTag>,
+ queue: VecDeque<MatroskaTag>,
pub position: usize,
}
@@ -18,7 +30,9 @@ pub trait EbmlRead: Sized {
impl EbmlReader {
pub fn new<T: Seek + Read + 'static>(inner: T) -> Self {
Self {
+ queue: VecDeque::new(),
inner: Box::new(inner),
+ stack: vec![],
position: 0,
}
}
@@ -64,14 +78,70 @@ impl EbmlReader {
pub fn read_tag_size(&mut self) -> Result<EbmlSize> {
Ok(EbmlSize::from_vint(self.read_vint_len()?))
}
- pub fn read_tag(&mut self) -> Result<MatroskaTag> {
+ pub fn read_stuff(&mut self) -> Result<()> {
+ if let Some(e) = self.stack.last().map(|e| *e) {
+ if let Some(end) = e.end {
+ if self.position >= end {
+ if self.position != end {
+ warn!("we missed the end")
+ }
+ self.stack.pop();
+ self.queue.push_back(MatroskaTag::parse(e.id, &[0])?);
+ }
+ }
+ }
+
let id = self.read_tag_id()?;
let size = self.read_tag_size()?;
- if MatroskaTag::is_master(id)? {
- Ok(MatroskaTag::parse(id, &[])?)
+ let is_master = MatroskaTag::is_master(id)?;
+ let tag = if is_master {
+ MatroskaTag::parse(id, &[])?
} else {
let data = self.read_buf(size)?;
- Ok(MatroskaTag::parse(id, &data)?)
+ MatroskaTag::parse(id, &data)?
+ };
+
+ if let Some(path) = tag.path() {
+ // we have slightly different rules for closing tags implicitly
+ // this closes as many tags as needed to make the next tag a valid child
+ while let Some(tag @ StackTag { end: None, .. }) = self.stack.last() {
+ let mut valid_child = false;
+ for p in path {
+ if *p == tag.id {
+ valid_child = true;
+ }
+ }
+ if valid_child {
+ break;
+ } else {
+ self.queue
+ .push_back(MatroskaTag::parse(self.stack.pop().unwrap().id, &[0])?);
+ }
+ }
+ }
+
+ if is_master {
+ self.stack.push(StackTag {
+ end: size.some().map(|s| s + self.position),
+ id,
+ });
+ }
+ self.queue.push_back(tag);
+ Ok(())
+ }
+}
+
+impl Iterator for EbmlReader {
+ type Item = Result<MatroskaTag>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let Some(t) = self.queue.pop_front() {
+ Some(Ok(t))
+ } else {
+ match self.read_stuff() {
+ Ok(()) => self.next(),
+ Err(e) => Some(Err(e)),
+ }
}
}
}
@@ -89,6 +159,12 @@ impl EbmlSize {
Self::Exact(value as usize)
}
}
+ pub fn some(self) -> Option<usize> {
+ match self {
+ EbmlSize::Exact(s) => Some(s),
+ EbmlSize::Unknown => None,
+ }
+ }
}
impl Into<usize> for EbmlSize {
fn into(self) -> usize {