]> git.sesse.net Git - casparcg/commitdiff
2.0. ffmpeg_producer: Added fix for reading FLV meta-data. FFMPEG reads it incorrectly.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 18 Aug 2011 14:48:25 +0000 (14:48 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 18 Aug 2011 14:48:25 +0000 (14:48 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1214 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

modules/ffmpeg/ffmpeg.vcxproj
modules/ffmpeg/ffmpeg.vcxproj.filters
modules/ffmpeg/producer/format/flv.cpp
modules/ffmpeg/producer/format/flv.h
modules/ffmpeg/producer/video/video_decoder.cpp

index 9fcfaf1a4b3adaf5e9e1a12477dd956536e9d38c..cc0f30750a53c4f4b4c4bef7d1633f68211cdfca 100644 (file)
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="producer\format\flv.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">Use</PrecompiledHeader>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">Use</PrecompiledHeader>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="producer\frame_muxer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     <ClInclude Include="producer\ffmpeg_producer.h" />\r
     <ClInclude Include="producer\filter\filter.h" />\r
     <ClInclude Include="producer\filter\parallel_yadif.h" />\r
+    <ClInclude Include="producer\format\flv.h" />\r
     <ClInclude Include="producer\frame_muxer.h" />\r
     <ClInclude Include="producer\input.h" />\r
     <ClInclude Include="producer\util.h" />\r
index 9a884cf4bdeb60627114adbaf547a6fb41d54803..055aedc01dc616073b966723a9c28ad714416589 100644 (file)
@@ -19,6 +19,9 @@
     <Filter Include="source\producer\video">\r
       <UniqueIdentifier>{4b0f3949-6dc5-4895-837f-4c3ef1759a90}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="source\producer\format">\r
+      <UniqueIdentifier>{613cfb2a-5714-46dc-b5ad-6964dded5b02}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\ffmpeg_producer.cpp">\r
@@ -55,6 +58,9 @@
     <ClCompile Include="producer\util.cpp">\r
       <Filter>source\producer</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="producer\format\flv.cpp">\r
+      <Filter>source\producer\format</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="producer\ffmpeg_producer.h">\r
     <ClInclude Include="producer\filter\parallel_yadif.h">\r
       <Filter>source\producer\filter</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="producer\format\flv.h">\r
+      <Filter>source\producer\format</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 3ebcc8ec0f330f2764506357b5d96cf3e09b6045..2d4d5641750febbabe3e7df5911da068e320bb9c 100644 (file)
@@ -8,6 +8,8 @@
 \r
 #include <iostream>\r
 \r
+#include <unordered_map>\r
+\r
 namespace caspar {\r
        \r
 double to_double(std::vector<char> bytes, bool readInReverse)\r
@@ -26,45 +28,73 @@ double to_double(std::vector<char> bytes, bool readInReverse)
     return val;\r
 }\r
 \r
-double next_double(std::fstream& fileStream, int offset, int length)\r
+double next_double(std::fstream& fileStream)\r
 {\r
-    fileStream.seekg(offset, std::ios::cur);\r
-       std::vector<char> bytes(length);\r
-    fileStream.read(bytes.data(), length);\r
+       std::vector<char> bytes(8);\r
+    fileStream.read(bytes.data(), bytes.size());\r
     return to_double(bytes, true);\r
-}\r
+} \r
 \r
-flv_meta_info read_flv_meta_info(const std::wstring& filename)\r
+bool next_bool(std::fstream& fileStream)\r
 {\r
-       if(!boost::filesystem::exists(filename))\r
-               BOOST_THROW_EXCEPTION(caspar_exception());\r
+       std::vector<char> bytes(1);\r
+    fileStream.read(bytes.data(), bytes.size());\r
+    return bytes[0] != 0;\r
+}\r
 \r
-       flv_meta_info meta_info;\r
+std::map<std::string, std::string> read_flv_meta_info(const std::string& filename)\r
+{\r
+       std::map<std::string, std::string>  values;\r
 \r
-    std::fstream fileStream = std::fstream(narrow(filename), std::fstream::in);\r
-       fileStream.seekg(27, std::ios::beg);\r
+       if(boost::filesystem2::path(filename).extension() != ".flv")\r
+               return values;\r
        \r
-    std::array<char, 10> bytes;\r
-    fileStream.read(bytes.data(), bytes.size());\r
+       try\r
+       {\r
+               if(!boost::filesystem2::exists(filename))\r
+                       BOOST_THROW_EXCEPTION(caspar_exception());\r
+       \r
+               std::fstream fileStream = std::fstream(filename, std::fstream::in);\r
+               fileStream.seekg(27, std::ios::beg);\r
+       \r
+               std::vector<char> bytes(10);\r
+               fileStream.read(bytes.data(), bytes.size());\r
+               \r
+               if (std::string(bytes.begin(), bytes.end()) == "onMetaData")\r
+               {\r
+                       fileStream.seekg(6, std::ios::cur);\r
+\r
+                       for(int n = 0; n < 9; ++n)\r
+                       {\r
+                               char name_size = 0;\r
+                               fileStream.read(&name_size, 1);\r
+\r
+                               std::vector<char> name(name_size);\r
+                               fileStream.read(name.data(), name.size());\r
+                               auto name_str = std::string(name.begin(), name.end());\r
+\r
+                               char data_type = 0;\r
+                               fileStream.read(&data_type, 1);\r
+\r
+                               switch(data_type)\r
+                               {\r
+                               case 0:\r
+                                       values[name_str] = boost::lexical_cast<std::string>(next_double(fileStream));\r
+                                       break;\r
+                               case 1:\r
+                                       values[name_str] = boost::lexical_cast<std::string>(next_bool(fileStream));\r
+                                       break;\r
+                               }\r
+                               fileStream.seekg(1, std::ios::cur);\r
+                       }\r
+               }\r
+       }\r
+       catch(...)\r
+       {\r
+               CASPAR_LOG_CURRENT_EXCEPTION();\r
+       }\r
 \r
-       auto on_meta_data = std::string(bytes.begin(), bytes.end());   \r
-       if (on_meta_data == "onMetaData")\r
-    {\r
-        //// 16 bytes past "onMetaData" is the data for "duration" \r
-        meta_info.duration = next_double(fileStream, 16, 8);\r
-        //// 8 bytes past "duration" is the data for "width"\r
-        meta_info.width = next_double(fileStream, 8, 8);\r
-        //// 9 bytes past "width" is the data for "height"\r
-        meta_info.height = next_double(fileStream, 9, 8);\r
-        //// 16 bytes past "height" is the data for "videoDataRate"\r
-        meta_info.video_data_rate = next_double(fileStream, 16, 8);\r
-        //// 16 bytes past "videoDataRate" is the data for "audioDataRate"\r
-        meta_info.audio_data_rate = next_double(fileStream, 16, 8);\r
-        //// 12 bytes past "audioDataRate" is the data for "frameRate"\r
-        meta_info.frame_rate = next_double(fileStream, 12, 8);\r
-    }\r
-    \r
-    return meta_info;\r
+    return values;\r
 }\r
 \r
 }
