2018-04-12 23:29:12 -04:00
|
|
|
use std::time::Instant;
|
|
|
|
|
2017-09-30 02:33:36 -04:00
|
|
|
use futures::Async;
|
|
|
|
use futures::stream::Stream;
|
2017-09-06 02:02:50 -04:00
|
|
|
|
2018-04-04 20:19:28 -04:00
|
|
|
use chunk::Chunk;
|
2017-09-30 02:33:36 -04:00
|
|
|
|
|
|
|
pub struct ChunkTimecodeFixer<S> {
|
2017-09-30 17:36:09 -04:00
|
|
|
stream: S,
|
|
|
|
current_offset: u64,
|
|
|
|
last_observed_timecode: u64,
|
2018-04-08 02:31:00 -04:00
|
|
|
assumed_duration: u64
|
2017-09-30 02:33:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: Stream<Item = Chunk>> Stream for ChunkTimecodeFixer<S>
|
|
|
|
{
|
|
|
|
type Item = S::Item;
|
|
|
|
type Error = S::Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
|
2017-09-30 17:36:09 -04:00
|
|
|
let mut poll_chunk = self.stream.poll();
|
|
|
|
match poll_chunk {
|
2018-03-28 00:31:58 -04:00
|
|
|
Ok(Async::Ready(Some(Chunk::ClusterHead(ref mut cluster_head)))) => {
|
|
|
|
let start = cluster_head.start;
|
2017-09-30 17:36:09 -04:00
|
|
|
if start < self.last_observed_timecode {
|
|
|
|
let next_timecode = self.last_observed_timecode + self.assumed_duration;
|
|
|
|
self.current_offset = next_timecode - start;
|
|
|
|
}
|
|
|
|
|
2018-03-28 00:31:58 -04:00
|
|
|
cluster_head.update_timecode(start + self.current_offset);
|
2018-03-30 02:44:42 -04:00
|
|
|
self.last_observed_timecode = cluster_head.end;
|
2017-09-30 17:36:09 -04:00
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
};
|
|
|
|
poll_chunk
|
2017-09-30 02:33:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-08 02:31:00 -04:00
|
|
|
pub struct StartingPointFinder<S> {
|
|
|
|
stream: S,
|
|
|
|
seen_header: bool,
|
|
|
|
seen_keyframe: bool
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: Stream<Item = Chunk>> Stream for StartingPointFinder<S>
|
|
|
|
{
|
|
|
|
type Item = S::Item;
|
|
|
|
type Error = S::Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
|
|
|
|
loop {
|
|
|
|
return match self.stream.poll() {
|
|
|
|
Ok(Async::Ready(Some(Chunk::ClusterHead(cluster_head)))) => {
|
|
|
|
if cluster_head.keyframe {
|
|
|
|
self.seen_keyframe = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.seen_keyframe {
|
|
|
|
Ok(Async::Ready(Some(Chunk::ClusterHead(cluster_head))))
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
chunk @ Ok(Async::Ready(Some(Chunk::ClusterBody {..}))) => {
|
|
|
|
if self.seen_keyframe {
|
|
|
|
chunk
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
chunk @ Ok(Async::Ready(Some(Chunk::Headers {..}))) => {
|
|
|
|
if self.seen_header {
|
|
|
|
// new stream starting, we don't need a new header but should wait for a safe spot to resume
|
|
|
|
self.seen_keyframe = false;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
self.seen_header = true;
|
|
|
|
chunk
|
|
|
|
}
|
|
|
|
},
|
|
|
|
chunk => chunk
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-12 23:29:12 -04:00
|
|
|
pub struct Throttle<S> {
|
|
|
|
stream: S,
|
|
|
|
start_time: Instant
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: Stream<Item = Chunk>> Stream for Throttle<S>
|
|
|
|
{
|
|
|
|
type Item = S::Item;
|
|
|
|
type Error = S::Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
|
|
|
|
self.stream.poll()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-07 01:09:17 -04:00
|
|
|
pub trait ChunkStream where Self : Sized + Stream<Item = Chunk> {
|
|
|
|
fn fix_timecodes(self) -> ChunkTimecodeFixer<Self> {
|
2017-09-30 02:33:36 -04:00
|
|
|
ChunkTimecodeFixer {
|
2017-09-30 17:36:09 -04:00
|
|
|
stream: self,
|
|
|
|
current_offset: 0,
|
|
|
|
last_observed_timecode: 0,
|
2018-04-08 02:31:00 -04:00
|
|
|
assumed_duration: 33
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn find_starting_point(self) -> StartingPointFinder<Self> {
|
|
|
|
StartingPointFinder {
|
|
|
|
stream: self,
|
|
|
|
seen_header: false,
|
|
|
|
seen_keyframe: false
|
2017-09-30 02:33:36 -04:00
|
|
|
}
|
|
|
|
}
|
2018-04-12 23:29:12 -04:00
|
|
|
|
|
|
|
fn throttle(self) -> Throttle<Self> {
|
|
|
|
Throttle {
|
|
|
|
stream: self,
|
|
|
|
start_time: Instant::now()
|
|
|
|
}
|
|
|
|
}
|
2017-09-30 02:33:36 -04:00
|
|
|
}
|
2018-04-07 01:09:17 -04:00
|
|
|
|
|
|
|
impl<T: Stream<Item = Chunk>> ChunkStream for T {}
|