2017-02-16 15:52:27 +00:00
|
|
|
// Copyright (C) 2016-2017 Sebastian Dröge <sebastian@centricular.com>
|
2016-11-24 14:29:43 +00:00
|
|
|
//
|
2017-02-16 15:52:27 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
2016-11-24 14:29:43 +00:00
|
|
|
|
|
|
|
use libc::c_char;
|
|
|
|
use std::os::raw::c_void;
|
|
|
|
use std::ffi::CString;
|
|
|
|
|
|
|
|
use std::panic::{self, AssertUnwindSafe};
|
|
|
|
|
|
|
|
use std::sync::Mutex;
|
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
|
|
|
|
use std::u32;
|
|
|
|
use std::u64;
|
|
|
|
|
|
|
|
use error::*;
|
|
|
|
|
2017-07-31 22:26:52 +00:00
|
|
|
use glib_ffi;
|
|
|
|
use gst_ffi;
|
2017-04-09 21:29:07 +00:00
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
use glib;
|
|
|
|
use glib::translate::*;
|
|
|
|
use gst;
|
|
|
|
|
2016-11-24 14:29:43 +00:00
|
|
|
pub type StreamIndex = u32;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum SeekResult {
|
|
|
|
TooEarly,
|
|
|
|
Ok(u64),
|
|
|
|
Eos,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum HandleBufferResult {
|
|
|
|
NeedMoreData,
|
|
|
|
Again,
|
|
|
|
// NeedDataFromOffset(u64),
|
|
|
|
StreamAdded(Stream),
|
|
|
|
HaveAllStreams,
|
|
|
|
StreamChanged(Stream),
|
|
|
|
// StreamsAdded(Vec<Stream>), // Implies HaveAllStreams
|
2016-12-04 18:24:44 +00:00
|
|
|
StreamsChanged(Vec<Stream>),
|
2016-11-24 14:29:43 +00:00
|
|
|
// TODO need something to replace/add new streams
|
|
|
|
// TODO should probably directly implement the GstStreams new world order
|
2017-09-16 17:35:01 +00:00
|
|
|
BufferForStream(StreamIndex, gst::Buffer),
|
2016-11-24 14:29:43 +00:00
|
|
|
Eos(Option<StreamIndex>),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait Demuxer {
|
2017-07-31 13:36:35 +00:00
|
|
|
fn start(
|
|
|
|
&mut self,
|
|
|
|
upstream_size: Option<u64>,
|
|
|
|
random_access: bool,
|
|
|
|
) -> Result<(), ErrorMessage>;
|
2016-11-24 14:29:43 +00:00
|
|
|
fn stop(&mut self) -> Result<(), ErrorMessage>;
|
|
|
|
|
|
|
|
fn seek(&mut self, start: u64, stop: Option<u64>) -> Result<SeekResult, ErrorMessage>;
|
2017-07-31 13:36:35 +00:00
|
|
|
fn handle_buffer(
|
|
|
|
&mut self,
|
2017-09-16 17:35:01 +00:00
|
|
|
buffer: Option<gst::Buffer>,
|
2017-07-31 13:36:35 +00:00
|
|
|
) -> Result<HandleBufferResult, FlowError>;
|
2016-11-24 14:29:43 +00:00
|
|
|
fn end_of_stream(&mut self) -> Result<(), ErrorMessage>;
|
|
|
|
|
|
|
|
fn is_seekable(&self) -> bool;
|
|
|
|
fn get_position(&self) -> Option<u64>;
|
|
|
|
fn get_duration(&self) -> Option<u64>;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Stream {
|
|
|
|
pub index: StreamIndex,
|
2017-09-16 17:35:01 +00:00
|
|
|
pub caps: gst::Caps,
|
2016-11-24 14:29:43 +00:00
|
|
|
pub stream_id: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Stream {
|
2017-09-16 17:35:01 +00:00
|
|
|
pub fn new(index: StreamIndex, caps: gst::Caps, stream_id: String) -> Stream {
|
2016-11-24 14:29:43 +00:00
|
|
|
Stream {
|
|
|
|
index: index,
|
2016-12-30 11:11:30 +00:00
|
|
|
caps: caps,
|
2016-11-24 14:29:43 +00:00
|
|
|
stream_id: stream_id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct DemuxerWrapper {
|
2017-07-31 22:26:52 +00:00
|
|
|
raw: *mut gst_ffi::GstElement,
|
2017-09-16 17:35:01 +00:00
|
|
|
cat: gst::DebugCategory,
|
2016-11-24 14:29:43 +00:00
|
|
|
demuxer: Mutex<Box<Demuxer>>,
|
|
|
|
panicked: AtomicBool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DemuxerWrapper {
|
2017-07-31 22:26:52 +00:00
|
|
|
fn new(raw: *mut gst_ffi::GstElement, demuxer: Box<Demuxer>) -> DemuxerWrapper {
|
2016-11-24 14:29:43 +00:00
|
|
|
DemuxerWrapper {
|
|
|
|
raw: raw,
|
2017-09-16 17:35:01 +00:00
|
|
|
cat: gst::DebugCategory::new(
|
|
|
|
"rsdemux",
|
|
|
|
gst::DebugColorFlags::empty(),
|
|
|
|
"Rust demuxer base class",
|
2017-07-31 13:36:35 +00:00
|
|
|
),
|
2016-11-24 14:29:43 +00:00
|
|
|
demuxer: Mutex::new(demuxer),
|
|
|
|
panicked: AtomicBool::new(false),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn start(&self, upstream_size: u64, random_access: bool) -> bool {
|
|
|
|
let demuxer = &mut self.demuxer.lock().unwrap();
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_debug!(
|
|
|
|
self.cat,
|
|
|
|
// TODO obj: demuxer
|
2017-07-31 13:36:35 +00:00
|
|
|
"Starting with upstream size {} and random access {}",
|
|
|
|
upstream_size,
|
|
|
|
random_access
|
|
|
|
);
|
2016-12-27 15:47:39 +00:00
|
|
|
|
2016-11-24 14:29:43 +00:00
|
|
|
let upstream_size = if upstream_size == u64::MAX {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(upstream_size)
|
|
|
|
};
|
|
|
|
|
|
|
|
match demuxer.start(upstream_size, random_access) {
|
2016-12-27 15:47:39 +00:00
|
|
|
Ok(..) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Successfully started"
|
|
|
|
);
|
2016-12-27 15:47:39 +00:00
|
|
|
true
|
|
|
|
}
|
2016-11-24 14:29:43 +00:00
|
|
|
Err(ref msg) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_error!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Failed to start: {:?}",
|
|
|
|
msg
|
|
|
|
);
|
2016-11-24 14:29:43 +00:00
|
|
|
self.post_message(msg);
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn stop(&self) -> bool {
|
|
|
|
let demuxer = &mut self.demuxer.lock().unwrap();
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_debug!(self.cat, /* TODO obj: demuxer,*/ "Stopping");
|
2016-12-27 15:47:39 +00:00
|
|
|
|
2016-11-24 14:29:43 +00:00
|
|
|
match demuxer.stop() {
|
2016-12-27 15:47:39 +00:00
|
|
|
Ok(..) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(self.cat, /* TODO obj: demuxer,*/ "Successfully stop");
|
2016-12-27 15:47:39 +00:00
|
|
|
true
|
|
|
|
}
|
2016-11-24 14:29:43 +00:00
|
|
|
Err(ref msg) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_error!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Failed to stop: {:?}",
|
|
|
|
msg
|
|
|
|
);
|
2016-11-24 14:29:43 +00:00
|
|
|
self.post_message(msg);
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_seekable(&self) -> bool {
|
|
|
|
let demuxer = &self.demuxer.lock().unwrap();
|
|
|
|
|
2016-12-27 15:47:39 +00:00
|
|
|
let seekable = demuxer.is_seekable();
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_debug!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Seekable {}",
|
|
|
|
seekable
|
|
|
|
);
|
2016-12-27 15:47:39 +00:00
|
|
|
|
|
|
|
seekable
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-31 22:26:52 +00:00
|
|
|
fn get_position(&self, position: &mut u64) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let demuxer = &self.demuxer.lock().unwrap();
|
|
|
|
|
|
|
|
match demuxer.get_position() {
|
|
|
|
None => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(self.cat, /* TODO obj: demuxer,*/ "Got no position");
|
2016-11-24 14:29:43 +00:00
|
|
|
*position = u64::MAX;
|
2017-07-31 22:26:52 +00:00
|
|
|
glib_ffi::GFALSE
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
Some(pos) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Returning position {}",
|
|
|
|
pos
|
|
|
|
);
|
2016-11-24 14:29:43 +00:00
|
|
|
*position = pos;
|
2017-07-31 22:26:52 +00:00
|
|
|
glib_ffi::GTRUE
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-31 22:26:52 +00:00
|
|
|
fn get_duration(&self, duration: &mut u64) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let demuxer = &self.demuxer.lock().unwrap();
|
|
|
|
|
|
|
|
match demuxer.get_duration() {
|
|
|
|
None => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(self.cat, /* TODO obj: demuxer,*/ "Got no duration");
|
2016-12-27 15:47:39 +00:00
|
|
|
*duration = u64::MAX;
|
2017-07-31 22:26:52 +00:00
|
|
|
glib_ffi::GFALSE
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
2016-12-27 15:47:39 +00:00
|
|
|
Some(dur) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Returning duration {}",
|
|
|
|
dur
|
|
|
|
);
|
2016-12-27 15:47:39 +00:00
|
|
|
*duration = dur;
|
2017-07-31 22:26:52 +00:00
|
|
|
glib_ffi::GTRUE
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn seek(&self, start: u64, stop: u64, offset: &mut u64) -> bool {
|
|
|
|
extern "C" {
|
2017-07-31 22:26:52 +00:00
|
|
|
fn gst_rs_demuxer_stream_eos(raw: *mut gst_ffi::GstElement, index: u32);
|
2016-11-24 14:29:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let stop = if stop == u64::MAX { None } else { Some(stop) };
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_debug!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Seeking to {:?}-{:?}",
|
|
|
|
start,
|
|
|
|
stop
|
|
|
|
);
|
2016-12-27 15:47:39 +00:00
|
|
|
|
2016-11-24 14:29:43 +00:00
|
|
|
let res = {
|
|
|
|
let mut demuxer = &mut self.demuxer.lock().unwrap();
|
|
|
|
|
|
|
|
match demuxer.seek(start, stop) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(ref msg) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_error!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Failed to seek: {:?}",
|
|
|
|
msg
|
|
|
|
);
|
2016-11-24 14:29:43 +00:00
|
|
|
self.post_message(msg);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match res {
|
2016-12-27 15:47:39 +00:00
|
|
|
SeekResult::TooEarly => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_debug!(self.cat, /* TODO obj: demuxer,*/ "Seeked too early");
|
2016-12-27 15:47:39 +00:00
|
|
|
false
|
|
|
|
}
|
2016-11-24 14:29:43 +00:00
|
|
|
SeekResult::Ok(off) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(self.cat, /* TODO obj: demuxer,*/ "Seeked successfully");
|
2016-11-24 14:29:43 +00:00
|
|
|
*offset = off;
|
|
|
|
true
|
|
|
|
}
|
|
|
|
SeekResult::Eos => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_debug!(self.cat, /* TODO obj: demuxer,*/ "Seeked after EOS");
|
2016-11-24 14:29:43 +00:00
|
|
|
*offset = u64::MAX;
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
gst_rs_demuxer_stream_eos(self.raw, u32::MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
fn handle_buffer(&self, buffer: gst::Buffer) -> gst::FlowReturn {
|
2016-11-24 14:29:43 +00:00
|
|
|
extern "C" {
|
2017-07-31 22:26:52 +00:00
|
|
|
fn gst_rs_demuxer_stream_eos(raw: *mut gst_ffi::GstElement, index: u32);
|
2017-07-31 13:36:35 +00:00
|
|
|
fn gst_rs_demuxer_add_stream(
|
2017-07-31 22:26:52 +00:00
|
|
|
raw: *mut gst_ffi::GstElement,
|
2017-07-31 13:36:35 +00:00
|
|
|
index: u32,
|
2017-07-31 22:26:52 +00:00
|
|
|
caps: *const gst_ffi::GstCaps,
|
2017-07-31 13:36:35 +00:00
|
|
|
stream_id: *const c_char,
|
|
|
|
);
|
2017-07-31 22:26:52 +00:00
|
|
|
fn gst_rs_demuxer_added_all_streams(raw: *mut gst_ffi::GstElement);
|
|
|
|
// fn gst_rs_demuxer_remove_all_streams(raw: *mut gst_ffi::GstElement);
|
2017-07-31 13:36:35 +00:00
|
|
|
fn gst_rs_demuxer_stream_format_changed(
|
2017-07-31 22:26:52 +00:00
|
|
|
raw: *mut gst_ffi::GstElement,
|
2017-07-31 13:36:35 +00:00
|
|
|
index: u32,
|
2017-07-31 22:26:52 +00:00
|
|
|
caps: *const gst_ffi::GstCaps,
|
2017-07-31 13:36:35 +00:00
|
|
|
);
|
|
|
|
fn gst_rs_demuxer_stream_push_buffer(
|
2017-07-31 22:26:52 +00:00
|
|
|
raw: *mut gst_ffi::GstElement,
|
2017-07-31 13:36:35 +00:00
|
|
|
index: u32,
|
2017-07-31 22:26:52 +00:00
|
|
|
buffer: *mut gst_ffi::GstBuffer,
|
|
|
|
) -> gst_ffi::GstFlowReturn;
|
2016-11-24 14:29:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let mut res = {
|
|
|
|
let mut demuxer = &mut self.demuxer.lock().unwrap();
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Handling buffer {:?}",
|
|
|
|
buffer
|
|
|
|
);
|
2016-12-27 15:47:39 +00:00
|
|
|
|
2016-11-24 14:29:43 +00:00
|
|
|
match demuxer.handle_buffer(Some(buffer)) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(flow_error) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_error!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Failed handling buffer: {:?}",
|
|
|
|
flow_error
|
|
|
|
);
|
2016-11-24 14:29:43 +00:00
|
|
|
match flow_error {
|
2017-07-31 13:36:35 +00:00
|
|
|
FlowError::NotNegotiated(ref msg) | FlowError::Error(ref msg) => {
|
|
|
|
self.post_message(msg)
|
|
|
|
}
|
2016-11-24 14:29:43 +00:00
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
return flow_error.to_native();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Loop until AllEos, NeedMoreData or error when pushing downstream
|
|
|
|
loop {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(self.cat, /* TODO obj: demuxer,*/ "Handled {:?}", res);
|
2016-12-27 15:47:39 +00:00
|
|
|
|
2016-11-24 14:29:43 +00:00
|
|
|
match res {
|
|
|
|
HandleBufferResult::NeedMoreData => {
|
2017-09-16 17:35:01 +00:00
|
|
|
return gst::FlowReturn::Ok;
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
2017-09-16 17:35:01 +00:00
|
|
|
HandleBufferResult::StreamAdded(stream) => unsafe {
|
|
|
|
gst_rs_demuxer_add_stream(
|
|
|
|
self.raw,
|
|
|
|
stream.index,
|
|
|
|
stream.caps.to_glib_none().0,
|
|
|
|
stream.stream_id.to_glib_none().0,
|
|
|
|
);
|
|
|
|
},
|
2016-11-24 14:29:43 +00:00
|
|
|
HandleBufferResult::HaveAllStreams => unsafe {
|
|
|
|
gst_rs_demuxer_added_all_streams(self.raw);
|
|
|
|
},
|
2016-12-30 11:11:30 +00:00
|
|
|
HandleBufferResult::StreamChanged(stream) => unsafe {
|
2017-07-31 13:36:35 +00:00
|
|
|
gst_rs_demuxer_stream_format_changed(
|
|
|
|
self.raw,
|
|
|
|
stream.index,
|
2017-09-16 17:35:01 +00:00
|
|
|
stream.caps.to_glib_none().0,
|
2017-07-31 13:36:35 +00:00
|
|
|
);
|
2016-12-30 11:11:30 +00:00
|
|
|
},
|
2017-07-31 13:36:35 +00:00
|
|
|
HandleBufferResult::StreamsChanged(streams) => for stream in streams {
|
|
|
|
unsafe {
|
|
|
|
gst_rs_demuxer_stream_format_changed(
|
|
|
|
self.raw,
|
|
|
|
stream.index,
|
2017-09-16 17:35:01 +00:00
|
|
|
stream.caps.to_glib_none().0,
|
2017-07-31 13:36:35 +00:00
|
|
|
);
|
2016-12-04 18:24:44 +00:00
|
|
|
}
|
2017-07-31 13:36:35 +00:00
|
|
|
},
|
2016-11-24 14:29:43 +00:00
|
|
|
HandleBufferResult::BufferForStream(index, buffer) => {
|
|
|
|
let flow_ret = unsafe {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_rs_demuxer_stream_push_buffer(self.raw, index, buffer.into_ptr())
|
2016-11-24 14:29:43 +00:00
|
|
|
};
|
2017-07-31 22:26:52 +00:00
|
|
|
if flow_ret != gst_ffi::GST_FLOW_OK {
|
2017-09-16 17:35:01 +00:00
|
|
|
return from_glib(flow_ret);
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
HandleBufferResult::Eos(index) => {
|
|
|
|
let index = index.unwrap_or(u32::MAX);
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
gst_rs_demuxer_stream_eos(self.raw, index);
|
|
|
|
}
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
return gst::FlowReturn::Eos;
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
HandleBufferResult::Again => {
|
|
|
|
// nothing, just call again
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_trace!(self.cat, /* TODO obj: demuxer,*/ "Calling again");
|
2016-12-27 15:47:39 +00:00
|
|
|
|
2016-11-24 14:29:43 +00:00
|
|
|
res = {
|
|
|
|
let mut demuxer = &mut self.demuxer.lock().unwrap();
|
|
|
|
match demuxer.handle_buffer(None) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(flow_error) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_error!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Failed calling again: {:?}",
|
|
|
|
flow_error
|
|
|
|
);
|
2016-11-24 14:29:43 +00:00
|
|
|
match flow_error {
|
2017-07-31 13:36:35 +00:00
|
|
|
FlowError::NotNegotiated(ref msg) | FlowError::Error(ref msg) => {
|
|
|
|
self.post_message(msg)
|
|
|
|
}
|
2016-11-24 14:29:43 +00:00
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
return flow_error.to_native();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn end_of_stream(&self) {
|
|
|
|
let mut demuxer = &mut self.demuxer.lock().unwrap();
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_debug!(self.cat, /* TODO obj: demuxer,*/ "End of stream");
|
2016-11-24 14:29:43 +00:00
|
|
|
match demuxer.end_of_stream() {
|
|
|
|
Ok(_) => (),
|
|
|
|
Err(ref msg) => {
|
2017-09-16 17:35:01 +00:00
|
|
|
gst_error!(
|
|
|
|
self.cat,
|
|
|
|
/* TODO obj: demuxer,*/ "Failed end of stream: {:?}",
|
|
|
|
msg
|
|
|
|
);
|
2016-11-24 14:29:43 +00:00
|
|
|
self.post_message(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn post_message(&self, msg: &ErrorMessage) {
|
|
|
|
unsafe {
|
2017-09-16 17:35:01 +00:00
|
|
|
msg.post(&gst::Element::from_glib_borrow(self.raw));
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 13:36:35 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_new(
|
2017-07-31 22:26:52 +00:00
|
|
|
demuxer: *mut gst_ffi::GstElement,
|
2017-09-16 17:35:01 +00:00
|
|
|
create_instance: fn(&gst::Element) -> Box<Demuxer>,
|
2017-07-31 13:36:35 +00:00
|
|
|
) -> *mut DemuxerWrapper {
|
2017-09-16 17:35:01 +00:00
|
|
|
let instance = create_instance(&from_glib_borrow(demuxer));
|
2016-12-25 11:16:12 +00:00
|
|
|
Box::into_raw(Box::new(DemuxerWrapper::new(demuxer, instance)))
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn demuxer_drop(ptr: *mut DemuxerWrapper) {
|
|
|
|
let _ = Box::from_raw(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 13:36:35 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_start(
|
|
|
|
ptr: *const DemuxerWrapper,
|
|
|
|
upstream_size: u64,
|
2017-07-31 22:26:52 +00:00
|
|
|
random_access: glib_ffi::gboolean,
|
|
|
|
) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let wrap: &DemuxerWrapper = &*ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
false,
|
|
|
|
{ wrap.start(upstream_size, random_access != glib_ffi::GFALSE) }
|
|
|
|
).to_glib()
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 22:26:52 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_stop(ptr: *const DemuxerWrapper) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let wrap: &DemuxerWrapper = &*ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
glib_ffi::GTRUE,
|
|
|
|
{
|
|
|
|
if wrap.stop() {
|
|
|
|
glib_ffi::GTRUE
|
|
|
|
} else {
|
|
|
|
glib_ffi::GFALSE
|
|
|
|
}
|
2017-04-09 21:29:07 +00:00
|
|
|
}
|
2017-09-16 17:35:01 +00:00
|
|
|
)
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 22:26:52 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_is_seekable(ptr: *const DemuxerWrapper) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let wrap: &DemuxerWrapper = &*ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
glib_ffi::GFALSE,
|
|
|
|
{
|
|
|
|
if wrap.is_seekable() {
|
|
|
|
glib_ffi::GTRUE
|
|
|
|
} else {
|
|
|
|
glib_ffi::GFALSE
|
|
|
|
}
|
2017-04-09 21:29:07 +00:00
|
|
|
}
|
2017-09-16 17:35:01 +00:00
|
|
|
)
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 13:36:35 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_get_position(
|
|
|
|
ptr: *const DemuxerWrapper,
|
|
|
|
position: *mut u64,
|
2017-07-31 22:26:52 +00:00
|
|
|
) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let wrap: &DemuxerWrapper = &*ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
glib_ffi::GFALSE,
|
|
|
|
{
|
|
|
|
let position = &mut *position;
|
|
|
|
wrap.get_position(position)
|
|
|
|
}
|
|
|
|
)
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 13:36:35 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_get_duration(
|
|
|
|
ptr: *const DemuxerWrapper,
|
|
|
|
duration: *mut u64,
|
2017-07-31 22:26:52 +00:00
|
|
|
) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let wrap: &DemuxerWrapper = &*ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
glib_ffi::GFALSE,
|
|
|
|
{
|
|
|
|
let duration = &mut *duration;
|
|
|
|
wrap.get_duration(duration)
|
|
|
|
}
|
|
|
|
)
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 13:36:35 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_seek(
|
|
|
|
ptr: *mut DemuxerWrapper,
|
|
|
|
start: u64,
|
|
|
|
stop: u64,
|
|
|
|
offset: *mut u64,
|
2017-07-31 22:26:52 +00:00
|
|
|
) -> glib_ffi::gboolean {
|
2016-11-24 14:29:43 +00:00
|
|
|
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
glib_ffi::GFALSE,
|
|
|
|
{
|
|
|
|
let offset = &mut *offset;
|
2016-11-24 14:29:43 +00:00
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
if wrap.seek(start, stop, offset) {
|
|
|
|
glib_ffi::GTRUE
|
|
|
|
} else {
|
|
|
|
glib_ffi::GFALSE
|
|
|
|
}
|
2017-04-09 21:29:07 +00:00
|
|
|
}
|
2017-09-16 17:35:01 +00:00
|
|
|
)
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-31 13:36:35 +00:00
|
|
|
pub unsafe extern "C" fn demuxer_handle_buffer(
|
|
|
|
ptr: *mut DemuxerWrapper,
|
2017-07-31 22:26:52 +00:00
|
|
|
buffer: *mut gst_ffi::GstBuffer,
|
|
|
|
) -> gst_ffi::GstFlowReturn {
|
2016-11-24 14:29:43 +00:00
|
|
|
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
gst::FlowReturn::Error,
|
|
|
|
{ wrap.handle_buffer(from_glib_full(buffer)) }
|
|
|
|
).to_glib()
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn demuxer_end_of_stream(ptr: *mut DemuxerWrapper) {
|
|
|
|
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
panic_to_error!(
|
|
|
|
wrap,
|
|
|
|
&gst::Element::from_glib_borrow(wrap.raw as *mut _),
|
|
|
|
(),
|
|
|
|
{
|
|
|
|
wrap.end_of_stream();
|
|
|
|
}
|
|
|
|
)
|
2016-11-24 14:29:43 +00:00
|
|
|
}
|
2016-12-23 16:10:38 +00:00
|
|
|
|
|
|
|
pub struct DemuxerInfo<'a> {
|
|
|
|
pub name: &'a str,
|
|
|
|
pub long_name: &'a str,
|
|
|
|
pub description: &'a str,
|
|
|
|
pub classification: &'a str,
|
|
|
|
pub author: &'a str,
|
|
|
|
pub rank: i32,
|
2017-09-16 17:35:01 +00:00
|
|
|
pub create_instance: fn(&gst::Element) -> Box<Demuxer>,
|
|
|
|
pub input_caps: &'a gst::Caps,
|
|
|
|
pub output_caps: &'a gst::Caps,
|
2016-12-23 16:10:38 +00:00
|
|
|
}
|
|
|
|
|
2017-09-16 17:35:01 +00:00
|
|
|
pub fn demuxer_register(plugin: &gst::Plugin, demuxer_info: &DemuxerInfo) {
|
2016-12-23 16:10:38 +00:00
|
|
|
extern "C" {
|
2017-07-31 13:36:35 +00:00
|
|
|
fn gst_rs_demuxer_register(
|
2017-07-31 22:26:52 +00:00
|
|
|
plugin: *const gst_ffi::GstPlugin,
|
2017-07-31 13:36:35 +00:00
|
|
|
name: *const c_char,
|
|
|
|
long_name: *const c_char,
|
|
|
|
description: *const c_char,
|
|
|
|
classification: *const c_char,
|
|
|
|
author: *const c_char,
|
|
|
|
rank: i32,
|
|
|
|
create_instance: *const c_void,
|
2017-07-31 22:26:52 +00:00
|
|
|
input_caps: *const gst_ffi::GstCaps,
|
|
|
|
output_caps: *const gst_ffi::GstCaps,
|
|
|
|
) -> glib_ffi::gboolean;
|
2016-12-23 16:10:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let cname = CString::new(demuxer_info.name).unwrap();
|
|
|
|
let clong_name = CString::new(demuxer_info.long_name).unwrap();
|
|
|
|
let cdescription = CString::new(demuxer_info.description).unwrap();
|
|
|
|
let cclassification = CString::new(demuxer_info.classification).unwrap();
|
|
|
|
let cauthor = CString::new(demuxer_info.author).unwrap();
|
|
|
|
|
|
|
|
unsafe {
|
2017-07-31 13:36:35 +00:00
|
|
|
gst_rs_demuxer_register(
|
2017-09-16 17:35:01 +00:00
|
|
|
plugin.to_glib_none().0,
|
2017-07-31 13:36:35 +00:00
|
|
|
cname.as_ptr(),
|
|
|
|
clong_name.as_ptr(),
|
|
|
|
cdescription.as_ptr(),
|
|
|
|
cclassification.as_ptr(),
|
|
|
|
cauthor.as_ptr(),
|
|
|
|
demuxer_info.rank,
|
|
|
|
demuxer_info.create_instance as *const c_void,
|
2017-09-16 17:35:01 +00:00
|
|
|
demuxer_info.input_caps.to_glib_none().0,
|
|
|
|
demuxer_info.output_caps.to_glib_none().0,
|
2017-07-31 13:36:35 +00:00
|
|
|
);
|
2016-12-23 16:10:38 +00:00
|
|
|
}
|
|
|
|
}
|