#![cfg(feature = "utils")]
use mkv_element::io::blocking_impl::{WriteElement, WriteTo};
use mkv_element::prelude::*;
use mkv_element::view::MatroskaView;
use std::io::Cursor;
fn ebml() -> Ebml {
Ebml {
crc32: None,
ebml_version: Some(EbmlVersion(1)),
ebml_read_version: Some(EbmlReadVersion(1)),
ebml_max_id_length: EbmlMaxIdLength(4),
ebml_max_size_length: EbmlMaxSizeLength(8),
doc_type: Some(DocType("matroska".to_string())),
doc_type_version: Some(DocTypeVersion(4)),
doc_type_read_version: Some(DocTypeReadVersion(2)),
void: None,
}
}
fn segment1() -> Segment {
let info = Info {
timestamp_scale: TimestampScale(1000000), muxing_app: MuxingApp("mkv-element".to_string()),
writing_app: WritingApp("integration-test".to_string()),
title: Some(Title("Test Segment 1".to_string())),
duration: Some(Duration(30000.0)), ..Default::default()
};
let video_track = TrackEntry {
track_number: TrackNumber(1),
track_uid: TrackUid(1234567890),
track_type: TrackType(1), codec_id: CodecId("V_VP9".to_string()),
name: Some(Name("Video Track".to_string())),
codec_name: Some(CodecName("VP9".to_string())),
video: Some(Video {
pixel_width: PixelWidth(1920),
pixel_height: PixelHeight(1080),
..Default::default()
}),
..Default::default()
};
let tracks = Tracks {
track_entry: vec![video_track],
..Default::default()
};
let cluster = Cluster {
timestamp: Timestamp(0),
blocks: vec![], ..Default::default()
};
Segment {
crc32: None,
void: None,
seek_head: vec![],
info,
cluster: vec![cluster],
tracks: Some(tracks),
cues: None,
attachments: None,
chapters: None,
tags: vec![],
}
}
fn segment_without_clusters() -> Segment {
let info = Info {
timestamp_scale: TimestampScale(1000000),
muxing_app: MuxingApp("mkv-element".to_string()),
writing_app: WritingApp("integration-test".to_string()),
title: Some(Title("No Clusters Segment".to_string())),
..Default::default()
};
let audio_track = TrackEntry {
track_number: TrackNumber(1),
track_uid: TrackUid(9876543210),
track_type: TrackType(2), codec_id: CodecId("A_OPUS".to_string()),
name: Some(Name("Audio Track".to_string())),
codec_name: Some(CodecName("Opus".to_string())),
audio: Some(Audio {
sampling_frequency: SamplingFrequency(48000.0),
channels: Channels(2),
..Default::default()
}),
..Default::default()
};
let tracks = Tracks {
track_entry: vec![audio_track],
..Default::default()
};
Segment {
crc32: None,
void: None,
seek_head: vec![],
info,
cluster: vec![], tracks: Some(tracks),
cues: None,
attachments: None,
chapters: None,
tags: vec![],
}
}
#[test]
fn test_basic_matroska_view() {
let ebml_header = ebml();
let segment = segment1();
let mut buffer = Vec::new();
ebml_header.write_to(&mut buffer).unwrap();
segment.write_to(&mut buffer).unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new(&mut cursor).unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 1);
let segment_view = &view.segments[0];
assert_eq!(segment_view.info.title.as_deref(), Some("Test Segment 1"));
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_ne!(segment_view.first_cluster_position, 0);
}
#[test]
fn test_segment_without_clusters() {
let ebml_header = ebml();
let segment = segment_without_clusters();
let mut buffer = Vec::new();
ebml_header.write_to(&mut buffer).unwrap();
segment.write_to(&mut buffer).unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new(&mut cursor).unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 1);
let segment_view = &view.segments[0];
assert_eq!(
segment_view.info.title.as_deref(),
Some("No Clusters Segment")
);
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_eq!(segment_view.first_cluster_position, 0); }
#[test]
fn test_multiple_segments() {
let ebml_header = ebml();
let segment1 = segment1();
let segment2 = segment1.clone();
let segment3 = segment1.clone();
let segment4 = segment_without_clusters();
let mut buffer = Vec::new();
ebml_header.write_to(&mut buffer).unwrap();
segment1.write_to(&mut buffer).unwrap();
segment2.write_to(&mut buffer).unwrap();
segment3.write_to(&mut buffer).unwrap();
segment4.write_to(&mut buffer).unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new(&mut cursor).unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 4, "should have 4 segments");
for (i, segment_view) in view.segments.iter().enumerate() {
if i < 3 {
assert_eq!(segment_view.info.title.as_deref(), Some("Test Segment 1"));
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_ne!(segment_view.first_cluster_position, 0);
} else {
assert_eq!(
segment_view.info.title.as_deref(),
Some("No Clusters Segment")
);
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_eq!(segment_view.first_cluster_position, 0); }
}
}
#[test]
fn test_unsize_segment() {
let ebml_header = ebml();
let segment_header = Header {
id: Segment::ID,
size: VInt64::new_unknown(),
};
let segment = segment1();
let mut buffer = Vec::new();
ebml_header.write_to(&mut buffer).unwrap();
segment.write_element(&segment_header, &mut buffer).unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new(&mut cursor).unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 1);
let segment_view = &view.segments[0];
assert_eq!(segment_view.info.title.as_deref(), Some("Test Segment 1"));
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_ne!(segment_view.first_cluster_position, 0);
}
#[cfg(feature = "tokio")]
mod async_tests {
use super::*;
use mkv_element::io::tokio_impl::{AsyncWriteElement, AsyncWriteTo};
#[tokio::test]
async fn test_basic_matroska_view_async() {
let ebml_header = ebml();
let segment = segment1();
let mut buffer = Vec::new();
ebml_header.async_write_to(&mut buffer).await.unwrap();
segment.async_write_to(&mut buffer).await.unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new_async(&mut cursor).await.unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 1);
let segment_view = &view.segments[0];
assert_eq!(segment_view.info.title.as_deref(), Some("Test Segment 1"));
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_ne!(segment_view.first_cluster_position, 0);
}
#[tokio::test]
async fn test_segment_without_clusters_async() {
let ebml_header = ebml();
let segment = segment_without_clusters();
let mut buffer = Vec::new();
ebml_header.async_write_to(&mut buffer).await.unwrap();
segment.async_write_to(&mut buffer).await.unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new_async(&mut cursor).await.unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 1);
let segment_view = &view.segments[0];
assert_eq!(
segment_view.info.title.as_deref(),
Some("No Clusters Segment")
);
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_eq!(segment_view.first_cluster_position, 0); }
#[tokio::test]
async fn test_multiple_segments_async() {
let ebml_header = ebml();
let segment1 = segment1();
let segment2 = segment1.clone();
let segment3 = segment1.clone();
let segment4 = segment_without_clusters();
let mut buffer = Vec::new();
ebml_header.async_write_to(&mut buffer).await.unwrap();
segment1.async_write_to(&mut buffer).await.unwrap();
segment2.async_write_to(&mut buffer).await.unwrap();
segment3.async_write_to(&mut buffer).await.unwrap();
segment4.async_write_to(&mut buffer).await.unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new_async(&mut cursor).await.unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 4, "should have 4 segments");
for (i, segment_view) in view.segments.iter().enumerate() {
if i < 3 {
assert_eq!(segment_view.info.title.as_deref(), Some("Test Segment 1"));
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_ne!(segment_view.first_cluster_position, 0);
} else {
assert_eq!(
segment_view.info.title.as_deref(),
Some("No Clusters Segment")
);
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_eq!(segment_view.first_cluster_position, 0); }
}
}
#[tokio::test]
async fn test_unsize_segment_async() {
let ebml_header = ebml();
let segment_header = Header {
id: Segment::ID,
size: VInt64::new_unknown(),
};
let segment = segment1();
let mut buffer = Vec::new();
ebml_header.async_write_to(&mut buffer).await.unwrap();
segment
.async_write_element(&segment_header, &mut buffer)
.await
.unwrap();
let mut cursor = Cursor::new(&buffer);
let view = MatroskaView::new_async(&mut cursor).await.unwrap();
assert_eq!(view.ebml.doc_type.as_deref(), Some("matroska"));
assert_eq!(view.segments.len(), 1);
let segment_view = &view.segments[0];
assert_eq!(segment_view.info.title.as_deref(), Some("Test Segment 1"));
assert_eq!(segment_view.tracks.as_ref().unwrap().track_entry.len(), 1);
assert_ne!(segment_view.first_cluster_position, 0);
}
}