]> git.sesse.net Git - casparcg/commitdiff
Dshow filter input (webcam, firewire dv) and live stream playback support.
authorJulian Waller <big.big.julez@gmail.com>
Thu, 23 May 2013 17:41:21 +0000 (18:41 +0100)
committerJulian Waller <big.big.julez@gmail.com>
Thu, 23 May 2013 17:41:21 +0000 (18:41 +0100)
Based on https://github.com/CasparCG/Server/pull/120 by cambell-prince

14 files changed:
common/memory/safe_ptr.h
core/producer/frame_producer.cpp
core/producer/frame_producer.h
modules/ffmpeg/ffmpeg.cpp
modules/ffmpeg/ffmpeg.vcxproj
modules/ffmpeg/ffmpeg.vcxproj.filters
modules/ffmpeg/producer/ffmpeg_params.h [new file with mode: 0644]
modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/ffmpeg/producer/input/input.cpp
modules/ffmpeg/producer/input/input.h
modules/ffmpeg/producer/util/util.cpp
modules/ffmpeg/producer/util/util.h
modules/ffmpeg/producer/video/video_decoder.cpp
shell/shell.vcxproj

index d42135f9bc535d2900facb14a2a69d149526c03c..257302c309429b0f5539d632b9af7852bd6feae2 100644 (file)
@@ -427,6 +427,18 @@ safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&&
        return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6), std::forward<P7>(p7)));\r
 }\r
 \r
+template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8)\r
+{\r
+       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6), std::forward<P7>(p7), std::forward<P8>(p8)));\r
+}\r
+\r
+template<typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>\r
+safe_ptr<T> make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8, P9&& p9)\r
+{\r
+       return safe_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4), std::forward<P5>(p5), std::forward<P6>(p6), std::forward<P7>(p7), std::forward<P8>(p8), std::forward<P9>(p9)));\r
+}\r
+\r
 template<typename T>\r
 safe_ptr<T>::safe_ptr() \r
     : p_(make_safe<T>())\r
index 0a1341f4d61122c818911f4a3edb05aed78c97d4..76aa3d7590ccea36cde58b405f47bbcc16f73259 100644 (file)
@@ -273,6 +273,14 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& my
        auto producer = do_create_producer(my_frame_factory, upper_case_params, original_case_params, g_factories);\r
        auto key_producer = frame_producer::empty();\r
        \r
+       std::wstring resource_name = L"";\r
+       auto tokens = protocol_split(original_case_params[0]);\r
+       if (tokens[0].empty())\r
+       {\r
+               resource_name = original_case_params[0];\r
+       }\r
+\r
+       if(!resource_name.empty()) {\r
        try // to find a key file.\r
        {\r
                auto upper_params_copy = upper_case_params;\r
@@ -292,6 +300,7 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& my
                }\r
        }\r
        catch(...){}\r
+       }\r
 \r
        if(producer != frame_producer::empty() && key_producer != frame_producer::empty())\r
                return create_separated_producer(producer, key_producer);\r
@@ -346,4 +355,21 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>& fa
        return create_producer(factory, tokens, tokens);\r
 }\r
 \r
+std::vector<std::wstring> protocol_split(std::wstring const& s)\r
+{\r
+  std::vector<std::wstring> result;\r
+  size_t pos;\r
+  if ((pos = s.find_first_of(L"://")) != std::wstring::npos)\r
+  {\r
+    result.push_back(s.substr(0, pos));\r
+    result.push_back(s.substr(pos + 3));\r
+  } else\r
+  {\r
+    result.push_back(L"");\r
+    result.push_back(s);\r
+  }\r
+  return result;\r
+}\r
+\r
+\r
 }}
