mirror of
https://github.com/nestriness/warp.git
synced 2025-12-13 02:15:42 +02:00
feat(sink): add init_segment for broadcasting
This commit is contained in:
66
src/media.rs
66
src/media.rs
@@ -16,16 +16,16 @@ use std::collections::HashMap;
|
|||||||
use std::io::{Cursor, Seek};
|
use std::io::{Cursor, Seek};
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
use mp4::{self, BoxHeader};
|
use mp4::{self, ReadBox};
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
// Atoms in init sequence that must be repeated at each key frame.
|
// Atoms in init sequence that must be repeated at each key frame.
|
||||||
ftyp_atom: Option<Vec<u8>>,
|
ftyp_atom: Option<Vec<u8>>,
|
||||||
moov_atom: Option<Vec<u8>>,
|
moov_atom: Option<Vec<u8>>,
|
||||||
|
|
||||||
bitrate: u64,
|
// bitrate: u64,
|
||||||
width: u64,
|
// width: u64,
|
||||||
height: u64,
|
// height: u64,
|
||||||
|
|
||||||
// We hold on to publisher so we don't close then while media is still being published.
|
// We hold on to publisher so we don't close then while media is still being published.
|
||||||
broadcast: broadcast::Publisher,
|
broadcast: broadcast::Publisher,
|
||||||
@@ -49,9 +49,9 @@ impl GST {
|
|||||||
let state = Arc::new(Mutex::new(State {
|
let state = Arc::new(Mutex::new(State {
|
||||||
ftyp_atom: Some(Vec::new()),
|
ftyp_atom: Some(Vec::new()),
|
||||||
moov_atom: Some(Vec::new()),
|
moov_atom: Some(Vec::new()),
|
||||||
bitrate: 2_048_000,
|
// bitrate: 2_048_000,
|
||||||
width: 1280,
|
// width: 1280,
|
||||||
height: 720,
|
// height: 720,
|
||||||
broadcast: broadcast.to_owned(),
|
broadcast: broadcast.to_owned(),
|
||||||
catalog: None,
|
catalog: None,
|
||||||
init: None,
|
init: None,
|
||||||
@@ -141,7 +141,7 @@ impl GST {
|
|||||||
let sample = sink
|
let sample = sink
|
||||||
.pull_sample()
|
.pull_sample()
|
||||||
.with_context(|| "Error pulling sample")
|
.with_context(|| "Error pulling sample")
|
||||||
.map_err(|e| gst::FlowError::Eos)?;
|
.map_err(|_e| gst::FlowError::Eos)?;
|
||||||
|
|
||||||
// The muxer only outputs non-empty buffer lists
|
// The muxer only outputs non-empty buffer lists
|
||||||
let buffer_list = sample.buffer_list_owned().expect("no buffer list");
|
let buffer_list = sample.buffer_list_owned().expect("no buffer list");
|
||||||
@@ -170,13 +170,54 @@ impl GST {
|
|||||||
}
|
}
|
||||||
mp4::BoxType::MoovBox => {
|
mp4::BoxType::MoovBox => {
|
||||||
println!("Found 'moov' box");
|
println!("Found 'moov' box");
|
||||||
let mut init_segment = Vec::new(); // Buffer to store the concatenated 'ftyp' and 'moov' atoms.
|
let mut init = Vec::new(); // Buffer to store the concatenated 'ftyp' and 'moov' atoms.
|
||||||
|
let mut broadcast = state.broadcast.clone();
|
||||||
|
// Parse the moov box so we can detect the timescales for each track.
|
||||||
|
let moov_box_cursor = Cursor::new(box_data.clone()); // Create a cursor for the 'moov' box data.
|
||||||
|
let moov = mp4::MoovBox::read_box(&mut moov_box_cursor, header.size).expect("could not read moov box");
|
||||||
|
|
||||||
match state.ftyp_atom.as_ref() {
|
match state.ftyp_atom.as_ref() {
|
||||||
Some(ftyp_atom) => {
|
Some(ftyp_atom) => {
|
||||||
// Concatenate 'ftyp' and 'moov' atoms.
|
// Concatenate 'ftyp' and 'moov' atoms.
|
||||||
init_segment.extend_from_slice(&ftyp_atom);
|
init.extend_from_slice(&ftyp_atom);
|
||||||
init_segment.extend_from_slice(&box_data);
|
init.extend_from_slice(&box_data);
|
||||||
state.moov_atom = Some(init_segment)
|
// state.moov_atom = Some(init); //FIXME: just realised, this is wrong
|
||||||
|
|
||||||
|
// Create the catalog track with a single segment.
|
||||||
|
let mut init_track = broadcast
|
||||||
|
.create_track("0.mp4")
|
||||||
|
.expect("could not create track");
|
||||||
|
|
||||||
|
let init_segment = init_track
|
||||||
|
.create_segment(segment::Info {
|
||||||
|
sequence: VarInt::ZERO,
|
||||||
|
priority: 0,
|
||||||
|
expires: None,
|
||||||
|
})
|
||||||
|
.expect("could not create init_segment");
|
||||||
|
|
||||||
|
// Create a single fragment, optionally setting the size
|
||||||
|
let mut init_fragment = init_segment
|
||||||
|
.final_fragment(VarInt::ZERO)
|
||||||
|
.expect("coild not create a single fragment");
|
||||||
|
|
||||||
|
init_fragment
|
||||||
|
.chunk(init.into())
|
||||||
|
.expect("could not create a broadcast chunk");
|
||||||
|
|
||||||
|
let mut tracks = HashMap::new();
|
||||||
|
|
||||||
|
for trak in &moov.traks {
|
||||||
|
let id = trak.tkhd.track_id;
|
||||||
|
let name = format!("{}.m4s", id);
|
||||||
|
|
||||||
|
let timescale = track_timescale(&moov, id);
|
||||||
|
|
||||||
|
// Store the track publisher in a map so we can update it later.
|
||||||
|
let track = broadcast.create_track(&name)?;
|
||||||
|
let track = Track::new(track, timescale);
|
||||||
|
tracks.insert(id, track);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
@@ -192,7 +233,6 @@ impl GST {
|
|||||||
}
|
}
|
||||||
cursor
|
cursor
|
||||||
.seek(SeekFrom::Current(header.size as i64))
|
.seek(SeekFrom::Current(header.size as i64))
|
||||||
// .map_err(|e| gst::FlowError::Eos)?;
|
|
||||||
.expect("Seeking failed");
|
.expect("Seeking failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user