diff --git a/.gitignore b/.gitignore index e86e769a..e3bcffe9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,12 @@ +## PROJECT CUSTOM IGNORES +# Transcoder build (auto generated from Kyoo.Transcoder sub-project) +Kyoo/Transcoder/Kyoo.Transcoder.dll +Kyoo/Transcoder/Kyoo.Transcoder.ilk +Kyoo/Transcoder/Kyoo.Transcoder.lib +Kyoo/Transcoder/Kyoo.Transcoder.pdb +Kyoo/Transcoder/Kyoo.Transcoder.exp + + ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## diff --git a/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj b/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj index 6419e8d4..d3fe88e3 100644 --- a/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj +++ b/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj @@ -72,35 +72,35 @@ true - $(ProjectDir)\ffmpeg\include;$(IncludePath) + $(ProjectDir)\ffmpeg\include;./include;$(IncludePath) $(ProjectDir)\ffmpeg\lib;$(LibraryPath) $(SolutionDir)Kyoo\Transcoder true $(SolutionDir)Kyoo\Transcoder - $(ProjectDir)\ffmpeg\include;$(IncludePath) + $(ProjectDir)\ffmpeg\include;./include;$(IncludePath) $(ProjectDir)\ffmpeg\lib;$(LibraryPath) false - $(ProjectDir)\ffmpeg\include;$(IncludePath) + $(ProjectDir)\ffmpeg\include;./include;$(IncludePath) $(ProjectDir)\ffmpeg\lib;$(LibraryPath) $(SolutionDir)Kyoo\Transcoder false $(SolutionDir)Kyoo\Transcoder - $(ProjectDir)\ffmpeg\include;$(IncludePath) + $(ProjectDir)\ffmpeg\include;./include;$(IncludePath) $(ProjectDir)\ffmpeg\lib;$(LibraryPath) - Use + NotUsing Level3 Disabled true - WIN32;_DEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1 + WIN32;_DEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1;_CRT_NONSTDC_NO_DEPRECATE true pch.h stdcpp17 @@ -115,11 +115,11 @@ - Use + NotUsing Level3 Disabled true - _DEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1 + _DEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1;_CRT_NONSTDC_NO_DEPRECATE true pch.h %(AdditionalIncludeDirectories) @@ -135,13 +135,13 @@ - Use + NotUsing Level3 MaxSpeed true true true - WIN32;NDEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1 + WIN32;NDEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1;_CRT_NONSTDC_NO_DEPRECATE true pch.h stdcpp17 @@ -158,13 +158,13 @@ - Use + NotUsing Level3 MaxSpeed true true true - NDEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1 + NDEBUG;KYOOTRANSCODER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);TRANSCODER_EXPORTS=1;_CRT_NONSTDC_NO_DEPRECATE true pch.h %(AdditionalIncludeDirectories) @@ -181,19 +181,12 @@ - - - - + + + - - - Create - Create - Create - Create - + diff --git a/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj.filters b/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj.filters index 6b6cf920..a89d7182 100644 --- a/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj.filters +++ b/Kyoo.Transcoder/Kyoo.Transcoder.vcxproj.filters @@ -12,30 +12,27 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + {851d2dff-3186-4d12-9f4a-4144143be6fb} + - - Source Files + + Headers - - Compiler Files + + Headers - - Compiler Files - - - Models + + Headers Source Files - - Compiler Files - - - Compiler Files + + Source Files \ No newline at end of file diff --git a/Kyoo.Transcoder/include/helper.h b/Kyoo.Transcoder/include/helper.h new file mode 100644 index 00000000..30025384 --- /dev/null +++ b/Kyoo.Transcoder/include/helper.h @@ -0,0 +1,11 @@ +#pragma once +extern "C" +{ + #include + #include + #include +} +int open_input_context(AVFormatContext** inputContext, const char* path); +AVStream* copy_stream_to_output(AVFormatContext* out_ctx, AVStream* in_stream); +int open_output_file_for_write(AVFormatContext* out_ctx, const char* out_path, AVDictionary **options); +void process_packet(AVPacket& pkt, AVStream* in_stream, AVStream* out_stream); \ No newline at end of file diff --git a/Kyoo.Transcoder/include/stream.h b/Kyoo.Transcoder/include/stream.h new file mode 100644 index 00000000..175e50c1 --- /dev/null +++ b/Kyoo.Transcoder/include/stream.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include + +extern "C" struct Stream +{ + char *title; + char *language; + char *codec; + bool is_default; + bool is_forced; + char *path; + + Stream() + : title(nullptr), language(nullptr), codec(nullptr), is_default(nullptr), is_forced(nullptr), path(nullptr) {} + + Stream(const char* title, const char* languageCode, const char* codec, bool isDefault, bool isForced) + : title(nullptr), language(nullptr), codec(nullptr), is_default(isDefault), is_forced(isForced), path(nullptr) + { + if(title != nullptr) + this->title= strdup(title); + + if (languageCode != nullptr) + language = strdup(languageCode); + else + language = strdup("und"); + + if (codec != nullptr) + this->codec = strdup(codec); + } + + Stream(const char *title, const char *languageCode, const char *codec, bool isDefault, bool isForced, const char *path) + : title(nullptr), language(nullptr), codec(nullptr), is_default(isDefault), is_forced(isForced), path(nullptr) + { + if (title != nullptr) + this->title = strdup(title); + + if (languageCode != nullptr) + language = strdup(languageCode); + else + language = strdup("und"); + + if (codec != nullptr) + this->codec = strdup(codec); + + if (path != nullptr) + this->path = strdup(path); + } +}; \ No newline at end of file diff --git a/Kyoo.Transcoder/src/Transcoder.h b/Kyoo.Transcoder/include/transcoder.h similarity index 51% rename from Kyoo.Transcoder/src/Transcoder.h rename to Kyoo.Transcoder/include/transcoder.h index a4049d79..47488853 100644 --- a/Kyoo.Transcoder/src/Transcoder.h +++ b/Kyoo.Transcoder/include/transcoder.h @@ -11,11 +11,11 @@ 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); + +extern "C" API Stream *get_track_info(const char *path, int *stream_count, int *track_count); //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* ExtractSubtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount); +extern "C" API Stream* extract_subtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount); -extern "C" API void FreeMemory(Stream *streamsPtr); - -extern "C" API Stream* TestMemory(const char *path, const char *outPath, int *streamCount, int *subtitleCount); +extern "C" API void free_memory(Stream *streamsPtr); \ No newline at end of file diff --git a/Kyoo.Transcoder/src/Stream.h b/Kyoo.Transcoder/src/Stream.h deleted file mode 100644 index 536157d4..00000000 --- a/Kyoo.Transcoder/src/Stream.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#ifdef TRANSCODER_EXPORTS -#define API __declspec(dllexport) -#else -#define API __declspec(dllimport) -#endif - -#include -#include - -extern "C" struct Stream -{ - char *title; - char *language; - char *codec; - bool isDefault; - bool isForced; - char *path; - - Stream() - : title(NULL), language(NULL), codec(NULL), isDefault(NULL), isForced(NULL), path(NULL) {} - - Stream(const char* title, const char* languageCode, const char* codec, bool isDefault, bool isForced) - : title(NULL), language(NULL), codec(NULL), isDefault(isDefault), isForced(isForced), path(NULL) - { - if(title != NULL) - this->title= _strdup(title); - - if (languageCode != NULL) - language = _strdup(languageCode); - else - language = _strdup("und"); - - if (codec != NULL) - this->codec = _strdup(codec); - } -}; \ No newline at end of file diff --git a/Kyoo.Transcoder/src/Transcoder.cpp b/Kyoo.Transcoder/src/Transcoder.cpp index 3e8e6a9d..210619f8 100644 --- a/Kyoo.Transcoder/src/Transcoder.cpp +++ b/Kyoo.Transcoder/src/Transcoder.cpp @@ -1,197 +1,96 @@ -#include "pch.h" #include #include -#include "Transcoder.h" - -//ffmpeg imports -extern "C" -{ - #include - #include - #include -} - -constexpr enum AVRounding operator |(const enum AVRounding a, const enum AVRounding b) -{ - return (enum AVRounding)(uint32_t(a) | uint32_t(b)); -} +#include "transcoder.h" +#include "helper.h" int Init() { return sizeof(Stream); } - -#pragma region InternalProcess -int open_input_context(AVFormatContext **inputContext, const char *path) +int transmux(const char *path, const char *out_path, float *playable_duration) { - if (avformat_open_input(inputContext, path, NULL, NULL)) - { - std::cout << "Error: Can't open the file at " << path << std::endl; - return 1; - } - - if (avformat_find_stream_info(*inputContext, NULL) < 0) - { - std::cout << "Error: Could't find streams informations for the file at " << path << std::endl; - return 1; - } - - av_dump_format(*inputContext, 0, path, false); - return 0; -} - -AVStream* copy_stream_to_output(AVFormatContext *outputContext, AVStream *inputStream) -{ - AVStream *outputStream = avformat_new_stream(outputContext, NULL); - if (outputStream == NULL) - { - std::cout << "Error: Couldn't create stream." << std::endl; - return NULL; - } - - if (avcodec_parameters_copy(outputStream->codecpar, inputStream->codecpar) < 0) - { - std::cout << "Error: Couldn't copy parameters to the output file." << std::endl; - return NULL; - } - outputStream->codecpar->codec_tag = 0; - - avformat_transfer_internal_stream_timing_info(outputContext->oformat, outputStream, inputStream, AVTimebaseSource::AVFMT_TBCF_AUTO); - outputStream->time_base = av_add_q(av_stream_get_codec_timebase(outputStream), AVRational{ 0, 1 }); - outputStream->duration = av_rescale_q(inputStream->duration, inputStream->time_base, outputStream->time_base); - outputStream->disposition = inputStream->disposition; - outputStream->avg_frame_rate = inputStream->avg_frame_rate; - outputStream->r_frame_rate = inputStream->r_frame_rate; - - //av_dict_copy(&outputStream->metadata, inputStream->metadata, NULL); - - //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); - // } - //} - - return outputStream; -} - -int open_output_file_for_write(AVFormatContext *outputContext, const char* outputPath) -{ - if (!(outputContext->flags & AVFMT_NOFILE)) - { - if (avio_open(&outputContext->pb, outputPath, AVIO_FLAG_WRITE) < 0) - { - std::cout << "Error: Couldn't open file at " << outputPath << std::endl; - return 1; - } - } - else - std::cout << "Output flag set to AVFMT_NOFILE." << std::endl; - - if (avformat_write_header(outputContext, NULL) < 0) - { - std::cout << "Error: Couldn't write headers to file at " << outputPath << std::endl; - return 1; - } - - return 0; -} - -void process_packet(AVPacket &pkt, AVStream* inputStream, AVStream* outputStream) -{ - pkt.pts = av_rescale_q_rnd(pkt.pts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); - pkt.dts = av_rescale_q_rnd(pkt.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); - pkt.duration = av_rescale_q(pkt.duration, inputStream->time_base, outputStream->time_base); - pkt.pos = -1; -} -#pragma endregion - - - - -int Transmux(const char *path, const char *outPath) -{ - AVFormatContext *inputContext = NULL; + AVFormatContext *in_ctx = NULL; + AVFormatContext *out_ctx = NULL; + AVStream *stream; + AVPacket pkt; + AVDictionary *options = NULL; + int *stream_map; + int stream_count; int ret = 0; - if (open_input_context(&inputContext, path) != 0) + *playable_duration = 0; + if (open_input_context(&in_ctx, path) != 0) return 1; - AVFormatContext *outputContext = NULL; - if (avformat_alloc_output_context2(&outputContext, NULL, NULL, outPath) < 0) + if (avformat_alloc_output_context2(&out_ctx, NULL, NULL, out_path) < 0) { std::cout << "Error: Couldn't create an output file." << std::endl; return 1; } - int *streamsMap = new int[inputContext->nb_streams]; - int streamCount = 0; + stream_map = new int[in_ctx->nb_streams]; + stream_count = 0; - for (unsigned int i = 0; i < inputContext->nb_streams; i++) + for (unsigned int i = 0; i < in_ctx->nb_streams; i++) { - AVStream *stream = inputContext->streams[i]; + stream = in_ctx->streams[i]; if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - streamsMap[i] = streamCount; - streamCount++; - if (copy_stream_to_output(outputContext, stream) == NULL) + stream_map[i] = stream_count; + stream_count++; + if (copy_stream_to_output(out_ctx, stream) == NULL) return 1; } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) //Should support multi-audio on a good format. { - streamsMap[i] = streamCount; - streamCount++; - if (copy_stream_to_output(outputContext, stream) == NULL) + stream_map[i] = stream_count; + stream_count++; + if (copy_stream_to_output(out_ctx, stream) == NULL) return 1; } else - streamsMap[i] = -1; + stream_map[i] = -1; } - av_dump_format(outputContext, 0, outPath, true); - if (open_output_file_for_write(outputContext, outPath) != 0) + av_dump_format(out_ctx, 0, out_path, true); + + std::filesystem::create_directory(((std::string)out_path).substr(0, strrchr(out_path, '/') - out_path).append("/dash/")); + av_dict_set(&options, "init_seg_name", "dash/init-stream$RepresentationID$.m4s", 0); + av_dict_set(&options, "media_seg_name", "dash/chunk-stream$RepresentationID$-$Number%05d$.m4s", 0); + av_dict_set(&options, "streaming", "1", 0); + + if (open_output_file_for_write(out_ctx, out_path, &options) != 0) return 1; - AVPacket pkt; - while (av_read_frame(inputContext, &pkt) == 0) + while (av_read_frame(in_ctx, &pkt) == 0) { - if (pkt.stream_index >= inputContext->nb_streams || streamsMap[pkt.stream_index] < 0) + if ((unsigned int)pkt.stream_index >= in_ctx->nb_streams || stream_map[pkt.stream_index] < 0) { av_packet_unref(&pkt); continue; } - AVStream *inputStream = inputContext->streams[pkt.stream_index]; - pkt.stream_index = streamsMap[pkt.stream_index]; - AVStream *outputStream = outputContext->streams[pkt.stream_index]; + 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; - process_packet(pkt, inputStream, outputStream); - - if (av_interleaved_write_frame(outputContext, &pkt) < 0) + if (av_interleaved_write_frame(out_ctx, &pkt) < 0) std::cout << "Error while writing a packet to the output file." << std::endl; av_packet_unref(&pkt); } - av_write_trailer(outputContext); - avformat_close_input(&inputContext); + av_dict_free(&options); + av_write_trailer(out_ctx); + avformat_close_input(&in_ctx); - if (outputContext && !(outputContext->oformat->flags & AVFMT_NOFILE)) - avio_closep(&outputContext->pb); - avformat_free_context(outputContext); - delete[] streamsMap; + if (out_ctx && !(out_ctx->oformat->flags & AVFMT_NOFILE)) + avio_close(out_ctx->pb); + avformat_free_context(out_ctx); + delete[] stream_map; if (ret < 0 && ret != AVERROR_EOF) return 1; @@ -199,154 +98,195 @@ int Transmux(const char *path, const char *outPath) return 0; } - -Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount) +Stream *get_track_info(const char *path, int *stream_count, int *track_count) { - AVFormatContext *inputContext = NULL; + AVFormatContext *ctx = NULL; + Stream *streams; - if (open_input_context(&inputContext, path) != 0) + if (open_input_context(&ctx, path) != 0) return nullptr; - *streamCount = inputContext->nb_streams; - *subtitleCount = 0; - Stream *streams = new Stream[*streamCount]; - - const unsigned int outputCount = inputContext->nb_streams; - AVFormatContext **outputList = new AVFormatContext*[outputCount]; + *stream_count = ctx->nb_streams; + *track_count = 0; + streams = new Stream[*stream_count]; //Initialize output and set headers. - for (unsigned int i = 0; i < inputContext->nb_streams; i++) + for (int i = 0; i < *stream_count; i++) { - AVStream *inputStream = inputContext->streams[i]; - const AVCodecParameters *inputCodecpar = inputStream->codecpar; + AVStream *stream = ctx->streams[i]; + const AVCodecParameters *codecpar = stream->codecpar; - if (inputCodecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) - outputList[i] = NULL; + if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO || codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + { + AVDictionaryEntry *languageptr = av_dict_get(stream->metadata, "language", NULL, 0); + + *track_count += 1; + + streams[i] = Stream(codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? "VIDEO" : NULL, // title + languageptr ? languageptr->value : NULL, // language + avcodec_get_name(codecpar->codec_id), // format + stream->disposition & AV_DISPOSITION_DEFAULT, // isDefault + stream->disposition & AV_DISPOSITION_FORCED, // isForced + path); // path + } + else + streams[i] = Stream(); + } + avformat_close_input(&ctx); + return streams; +} + +Stream *extract_subtitles(const char *path, const char *out_path, int *stream_count, int *subtitle_count) +{ + AVFormatContext *int_ctx = NULL; + AVFormatContext **output_list; + Stream *streams; + AVPacket pkt; + unsigned int out_count; + + if (open_input_context(&int_ctx, path) != 0) + return nullptr; + + *stream_count = int_ctx->nb_streams; + *subtitle_count = 0; + streams = new Stream[*stream_count]; + + out_count = int_ctx->nb_streams; + output_list = new AVFormatContext *[out_count]; + + //Initialize output and set headers. + for (unsigned int i = 0; i < int_ctx->nb_streams; i++) + { + AVStream *in_stream = int_ctx->streams[i]; + const AVCodecParameters *in_codecpar = in_stream->codecpar; + + if (in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) + { + output_list[i] = NULL; + streams[i] = Stream(); + } else { - *subtitleCount += 1; + *subtitle_count += 1; - AVDictionaryEntry *languagePtr = av_dict_get(inputStream->metadata, "language", NULL, 0); + AVDictionaryEntry *languageptr = av_dict_get(in_stream->metadata, "language", NULL, 0); //Get metadata for file name streams[i] = Stream(NULL, //title - languagePtr ? languagePtr->value : NULL, //language - avcodec_get_name(inputCodecpar->codec_id), //format - inputStream->disposition & AV_DISPOSITION_DEFAULT, //isDefault - inputStream->disposition & AV_DISPOSITION_FORCED); //isForced + languageptr ? languageptr->value : NULL, //language + avcodec_get_name(in_codecpar->codec_id), //format + in_stream->disposition & AV_DISPOSITION_DEFAULT, //isDefault + in_stream->disposition & AV_DISPOSITION_FORCED); //isForced //Create the language subfolder - std::stringstream outStream; - outStream << outPath << (char)std::filesystem::path::preferred_separator << streams[i].language; - std::filesystem::create_directory(outStream.str()); + std::stringstream out_strstream; + out_strstream << out_path << (char)std::filesystem::path::preferred_separator << streams[i].language; + std::filesystem::create_directory(out_strstream.str()); //Get file name - std::string fileName(path); - size_t lastSeparator = fileName.find_last_of((char)std::filesystem::path::preferred_separator); - fileName = fileName.substr(lastSeparator, fileName.find_last_of('.') - lastSeparator); + std::string file_name(path); + size_t last_separator = file_name.find_last_of((char)std::filesystem::path::preferred_separator); + file_name = file_name.substr(last_separator, file_name.find_last_of('.') - last_separator); //Construct output file name - outStream << fileName << "." << streams[i].language; + out_strstream << file_name << "." << streams[i].language; - if (streams[i].isDefault) - outStream << ".default"; - if (streams[i].isForced) - outStream << ".forced"; + if (streams[i].is_default) + out_strstream << ".default"; + if (streams[i].is_forced) + out_strstream << ".forced"; if (strcmp(streams[i].codec, "subrip") == 0) - outStream << ".srt"; + out_strstream << ".srt"; else if (strcmp(streams[i].codec, "ass") == 0) - outStream << ".ass"; + out_strstream << ".ass"; else { std::cout << "Unsupported subtitle codec: " << streams[i].codec << std::endl; - outputList[i] = NULL; + output_list[i] = NULL; continue; } - streams[i].path = _strdup(outStream.str().c_str()); + streams[i].path = strdup(out_strstream.str().c_str()); - std::cout << "Stream #" << i << "(" << streams[i].language << "), stream type: " << inputCodecpar->codec_type << " codec: " << streams[i].codec << std::endl; + std::cout << "Stream #" << i << "(" << streams[i].language << "), stream type: " << in_codecpar->codec_type << " codec: " << streams[i].codec << std::endl; - AVFormatContext *outputContext = NULL; - if (avformat_alloc_output_context2(&outputContext, NULL, NULL, streams[i].path) < 0) + AVFormatContext *out_ctx = NULL; + if (avformat_alloc_output_context2(&out_ctx, NULL, NULL, streams[i].path) < 0) { std::cout << "Error: Couldn't create an output file." << std::endl; continue; } - av_dict_copy(&outputContext->metadata, inputContext->metadata, NULL); + av_dict_copy(&out_ctx->metadata, int_ctx->metadata, NULL); - AVStream *outputStream = copy_stream_to_output(outputContext, inputStream); - if (outputStream == NULL) + AVStream *out_stream = copy_stream_to_output(out_ctx, in_stream); + if (out_stream == NULL) goto end; - av_dump_format(outputContext, 0, streams[i].path, true); + av_dump_format(out_ctx, 0, streams[i].path, true); - if (open_output_file_for_write(outputContext, streams[i].path) != 0) + if (open_output_file_for_write(out_ctx, streams[i].path, NULL) != 0) goto end; - outputList[i] = outputContext; + output_list[i] = out_ctx; if (false) { end: - if (outputContext && !(outputContext->flags & AVFMT_NOFILE)) - avio_closep(&outputContext->pb); - avformat_free_context(outputContext); + if (out_ctx && !(out_ctx->flags & AVFMT_NOFILE)) + avio_closep(&out_ctx->pb); + avformat_free_context(out_ctx); - outputList[i] = nullptr; + output_list[i] = nullptr; std::cout << "An error occured, cleaning up th output context for the stream #" << i << std::endl; } } } + //Write subtitle data to files. - AVPacket pkt; - while (av_read_frame(inputContext, &pkt) == 0) + while (av_read_frame(int_ctx, &pkt) == 0) { - if (pkt.stream_index >= outputCount) + if ((unsigned int)pkt.stream_index >= out_count) continue; - AVFormatContext *outputContext = outputList[pkt.stream_index]; - if (outputContext == nullptr) + AVFormatContext *out_ctx = output_list[pkt.stream_index]; + if (out_ctx == nullptr) { av_packet_unref(&pkt); continue; } - AVStream *inputStream = inputContext->streams[pkt.stream_index]; - AVStream *outputStream = outputContext->streams[0]; - + process_packet(pkt, int_ctx->streams[pkt.stream_index], out_ctx->streams[0]); pkt.stream_index = 0; - process_packet(pkt, inputStream, outputStream); - if (av_interleaved_write_frame(outputContext, &pkt) < 0) + if (av_interleaved_write_frame(out_ctx, &pkt) < 0) std::cout << "Error while writing a packet to the output file." << std::endl; av_packet_unref(&pkt); } - avformat_close_input(&inputContext); + avformat_close_input(&int_ctx); - for (unsigned int i = 0; i < outputCount; i++) + for (unsigned int i = 0; i < out_count; i++) { - AVFormatContext *outputContext = outputList[i]; + AVFormatContext *out_ctx = output_list[i]; - if (outputContext == NULL) + if (out_ctx == NULL) continue; - av_write_trailer(outputContext); + av_write_trailer(out_ctx); - if (outputContext && !(outputContext->flags & AVFMT_NOFILE)) - avio_closep(&outputContext->pb); - avformat_free_context(outputContext); + if (out_ctx && !(out_ctx->flags & AVFMT_NOFILE)) + avio_closep(&out_ctx->pb); + avformat_free_context(out_ctx); } - delete[] outputList; + delete[] output_list; return streams; } -void FreeMemory(Stream *streamsPtr) +void free_memory(Stream *stream_ptr) { - delete[] streamsPtr; + delete[] stream_ptr; } \ No newline at end of file diff --git a/Kyoo.Transcoder/src/dllmain.cpp b/Kyoo.Transcoder/src/dllmain.cpp deleted file mode 100644 index f2665971..00000000 --- a/Kyoo.Transcoder/src/dllmain.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// dllmain.cpp : Defines the entry point for the DLL application. -#include "pch.h" - -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} - diff --git a/Kyoo.Transcoder/src/framework.h b/Kyoo.Transcoder/src/framework.h deleted file mode 100644 index 54b83e94..00000000 --- a/Kyoo.Transcoder/src/framework.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files -#include diff --git a/Kyoo.Transcoder/src/helper.cpp b/Kyoo.Transcoder/src/helper.cpp new file mode 100644 index 00000000..d390bc0a --- /dev/null +++ b/Kyoo.Transcoder/src/helper.cpp @@ -0,0 +1,75 @@ +#include "helper.h" +#include + +int open_input_context(AVFormatContext **in_ctx, const char *path) +{ + if (avformat_open_input(in_ctx, path, NULL, NULL)) + { + std::cout << "Error: Can't open the file at " << path << std::endl; + return 1; + } + if (avformat_find_stream_info(*in_ctx, NULL) < 0) + { + std::cout << "Error: Could't find streams informations for the file at " << path << std::endl; + return 1; + } + av_dump_format(*in_ctx, 0, path, false); + return 0; +} + +AVStream *copy_stream_to_output(AVFormatContext *out_ctx, AVStream *in_stream) +{ + AVStream *out_stream = avformat_new_stream(out_ctx, NULL); + + if (out_stream == NULL) + { + std::cout << "Error: Couldn't create stream." << std::endl; + return NULL; + } + if (avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar) < 0) + { + std::cout << "Error: Couldn't copy parameters to the output file." << std::endl; + return NULL; + } + out_stream->codecpar->codec_tag = 0; + avformat_transfer_internal_stream_timing_info(out_ctx->oformat, out_stream, in_stream, AVTimebaseSource::AVFMT_TBCF_AUTO); + out_stream->time_base = av_add_q(av_stream_get_codec_timebase(out_stream), AVRational {0, 1}); + out_stream->duration = av_rescale_q(in_stream->duration, in_stream->time_base, out_stream->time_base); + out_stream->disposition = in_stream->disposition; + out_stream->avg_frame_rate = in_stream->avg_frame_rate; + out_stream->r_frame_rate = in_stream->r_frame_rate; + return out_stream; +} + +constexpr enum AVRounding operator |(const enum AVRounding a, const enum AVRounding b) +{ + return (enum AVRounding)(uint32_t(a) | uint32_t(b)); +} + +int open_output_file_for_write(AVFormatContext *out_ctx, const char *out_path, AVDictionary **options) +{ + if (!(out_ctx->oformat->flags & AVFMT_NOFILE)) + { + if (avio_open(&out_ctx->pb, out_path, AVIO_FLAG_WRITE) < 0) + { + std::cout << "Error: Couldn't open file at " << out_path << std::endl; + return 1; + } + } + else + std::cout << "Output flag set to AVFMT_NOFILE." << std::endl; + if (avformat_write_header(out_ctx, options) < 0) + { + std::cout << "Error: Couldn't write headers to file at " << out_path << std::endl; + return 1; + } + return 0; +} + +void process_packet(AVPacket &pkt, AVStream *in_stream, AVStream *out_stream) +{ + pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); + pkt.pos = -1; +} \ No newline at end of file diff --git a/Kyoo.Transcoder/src/pch.cpp b/Kyoo.Transcoder/src/pch.cpp deleted file mode 100644 index 64b7eef6..00000000 --- a/Kyoo.Transcoder/src/pch.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// pch.cpp: source file corresponding to the pre-compiled header - -#include "pch.h" - -// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/Kyoo.Transcoder/src/pch.h b/Kyoo.Transcoder/src/pch.h deleted file mode 100644 index cb101bfa..00000000 --- a/Kyoo.Transcoder/src/pch.h +++ /dev/null @@ -1,14 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#ifndef PCH_H -#define PCH_H - -// add headers that you want to pre-compile here -#include "framework.h" -#include - -#endif //PCH_H 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/.gitignore b/Kyoo/.gitignore index 0d10972f..eb271f87 100644 --- a/Kyoo/.gitignore +++ b/Kyoo/.gitignore @@ -1,3 +1,11 @@ +## PROJECT CUSTOM IGNORES +# Transcoder build (auto generated from Kyoo.Transcoder sub-project) +Transcoder/Kyoo.Transcoder.dll +Transcoder/Kyoo.Transcoder.ilk +Transcoder/Kyoo.Transcoder.lib +Transcoder/Kyoo.Transcoder.pdb + + /Properties/launchSettings.json ## Ignore Visual Studio temporary files, build results, and diff --git a/Kyoo/ClientApp/angular.json b/Kyoo/ClientApp/angular.json index 806ebe16..4be75a64 100644 --- a/Kyoo/ClientApp/angular.json +++ b/Kyoo/ClientApp/angular.json @@ -32,8 +32,8 @@ "scripts": [ "./node_modules/jquery/dist/jquery.min.js", "./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js", - "./src/libraries/subtitles.js", - "./node_modules/video.js/dist/video.min.js" + "./node_modules/dashjs/dist/dash.all.min.js", + "./src/libraries/subtitles.js" ] }, "configurations": { @@ -56,7 +56,7 @@ "budgets": [ { "type": "initial", - "maximumWarning": "2mb", + "maximumWarning": "3mb", "maximumError": "5mb" }, { diff --git a/Kyoo/ClientApp/package-lock.json b/Kyoo/ClientApp/package-lock.json index 39ca2711..5d978d81 100644 --- a/Kyoo/ClientApp/package-lock.json +++ b/Kyoo/ClientApp/package-lock.json @@ -1134,21 +1134,6 @@ "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "dev": true }, - "@babel/runtime": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz", - "integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==", - "requires": { - "regenerator-runtime": "^0.13.2" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" - } - } - }, "@babel/template": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", @@ -1345,6 +1330,12 @@ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", "dev": true }, + "@types/video.js": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@types/video.js/-/video.js-7.3.2.tgz", + "integrity": "sha512-r6oXapONKV4QRJ4K5/rOKlD9VdMQHY4JGVafJpf5ynDnJtV3PIxglS1i1VWNYQGZYGGL3aFDWedWNODLO4bxhw==", + "dev": true + }, "@types/webpack-sources": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz", @@ -1364,20 +1355,6 @@ } } }, - "@videojs/http-streaming": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-1.10.6.tgz", - "integrity": "sha512-uPBuunHnxWeFRYxRX0j6h1IIWv3+QKvSkZGmW9TvqxWBqeNGSrQymR6tm1nVjQ2HhMVxVphQTUhUTTPDVWqmQg==", - "requires": { - "aes-decrypter": "3.0.0", - "global": "^4.3.0", - "m3u8-parser": "4.4.0", - "mpd-parser": "0.8.1", - "mux.js": "5.2.1", - "url-toolkit": "^2.1.3", - "video.js": "^6.8.0 || ^7.0.0" - } - }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -1604,16 +1581,6 @@ "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", "dev": true }, - "aes-decrypter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.0.0.tgz", - "integrity": "sha1-eEihwUW5/b9Xrj4rWxvHzwZEqPs=", - "requires": { - "commander": "^2.9.0", - "global": "^4.3.2", - "pkcs7": "^1.0.2" - } - }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -2787,6 +2754,11 @@ } } }, + "codem-isoboxer": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.6.tgz", + "integrity": "sha512-LuO8/7LW6XuR5ERn1yavXAfodGRhuY2yP60JTZIw5yNYMCE5lUVbk3NFUCJxjnphQH+Xemp5hOGb1LgUXm00Xw==" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2830,7 +2802,8 @@ "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true }, "commondir": { "version": "1.0.1", @@ -3173,6 +3146,16 @@ "assert-plus": "^1.0.0" } }, + "dashjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dashjs/-/dashjs-3.0.0.tgz", + "integrity": "sha512-XyVkjeHB4mqzf/Y7ARQ1IqbRBaee0osAulwCFV5ZNZ734wea8LbSC/23zKI32BulW7Kk6f7I6onW1WDMHRgz7Q==", + "requires": { + "codem-isoboxer": "0.3.6", + "fast-deep-equal": "2.0.1", + "imsc": "^1.0.2" + } + }, "date-format": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", @@ -3241,6 +3224,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -3358,6 +3342,11 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, + "detect-browser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-4.8.0.tgz", + "integrity": "sha512-f4h2dFgzHUIpjpBLjhnDIteXv8VQiUm8XzAuzQtYUqECX/eKh67ykuiVoyb7Db7a0PUSmJa3OGXStG0CbQFUVw==" + }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -3452,11 +3441,6 @@ "void-elements": "^2.0.0" } }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" - }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -3673,6 +3657,7 @@ "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, "requires": { "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", @@ -3686,6 +3671,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -4013,8 +3999,7 @@ "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -4170,14 +4155,6 @@ } } }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } - }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -4289,16 +4266,17 @@ "dev": true }, "fsevents": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", - "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "genfun": { "version": "5.0.0", @@ -4371,22 +4349,6 @@ } } }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "requires": { - "min-document": "^2.19.0", - "process": "~0.5.1" - }, - "dependencies": { - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" - } - } - }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", @@ -4433,9 +4395,9 @@ "dev": true }, "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -4472,6 +4434,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -4517,7 +4480,8 @@ "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true }, "has-value": { "version": "1.0.0", @@ -4730,9 +4694,9 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -4852,6 +4816,21 @@ "resolve-cwd": "^2.0.0" } }, + "imsc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/imsc/-/imsc-1.1.0.tgz", + "integrity": "sha512-z2aUE3X00O39fCgkLHEVbfKG/D9cBrmsbf4NjP7K1gQb06YBjgljq5nZD72HYMFG2lRJI7QY7v+JVxg6o6I/Jg==", + "requires": { + "sax": "1.2.1" + }, + "dependencies": { + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + } + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4864,11 +4843,6 @@ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, - "individual": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/individual/-/individual-2.0.0.tgz", - "integrity": "sha1-gzsJfa0jKU52EXqY+zjg2a1hu5c=" - }, "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -5022,7 +4996,8 @@ "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true }, "is-data-descriptor": { "version": "0.1.4", @@ -5047,7 +5022,8 @@ "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true }, "is-descriptor": { "version": "0.1.6", @@ -5101,11 +5077,6 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-function": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", - "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" - }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -5170,6 +5141,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, "requires": { "has": "^1.0.1" } @@ -5184,6 +5156,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, "requires": { "has-symbols": "^1.0.0" } @@ -6379,11 +6352,6 @@ "source-map-support": "^0.5.5" } }, - "keycode": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz", - "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=" - }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -6560,14 +6528,6 @@ "yallist": "^3.0.2" } }, - "m3u8-parser": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.4.0.tgz", - "integrity": "sha512-iH2AygTFILtato+XAgnoPYzLHM4R3DjATj7Ozbk7EHdB2XoLF2oyOUguM7Kc4UVHbQHHL/QPaw98r7PbWzG0gg==", - "requires": { - "global": "^4.3.2" - } - }, "magic-string": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", @@ -6867,14 +6827,6 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "requires": { - "dom-walk": "^0.1.0" - } - }, "mini-css-extract-plugin": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz", @@ -7021,15 +6973,6 @@ "run-queue": "^1.0.3" } }, - "mpd-parser": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.8.1.tgz", - "integrity": "sha512-WBTJ1bKk8OLUIxBh6s1ju1e2yz/5CzhPbgi6P3F3kJHKhGy1Z+ElvEnuzEbtC/dnbRcJtMXazE3f93N5LLdp9Q==", - "requires": { - "global": "^4.3.2", - "url-toolkit": "^2.1.1" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -7058,11 +7001,6 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "mux.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.2.1.tgz", - "integrity": "sha512-1t2payD3Y8izfZRq7tfUQlhL2fKzjeLr9v1/2qNCTkEQnd9Abtn1JgzsBgGZubEXh6lM5L8B0iLGoWQiukjtbQ==" - }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -7372,7 +7310,8 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -7687,15 +7626,6 @@ "safe-buffer": "^5.1.1" } }, - "parse-headers": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.2.tgz", - "integrity": "sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg==", - "requires": { - "for-each": "^0.3.3", - "string.prototype.trim": "^1.1.2" - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -7853,11 +7783,6 @@ "pinkie": "^2.0.0" } }, - "pkcs7": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.2.tgz", - "integrity": "sha1-ttulJ1KMKUK/wSLOLa/NteWQdOc=" - }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -8672,18 +8597,11 @@ "aproba": "^1.1.1" } }, - "rust-result": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rust-result/-/rust-result-1.0.0.tgz", - "integrity": "sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I=", - "requires": { - "individual": "^2.0.0" - } - }, "rxjs": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, "requires": { "tslib": "^1.9.0" } @@ -8694,14 +8612,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "safe-json-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-4.0.0.tgz", - "integrity": "sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw=", - "requires": { - "rust-result": "^1.0.0" - } - }, "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -9710,16 +9620,6 @@ } } }, - "string.prototype.trim": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz", - "integrity": "sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.13.0", - "function-bind": "^1.1.1" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -10129,16 +10029,23 @@ "dev": true }, "uglify-js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", - "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.9.tgz", + "integrity": "sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==", "dev": true, "optional": true, "requires": { - "commander": "~2.20.0", + "commander": "~2.20.3", "source-map": "~0.6.1" }, "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -10313,11 +10220,6 @@ "requires-port": "^1.0.0" } }, - "url-toolkit": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.1.6.tgz", - "integrity": "sha512-UaZ2+50am4HwrV2crR/JAf63Q4VvPYphe63WGeoJxeu8gmOm0qxPt+KsukfakPNrX9aymGNEkkaoICwn+OuvBw==" - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -10432,34 +10334,6 @@ "extsprintf": "^1.2.0" } }, - "video.js": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/video.js/-/video.js-7.6.5.tgz", - "integrity": "sha512-r0kC9SNJhXz9th/wwbRaLVOIZTvXkF+rhFq9/FWU+e+EJClwClRCgP8STGmfrPHDXrfWiJwH9YY21JZK61vGGQ==", - "requires": { - "@babel/runtime": "^7.4.5", - "@videojs/http-streaming": "1.10.6", - "global": "4.3.2", - "keycode": "^2.2.0", - "safe-json-parse": "4.0.0", - "videojs-font": "3.2.0", - "videojs-vtt.js": "^0.14.1", - "xhr": "2.4.0" - } - }, - "videojs-font": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz", - "integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==" - }, - "videojs-vtt.js": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.14.1.tgz", - "integrity": "sha512-YxOiywx6N9t3J5nqsE5WN2Sw4CSqVe3zV+AZm2T4syOc2buNJaD6ZoexSdeszx2sHLU/RRo2r4BJAXFDQ7Qo2Q==", - "requires": { - "global": "^4.3.1" - } - }, "vm-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", @@ -12168,17 +12042,6 @@ "ultron": "~1.1.0" } }, - "xhr": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.0.tgz", - "integrity": "sha1-4W5mpF+GmGHu76tBbV7/ci3ECZM=", - "requires": { - "global": "~4.3.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -12212,7 +12075,8 @@ "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true }, "y18n": { "version": "4.0.0", diff --git a/Kyoo/ClientApp/package.json b/Kyoo/ClientApp/package.json index 62f978c0..a04cd18a 100644 --- a/Kyoo/ClientApp/package.json +++ b/Kyoo/ClientApp/package.json @@ -22,12 +22,11 @@ "@angular/platform-browser-dynamic": "~8.2.0", "@angular/router": "~8.2.0", "bootstrap": "^4.3.1", + "dashjs": "^3.0.0", + "detect-browser": "^4.8.0", "hammerjs": "^2.0.8", "jquery": "^3.4.1", "popper.js": "^1.15.0", - "rxjs": "~6.4.0", - "tslib": "^1.10.0", - "video.js": "^7.6.5", "zone.js": "~0.9.1" }, "devDependencies": { @@ -40,6 +39,7 @@ "@types/jasminewd2": "~2.0.3", "@types/jquery": "^3.3.31", "@types/node": "~8.9.4", + "@types/video.js": "^7.3.2", "codelyzer": "^5.0.0", "jasmine-core": "~3.4.0", "jasmine-spec-reporter": "~4.2.1", diff --git a/Kyoo/ClientApp/src/app/app-routing.module.ts b/Kyoo/ClientApp/src/app/app-routing.module.ts index afe02312..2bd33fbb 100644 --- a/Kyoo/ClientApp/src/app/app-routing.module.ts +++ b/Kyoo/ClientApp/src/app/app-routing.module.ts @@ -14,22 +14,22 @@ import { StreamResolverService } from "./services/stream-resolver.service"; import { ShowDetailsComponent } from './show-details/show-details.component'; const routes: Routes = [ - { path: "browse", component: BrowseComponent, pathMatch: "full", resolve: { shows: LibraryResolverService } }, - { path: "browse/:library-slug", component: BrowseComponent, resolve: { shows: LibraryResolverService } }, - { path: "show/:show-slug", component: ShowDetailsComponent, resolve: { show: ShowResolverService } }, + { path: "browse", component: BrowseComponent, pathMatch: "full", resolve: { shows: LibraryResolverService } }, + { path: "browse/:library-slug", component: BrowseComponent, resolve: { shows: LibraryResolverService } }, + { path: "show/:show-slug", component: ShowDetailsComponent, resolve: { show: ShowResolverService } }, { path: "collection/:collection-slug", component: CollectionComponent, resolve: { collection: CollectionResolverService } }, { path: "people/:people-slug", component: CollectionComponent, resolve: { collection: PeopleResolverService } }, { path: "watch/:item", component: PlayerComponent, resolve: { item: StreamResolverService } }, { path: "search/:query", component: SearchComponent, resolve: { items: SearchResolverService } }, - { path: "**", component: NotFoundComponent } + { path: "**", component: NotFoundComponent } ]; @NgModule({ - imports: [RouterModule.forRoot(routes, - { - scrollPositionRestoration: "enabled" - })], - exports: [RouterModule], + imports: [RouterModule.forRoot(routes, + { + scrollPositionRestoration: "enabled" + })], + exports: [RouterModule], providers: [ LibraryResolverService, ShowResolverService, diff --git a/Kyoo/ClientApp/src/app/browse/browse.component.ts b/Kyoo/ClientApp/src/app/browse/browse.component.ts index 6399fd77..4e9ed453 100644 --- a/Kyoo/ClientApp/src/app/browse/browse.component.ts +++ b/Kyoo/ClientApp/src/app/browse/browse.component.ts @@ -8,7 +8,7 @@ import { Show } from "../../models/show"; templateUrl: './browse.component.html', styleUrls: ['./browse.component.scss'] }) -export class BrowseComponent implements OnInit +export class BrowseComponent { @Input() shows: Show[]; sortType: string = "title"; @@ -16,13 +16,13 @@ export class BrowseComponent implements OnInit sortTypes: string[] = ["title", "release date"]; - constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer) { } - - ngOnInit() - { - if (this.shows == null) - this.shows = this.route.snapshot.data.shows; - } + constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer) + { + this.route.data.subscribe((data) => + { + this.shows = data.shows; + }); + } getThumb(slug: string) { diff --git a/Kyoo/ClientApp/src/app/collection/collection.component.ts b/Kyoo/ClientApp/src/app/collection/collection.component.ts index 4956c985..1b462d9e 100644 --- a/Kyoo/ClientApp/src/app/collection/collection.component.ts +++ b/Kyoo/ClientApp/src/app/collection/collection.component.ts @@ -8,16 +8,17 @@ import { DomSanitizer } from "@angular/platform-browser"; templateUrl: './collection.component.html', styleUrls: ['./collection.component.scss'] }) -export class CollectionComponent implements OnInit +export class CollectionComponent { collection: Collection; - constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer) { } - - ngOnInit() - { - this.collection = this.route.snapshot.data.collection; - } + constructor(private route: ActivatedRoute, private sanitizer: DomSanitizer) + { + this.route.data.subscribe((data) => + { + this.collection = data.collection; + }); + } getThumb() { diff --git a/Kyoo/ClientApp/src/app/player/player.component.html b/Kyoo/ClientApp/src/app/player/player.component.html index 606b5899..9f424835 100644 --- a/Kyoo/ClientApp/src/app/player/player.component.html +++ b/Kyoo/ClientApp/src/app/player/player.component.html @@ -1,8 +1,6 @@
-
-
-