Adding stream detections in the Subtitle Extract and adding logic into the c# linker.

This commit is contained in:
Zoe Roux 2019-09-14 03:16:08 +02:00
parent 40d8575e55
commit 1ced45a763
9 changed files with 102 additions and 51 deletions

View File

@ -7,12 +7,15 @@
#include <iostream> #include <iostream>
//extern "C" API struct Stream extern "C" struct Stream
//{ {
// std::string title; std::string title;
// std::string languageCode; std::string language;
// std::string format; std::string format;
// bool isDefault; bool isDefault;
// bool isForced; bool isForced;
// std::string path; 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) { }
};

View File

@ -21,24 +21,25 @@ int Init()
return 42; return 42;
} }
void ExtractSubtitles(const char* path, const char* outPath) int ExtractSubtitles(const char* path, const char* outPath, Stream* streams)
{ {
AVFormatContext* inputContext = NULL; AVFormatContext* inputContext = NULL;
if (avformat_open_input(&inputContext, path, NULL, NULL)) if (avformat_open_input(&inputContext, path, NULL, NULL))
{ {
std::cout << "Error: Can't open the file at " << path << std::endl; std::cout << "Error: Can't open the file at " << path << std::endl;
return; return 0;
} }
if (avformat_find_stream_info(inputContext, NULL) < 0) if (avformat_find_stream_info(inputContext, NULL) < 0)
{ {
std::cout << "Error: Could't find streams informations for the file at " << path << std::endl; 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); av_dump_format(inputContext, 0, path, false);
std::vector<Stream> subtitleStreams;
const unsigned int outputCount = inputContext->nb_streams; const unsigned int outputCount = inputContext->nb_streams;
AVFormatContext** outputList = new AVFormatContext*[outputCount]; AVFormatContext** outputList = new AVFormatContext*[outputCount];
@ -53,13 +54,20 @@ void ExtractSubtitles(const char* path, const char* outPath)
else else
{ {
//Get metadata for file name //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 //Create output folder
std::stringstream outStream; 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()); std::filesystem::create_directory(outStream.str());
//Get file name //Get file name
@ -68,7 +76,7 @@ void ExtractSubtitles(const char* path, const char* outPath)
fileName = fileName.substr(lastSeparator, fileName.find_last_of('.') - lastSeparator); fileName = fileName.substr(lastSeparator, fileName.find_last_of('.') - lastSeparator);
//Construct output file name //Construct output file name
outStream << fileName << "." << language; outStream << fileName << "." << stream.language;
outStream << ".ass"; outStream << ".ass";
std::string outStr = outStream.str(); std::string outStr = outStream.str();
const char* output = outStr.c_str(); const char* output = outStr.c_str();
@ -204,4 +212,8 @@ void ExtractSubtitles(const char* path, const char* outPath)
} }
delete[] outputList; delete[] outputList;
//std::copy()
//streams = subtitleStreams.data(); //SHOULDN'T COPY LIKE THAT, WE OVERRIDE THE POINTER HERE.
return subtitleStreams.size();
} }

View File

@ -11,4 +11,5 @@
extern "C" API int Init(); 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);

View File

@ -8,6 +8,7 @@ using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Stream = Kyoo.Models.Watch.Stream;
namespace Kyoo.InternalAPI namespace Kyoo.InternalAPI
{ {
@ -16,12 +17,14 @@ namespace Kyoo.InternalAPI
private readonly IConfiguration config; private readonly IConfiguration config;
private readonly ILibraryManager libraryManager; private readonly ILibraryManager libraryManager;
private readonly IMetadataProvider metadataProvider; 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; config = configuration;
this.libraryManager = libraryManager; this.libraryManager = libraryManager;
this.metadataProvider = metadataProvider; this.metadataProvider = metadataProvider;
this.transcoder = transcoder;
} }
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
@ -140,7 +143,10 @@ namespace Kyoo.InternalAPI
Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, path); Episode episode = await metadataProvider.GetEpisode(showProviderIDs, seasonNumber, episodeNumber, path);
episode.ShowID = showID; episode.ShowID = showID;
episode.SeasonID = seasonID; episode.SeasonID = seasonID;
libraryManager.RegisterEpisode(episode); long episodeID = libraryManager.RegisterEpisode(episode);
Stream[] streams = transcoder.ExtractSubtitles(episode.Path);
//libraryManager.RegisterStreams(episodeID, streams);
} }
} }

View File

@ -205,10 +205,10 @@ namespace Kyoo.InternalAPI
{ {
Stream stream = Stream.FromReader(reader); Stream stream = Stream.FromReader(reader);
if (stream.type == StreamType.Audio) //if (stream.type == StreamType.Audio)
audios.Add(stream); // audios.Add(stream);
else if (stream.type == StreamType.Subtitle) //else if (stream.type == StreamType.Subtitle)
subtitles.Add(stream); // subtitles.Add(stream);
} }
return (audios, subtitles); return (audios, subtitles);

