#![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, } async fn create_transcode(req: Request) -> Result { let params = req.query::>()?; 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) -> Result { let _manager = req.state().manager.read().await; // manager.get() Err(HttpError::from_str(StatusCode::NotFound, ":3")) } async fn get_instance(req: &Request) -> Result, HttpError> { let id = req.param::("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) -> Result { 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) -> Result { // let id = req.param::("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 }