]> git.sesse.net Git - casparcg/blobdiff - modules/ffmpeg/producer/util.cpp
2.0. ffmpeg_producer: Refactored meta data fix.
[casparcg] / modules / ffmpeg / producer / util.cpp
index 4a5782dd7df274dc3eba1da7f9104121947d2d8b..8e1d26c48effc3ca49286dacb306395a0eaaf592 100644 (file)
@@ -202,4 +202,74 @@ safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVF
        }\r
 }\r
 \r
+bool is_sane_fps(AVRational time_base)\r
+{\r
+       double fps = static_cast<double>(time_base.den) / static_cast<double>(time_base.num);\r
+       return fps > 20.0 && fps < 65.0;\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
+       auto audio_index = av_find_best_stream(&context, AVMEDIA_TYPE_AUDIO, -1, -1, 0, 0);\r
+\r
+       if(video_index < 0)\r
+               return;\r
+\r
+       auto& video_context = *context.streams[video_index]->codec;\r
+       auto& video_stream  = *context.streams[video_index];\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_context.time_base.num = 1000000;\r
+                       video_context.time_base.den = static_cast<int>(fps*1000000.0);\r
+                       video_stream.nb_frames = static_cast<int64_t>(boost::lexical_cast<double>(meta["duration"])*fps);\r
+               }\r
+               catch(...){}\r
+       }\r
+       else\r
+       {\r
+               if(video_stream.nb_frames == 0)\r
+                       video_stream.nb_frames = video_stream.duration;\r
+\r
+               if(!is_sane_fps(video_context.time_base))\r
+               {                       \r
+                       if(video_context.time_base.num == 1)\r
+                               video_context.time_base.num = static_cast<int>(std::pow(10.0, static_cast<int>(std::log10(static_cast<float>(video_context.time_base.den)))-1));        \r
+\r
+                       if(!is_sane_fps(video_context.time_base) && audio_index > -1)\r
+                       {\r
+                               auto& audio_context = *context.streams[audio_index]->codec;\r
+                               auto& audio_stream  = *context.streams[audio_index];\r
+\r
+                               double duration_sec = audio_stream.duration / static_cast<double>(audio_context.sample_rate);\r
+                                                               \r
+                               video_context.time_base.num = static_cast<int>(duration_sec*100000.0);\r
+                               video_context.time_base.den = static_cast<int>(video_stream.nb_frames*100000);\r
+                       }\r
+               }\r
+       }\r
+\r
+       double fps = static_cast<double>(video_context.time_base.den) / static_cast<double>(video_context.time_base.num);\r
+\r
+       double closest_fps = 0.0;\r
+       for(int n = 0; n < core::video_format::count; ++n)\r
+       {\r
+               auto format = core::video_format_desc::get(static_cast<core::video_format::type>(n));\r
+\r
+               double diff1 = std::abs(format.fps - fps);\r
+               double diff2 = std::abs(closest_fps - fps);\r
+\r
+               if(diff1 < diff2)\r
+                       closest_fps = format.fps;\r
+       }\r
+       \r
+       video_context.time_base.num = 1000000;\r
+       video_context.time_base.den = static_cast<int>(closest_fps*1000000.0);\r
+}\r
+\r
 }
\ No newline at end of file