View File

@ -1,3 +1,5 @@
using Kyoo.Models.Watch;
namespace Kyoo.InternalAPI namespace Kyoo.InternalAPI
{ {
public interface ITranscoder public interface ITranscoder
@ -9,6 +11,6 @@ namespace Kyoo.InternalAPI
string Transcode(string path); string Transcode(string path);
//Extract all subtitles of a video and save them in the subtitles sub-folder. //Extract all subtitles of a video and save them in the subtitles sub-folder.
void ExtractSubtitles(string path); Stream[] ExtractSubtitles(string path);
} }
} }

View File

@ -2,6 +2,7 @@ using Kyoo.InternalAPI.TranscoderLink;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using Stream = Kyoo.Models.Watch.Stream;
namespace Kyoo.InternalAPI namespace Kyoo.InternalAPI
{ {
@ -12,11 +13,13 @@ namespace Kyoo.InternalAPI
Debug.WriteLine("&Api INIT: " + TranscoderAPI.Init()); Debug.WriteLine("&Api INIT: " + TranscoderAPI.Init());
} }
public void ExtractSubtitles(string path) public Stream[] ExtractSubtitles(string path)
{ {
string output = Path.Combine(Path.GetDirectoryName(path), "Subtitles"); string output = Path.Combine(Path.GetDirectoryName(path), "Subtitles");
Directory.CreateDirectory(output); Directory.CreateDirectory(output);
TranscoderAPI.ExtractSubtitles(path, output); TranscoderAPI.ExtractSubtitles(path, output, out Stream[] streams);
return streams;
} }
public void GetVideo(string path) public void GetVideo(string path)

View File

@ -1,4 +1,6 @@
using System.Runtime.InteropServices; using System;
using System.Runtime.InteropServices;
using Kyoo.Models.Watch;
namespace Kyoo.InternalAPI.TranscoderLink namespace Kyoo.InternalAPI.TranscoderLink
{ {
@ -10,6 +12,25 @@ namespace Kyoo.InternalAPI.TranscoderLink
public extern static int Init(); public extern static int Init();
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] [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<Stream>();
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<Stream>(streamsPtr);
streamsPtr += size;
}
}
else
streams = null;
}
} }
} }

View File

@ -1,4 +1,5 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Runtime.InteropServices;
namespace Kyoo.Models.Watch namespace Kyoo.Models.Watch
{ {
@ -7,40 +8,42 @@ namespace Kyoo.Models.Watch
Audio, Subtitle, Unknow Audio, Subtitle, Unknow
} }
[StructLayout(LayoutKind.Sequential)]
public class Stream public class Stream
{ {
[JsonIgnore] public StreamType type;
public string Title; public string Title;
public string Language; public string Language;
public string Format;
public bool IsDefault; public bool IsDefault;
public bool IsForced; public bool IsForced;
public string Format;
[JsonIgnore] public bool IsExternal;
[JsonIgnore] public string Path; [JsonIgnore] public string Path;
public Stream(StreamType type, string title, string language, bool isDefault, bool isForced, string format, bool isExternal, string path) //[JsonIgnore] public StreamType type;
{ //[JsonIgnore] public bool IsExternal;
this.type = type;
Title = title; //public Stream(StreamType type, string title, string language, bool isDefault, bool isForced, string format, bool isExternal, string path)
Language = language; //{
IsDefault = isDefault; // this.type = type;
IsForced = isForced; // Title = title;
Format = format; // Language = language;
IsExternal = isExternal; // IsDefault = isDefault;
Path = path; // IsForced = isForced;
} // Format = format;
// IsExternal = isExternal;
// Path = path;
//}
public static Stream FromReader(System.Data.SQLite.SQLiteDataReader reader) public static Stream FromReader(System.Data.SQLite.SQLiteDataReader reader)
{ {
return new Stream(reader["streamType"] as StreamType? ?? StreamType.Unknow, return new Stream();
reader["title"] as string, //return new Stream(reader["streamType"] as StreamType? ?? StreamType.Unknow,
reader["language"] as string, // reader["title"] as string,
reader["isDefault"] as bool? ?? false, // reader["language"] as string,
reader["isForced"] as bool? ?? false, // reader["isDefault"] as bool? ?? false,
reader["codec"] as string, // reader["isForced"] as bool? ?? false,
reader["isExternal"] as bool? ?? false, // reader["codec"] as string,
reader["path"] as string); // reader["isExternal"] as bool? ?? false,
// reader["path"] as string);
} }
} }
} }