diff --git a/Kyoo.Transcoder/include/transcoder.h b/Kyoo.Transcoder/include/transcoder.h index ae76c326..24a7e338 100644 --- a/Kyoo.Transcoder/include/transcoder.h +++ b/Kyoo.Transcoder/include/transcoder.h @@ -11,7 +11,7 @@ extern "C" API int Init(); -extern "C" API int transmux(const char *path, const char *outPath); +extern "C" API int transmux(const char *path, const char *out_path, float *playable_duration); //Take the path of the file and the path of the output directory. It will return the list of subtitle streams in the streams variable. The int returned is the number of subtitles extracted. extern "C" API Stream* extract_subtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount); diff --git a/Kyoo.Transcoder/src/Transcoder.cpp b/Kyoo.Transcoder/src/Transcoder.cpp index 51d1c18f..18fae9fc 100644 --- a/Kyoo.Transcoder/src/Transcoder.cpp +++ b/Kyoo.Transcoder/src/Transcoder.cpp @@ -8,7 +8,7 @@ int Init() return sizeof(Stream); } -int transmux(const char *path, const char *out_path) +int transmux(const char *path, const char *out_path, float *playable_duration) { AVFormatContext *in_ctx = NULL; AVFormatContext *out_ctx = NULL; @@ -19,6 +19,7 @@ int transmux(const char *path, const char *out_path) int stream_count; int ret = 0; + *playable_duration = 0; if (open_input_context(&in_ctx, path) != 0) return 1; @@ -73,6 +74,8 @@ int transmux(const char *path, const char *out_path) stream = in_ctx->streams[pkt.stream_index]; pkt.stream_index = stream_map[pkt.stream_index]; process_packet(pkt, stream, out_ctx->streams[pkt.stream_index]); + if (pkt.stream_index == 0) + *playable_duration += pkt.duration * (float)out_ctx->streams[pkt.stream_index]->time_base.num / out_ctx->streams[pkt.stream_index]->time_base.den; if (av_interleaved_write_frame(out_ctx, &pkt) < 0) std::cout << "Error while writing a packet to the output file." << std::endl; diff --git a/Kyoo/.editorconfig b/Kyoo/.editorconfig new file mode 100644 index 00000000..d7809230 --- /dev/null +++ b/Kyoo/.editorconfig @@ -0,0 +1,7 @@ +[*.cs] + +# CS4014: Because this call is not awaited, execution of the current method continues before the call is completed +dotnet_diagnostic.CS4014.severity = silent + +# IDE1006: Naming Styles +dotnet_diagnostic.IDE1006.severity = none diff --git a/Kyoo/Controllers/VideoController.cs b/Kyoo/Controllers/VideoController.cs index 28c69026..b1a55ce5 100644 --- a/Kyoo/Controllers/VideoController.cs +++ b/Kyoo/Controllers/VideoController.cs @@ -3,6 +3,7 @@ using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System.IO; +using System.Threading.Tasks; namespace Kyoo.Controllers { @@ -33,13 +34,13 @@ namespace Kyoo.Controllers } [HttpGet("transmux/{showSlug}-s{seasonNumber}e{episodeNumber}/")] - public IActionResult Transmux(string showSlug, long seasonNumber, long episodeNumber) + public async Task Transmux(string showSlug, long seasonNumber, long episodeNumber) { WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber); if (episode != null && System.IO.File.Exists(episode.Path)) { - string path = transcoder.Transmux(episode); + string path = await transcoder.Transmux(episode); if (path != null) return PhysicalFile(path, "application/dash+xml", true); else @@ -61,15 +62,16 @@ namespace Kyoo.Controllers [HttpGet("transcode/{showSlug}-s{seasonNumber}e{episodeNumber}")] public IActionResult Transcode(string showSlug, long seasonNumber, long episodeNumber) { - WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber); + return null; + //WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber); - if (episode != null && System.IO.File.Exists(episode.Path)) - { - string path = transcoder.Transcode(episode.Path); - return PhysicalFile(path, "video/mp4", true); //Should use mpeg dash - } - else - return NotFound(); + //if (episode != null && System.IO.File.Exists(episode.Path)) + //{ + // string path = transcoder.Transcode(episode.Path); + // return PhysicalFile(path, "video/mp4", true); //Should use mpeg dash + //} + //else + // return NotFound(); } } } \ No newline at end of file diff --git a/Kyoo/GlobalSuppressions.cs b/Kyoo/GlobalSuppressions.cs deleted file mode 100644 index 7f23fd1a..00000000 --- a/Kyoo/GlobalSuppressions.cs +++ /dev/null @@ -1,8 +0,0 @@ -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "C++ bindings", Scope = "member", Target = "~M:Kyoo.InternalAPI.TranscoderLink.TranscoderAPI.transmux(System.String,System.String)~System.Int32")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "C++ bindings", Scope = "member", Target = "~M:Kyoo.InternalAPI.TranscoderLink.TranscoderAPI.free_memory(System.IntPtr)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "C++ bindings", Scope = "member", Target = "~M:Kyoo.InternalAPI.TranscoderLink.TranscoderAPI.extract_subtitles(System.String,System.String,System.Int32@,System.Int32@)~System.IntPtr")] diff --git a/Kyoo/InternalAPI/Transcoder/ITranscoder.cs b/Kyoo/InternalAPI/Transcoder/ITranscoder.cs index a264846f..8fdb59d7 100644 --- a/Kyoo/InternalAPI/Transcoder/ITranscoder.cs +++ b/Kyoo/InternalAPI/Transcoder/ITranscoder.cs @@ -7,10 +7,10 @@ namespace Kyoo.InternalAPI public interface ITranscoder { //Should transcode to a mp4 container (same video/audio format if possible, no subtitles). - string Transmux(WatchItem episode); + Task Transmux(WatchItem episode); //Should transcode to a mp4 container with a h264 video format and a AAC audio format, no subtitles. - string Transcode(string path); + Task Transcode(WatchItem episode); //Extract all subtitles of a video and save them in the subtitles sub-folder. Task ExtractSubtitles(string path); diff --git a/Kyoo/InternalAPI/Transcoder/Transcoder.cs b/Kyoo/InternalAPI/Transcoder/Transcoder.cs index 910739ee..71f64930 100644 --- a/Kyoo/InternalAPI/Transcoder/Transcoder.cs +++ b/Kyoo/InternalAPI/Transcoder/Transcoder.cs @@ -31,22 +31,29 @@ namespace Kyoo.InternalAPI }); } - public string Transmux(WatchItem episode) + public async Task Transmux(WatchItem episode) { string folder = Path.Combine(transmuxPath, episode.Link); string manifest = Path.Combine(folder, episode.Link + ".mpd"); + float playableDuration = 0; + bool transmuxFailed = false; Directory.CreateDirectory(folder); Debug.WriteLine("&Transmuxing " + episode.Link + " at " + episode.Path + ", outputPath: " + folder); - //FFMPEG require us to put DirectorySeparaorChar as '/' for his internal regex. - if (File.Exists(manifest) || TranscoderAPI.transmux(episode.Path, manifest.Replace('\\', '/')) == 0) + if (File.Exists(manifest)) return manifest; - else - return null; + Task.Run(() => + { + transmuxFailed = TranscoderAPI.transmux(episode.Path, manifest.Replace('\\', '/'), out playableDuration) != 0; + playableDuration = float.MaxValue; + }); + while (playableDuration < 20 || (!File.Exists(manifest) && !transmuxFailed)) + await Task.Delay(10); + return transmuxFailed ? null : manifest; } - public string Transcode(string path) + public Task Transcode(WatchItem episode) { //NOT IMPLEMENTED YET return null; diff --git a/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs b/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs index 015ccd94..78fbe864 100644 --- a/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs +++ b/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Watch; @@ -14,7 +15,7 @@ namespace Kyoo.InternalAPI.TranscoderLink public extern static int Init(); [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] - public extern static int transmux(string path, string out_path); + public extern static int transmux(string path, string out_path, out float playableDuration); [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] private extern static IntPtr extract_subtitles(string path, string out_path, out int array_length, out int track_count);