diff --git a/Kyoo.Transcoder/src/Transcoder.cpp b/Kyoo.Transcoder/src/Transcoder.cpp index 089d3919..fcebf480 100644 --- a/Kyoo.Transcoder/src/Transcoder.cpp +++ b/Kyoo.Transcoder/src/Transcoder.cpp @@ -8,47 +8,125 @@ extern "C" #include } + int Init() { return 42; } -void ExtractSubtitles(const char* path) +void ExtractSubtitles(const char* path, const char* outPath) { - AVFormatContext* formatContext = NULL; + AVFormatContext* inputContext = NULL; - if (avformat_open_input(&formatContext, path, NULL, NULL)) + if (avformat_open_input(&inputContext, path, NULL, NULL)) { std::cout << "Error: Can't open the file at " << path << std::endl; return; } - if (avformat_find_stream_info(formatContext, 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; return; } - for (unsigned int i = 0; i < formatContext->nb_streams; i++) + for (unsigned int i = 0; i < inputContext->nb_streams; i++) { - AVStream* stream = formatContext->streams[i]; - const AVCodecContext* streamContext = stream->codec; + AVStream* inputStream = inputContext->streams[i]; + const AVCodecParameters* inputCodecpar = inputStream->codecpar; - if (streamContext->codec_type == AVMEDIA_TYPE_SUBTITLE) + if (inputCodecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { - const AVCodec* dec = streamContext->codec; - std::cout << "Stream #" << i << ", stream type: " << streamContext->codec_type << " codec: " << dec->long_name << std::endl; + const char* output = outPath; + const AVCodec* codec = avcodec_find_decoder(inputCodecpar->codec_id); + std::cout << "Stream #" << i << ", stream type: " << inputCodecpar->codec_type << " codec: " << codec->name << " long name: " << codec->long_name << std::endl; + + AVFormatContext* outputContext = NULL; + if (avformat_alloc_output_context2(&outputContext, NULL, NULL, output) < 0) + { + std::cout << "Error: Couldn't create an output file." << std::endl; + continue; + } + + AVStream* outputStream = avformat_new_stream(outputContext, codec); + if (outputStream == NULL) + { + std::cout << "Error: Couldn't create stream." << std::endl; + avformat_free_context(outputContext); + return; + } + + AVCodecParameters* outputCodecpar = outputStream->codecpar; + avcodec_parameters_copy(outputCodecpar, inputCodecpar); + + //outputStream->disposition = inputStream->disposition; + + //if (inputStream->nb_side_data) + //{ + // for (int i = 0; i < inputStream->nb_side_data; i++) + // { + // std::cout << "Copying side packet #" << i << std::endl; + + // AVPacketSideData* sidePkt = &inputStream->side_data[i]; + // uint8_t* newPkt = av_stream_new_side_data(outputStream, sidePkt->type, sidePkt->size); + // if (newPkt == NULL) + // { + // std::cout << "Error copying side package." << std::endl; + // //Should handle return here + // return; + // } + // memcpy(newPkt, sidePkt->data, sidePkt->size); + // } + //} + + if (avio_open(&outputContext->pb, output, AVIO_FLAG_WRITE) < 0) + { + std::cout << "Error: Couldn't open file at " << output << std::endl; + avformat_free_context(outputContext); + return; + } + + if (avformat_write_header(outputContext, NULL) < 0) + { + std::cout << "Error: Couldn't write headers to file at " << output << std::endl; + avformat_free_context(outputContext); + avio_closep(&outputContext->pb); + return; + } + + AVPacket pkt; + int i = 0; + while (av_read_frame(inputContext, &pkt) == 0) + { + if (pkt.stream_index != inputStream->index) + continue; + + std::cout << "Reading packet... " << i << std::endl; + i++; + + pkt.pts = av_rescale_q_rnd(pkt.pts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF); + pkt.dts = av_rescale_q_rnd(pkt.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF); + pkt.duration = av_rescale_q(pkt.duration, inputStream->time_base, outputStream->time_base); + pkt.pos = -1; + pkt.stream_index = 0; + + if (av_interleaved_write_frame(outputContext, &pkt) < 0) + { + //Should handle packet copy error; + } + + av_packet_unref(&pkt); + } + av_write_trailer(outputContext); + + avio_closep(&outputContext->pb); + avformat_free_context(outputContext); + + goto end; } } - //const char* outputPath = "subtitle.ass"; - //if (avformat_alloc_output_context2(&formatContext, NULL, NULL, outputPath) < 0) - //{ - // std::cout << "Error: Can't create output file at " << outputPath << std::endl; - // return; - //} - - avformat_close_input(&formatContext); - +end: + avformat_close_input(&inputContext); return; } \ No newline at end of file diff --git a/Kyoo.Transcoder/src/Transcoder.h b/Kyoo.Transcoder/src/Transcoder.h index 3ffef510..d809e6dd 100644 --- a/Kyoo.Transcoder/src/Transcoder.h +++ b/Kyoo.Transcoder/src/Transcoder.h @@ -11,4 +11,4 @@ extern "C" API int Init(); -extern "C" API void ExtractSubtitles(const char* path); +extern "C" API void ExtractSubtitles(const char* path, const char* outPath); diff --git a/Kyoo/Controllers/SubtitleController.cs b/Kyoo/Controllers/SubtitleController.cs index a87bae06..85985d37 100644 --- a/Kyoo/Controllers/SubtitleController.cs +++ b/Kyoo/Controllers/SubtitleController.cs @@ -31,12 +31,12 @@ namespace Kyoo.Controllers } [HttpGet("extract/{showSlug}-s{seasonNumber}e{episodeNumber}")] - public IActionResult ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber) + public string ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber) { Episode episode = libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); transcoder.ExtractSubtitles(episode.Path); - return null; + return "Processing..."; } } } \ No newline at end of file diff --git a/Kyoo/InternalAPI/Transcoder/Transcoder.cs b/Kyoo/InternalAPI/Transcoder/Transcoder.cs index 2942abe1..8f0048ee 100644 --- a/Kyoo/InternalAPI/Transcoder/Transcoder.cs +++ b/Kyoo/InternalAPI/Transcoder/Transcoder.cs @@ -1,6 +1,7 @@ using Kyoo.InternalAPI.TranscoderLink; using Microsoft.Extensions.Configuration; using System.Diagnostics; +using System.IO; namespace Kyoo.InternalAPI { @@ -13,7 +14,9 @@ namespace Kyoo.InternalAPI public void ExtractSubtitles(string path) { - TranscoderAPI.ExtractSubtitles(path); + string output = Path.GetDirectoryName(path); + output = Path.Combine(output, "fre\\output.ass"); + TranscoderAPI.ExtractSubtitles(path, output); } public void GetVideo(string path) diff --git a/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs b/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs index 40571d2a..32f0aa9f 100644 --- a/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs +++ b/Kyoo/InternalAPI/Transcoder/TranscoderAPI.cs @@ -10,6 +10,6 @@ namespace Kyoo.InternalAPI.TranscoderLink public extern static int Init(); [DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)] - public extern static void ExtractSubtitles(string path); + public extern static void ExtractSubtitles(string path, string outPath); } }