Fuse ClusterHead & ClusterBody chunks into one chunk type

(there is still a technical body chunk variant for iteration purposes, but it won't be produced by the parser)
This commit is contained in:
Tangent Wantwight 2020-09-11 20:34:40 -04:00
parent 9cc7d8064d
commit 43acf93fa9
2 changed files with 19 additions and 32 deletions

View File

@ -58,15 +58,16 @@ pub enum Chunk {
Headers { Headers {
bytes: Bytes bytes: Bytes
}, },
ClusterHead(ClusterHead), Cluster(ClusterHead, Bytes),
ClusterBody { // for iteration only
bytes: Bytes #[doc(hidden)]
}, RemainingBody(Bytes),
// for iteration only
#[doc(hidden)]
Empty Empty
} }
pub struct Iter(Chunk); // TODO: make an external iterator type so we can remove Chunk::RemainingBody & Chunk::Empty
impl Iterator for Chunk { impl Iterator for Chunk {
type Item = Bytes; type Item = Bytes;
@ -77,12 +78,13 @@ impl Iterator for Chunk {
*self = Chunk::Empty; *self = Chunk::Empty;
Some(bytes) Some(bytes)
}, },
Chunk::ClusterHead(ClusterHead {bytes, ..}) => { Chunk::Cluster(ClusterHead {bytes, ..}, body) => {
let bytes = mem::replace(bytes, BytesMut::new()); let bytes = mem::replace(bytes, BytesMut::new());
*self = Chunk::Empty; let body = mem::replace(body, Bytes::new());
*self = Chunk::RemainingBody(body);
Some(bytes.freeze()) Some(bytes.freeze())
}, },
Chunk::ClusterBody {bytes, ..} => { Chunk::RemainingBody(bytes) => {
let bytes = mem::replace(bytes, Bytes::new()); let bytes = mem::replace(bytes, Bytes::new());
*self = Chunk::Empty; *self = Chunk::Empty;
Some(bytes) Some(bytes)
@ -104,7 +106,6 @@ pub struct WebmChunker<S> {
source: EbmlStreamingParser<S>, source: EbmlStreamingParser<S>,
buffer_size_limit: Option<usize>, buffer_size_limit: Option<usize>,
state: ChunkerState, state: ChunkerState,
pending_chunk: Option<Chunk>,
} }
impl<S> WebmChunker<S> { impl<S> WebmChunker<S> {
@ -135,9 +136,6 @@ where
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Result<Chunk, WebmetroError>>> { fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Result<Chunk, WebmetroError>>> {
let mut chunker = self.get_mut(); let mut chunker = self.get_mut();
if chunker.pending_chunk.is_some() {
return Ready(chunker.pending_chunk.take().map(Ok));
}
loop { loop {
match chunker.state { match chunker.state {
ChunkerState::BuildingHeader(ref mut buffer) => { ChunkerState::BuildingHeader(ref mut buffer) => {
@ -180,9 +178,8 @@ where
let mut new_header_cursor = Cursor::new(Vec::new()); let mut new_header_cursor = Cursor::new(Vec::new());
match encode(element, &mut new_header_cursor, chunker.buffer_size_limit) { match encode(element, &mut new_header_cursor, chunker.buffer_size_limit) {
Ok(_) => { Ok(_) => {
chunker.pending_chunk = Some(Chunk::ClusterBody {bytes: Bytes::from(liberated_buffer.into_inner())});
chunker.state = ChunkerState::BuildingHeader(new_header_cursor); chunker.state = ChunkerState::BuildingHeader(new_header_cursor);
return Ready(Some(Ok(Chunk::ClusterHead(liberated_cluster_head)))); return Ready(Some(Ok(Chunk::Cluster(liberated_cluster_head, Bytes::from(liberated_buffer.into_inner())))));
}, },
Err(err) => { Err(err) => {
chunker.state = ChunkerState::End; chunker.state = ChunkerState::End;
@ -194,8 +191,7 @@ where
let liberated_cluster_head = mem::replace(cluster_head, ClusterHead::new(0)); let liberated_cluster_head = mem::replace(cluster_head, ClusterHead::new(0));
let liberated_buffer = mem::replace(buffer, Cursor::new(Vec::new())); let liberated_buffer = mem::replace(buffer, Cursor::new(Vec::new()));
chunker.pending_chunk = Some(Chunk::ClusterBody {bytes: Bytes::from(liberated_buffer.into_inner())}); return Ready(Some(Ok(Chunk::Cluster(liberated_cluster_head, Bytes::from(liberated_buffer.into_inner())))));
return Ready(Some(Ok(Chunk::ClusterHead(liberated_cluster_head))));
}, },
WebmElement::Timecode(timecode) => { WebmElement::Timecode(timecode) => {
cluster_head.update_timecode(timecode); cluster_head.update_timecode(timecode);
@ -226,9 +222,8 @@ where
let liberated_cluster_head = mem::replace(cluster_head, ClusterHead::new(0)); let liberated_cluster_head = mem::replace(cluster_head, ClusterHead::new(0));
let liberated_buffer = mem::replace(buffer, Cursor::new(Vec::new())); let liberated_buffer = mem::replace(buffer, Cursor::new(Vec::new()));
chunker.pending_chunk = Some(Chunk::ClusterBody {bytes: Bytes::from(liberated_buffer.into_inner())});
chunker.state = ChunkerState::End; chunker.state = ChunkerState::End;
return Ready(Some(Ok(Chunk::ClusterHead(liberated_cluster_head)))); return Ready(Some(Ok(Chunk::Cluster(liberated_cluster_head, Bytes::from(liberated_buffer.into_inner())))));
} }
} }
}, },
@ -249,8 +244,7 @@ impl<S: Stream> WebmStream for EbmlStreamingParser<S> {
WebmChunker { WebmChunker {
source: self, source: self,
buffer_size_limit: None, buffer_size_limit: None,
state: ChunkerState::BuildingHeader(Cursor::new(Vec::new())), state: ChunkerState::BuildingHeader(Cursor::new(Vec::new()))
pending_chunk: None
} }
} }
} }

View File

@ -30,7 +30,7 @@ impl ChunkTimecodeFixer {
} }
pub fn process(&mut self, mut chunk: Chunk) -> Chunk { pub fn process(&mut self, mut chunk: Chunk) -> Chunk {
match chunk { match chunk {
Chunk::ClusterHead(ref mut cluster_head) => { Chunk::Cluster(ref mut cluster_head, _) => {
let start = cluster_head.start; let start = cluster_head.start;
if start < self.last_observed_timecode { if start < self.last_observed_timecode {
let next_timecode = self.last_observed_timecode + self.assumed_duration; let next_timecode = self.last_observed_timecode + self.assumed_duration;
@ -59,20 +59,13 @@ impl<S: TryStream<Ok = Chunk> + Unpin> Stream for StartingPointFinder<S>
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Result<Chunk, S::Error>>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Result<Chunk, S::Error>>> {
loop { loop {
return match self.stream.try_poll_next_unpin(cx) { return match self.stream.try_poll_next_unpin(cx) {
Poll::Ready(Some(Ok(Chunk::ClusterHead(cluster_head)))) => { Poll::Ready(Some(Ok(Chunk::Cluster(cluster_head, cluster_body)))) => {
if cluster_head.keyframe { if cluster_head.keyframe {
self.seen_keyframe = true; self.seen_keyframe = true;
} }
if self.seen_keyframe { if self.seen_keyframe {
Poll::Ready(Some(Ok(Chunk::ClusterHead(cluster_head)))) Poll::Ready(Some(Ok(Chunk::Cluster(cluster_head, cluster_body))))
} else {
continue;
}
},
chunk @ Poll::Ready(Some(Ok(Chunk::ClusterBody {..}))) => {
if self.seen_keyframe {
chunk
} else { } else {
continue; continue;
} }
@ -121,7 +114,7 @@ impl<S: TryStream<Ok = Chunk> + Unpin> Stream for Throttle<S>
} }
let next_chunk = self.stream.try_poll_next_unpin(cx); let next_chunk = self.stream.try_poll_next_unpin(cx);
if let Poll::Ready(Some(Ok(Chunk::ClusterHead(ref cluster_head)))) = next_chunk { if let Poll::Ready(Some(Ok(Chunk::Cluster(ref cluster_head, _)))) = next_chunk {
// we have actual data, so start the clock if we haven't yet // we have actual data, so start the clock if we haven't yet
let start_time = self.start_time.get_or_insert_with(Instant::now); let start_time = self.start_time.get_or_insert_with(Instant::now);
// snooze until real time has "caught up" to the stream // snooze until real time has "caught up" to the stream