X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fffmpeg%2Fproducer%2Finput%2Finput.cpp;h=9103c7b261e8370ad14bfb60aa53118215d269de;hb=a111f54e43d6b3974036b6e7812b39558409910f;hp=1e081a17a09214b589ecd3d2cd4c8dd6d91273bb;hpb=c64b8283bfe0bcc28b0d196f997d6deec6b41a3f;p=casparcg diff --git a/modules/ffmpeg/producer/input/input.cpp b/modules/ffmpeg/producer/input/input.cpp index 1e081a17a..9103c7b26 100644 --- a/modules/ffmpeg/producer/input/input.cpp +++ b/modules/ffmpeg/producer/input/input.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -85,10 +87,10 @@ struct input::implementation : boost::noncopyable executor executor_; - explicit implementation(const spl::shared_ptr graph, const std::wstring& filename, FFMPEG_Resource resource_type, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const ffmpeg_options& vid_params) + explicit implementation(const spl::shared_ptr graph, const std::wstring& url_or_file, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const ffmpeg_options& vid_params) : graph_(graph) - , format_context_(open_input(filename, resource_type, vid_params)) - , filename_(filename) + , format_context_(open_input(url_or_file, vid_params)) + , filename_(url_or_file) , thumbnail_mode_(thumbnail_mode) , executor_(print()) { @@ -235,69 +237,55 @@ struct input::implementation : boost::noncopyable }); } - spl::shared_ptr open_input(const std::wstring resource_name, FFMPEG_Resource resource_type, const ffmpeg_options& vid_params) + spl::shared_ptr open_input(const std::wstring& url_or_file, const ffmpeg_options& vid_params) { - AVFormatContext* weak_context = nullptr; + AVDictionary* format_options = nullptr; - switch (resource_type) { - case FFMPEG_Resource::FFMPEG_FILE: - THROW_ON_ERROR2(avformat_open_input(&weak_context, u8(resource_name).c_str(), nullptr, nullptr), resource_name); - break; - case FFMPEG_Resource::FFMPEG_DEVICE: - { - AVDictionary* format_options = NULL; - for (auto& option : vid_params) - { - av_dict_set(&format_options, option.first.c_str(), option.second.c_str(), 0); - } - AVInputFormat* input_format = av_find_input_format("dshow"); - THROW_ON_ERROR2(avformat_open_input(&weak_context, u8(resource_name).c_str(), input_format, &format_options), resource_name); - if (format_options != nullptr) - { - std::string unsupported_tokens = ""; - AVDictionaryEntry *t = NULL; - while ((t = av_dict_get(format_options, "", t, AV_DICT_IGNORE_SUFFIX)) != nullptr) - { - if (!unsupported_tokens.empty()) - unsupported_tokens += ", "; - unsupported_tokens += t->key; - } - avformat_close_input(&weak_context); - BOOST_THROW_EXCEPTION(ffmpeg_error() << msg_info(unsupported_tokens)); - } - av_dict_free(&format_options); - } - break; - case FFMPEG_Resource::FFMPEG_STREAM: - { - AVDictionary* format_options = NULL; - for (auto& option : vid_params) - { - av_dict_set(&format_options, option.first.c_str(), option.second.c_str(), 0); - } - THROW_ON_ERROR2(avformat_open_input(&weak_context, u8(resource_name).c_str(), nullptr, &format_options), resource_name); - if (format_options != nullptr) - { - std::string unsupported_tokens = ""; - AVDictionaryEntry *t = NULL; - while ((t = av_dict_get(format_options, "", t, AV_DICT_IGNORE_SUFFIX)) != nullptr) - { - if (!unsupported_tokens.empty()) - unsupported_tokens += ", "; - unsupported_tokens += t->key; - } - avformat_close_input(&weak_context); - BOOST_THROW_EXCEPTION(ffmpeg_error() << msg_info(unsupported_tokens)); - } + CASPAR_SCOPE_EXIT + { + if (format_options) av_dict_free(&format_options); - } - break; }; - spl::shared_ptr context(weak_context, [](AVFormatContext* p) + + for (auto& option : vid_params) + av_dict_set(&format_options, option.first.c_str(), option.second.c_str(), 0); + + auto resource_name = std::wstring(); + auto parts = caspar::protocol_split(url_or_file); + AVInputFormat* input_format = nullptr; + + if (parts.at(0).empty()) + resource_name = parts.at(1); + else if (parts.at(0) == L"dshow") + { + input_format = av_find_input_format("dshow"); + resource_name = parts.at(1); + } + else + resource_name = parts.at(0) + L"://" + parts.at(1); + + AVFormatContext* weak_context = nullptr; + THROW_ON_ERROR2(avformat_open_input(&weak_context, u8(resource_name).c_str(), input_format, &format_options), resource_name); + + spl::shared_ptr context(weak_context, [](AVFormatContext* ptr) { - avformat_close_input(&p); + avformat_close_input(&ptr); }); - THROW_ON_ERROR2(avformat_find_stream_info(weak_context, nullptr), resource_name); + + if (format_options) + { + std::string unsupported_tokens = ""; + AVDictionaryEntry *t = NULL; + while ((t = av_dict_get(format_options, "", t, AV_DICT_IGNORE_SUFFIX)) != nullptr) + { + if (!unsupported_tokens.empty()) + unsupported_tokens += ", "; + unsupported_tokens += t->key; + } + CASPAR_THROW_EXCEPTION(user_error() << msg_info(unsupported_tokens)); + } + + THROW_ON_ERROR2(avformat_find_stream_info(context.get(), nullptr), resource_name); fix_meta_data(*context); return context; } @@ -394,8 +382,8 @@ struct input::implementation : boost::noncopyable } }; -input::input(const spl::shared_ptr& graph, const std::wstring& filename, FFMPEG_Resource resource_type, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const ffmpeg_options& vid_params) - : impl_(new implementation(graph, filename, resource_type, loop, start, length, thumbnail_mode, vid_params)){} +input::input(const spl::shared_ptr& graph, const std::wstring& url_or_file, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const ffmpeg_options& vid_params) + : impl_(new implementation(graph, url_or_file, loop, start, length, thumbnail_mode, vid_params)){} bool input::eof() const {return !impl_->executor_.is_running();} bool input::try_pop(std::shared_ptr& packet){return impl_->try_pop(packet);} spl::shared_ptr input::context(){return impl_->format_context_;}