\ No newline at end of file
index 65b694440aea6dd9164fe3e46dff957088b53561..083823b15b3f012791da2245bf947c60b69d0f9b 100644 (file)
@@ -92,4 +92,6 @@ safe_ptr<core::frame_producer> create_producer_destroy_proxy(safe_ptr<core::fram
 safe_ptr<core::frame_producer> create_producer_print_proxy(safe_ptr<core::frame_producer> producer);\r
 safe_ptr<core::frame_producer> create_thumbnail_producer(const safe_ptr<frame_factory>& factory, const std::wstring& media_file);\r
 \r
+std::vector<std::wstring> protocol_split(std::wstring const& s);\r
+\r
 }}\r
index 16a1a970e413afb5cbfef06705f1c26bcd99e2f2..3bf0f8fd8eb17b71df693f0cb202d42e81ba0a24 100644 (file)
@@ -47,6 +47,7 @@ extern "C"
        #include <libswscale/swscale.h>\r
        #include <libavutil/avutil.h>\r
        #include <libavfilter/avfilter.h>\r
+       #include <libavdevice/avdevice.h>\r
 }\r
 \r
 namespace caspar { namespace ffmpeg {\r
@@ -239,11 +240,12 @@ void init()
        av_lockmgr_register(ffmpeg_lock_callback);\r
        av_log_set_callback(log_for_thread);\r
 \r
+       avdevice_register_all();\r
     avfilter_register_all();\r
        //fix_yadif_filter_format_query();\r
        av_register_all();\r
     avformat_network_init();\r
-       avcodec_init();\r
+       //avcodec_init();\r
     avcodec_register_all();\r
        \r
        core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_consumer(params);});\r
index ed5f8a1269cb183c1eba614a8012da9c749bf5ea..7f7316646b169a3862bbeaf42155dfcb2ba1f5c3 100644 (file)
     <ClInclude Include="ffmpeg_error.h" />\r
     <ClInclude Include="producer\audio\audio_decoder.h" />\r
     <ClInclude Include="producer\audio\audio_resampler.h" />\r
+    <ClInclude Include="producer\ffmpeg_params.h" />\r
     <ClInclude Include="producer\ffmpeg_producer.h" />\r
     <ClInclude Include="producer\filter\filter.h" />\r
     <ClInclude Include="producer\filter\parallel_yadif.h" />\r
index 8e2e3ad4f2ac018751fdd3dde2b1ea3fc414e218..c8203601184a993b4be56e54f2c4fe6db4fd934d 100644 (file)
     <ClInclude Include="producer\tbb_avcodec.h">\r
       <Filter>source\producer</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="producer\ffmpeg_params.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
diff --git a/modules/ffmpeg/producer/ffmpeg_params.h b/modules/ffmpeg/producer/ffmpeg_params.h
new file mode 100644 (file)
index 0000000..fdeace2
--- /dev/null
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <string>
+
+namespace caspar {
+namespace ffmpeg {
+
+enum FFMPEG_Resource {
+       FFMPEG_FILE,
+       FFMPEG_DEVICE,
+       FFMPEG_STREAM
+};
+
+struct ffmpeg_params
+{
+       std::wstring  size_str;
+       std::wstring  pixel_format;
+       std::wstring  frame_rate;
+
+
+       ffmpeg_params() 
+               : size_str(L"")
+               , pixel_format(L"")
+               , frame_rate(L"")
+       {
+       }
+
+};
+
+}}
\ No newline at end of file
index 4a0cd37bd285356155b558a0575d6629da7e8a88..03b89ecb5f88e1120aec1b514c0b683fc9fc8ec7 100644 (file)
@@ -25,6 +25,7 @@
 \r
 #include "../ffmpeg_error.h"\r
 #include "../ffmpeg.h"\r