\ No newline at end of file
index 8ec2265c4c00bcf49bad73b8e42b4ab91139af89..931e7fffbef16a082821b3bbf4bd2db066bf4c4e 100644 (file)
@@ -1,26 +1,7 @@
 #pragma once\r
 \r
 namespace caspar {\r
-          \r
-struct flv_meta_info\r
-{\r
-   double duration;\r
-   double width;\r
-   double height;\r
-   double frame_rate;\r
-   double video_data_rate;\r
-   double audio_data_rate;\r
-\r
-   flv_meta_info()\r
-          : duration(0.0)\r
-          , width(0.0)\r
-          , height(0.0)\r
-          , frame_rate(0.0)\r
-          , video_data_rate(0.0)\r
-          , audio_data_rate(0.0)\r
-   {}\r
-};\r
-\r
-flv_meta_info read_flv_meta_info(const std::wstring& filename);\r
+       \r
+std::map<std::string, std::string> read_flv_meta_info(const std::string& filename);\r
 \r
 }
\ No newline at end of file
index d78361f678db523817fdbb35578c523be52c463f..4b3e2bcd4229525abedc79820886973ee53e5356 100644 (file)
@@ -21,6 +21,7 @@
 \r
 #include "video_decoder.h"\r
 \r
+#include "../format/flv.h"\r
 #include "../util.h"\r
 #include "../filter/filter.h"\r
 \r
@@ -31,6 +32,7 @@
 #include <core/producer/frame/frame_factory.h>\r
 \r
 #include <boost/range/algorithm_ext/push_back.hpp>\r
+#include <boost/filesystem.hpp>\r
 \r
 #include <queue>\r
 \r
@@ -88,12 +90,25 @@ public:
                        // Some files give an invalid time_base numerator, try to fix it.\r
                        if(codec_context_ && codec_context_->time_base.num == 1)\r
                                codec_context_->time_base.num = static_cast<int>(std::pow(10.0, static_cast<int>(std::log10(static_cast<float>(codec_context_->time_base.den)))-1));    \r
-               \r
-                       nb_frames_ = context->streams[index_]->nb_frames;\r
-                       if(nb_frames_ == 0)\r
-                               nb_frames_ = context->streams[index_]->duration;// * context->streams[index_]->time_base.den;\r
+                                       \r
+                       if(boost::filesystem2::path(context->filename).extension() == ".flv")\r
+                       {\r
+                               try\r
+                               {\r
+                                       auto meta = read_flv_meta_info(context->filename);\r
+                                       fps_ = boost::lexical_cast<double>(meta["framerate"]);\r
+                                       nb_frames_ = static_cast<int64_t>(boost::lexical_cast<double>(meta["duration"])*fps_);\r
+                               }\r
+                               catch(...){}\r
+                       }\r
+                       else\r
+                       {\r
+                               fps_ = static_cast<double>(codec_context_->time_base.den) / static_cast<double>(codec_context_->time_base.num);\r
+                               nb_frames_ = context->streams[index_]->nb_frames;\r
+                               if(nb_frames_ == 0)\r
+                                       nb_frames_ = context->streams[index_]->duration;// * context->streams[index_]->time_base.den;\r
+                       }\r
 \r
-                       fps_ = static_cast<double>(codec_context_->time_base.den) / static_cast<double>(codec_context_->time_base.num);\r
                        if(double_rate(filter))\r
                                fps_ *= 2;\r
 \r