#include <common/env.h>\r
\r
#include <boost/thread/once.hpp>\r
+#include <boost/algorithm/string.hpp>\r
\r
#include <tbb/cache_aligned_allocator.h>\r
#include <tbb/parallel_invoke.h>\r
std::shared_ptr<SwsContext> img_convert_ctx_;\r
\r
public:\r
- ffmpeg_consumer(const std::string& filename, const core::video_format_desc& format_desc)\r
+ ffmpeg_consumer(const std::string& filename, const core::video_format_desc& format_desc, const std::string& codec, int bitrate)\r
: filename_(filename + ".mov")\r
, video_outbuf_(1920*1080*8)\r
, audio_outbuf_(48000)\r
\r
strcpy_s(oc_->filename, filename_.c_str());\r
\r
+ auto video_codec = avcodec_find_encoder_by_name(codec.c_str());\r
+ if(video_codec == nullptr)\r
+ BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info(codec));\r
+\r
// Add the audio and video streams using the default format codecs and initialize the codecs .\r
- video_st_ = add_video_stream(oc_->oformat->video_codec);\r
- audio_st_ = add_audio_stream(oc_->oformat->audio_codec);\r
+ video_st_ = add_video_stream(video_codec->id, bitrate);\r
+ audio_st_ = add_audio_stream();\r
\r
dump_format(oc_.get(), 0, filename_.c_str(), 1);\r
\r
\r
THROW_ON_ERROR2(av_write_header(oc_.get()), "[ffmpeg_consumer]");\r
\r
- CASPAR_LOG(info) << print() << L" Successfully initialized."; \r
+ CASPAR_LOG(info) << print() << L" Successfully Initialized."; \r
}\r
\r
~ffmpeg_consumer()\r
\r
if (!(oc_->oformat->flags & AVFMT_NOFILE)) \r
THROW_ON_ERROR2(avio_close(oc_->pb), "[ffmpeg_consumer]"); // Close the output ffmpeg.\r
+\r
+ CASPAR_LOG(info) << print() << L" Successfully Uninitialized."; \r
}\r
catch(...)\r
{\r
return L"ffmpeg[" + widen(filename_) + L"]";\r
}\r
\r
- std::shared_ptr<AVStream> add_video_stream(enum CodecID codec_id)\r
+ std::shared_ptr<AVStream> add_video_stream(enum CodecID codec_id, int bitrate)\r
{ \r
auto st = av_new_stream(oc_.get(), 0);\r
if (!st) \r
<< msg_info("Could not alloc video-stream") \r
<< boost::errinfo_api_function("av_new_stream"));\r
}\r
-\r
- st->codec->codec_id = CODEC_ID_DNXHD;\r
+ \r
+ st->codec->codec_id = codec_id;\r
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;\r
- st->codec->bit_rate = 145*1000000;\r
- st->codec->width = std::min<size_t>(1280, format_desc_.width);\r
- st->codec->height = std::min<size_t>(720, format_desc_.height);\r
+ st->codec->width = format_desc_.width;\r
+ st->codec->height = format_desc_.height;\r
st->codec->time_base.den = format_desc_.time_scale;\r
st->codec->time_base.num = format_desc_.duration;\r
- st->codec->pix_fmt = st->codec->pix_fmt == -1 ? PIX_FMT_YUV422P : st->codec->pix_fmt;\r
-
- if(oc_->oformat->flags & AVFMT_GLOBALHEADER)
+\r
+ if(st->codec->codec_id == CODEC_ID_PRORES)\r
+ { \r
+ st->codec->bit_rate = bitrate > 0 ? bitrate : format_desc_.width < 1280 ? 42*1000000 : 147*1000000;\r
+ st->codec->pix_fmt = PIX_FMT_YUV422P10;\r
+ }\r
+ else if(st->codec->codec_id == CODEC_ID_DNXHD)\r
+ {\r
+ st->codec->bit_rate = bitrate > 0 ? bitrate : 145*1000000;\r
+ st->codec->width = std::min<size_t>(1280, format_desc_.width);\r
+ st->codec->height = std::min<size_t>(720, format_desc_.height);\r
+ st->codec->pix_fmt = PIX_FMT_YUV422P;\r
+ }\r
+ else\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("unsupported codec"));\r
+ \r
+ if(oc_->oformat->flags & AVFMT_GLOBALHEADER)\r
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;\r
\r
auto codec = avcodec_find_encoder(st->codec->codec_id);\r
});\r
}\r
\r
- std::shared_ptr<AVStream> add_audio_stream(enum CodecID codec_id)\r
+ std::shared_ptr<AVStream> add_audio_stream()\r
{\r
auto st = av_new_stream(oc_.get(), 1);\r
if (!st) \r
st->codec->sample_rate = 48000;\r
st->codec->channels = 2;\r
st->codec->sample_fmt = SAMPLE_FMT_S16;\r
-
- if(oc_->oformat->flags & AVFMT_GLOBALHEADER)
+ \r
+ if(oc_->oformat->flags & AVFMT_GLOBALHEADER)\r
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;\r
\r
auto codec = avcodec_find_encoder(st->codec->codec_id);\r
\r
struct ffmpeg_consumer_proxy : public core::frame_consumer\r
{\r
- const std::wstring filename_;\r
- const bool key_only_;\r
+ const std::wstring filename_;\r
+ const bool key_only_;\r
+ const std::string codec_;\r
+ const int bitrate_;\r
\r
std::unique_ptr<ffmpeg_consumer> consumer_;\r
\r
public:\r
\r
- ffmpeg_consumer_proxy(const std::wstring& filename, bool key_only)\r
+ ffmpeg_consumer_proxy(const std::wstring& filename, bool key_only, const std::string codec, int bitrate)\r
: filename_(filename)\r
- , key_only_(key_only){}\r
+ , key_only_(key_only)\r
+ , codec_(boost::to_lower_copy(codec))\r
+ , bitrate_(bitrate)\r
+ {\r
+ }\r
\r
virtual void initialize(const core::video_format_desc& format_desc, int, int)\r
{\r
consumer_.reset();\r
- consumer_.reset(new ffmpeg_consumer(narrow(filename_), format_desc));\r
+ consumer_.reset(new ffmpeg_consumer(narrow(filename_), format_desc, codec_, bitrate_));\r
}\r
\r
virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
boost::filesystem::remove(boost::filesystem::wpath(env::media_folder() + params[1])); // Delete the file if it exists\r
bool key_only = std::find(params.begin(), params.end(), L"KEY_ONLY") != params.end();\r
\r
- return make_safe<ffmpeg_consumer_proxy>(env::media_folder() + params[1], key_only);\r
+ std::string codec = "dnxhd";\r
+ auto codec_it = std::find(params.begin(), params.end(), L"CODEC");\r
+ if(codec_it++ != params.end())\r
+ codec = narrow(*codec_it);\r
+\r
+ int bitrate = 0; \r
+ auto bitrate_it = std::find(params.begin(), params.end(), L"BITRATE");\r
+ if(bitrate_it++ != params.end())\r
+ bitrate = boost::lexical_cast<int>(*codec_it);\r
+\r
+ return make_safe<ffmpeg_consumer_proxy>(env::media_folder() + params[1], key_only, codec, bitrate);\r
}\r
\r
safe_ptr<core::frame_consumer> create_ffmpeg_consumer(const boost::property_tree::ptree& ptree)\r
{\r
std::string filename = ptree.get<std::string>("path");\r
- bool key_only = ptree.get("key-only", false);\r
+ auto key_only = ptree.get("key-only", false);\r
+ auto codec = ptree.get("codec", "dnxhd");\r
+ auto bitrate = ptree.get("bitrate", 0);\r
\r
- return make_safe<ffmpeg_consumer_proxy>(env::media_folder() + widen(filename), key_only);\r
+ return make_safe<ffmpeg_consumer_proxy>(env::media_folder() + widen(filename), key_only, codec, bitrate);\r
}\r
\r
}}\r