+#include "ffmpeg_params.h"\r
 \r
 #include "muxer/frame_muxer.h"\r
 #include "input/input.h"\r
 #include <queue>\r
 \r
 namespace caspar { namespace ffmpeg {\r
+\r
                                \r
 struct ffmpeg_producer : public core::frame_producer\r
 {\r
        core::monitor::subject                                                                          monitor_subject_;\r
        const std::wstring                                                                                      filename_;\r
+\r
+       FFMPEG_Resource                                                                                         resource_type_;\r
        \r
        const safe_ptr<diagnostics::graph>                                                      graph_;\r
        boost::timer                                                                                            frame_timer_;\r
@@ -92,12 +96,13 @@ struct ffmpeg_producer : public core::frame_producer
        uint32_t                                                                                                        file_frame_number_;\r
                \r
 public:\r
-       explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const std::wstring& custom_channel_order)\r
+       explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, FFMPEG_Resource resource_type, const std::wstring& filter, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const std::wstring& custom_channel_order, const ffmpeg_params& vid_params)\r
                : filename_(filename)\r
+               , resource_type_(resource_type)\r
                , frame_factory_(frame_factory)         \r
                , format_desc_(frame_factory->get_video_format_desc())\r
                , initial_logger_disabler_(temporary_disable_logging_for_thread(thumbnail_mode))\r
-               , input_(graph_, filename_, loop, start, length, thumbnail_mode)\r
+               , input_(graph_, filename_, resource_type, loop, start, length, thumbnail_mode, vid_params)\r
                , fps_(read_fps(*input_.context(), format_desc_.fps))\r
                , start_(start)\r
                , length_(length)\r
@@ -176,14 +181,20 @@ public:
                        try_decode_frame(hints);\r
                \r
                graph_->set_value("frame-time", frame_timer_.elapsed()*format_desc_.fps*0.5);\r
-                               \r
-               if(frame_buffer_.empty() && input_.eof())\r
-                       return std::make_pair(last_frame(), -1);\r
 \r
                if(frame_buffer_.empty())\r
                {\r
-                       graph_->set_tag("underflow");   \r
-                       return std::make_pair(core::basic_frame::late(), -1);\r
+                       if (input_.eof())\r
+                       {\r
+                               return std::make_pair(last_frame(), -1);\r
+                       } else if (resource_type_ == FFMPEG_FILE)\r
+                       {\r
+                               graph_->set_tag("underflow");  \r
+                               return std::make_pair(core::basic_frame::late(), -1);     \r
+                       } else\r
+                       {\r
+                               return std::make_pair(last_frame(), -1);\r
+                       }\r
                }\r
                \r
                auto frame = frame_buffer_.front(); \r
@@ -308,7 +319,8 @@ public:
 \r
        virtual uint32_t nb_frames() const override\r
        {\r
-               if(input_.loop())\r
+               //if(input_.loop())\r
+               if(resource_type_ == FFMPEG_DEVICE || resource_type_ == FFMPEG_STREAM || input_.loop()) \r
                        return std::numeric_limits<uint32_t>::max();\r
 \r
                uint32_t nb_frames = file_nb_frames();\r
@@ -453,7 +465,36 @@ safe_ptr<core::frame_producer> create_producer(
                const std::vector<std::wstring>& original_case_params)\r
 {              \r
        static const std::vector<std::wstring> invalid_exts = boost::assign::list_of(L".png")(L".tga")(L".bmp")(L".jpg")(L".jpeg")(L".gif")(L".tiff")(L".tif")(L".jp2")(L".jpx")(L".j2k")(L".j2c")(L".swf")(L".ct");\r
-       auto filename = probe_stem(env::media_folder() + L"\\" + params.at(0), invalid_exts);\r
+\r
+       // Infer the resource type from the resource_name\r
+       auto resource_type = FFMPEG_FILE;\r
+       auto tokens = caspar::core::protocol_split(original_case_params[0]);\r
+       auto filename = params[0];\r
+       if (!tokens[0].empty())\r
+       {\r
+               if (tokens[0] == L"dshow")\r
+               {\r
+                       // Camera\r
+                       resource_type = FFMPEG_DEVICE;\r
+                       filename = tokens[1];\r
+               } else\r
+               {\r
+                       // Stream\r
+                       resource_type = FFMPEG_STREAM;\r
+                       filename = original_case_params[0];\r
+               }\r
+       } else\r
+       {\r
+               // File\r
+               resource_type = FFMPEG_FILE;\r
+               filename = env::media_folder() + L"\\" + tokens[1];\r
+               if(!boost::filesystem::exists(filename))\r
+                       filename = probe_stem(filename);\r
+\r
+               //TODO fix these?\r
+               //ffmpeg_params->loop       = params.has(L"LOOP");\r
+               //ffmpeg_params->start     = params.get(L"SEEK", static_cast<uint32_t>(0));\r
+       }\r
 \r
        if(filename.empty())\r
                return core::frame_producer::empty();\r
@@ -466,8 +507,13 @@ safe_ptr<core::frame_producer> create_producer(
 \r
        boost::replace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1");\r
        boost::replace_all(filter_str, L"DEINTERLACE_BOB", L"YADIF=1:-1");\r
+\r
+       ffmpeg_params vid_params;\r
+       vid_params.size_str = get_param(L"SIZE", params, L"");\r
+       vid_params.pixel_format = get_param(L"PIXFMT", params, L"");\r
+       vid_params.frame_rate = get_param(L"FRAMERATE", params, L"");\r
        \r
-       return create_producer_destroy_proxy(make_safe<ffmpeg_producer>(frame_factory, filename, filter_str, loop, start, length, false, custom_channel_order));\r
+       return create_producer_destroy_proxy(make_safe<ffmpeg_producer>(frame_factory, filename, resource_type, filter_str, loop, start, length, false, custom_channel_order, vid_params));\r
 }\r
 \r
 safe_ptr<core::frame_producer> create_thumbnail_producer(\r
@@ -488,7 +534,9 @@ safe_ptr<core::frame_producer> create_thumbnail_producer(
        auto length             = std::numeric_limits<uint32_t>::max();\r
        auto filter_str = L"";\r
                \r
-       return create_producer_destroy_proxy(make_safe<ffmpeg_producer>(frame_factory, filename, filter_str, loop, start, length, true, L""));\r
+       ffmpeg_params vid_params;\r
+\r
+       return create_producer_destroy_proxy(make_safe<ffmpeg_producer>(frame_factory, filename, FFMPEG_FILE, filter_str, loop, start, length, true, L"", vid_params));\r
 }\r
 \r
 }}
\ No newline at end of file
index 849af4f19f7748639b58bd6f21c6d99fef15001a..de3f2264f1908877047e75c1ccd3aca6a68b075d 100644 (file)
@@ -24,6 +24,7 @@
 #include "input.h"\r
 \r
 #include "../util/util.h"\r
+#include "../util/flv.h"\r
 #include "../../ffmpeg_error.h"\r
 #include "../../ffmpeg.h"\r
 \r
@@ -83,9 +84,9 @@ struct input::implementation : boost::noncopyable
                \r
        executor                                                                                                        executor_;\r
        \r
-       explicit implementation(const safe_ptr<diagnostics::graph> graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode\r
+       explicit implementation(const safe_ptr<diagnostics::graph> graph, const std::wstring& filename, FFMPEG_Resource resource_type, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const ffmpeg_params& vid_params\r
                : graph_(graph)\r
-               , format_context_(open_input(filename))         \r
+               , format_context_(open_input(filename, resource_type, vid_params))              \r
                , default_stream_index_(av_find_default_stream_index(format_context_.get()))\r
                , filename_(filename)\r
                , start_(start)\r
@@ -234,6 +235,72 @@ struct input::implementation : boost::noncopyable
                        }\r
                });\r
        }       \r
