]> git.sesse.net Git - casparcg/blobdiff - modules/ffmpeg/producer/format/flv.cpp
2.0. ffmpeg_producer: Added fix for reading FLV meta-data. FFMPEG reads it incorrectly.
[casparcg] / modules / ffmpeg / producer / format / flv.cpp
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