]> git.sesse.net Git - casparcg/commitdiff
Improved read_fps.
authorRobert Nagy <ronag@live.com>
Sun, 3 Nov 2013 16:41:58 +0000 (17:41 +0100)
committerRobert Nagy <ronag@live.com>
Sun, 3 Nov 2013 16:41:58 +0000 (17:41 +0100)
casparcg.sln
modules/ffmpeg/producer/util/util.cpp
modules/ffmpeg/producer/util/util.h
protocol/amcp/AMCPCommandsImpl.cpp

index bbbda09568c075fd79fb4a648cf6406b7ad6b177..695425a11dae80c07101e129f7a9f737b9d52c5d 100644 (file)
@@ -1,6 +1,6 @@
 \r
 Microsoft Visual Studio Solution File, Format Version 12.00\r
-# Visual Studio 2010\r
+# Visual Studio 2012\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "core\core.vcxproj", "{79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}"\r
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shell", "shell\shell.vcxproj", "{8C26C94F-8092-4769-8D84-DEA479721C5B}"\r
index b34f0e29ad922103bda94f8f50b5044b56786847..79cacf0d81d71fa4d650c54aa5c4e925a41e3fef 100644 (file)
@@ -336,7 +336,15 @@ double read_fps(AVFormatContext& context, double fail_value)
        {\r
                const auto video_context = context.streams[video_index]->codec;\r
                const auto video_stream  = context.streams[video_index];\r
-                                               \r
+                               \r
+               auto frame_rate_time_base = video_stream->avg_frame_rate;\r
+               std::swap(frame_rate_time_base.num, frame_rate_time_base.den);\r
+\r
+               if(is_sane_fps(frame_rate_time_base))\r
+               {\r
+                       return static_cast<double>(frame_rate_time_base.den) / static_cast<double>(frame_rate_time_base.num);\r
+               }\r
+\r
                AVRational time_base = video_context->time_base;\r
 \r
                if(boost::filesystem2::path(context.filename).extension() == ".flv")\r
@@ -465,6 +473,30 @@ bool is_valid_file(const std::wstring filename)
        return is_valid_file(filename, invalid_exts);\r
 }\r
 \r
+bool try_get_duration(const std::wstring filename, std::int64_t& duration, boost::rational<std::int64_t>& time_base)\r
+{              \r
+       AVFormatContext* weak_context = nullptr;\r
+       if(avformat_open_input(&weak_context, narrow(filename).c_str(), nullptr, nullptr) < 0)\r
+               return false;\r
+\r
+       std::shared_ptr<AVFormatContext> context(weak_context, av_close_input_file);\r
+       \r
+       context->probesize = context->probesize / 10;\r
+       context->max_analyze_duration = context->probesize / 10;\r
+\r
+       if(avformat_find_stream_info(context.get(), nullptr) < 0)\r
+               return false;\r
+\r
+       const auto fps = read_fps(*context, 1.0);\r
+               \r
+       const auto rational_fps = boost::rational<std::int64_t>(static_cast<int>(fps * AV_TIME_BASE), AV_TIME_BASE);\r
+       \r
+       duration = boost::rational_cast<std::int64_t>(context->duration * rational_fps / AV_TIME_BASE);\r
+       time_base = 1/rational_fps;\r
+\r
+       return true;\r
+}\r
+\r
 std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>& invalid_exts)\r
 {\r
        auto stem2 = boost::filesystem2::wpath(stem);\r
index 4699e7101122ec937b03d3b20986ce9125262c65..2e0f4c0384ba49e38bcdd700496051af1083e813 100644 (file)
 #include <core/producer/frame/pixel_format.h>\r
 #include <core/mixer/audio/audio_mixer.h>\r
 \r
+#include <boost/rational.hpp>\r
+#include <boost/optional.hpp>\r
+\r
+#include <tuple>\r
+\r
+#include <cstdint>\r
+\r
 enum PixelFormat;\r
 struct AVFrame;\r
 struct AVFormatContext;\r
@@ -75,6 +82,7 @@ std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>
 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
+bool try_get_duration(const std::wstring filename, std::int64_t& duration, boost::rational<std::int64_t>& time_base);\r
 \r
 core::channel_layout get_audio_channel_layout(const AVCodecContext& context, const std::wstring& custom_channel_order);\r
 \r
index 90a084e6d0fe1cab9e66eae6a99527abf47ef887..2d1d12bccf8395c684c5e80927f0bfea941936f1 100644 (file)
@@ -201,20 +201,30 @@ std::wstring MediaInfo(const boost::filesystem::wpath& path)
 {\r
        if(boost::filesystem::is_regular_file(path))\r
        {\r
+               std::int64_t duration = 0;\r
+               boost::rational<std::int64_t> time_base;\r
+                               \r
                std::wstring clipttype = TEXT(" N/A ");\r
                std::wstring extension = boost::to_upper_copy(path.extension());\r
                if(extension == TEXT(".TGA") || extension == TEXT(".COL") || extension == L".PNG" || extension == L".JPEG" || extension == L".JPG" ||\r
                        extension == L"GIF" || extension == L"BMP")\r
-                       clipttype = TEXT(" STILL ");\r
+               {\r
+                       clipttype = TEXT(" STILL ");                    \r
+               }\r
                else if(extension == TEXT(".WAV") || extension == TEXT(".MP3"))\r
+               {\r
                        clipttype = TEXT(" AUDIO ");\r
+               }\r
                else if(extension == TEXT(".SWF") || extension == TEXT(".CT") || \r
                            extension == TEXT(".DV") || extension == TEXT(".MOV") || \r
                                extension == TEXT(".MPG") || extension == TEXT(".AVI") || \r
                                extension == TEXT(".MP4") || extension == TEXT(".FLV") || \r
                                extension == TEXT(".STGA") || \r
                                caspar::ffmpeg::is_valid_file(path.file_string()))\r
+               {\r
+                       ffmpeg::try_get_duration(path.file_string(), duration, time_base);\r
                        clipttype = TEXT(" MOVIE ");\r
+               }\r
 \r
                if(clipttype != TEXT(" N/A "))\r
                {               \r
@@ -233,19 +243,22 @@ std::wstring MediaInfo(const boost::filesystem::wpath& path)
                        auto str = relativePath.replace_extension(TEXT("")).external_file_string();\r
                        if(str[0] == '\\' || str[0] == '/')\r
                                str = std::wstring(str.begin() + 1, str.end());\r
-\r
-                       return std::wstring() + TEXT("\"") + str +\r
-                                       + TEXT("\" ") + clipttype +\r
-                                       + TEXT(" ") + sizeStr +\r
-                                       + TEXT(" ") + writeTimeWStr +\r
-                                       + TEXT("\r\n");         \r
+                       \r
+                       return std::wstring() \r
+                                       + L"\""         + str +\r
+                                       + L"\" "        + clipttype +\r
+                                       + L" "          + sizeStr +\r
+                                       + L" "          + writeTimeWStr +\r
+                                       + L" "          + boost::lexical_cast<std::wstring>(duration) +\r
+                                       + L" "          + boost::lexical_cast<std::wstring>(time_base.numerator()) + L"/" + boost::lexical_cast<std::wstring>(time_base.denominator())\r
+                                       + L"\r\n";      \r
                }       \r
        }\r
        return L"";\r
 }\r
 \r
 std::wstring ListMedia()\r
-{      \r
+{              \r
        std::wstringstream replyString;\r
        for (boost::filesystem::wrecursive_directory_iterator itr(env::media_folder()), end; itr != end; ++itr) \r
                replyString << MediaInfo(itr->path());\r