+\r
+       safe_ptr<AVFormatContext> open_input(const std::wstring resource_name, FFMPEG_Resource resource_type, const ffmpeg_params& vid_params)\r
+  {\r
+    AVFormatContext* weak_context = nullptr;\r
+\r
+    switch (resource_type) {\r
+    case FFMPEG_FILE:\r
+      THROW_ON_ERROR2(avformat_open_input(&weak_context, narrow(resource_name).c_str(), nullptr, nullptr), resource_name);\r
+      break;\r
+    case FFMPEG_DEVICE: {\r
+      AVDictionary* format_options = NULL;\r
+         if(vid_params.size_str != L"")\r
+               av_dict_set(&format_options, "video_size", narrow(vid_params.size_str).c_str(), 0); // 640x360 for 16:9\r
+         if(vid_params.pixel_format != L"")\r
+               av_dict_set(&format_options, "pixel_format", narrow(vid_params.pixel_format).c_str(), 0); // yuyv422 for sony\r
+      av_dict_set(&format_options, "avioflags", "direct", 0);\r
+\r
+      // Don't set framerate here, it is typically set to a fixed rate anyway. Better to insert a fps filter to adjust the frame rate.\r
+         // Im going to try anyway for now\r
+      if(vid_params.frame_rate != L"")\r
+               av_dict_set(&format_options, "framerate", narrow(vid_params.frame_rate).c_str(), 0);\r
+      AVInputFormat* input_format = av_find_input_format("dshow");\r
+      THROW_ON_ERROR2(avformat_open_input(&weak_context, narrow(resource_name).c_str(), input_format, &format_options), resource_name);\r
+      av_dict_free(&format_options);\r
+      } break;\r
+    case FFMPEG_STREAM:\r
+      THROW_ON_ERROR2(avformat_open_input(&weak_context, narrow(resource_name).c_str(), nullptr, nullptr), resource_name);\r
+      break;\r
+    };\r
+    safe_ptr<AVFormatContext> context(weak_context, av_close_input_file);      \r
+    THROW_ON_ERROR2(avformat_find_stream_info(weak_context, nullptr), resource_name);\r
+    fix_meta_data(*context);\r
+    return context;\r
+  }\r
+\r
+  void fix_meta_data(AVFormatContext& context)\r
+  {\r
+    auto video_index = av_find_best_stream(&context, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);\r
+\r
+    if(video_index > -1)\r
+    {\r
+     auto video_stream   = context.streams[video_index];\r
+      auto video_context  = context.streams[video_index]->codec;\r
+            \r
+      if(boost::filesystem2::path(context.filename).extension() == ".flv")\r
+      {\r
+        try\r
+        {\r
+          auto meta = read_flv_meta_info(context.filename);\r
+          double fps = boost::lexical_cast<double>(meta["framerate"]);\r
+          video_stream->nb_frames = static_cast<int64_t>(boost::lexical_cast<double>(meta["duration"])*fps);\r
+        }\r
+        catch(...){}\r
+      }\r
+      else\r
+      {\r
+        auto stream_time = video_stream->time_base;\r
+        auto duration   = video_stream->duration;\r
+        auto codec_time  = video_context->time_base;\r
+        auto ticks     = video_context->ticks_per_frame;\r
+\r
+        if(video_stream->nb_frames == 0)\r
+          video_stream->nb_frames = (duration*stream_time.num*codec_time.den)/(stream_time.den*codec_time.num*ticks);  \r
+      }\r
+    }\r
+  }\r
                        \r
        void queued_seek(const uint32_t target)\r
        {       \r
@@ -278,8 +345,8 @@ struct input::implementation : boost::noncopyable
        }\r
 };\r
 \r
