diff --git a/Kyoo.Transcoder/src/Stream.h b/Kyoo.Transcoder/src/Stream.h index 4fda3f6f..f873a835 100644 --- a/Kyoo.Transcoder/src/Stream.h +++ b/Kyoo.Transcoder/src/Stream.h @@ -7,12 +7,15 @@ #include -//extern "C" API struct Stream -//{ -// std::string title; -// std::string languageCode; -// std::string format; -// bool isDefault; -// bool isForced; -// std::string path; -//}; \ No newline at end of file +extern "C" struct Stream +{ + std::string title; + std::string language; + std::string format; + bool isDefault; + bool isForced; + std::string path; + + Stream(std::string title, std::string languageCode, std::string format, bool isDefault, bool isForced, std::string path) + : title(title), language(languageCode), format(format), isDefault(isDefault), isForced(isForced), path(path) { } +}; \ No newline at end of file diff --git a/Kyoo.Transcoder/src/Transcoder.cpp b/Kyoo.Transcoder/src/Transcoder.cpp index fbb52852..24ac4a50 100644 --- a/Kyoo.Transcoder/src/Transcoder.cpp +++ b/Kyoo.Transcoder/src/Transcoder.cpp @@ -21,24 +21,25 @@ int Init() return 42; } -void ExtractSubtitles(const char* path, const char* outPath) +int ExtractSubtitles(const char* path, const char* outPath, Stream* streams) { AVFormatContext* inputContext = NULL; if (avformat_open_input(&inputContext, path, NULL, NULL)) { std::cout << "Error: Can't open the file at " << path << std::endl; - return; + return 0; } if (avformat_find_stream_info(inputContext, NULL) < 0) { std::cout << "Error: Could't find streams informations for the file at " << path << std::endl; - return; + return 0; } av_dump_format(inputContext, 0, path, false); + std::vector subtitleStreams; const unsigned int outputCount = inputContext->nb_streams; AVFormatContext** outputList = new AVFormatContext*[outputCount]; @@ -53,13 +54,20 @@ void ExtractSubtitles(const char* path, const char* outPath) else { //Get metadata for file name - const char* language = av_dict_get(inputStream->metadata, "language", NULL, 0)->value; + Stream stream("title", //title + av_dict_get(inputStream->metadata, "language", NULL, 0)->value, //language + "format", //format + false, //isDefault + false, //isForced + "path"); //path - std::cout << "Stream #" << i << "(" << language << "), stream type: " << inputCodecpar->codec_type << " codec: " << inputCodecpar->codec_tag << std::endl; + subtitleStreams.push_back(stream); + + std::cout << "Stream #" << i << "(" << stream.language << "), stream type: " << inputCodecpar->codec_type << " codec: " << inputCodecpar->codec_tag << std::endl; //Create output folder std::stringstream outStream; - outStream << outPath << (char)std::filesystem::path::preferred_separator << language; + outStream << outPath << (char)std::filesystem::path::preferred_separator << stream.language; std::filesystem::create_directory(outStream.str()); //Get file name @@ -68,7 +76,7 @@ void ExtractSubtitles(const char* path, const char* outPath) fileName = fileName.substr(lastSeparator, fileName.find_last_of('.') - lastSeparator); //Construct output file name - outStream << fileName << "." << language; + outStream << fileName << "." << stream.language; outStream << ".ass"; std::string outStr = outStream.str(); const char* output = outStr.c_str(); @@ -204,4 +212,8 @@ void ExtractSubtitles(const char* path, const char* outPath) } delete[] outputList; + + //std::copy() + //streams = subtitleStreams.data(); //SHOULDN'T COPY LIKE THAT, WE OVERRIDE THE POINTER HERE. + return subtitleStreams.size(); } \ No newline at end of file diff --git a/Kyoo.Transcoder/src/Transcoder.h b/Kyoo.Transcoder/src/Transcoder.h index d809e6dd..77f5f536 100644 --- a/Kyoo.Transcoder/src/Transcoder.h +++ b/Kyoo.Transcoder/src/Transcoder.h @@ -11,4 +11,5 @@ extern "C" API int Init(); -extern "C" API void ExtractSubtitles(const char* path, const char* outPath); +//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 int ExtractSubtitles(const char* path, const char* outPath, Stream* streams); diff --git a/Kyoo/InternalAPI/Crawler/Crawler.cs b/Kyoo/InternalAPI/Crawler/Crawler.cs index 378dff8b..724e87d3 100644 --- a/Kyoo/InternalAPI/Crawler/Crawler.cs +++ b/Kyoo/InternalAPI/Crawler/Crawler.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Stream = Kyoo.Models.Watch.Stream; namespace Kyoo.InternalAPI { @@ -16,12 +17,14 @@ namespace Kyoo.InternalAPI private readonly IConfiguration config; private readonly ILibraryManager libraryManager; private readonly IMetadataProvider metadataProvider; + private readonly ITranscoder transcoder; - public Crawler(IConfiguration configuration, ILibraryManager libraryManager, IMetadataProvider metadataProvider) + public Crawler(IConfiguration configuration, ILibraryManager libraryManager, IMetadataProvider metadataProvider, ITranscoder transcoder) { config = configuration; this.libraryManager = libraryManager; this.metadataProvider = metadataProvider; + this.transcoder = transcoder; } public Task StartAsync(CancellationToken cancellationToken) @@ -140,7 +143,10 @@ namespace Kyoo.InternalAPI Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, path); episode.ShowID = showID; episode.SeasonID = seasonID; - libraryManager.RegisterEpisode(episode); + long episodeID = libraryManager.RegisterEpisode(episode); + + Stream[] streams = transcoder.ExtractSubtitles(episode.Path); + //libraryManager.RegisterStreams(episodeID, streams); } } diff --git a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs index 88ef1bd1..d0660715 100644 --- a/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs +++ b/Kyoo/InternalAPI/LibraryManager/LibraryManager.cs @@ -205,10 +205,10 @@ namespace Kyoo.InternalAPI { Stream stream = Stream.FromReader(reader); - if (stream.type == StreamType.Audio) - audios.Add(stream); - else if (stream.type == StreamType.Subtitle) - subtitles.Add(stream); + //if (stream.type == StreamType.Audio) + // audios.Add(stream); + //else if (stream.type == StreamType.Subtitle) + // subtitles.Add(stream); } return (audios, subtitles); diff --git a/Kyoo/InternalAPI/Transcoder/ITranscoder.cs b/Kyoo/InternalAPI/Transcoder/ITranscoder.cs index 2c2aa716..7cabd66d 100644 --- a/Kyoo/InternalAPI/Transcoder/ITranscoder.cs +++ b/Kyoo/InternalAPI/Transcoder/ITranscoder.cs @@ -1,3 +1,5 @@ +using Kyoo.Models.Watch; + namespace Kyoo.InternalAPI { public interface ITranscoder @@ -9,6 +11,6 @@ namespace Kyoo.InternalAPI string Transcode(string path); //Extract all subtitles of a video and save them in the subtitles sub-folder. - void ExtractSubtitles(string path); + Stream[] ExtractSubtitles(string path); } } diff --git a/Kyoo/InternalAPI/Transcoder/Transcoder.cs b/Kyoo/InternalAPI/Transcoder/Transcoder.cs index fda8d94f..94258ede 100644 --- a/Kyoo/InternalAPI/Transcoder/Transcoder.cs +++ b/Kyoo/InternalAPI/Transcoder/Transcoder.cs @@ -2,6 +2,7 @@ using Kyoo.InternalAPI.TranscoderLink; using Microsoft.Extensions.Configuration; using System.Diagnostics; using System.IO; +using Stream = Kyoo.Models.Watch.Stream; namespace Kyoo.InternalAPI { @@ -12,11 +13,13 @@ namespace Kyoo.InternalAPI Debug.WriteLine("&Api INIT: " + TranscoderAPI.Init()); } - public void ExtractSubtitles(string path) + public Stream[] ExtractSubtitles(string path) { string output = Path.Combine(Path.GetDirectoryName(path), "Subtitles"); Directory.CreateDirectory(output); - TranscoderAPI.ExtractSubtitles(path, output); + TranscoderAPI.ExtractSubtitles(path, output, out Stream[] streams); + + return streams; } public void GetVideo(string path) diff --git a/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs b/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs index 32f0aa9f..4d9b6aa4 100644 --- a/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs +++ b/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs @@ -1,4 +1,6 @@ -using System.Runtime.InteropServices; +using System; +using System.Runtime.InteropServices; +using Kyoo.Models.Watch; namespace Kyoo.InternalAPI.TranscoderLink { @@ -10,6 +12,25 @@ namespace Kyoo.InternalAPI.TranscoderLink public extern static int Init(); [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] - public extern static void ExtractSubtitles(string path, string outPath); + private extern static int ExtractSubtitles(string path, string outPath, out IntPtr streams); + + public static void ExtractSubtitles(string path, string outPath, out Stream[] streams) + { + int size = Marshal.SizeOf(); + + int length = ExtractSubtitles(path, outPath, out IntPtr streamsPtr); //The streamsPtr is always nullptr + if (length > 0) + { + streams = new Stream[length]; + + for (int i = 0; i < length; i++) + { + streams[i] = Marshal.PtrToStructure(streamsPtr); + streamsPtr += size; + } + } + else + streams = null; + } } } diff --git a/Kyoo/Models/Stream.cs b/Kyoo/Models/Stream.cs index dd91de5e..28deb770 100644 --- a/Kyoo/Models/Stream.cs +++ b/Kyoo/Models/Stream.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using System.Runtime.InteropServices; namespace Kyoo.Models.Watch { @@ -7,40 +8,42 @@ namespace Kyoo.Models.Watch Audio, Subtitle, Unknow } + [StructLayout(LayoutKind.Sequential)] public class Stream { - [JsonIgnore] public StreamType type; public string Title; public string Language; + public string Format; public bool IsDefault; public bool IsForced; - public string Format; - - [JsonIgnore] public bool IsExternal; [JsonIgnore] public string Path; - public Stream(StreamType type, string title, string language, bool isDefault, bool isForced, string format, bool isExternal, string path) - { - this.type = type; - Title = title; - Language = language; - IsDefault = isDefault; - IsForced = isForced; - Format = format; - IsExternal = isExternal; - Path = path; - } + //[JsonIgnore] public StreamType type; + //[JsonIgnore] public bool IsExternal; + + //public Stream(StreamType type, string title, string language, bool isDefault, bool isForced, string format, bool isExternal, string path) + //{ + // this.type = type; + // Title = title; + // Language = language; + // IsDefault = isDefault; + // IsForced = isForced; + // Format = format; + // IsExternal = isExternal; + // Path = path; + //} public static Stream FromReader(System.Data.SQLite.SQLiteDataReader reader) { - return new Stream(reader["streamType"] as StreamType? ?? StreamType.Unknow, - reader["title"] as string, - reader["language"] as string, - reader["isDefault"] as bool? ?? false, - reader["isForced"] as bool? ?? false, - reader["codec"] as string, - reader["isExternal"] as bool? ?? false, - reader["path"] as string); + return new Stream(); + //return new Stream(reader["streamType"] as StreamType? ?? StreamType.Unknow, + // reader["title"] as string, + // reader["language"] as string, + // reader["isDefault"] as bool? ?? false, + // reader["isForced"] as bool? ?? false, + // reader["codec"] as string, + // reader["isExternal"] as bool? ?? false, + // reader["path"] as string); } } }