/* Copyright (C) 2014-2022 FastoGT. All right reserved. This file is part of fastocloud. fastocloud is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. fastocloud is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with fastocloud. If not, see . */ #include "stream/configs_factory.h" #include #include #include #include "base/config_fields.h" #include "base/link_generator/ilink_generator.h" #include "stream/streams/configs/encode_config.h" #include "stream/streams/configs/relay_config.h" namespace fastocloud { namespace stream { namespace { const size_t kDefaultRestartAttempts = 10; } // namespace common::Error make_config(const StreamConfig& config_args, Config** config) { if (!config_args || !config) { return common::make_error_inval(); } int64_t type; common::Value* type_field = config_args->Find(TYPE_FIELD); if (!type_field || !type_field->GetAsInteger64(&type)) { return common::make_error("Define " TYPE_FIELD " variable and make it valid"); } fastotv::StreamType stream_type = static_cast(type); if (stream_type == fastotv::PROXY || stream_type == fastotv::VOD_PROXY) { return common::make_error("Proxy streams not handled for now"); } const auto input_urls = ReadInput(config_args); if (!input_urls) { return common::make_error("Define " INPUT_FIELD " variable and make it valid"); } const auto output_urls = ReadOutput(config_args); if (!output_urls) { return common::make_error("Define " OUTPUT_FIELD " variable and make it valid"); } int64_t max_restart_attempts; common::Value* restart_attempts_field = config_args->Find(RESTART_ATTEMPTS_FIELD); if (!restart_attempts_field || restart_attempts_field->GetAsInteger64(&max_restart_attempts)) { max_restart_attempts = kDefaultRestartAttempts; } CHECK(max_restart_attempts > 0) << "restart attempts must be grether than 0"; Config conf(static_cast(stream_type), max_restart_attempts, *input_urls, *output_urls); conf.SetTimeToLifeStream(GetTTL(config_args)); streams::AudioVideoConfig aconf(conf); bool have_video; common::Value* have_video_field = config_args->Find(HAVE_VIDEO_FIELD); if (have_video_field && have_video_field->GetAsBoolean(&have_video)) { aconf.SetHaveVideo(have_video); } bool have_audio; common::Value* have_audio_field = config_args->Find(HAVE_AUDIO_FIELD); if (have_audio_field && have_audio_field->GetAsBoolean(&have_audio)) { aconf.SetHaveAudio(have_audio); } bool have_subtitle; common::Value* have_subtitle_field = config_args->Find(HAVE_SUBTITLE_FIELD); if (have_subtitle_field && have_subtitle_field->GetAsBoolean(&have_subtitle)) { aconf.SetHaveSubtitle(have_subtitle); } int64_t audio_select; common::Value* audio_select_field = config_args->Find(AUDIO_SELECT_FIELD); if (audio_select_field && audio_select_field->GetAsInteger64(&audio_select)) { aconf.SetAudioSelect(audio_select); } bool loop; common::Value* loop_field = config_args->Find(LOOP_FIELD); if (loop_field && loop_field->GetAsBoolean(&loop)) { aconf.SetLoop(loop); } if (stream_type == fastotv::RELAY || stream_type == fastotv::TIMESHIFT_PLAYER || stream_type == fastotv::TEST_LIFE || stream_type == fastotv::VOD_RELAY || stream_type == fastotv::COD_RELAY) { streams::RelayConfig* rconfig = new streams::RelayConfig(aconf); std::string video_parser; common::Value* video_parser_field = config_args->Find(VIDEO_PARSER_FIELD); if (video_parser_field && video_parser_field->GetAsBasicString(&video_parser)) { rconfig->SetVideoParser(video_parser); } std::string audio_parser; common::Value* audio_parser_field = config_args->Find(AUDIO_PARSER_FIELD); if (audio_parser_field && audio_parser_field->GetAsBasicString(&audio_parser)) { rconfig->SetAudioParser(audio_parser); } if (stream_type == fastotv::VOD_RELAY) { streams::VodRelayConfig* vconf = new streams::VodRelayConfig(*rconfig); delete rconfig; rconfig = vconf; bool cleanup_ts; common::Value* cleanup_ts_field = config_args->Find(CLEANUP_TS_FIELD); if (cleanup_ts_field && cleanup_ts_field->GetAsBoolean(&cleanup_ts)) { vconf->SetCleanupTS(cleanup_ts); } } *config = rconfig; return common::Error(); } else if (stream_type == fastotv::ENCODE || stream_type == fastotv::VOD_ENCODE || stream_type == fastotv::COD_ENCODE || stream_type == fastotv::EVENT) { streams::EncodeConfig* econfig = new streams::EncodeConfig(aconf); bool relay_audio; common::Value* relay_audio_field = config_args->Find(RELAY_AUDIO_FIELD); if (relay_audio_field && relay_audio_field->GetAsBoolean(&relay_audio)) { econfig->SetRelayAudio(relay_audio); } bool relay_video; common::Value* relay_video_field = config_args->Find(RELAY_VIDEO_FIELD); if (relay_video_field && relay_video_field->GetAsBoolean(&relay_video)) { econfig->SetRelayVideo(relay_video); } bool deinterlace; common::Value* deinterlace_field = config_args->Find(DEINTERLACE_FIELD); if (deinterlace_field && deinterlace_field->GetAsBoolean(&deinterlace)) { econfig->SetDeinterlace(deinterlace); } common::media::Rational frame_rate; common::Value* frame_field = config_args->Find(FRAME_RATE_FIELD); std::string frame_str; if (frame_field && frame_field->GetAsBasicString(&frame_str) && common::ConvertFromString(frame_str, &frame_rate)) { econfig->SetFrameRate(frame_rate); } double volume; common::Value* volume_field = config_args->Find(VOLUME_FIELD); if (volume_field && volume_field->GetAsDouble(&volume)) { econfig->SetVolume(volume); } std::string video_codec; common::Value* video_codec_field = config_args->Find(VIDEO_CODEC_FIELD); if (video_codec_field && video_codec_field->GetAsBasicString(&video_codec)) { econfig->SetVideoEncoder(video_codec); } std::string audio_codec; common::Value* audio_codec_field = config_args->Find(AUDIO_CODEC_FIELD); if (audio_codec_field && audio_codec_field->GetAsBasicString(&audio_codec)) { econfig->SetAudioEncoder(audio_codec); } int64_t audio_channels; common::Value* audio_channels_field = config_args->Find(AUDIO_CHANNELS_FIELD); if (audio_channels_field && audio_channels_field->GetAsInteger64(&audio_channels)) { econfig->SetAudioChannelsCount(audio_channels); } common::HashValue* size_hash = nullptr; common::Value* size_field = config_args->Find(SIZE_FIELD); if (size_field && size_field->GetAsHash(&size_hash)) { auto size = fastotv::MakeSize(size_hash); econfig->SetSize(size); } int64_t v_bitrate; common::Value* video_bitrate_field = config_args->Find(VIDEO_BIT_RATE_FIELD); if (video_bitrate_field && video_bitrate_field->GetAsInteger64(&v_bitrate)) { econfig->SetVideoBitrate(v_bitrate); } int64_t a_bitrate; common::Value* audio_bitrate_field = config_args->Find(AUDIO_BIT_RATE_FIELD); if (audio_bitrate_field && audio_bitrate_field->GetAsInteger64(&a_bitrate)) { econfig->SetAudioBitrate(a_bitrate); } #if defined(MACHINE_LEARNING) common::HashValue* deep_learning_hash = nullptr; common::Value* deep_learning_field = config_args->Find(DEEP_LEARNING_FIELD); if (deep_learning_field && deep_learning_field->GetAsHash(&deep_learning_hash)) { auto deep_learning = machine_learning::DeepLearning::MakeDeepLearning(deep_learning_hash); if (deep_learning) { econfig->SetDeepLearning(*deep_learning); } } common::HashValue* deep_learning_overlay_hash = nullptr; common::Value* deep_learning_overlay_field = config_args->Find(DEEP_LEARNING_OVERLAY_FIELD); if (deep_learning_overlay_field && deep_learning_overlay_field->GetAsHash(&deep_learning_overlay_hash)) { auto deep_learning_overlay = machine_learning::DeepLearningOverlay::MakeDeepLearningOverlay(deep_learning_overlay_hash); if (deep_learning_overlay) { econfig->SetDeepLearningOverlay(*deep_learning_overlay); } } #endif common::HashValue* logo_hash = nullptr; common::Value* logo_field = config_args->Find(LOGO_FIELD); if (logo_field && logo_field->GetAsHash(&logo_hash)) { auto logo = fastotv::Logo::Make(logo_hash); econfig->SetLogo(logo); } common::HashValue* rsvg_logo_hash = nullptr; common::Value* rsvg_logo_field = config_args->Find(RSVG_LOGO_FIELD); if (rsvg_logo_field && rsvg_logo_field->GetAsHash(&rsvg_logo_hash)) { auto logo = fastotv::RSVGLogo::Make(rsvg_logo_hash); econfig->SetRSVGLogo(logo); } common::HashValue* rat_hash = nullptr; common::Value* rat_field = config_args->Find(ASPECT_RATIO_FIELD); if (rat_field && rat_field->GetAsHash(&rat_hash)) { auto rat = fastotv::MakeRational(rat_hash); econfig->SetAspectRatio(rat); } int64_t decl_vm; common::Value* decl_vm_field = config_args->Find(DECKLINK_VIDEO_MODE_FIELD); if (decl_vm_field && decl_vm_field->GetAsInteger64(&decl_vm)) { econfig->SetDecklinkMode(decl_vm); } if (stream_type == fastotv::VOD_ENCODE) { streams::VodEncodeConfig* vconf = new streams::VodEncodeConfig(*econfig); delete econfig; econfig = vconf; bool cleanup_ts; common::Value* cleanup_ts_field = config_args->Find(CLEANUP_TS_FIELD); if (cleanup_ts_field && cleanup_ts_field->GetAsBoolean(&cleanup_ts)) { vconf->SetCleanupTS(cleanup_ts); } } *config = econfig; return common::Error(); } else if (stream_type == fastotv::TIMESHIFT_RECORDER || stream_type == fastotv::CATCHUP) { streams::RelayConfig rel(aconf); std::string video_parser; common::Value* video_parser_field = config_args->Find(VIDEO_PARSER_FIELD); if (video_parser_field && video_parser_field->GetAsBasicString(&video_parser)) { rel.SetVideoParser(video_parser); } std::string audio_parser; common::Value* audio_parser_field = config_args->Find(AUDIO_PARSER_FIELD); if (audio_parser_field && audio_parser_field->GetAsBasicString(&audio_parser)) { rel.SetAudioParser(audio_parser); } streams::TimeshiftConfig* tconf = new streams::TimeshiftConfig(rel); int64_t timeshift_chunk_duration; common::Value* timeshift_chunk_duration_field = config_args->Find(TIMESHIFT_CHUNK_DURATION_FIELD); if (timeshift_chunk_duration_field && timeshift_chunk_duration_field->GetAsInteger64(×hift_chunk_duration)) { tconf->SetTimeShiftChunkDuration(timeshift_chunk_duration); } CHECK(tconf->GetTimeShiftChunkDuration()) << "Avoid division by zero"; *config = tconf; return common::Error(); } return common::make_error(common::MemSPrintf("Unhandled stream type: %d", stream_type)); } Config* make_config_copy(const Config* conf, const link_generator::ILinkGenerator* generator) { Config* copy = conf->Clone(); if (generator) { input_t input = copy->GetInput(); for (size_t i = 0; i < input.size(); ++i) { fastotv::InputUri url; if (generator->Generate(input[i], &url)) { input[i] = url; DEBUG_LOG() << "Generated url: " << url.GetUrl().spec(); } } copy->SetInput(input); } return copy; } } // namespace stream } // namespace fastocloud