-input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode\r
-       : impl_(new implementation(graph, filename, loop, start, length, thumbnail_mode)){}\r
+input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, FFMPEG_Resource resource_type, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const ffmpeg_params& vid_params\r
+       : impl_(new implementation(graph, filename, resource_type, loop, start, length, thumbnail_mode, vid_params)){}\r
 bool input::eof() const {return !impl_->executor_.is_running();}\r
 bool input::try_pop(std::shared_ptr<AVPacket>& packet){return impl_->try_pop(packet);}\r
 safe_ptr<AVFormatContext> input::context(){return impl_->format_context_;}\r
index 69984c6ade2536980235917044e00c5f9f143045..7406430fcbeb7d3b833c76a8226e3872688afcf7 100644 (file)
@@ -20,6 +20,7 @@
 */\r
 \r
 #pragma once\r
+#include "../ffmpeg_params.h"\r
 \r
 #include <common/memory/safe_ptr.h>\r
 \r
@@ -46,7 +47,7 @@ namespace ffmpeg {
 class input : boost::noncopyable\r
 {\r
 public:\r
-       explicit input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode);\r
+       explicit input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, FFMPEG_Resource resource_type, bool loop, uint32_t start, uint32_t length, bool thumbnail_mode, const ffmpeg_params& vid_params);\r
 \r
        bool try_pop(std::shared_ptr<AVPacket>& packet);\r
        bool eof() const;\r
