<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
<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
<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
\r
#include <iostream>\r
\r
+#include <unordered_map>\r
+\r
namespace caspar {\r
\r
double to_double(std::vector<char> bytes, bool readInReverse)\r
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
\r
#include "video_decoder.h"\r
\r
+#include "../format/flv.h"\r
#include "../util.h"\r
#include "../filter/filter.h"\r
\r
#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
// 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