You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
4.2 KiB
Rust

#![allow(dead_code)]
use crate::av::init;
use crate::transcoder_manager::{TranscoderInstance, TranscoderManager};
use async_std::fs::File;
use async_std::sync::{Arc, RwLock};
use ffmpeg_sys_next::{av_make_error_string, av_malloc, av_version_info};
use http_types::Error as HttpError;
use lazy_static::lazy_static;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::option::Option::Some;
use std::os::raw::{c_char, c_int};
use std::str::FromStr;
use tide::{Request, StatusCode};
use uuid::Uuid;
pub mod av;
pub mod transcoder;
pub mod transcoder_manager;
pub mod utils;
// const INPUT_PATH: &str = "/tank/ephemeral/anime/series/Witch Hunter Robin - 2ndfire/[2ndfire]Witch_Hunter_Robin_-_01[91DCE49A].mkv";
const INPUT_PATH: &str = "/tank/ephemeral/anime/series/Brave Witches - Eila/Extras/[Eila] Brave Witches - NCOP [BD 1080p][DB44ED0B].mkv";
const OUTPUT_PATH: &str = "/tmp/transotf";
fn av_err2str(error_code: c_int) -> String {
unsafe {
let str: *mut c_char = av_malloc(1024).cast();
av_make_error_string(str, 1024, error_code);
CString::from_raw(str).to_str().unwrap().to_string()
}
}
lazy_static! {
static ref HOME_PAGE: String = {
format!(
"{}: {}\nffmpeg: {}",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
unsafe { CStr::from_ptr(av_version_info()).to_str().unwrap_or("n/a") },
)
};
}
#[derive(Default)]
struct State {
manager: RwLock<TranscoderManager>,
}
async fn create_transcode(req: Request<State>) -> Result<String, HttpError> {
let params = req.query::<HashMap<String, String>>()?;
let target = params.get(&"target".to_string());
let target = if let Some(target) = target {
target
} else {
return Err(HttpError::from_str(
StatusCode::BadRequest,
"no target given",
));
};
{
File::open(target).await.map_err(|err| {
HttpError::from_str(
StatusCode::BadRequest,
format!("Failed to open file: {}", err),
)
})?;
}
let id = req
.state()
.manager
.write()
.await
.start(target.clone(), None, None)
.map_err(|err| {
HttpError::from_str(
StatusCode::InternalServerError,
format!("Failed to start transcoder: {}", err),
)
})?;
Ok(format!("{}", id))
}
async fn get_init(req: Request<State>) -> Result<String, HttpError> {
let _manager = req.state().manager.read().await;
// manager.get()
Err(HttpError::from_str(StatusCode::NotFound, ":3"))
}
async fn get_instance(req: &Request<State>) -> Result<Arc<TranscoderInstance>, HttpError> {
let id = req.param::<String>("id")?;
let id = Uuid::from_str(&id)?;
let manager = req.state().manager.read().await;
if let Some(instance) = manager.get(id) {
Ok(instance)
} else {
Err(HttpError::from_str(
StatusCode::NotFound,
format!("Can't find transcoder with id {}", id),
))
}
}
async fn get_manifest(req: Request<State>) -> Result<String, HttpError> {
let transcoder_instance = get_instance(&req).await?;
let (duration, segments, init_written) = transcoder_instance
.state(|item| {
(
item.duration(),
item.segments().clone(),
item.init_written(),
)
.clone()
})
.await;
Ok(format!("{} {:?} {}", duration, segments, init_written))
}
// async fn get_status(req: Request<State>) -> Result<String, HttpError> {
// let id = req.param::<String>("id")?;
// let id = Uuid::from_str(&id)?;
// let manager = req.state().manager.read().await;
// }
#[async_std::main]
async fn main() -> std::io::Result<()> {
println!("{}", HOME_PAGE.clone());
init();
let mut app = tide::with_state(State::default());
app.at("/").get(|_| async { Ok(HOME_PAGE.clone()) });
app.at("/transcode").get(create_transcode);
// app.at("/session/:id").get(get_status);
app.at("/session/:id/manifest").get(get_manifest);
// app.at("/session/:id/{type}/init.mp4");
// app.at("/session/:id/{type}/{nr}.m4s");
app.listen("0:8000").await
}