index f1f34c08e8b3760694c26628d64a63357bd54215..ac6b677d3eb68b368fbd81d052c397a2042aaad2 100644 (file)
@@ -392,38 +392,6 @@ double read_fps(AVFormatContext& context, double fail_value)
        return fail_value;      \r
 }\r
 \r
-void fix_meta_data(AVFormatContext& context)\r
-{\r
-       auto video_index = av_find_best_stream(&context, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);\r
-\r
-       if(video_index > -1)\r
-       {\r
-               auto video_stream   = context.streams[video_index];\r
-               auto video_context  = context.streams[video_index]->codec;\r
-                                               \r
-               if(boost::filesystem2::path(context.filename).extension() == ".flv")\r
-               {\r
-                       try\r
-                       {\r
-                               auto meta = read_flv_meta_info(context.filename);\r
-                               double fps = boost::lexical_cast<double>(meta["framerate"]);\r
-                               video_stream->nb_frames = static_cast<int64_t>(boost::lexical_cast<double>(meta["duration"])*fps);\r
-                       }\r
-                       catch(...){}\r
-               }\r
-               else\r
-               {\r
-                       auto stream_time = video_stream->time_base;\r
-                       auto duration    = video_stream->duration;\r
-                       auto codec_time  = video_context->time_base;\r
-                       auto ticks               = video_context->ticks_per_frame;\r
-\r
-                       if(video_stream->nb_frames == 0)\r
-                               video_stream->nb_frames = (duration*stream_time.num*codec_time.den)/(stream_time.den*codec_time.num*ticks);     \r
-               }\r
-       }\r
-}\r
-\r
 safe_ptr<AVPacket> create_packet()\r
 {\r
        safe_ptr<AVPacket> packet(new AVPacket, [](AVPacket* p)\r
@@ -447,16 +415,6 @@ safe_ptr<AVCodecContext> open_codec(AVFormatContext& context, enum AVMediaType t
        return safe_ptr<AVCodecContext>(context.streams[index]->codec, tbb_avcodec_close);\r
 }\r
 \r
-safe_ptr<AVFormatContext> open_input(const std::wstring& filename)\r
-{\r
-       AVFormatContext* weak_context = nullptr;\r
-       THROW_ON_ERROR2(avformat_open_input(&weak_context, narrow(filename).c_str(), nullptr, nullptr), filename);\r
-       safe_ptr<AVFormatContext> context(weak_context, av_close_input_file);                   \r
-       THROW_ON_ERROR2(avformat_find_stream_info(weak_context, nullptr), filename);\r
-       fix_meta_data(*context);\r
-       return context;\r
-}\r
-\r
 std::wstring print_mode(size_t width, size_t height, double fps, bool interlaced)\r
 {\r
        std::wostringstream fps_ss;\r
@@ -519,6 +477,18 @@ std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>
        return L"";\r
 }\r
 \r
+std::wstring probe_stem(const std::wstring stem)\r
+{\r
+       auto stem2 = boost::filesystem2::wpath(stem);\r
+       auto dir = stem2.parent_path();\r
+       for(auto it = boost::filesystem2::wdirectory_iterator(dir); it != boost::filesystem2::wdirectory_iterator(); ++it)\r
+       {\r
+               if(boost::iequals(it->path().stem(), stem2.filename()) && is_valid_file(it->path().file_string()))\r
+                       return it->path().file_string();\r
+       }\r
+       return L"";\r
+}\r
+\r
 core::channel_layout get_audio_channel_layout(\r
                const AVCodecContext& context, const std::wstring& custom_channel_order)\r
 {\r
index 4e8e3f2d1624c80732a08b256f783c76b0f4f9af..7c58ac757653503986c6657ac27a4fc505465f29 100644 (file)
@@ -63,7 +63,6 @@ safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVF
 safe_ptr<AVPacket> create_packet();\r
 \r
 safe_ptr<AVCodecContext> open_codec(AVFormatContext& context,  enum AVMediaType type, int& index);\r
-safe_ptr<AVFormatContext> open_input(const std::wstring& filename);\r
 \r
 bool is_sane_fps(AVRational time_base);\r
 AVRational fix_time_base(AVRational time_base);\r
@@ -73,6 +72,7 @@ double read_fps(AVFormatContext& context, double fail_value);
 std::wstring print_mode(size_t width, size_t height, double fps, bool interlaced);\r
 \r
 std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>& invalid_exts);\r
+std::wstring probe_stem(const std::wstring stem);\r
 bool is_valid_file(const std::wstring filename, const std::vector<std::wstring>& invalid_exts);\r
 bool is_valid_file(const std::wstring filename);\r
 \r
index 416f3d3149d51743ee0aacaa995c044ffe29bec9..91d7161e49ed7bd60654ab5966c2e58f55aa5771 100644 (file)
@@ -93,29 +93,30 @@ public:
                                        \r
                if(packet->data == nullptr)\r
                {                       \r
+                       packets_.pop();\r
                        if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
                        {\r
-                               auto video = decode(*packet);\r
+                               auto video = decode(packet.get());\r
                                if(video)\r
                                        return video;\r
                        }\r
                                        \r
-                       packets_.pop();\r
+                       //packets_.pop();\r
                        file_frame_number_ = static_cast<size_t>(packet->pos);\r
                        avcodec_flush_buffers(codec_context_.get());\r
                        return flush_video();   \r
                }\r
                        \r
                packets_.pop();\r
-               return decode(*packet);\r
+               return decode(packet.get());\r
        }\r
 \r
-       std::shared_ptr<AVFrame> decode(AVPacket& pkt)\r
+       std::shared_ptr<AVFrame> decode(AVPacket* pkt)\r
        {\r
                std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
 \r
                int frame_finished = 0;\r
-               THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, &pkt), "[video_decocer]");\r
+               THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, pkt), "[video_decocer]");\r
                \r
                // If a decoder consumes less then the whole packet then something is wrong\r
                // that might be just harmless padding at the end, or a problem with the\r
@@ -131,7 +132,8 @@ public:
                \r
                ++file_frame_number_;\r
 \r
-               return decoded_frame;\r
+               //return decoded_frame;\r
+               return std::shared_ptr<AVFrame>(decoded_frame.get(), [decoded_frame, pkt](AVFrame*){});\r
        }\r
        \r
        bool ready() const\r
index 18bb39c9bd41d8a8fd9be900ce1afce9d3820758..9517c97d248a2bd837f6f7442f308bbfb9cbc4b7 100644 (file)
       <ForcedIncludeFiles>common/compiler/vs/disable_silly_warnings.h</ForcedIncludeFiles>\r
     </ClCompile>\r
     <Link>\r
-      <AdditionalDependencies>sfml-system-d.lib;sfml-audio-d.lib;sfml-window-d.lib;sfml-graphics-d.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
+      <AdditionalDependencies>sfml-system-d.lib;sfml-audio-d.lib;sfml-window-d.lib;sfml-graphics-d.lib;OpenGL32.lib;FreeImage.lib;Winmm.lib;Ws2_32.lib;avformat.lib;avcodec.lib;avdevice.lib;avutil.lib;avfilter.lib;swscale.lib;tbb.lib;glew32.lib;zdll.lib</AdditionalDependencies>\r
       <Version>\r
       </Version>\r
       <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r