#define __STDC_CONSTANT_MACROS\r
#define __STDC_LIMIT_MACROS\r
#include <libavformat/avformat.h>\r
- #include <libswscale/swscale.h>\r
+ #include <libswscale/swscale.h>
+ #include <libavutil/opt.h>\r
}\r
#if defined(_MSC_VER)\r
#pragma warning (pop)\r
\r
std::vector<uint8_t> picture_buf_;\r
std::shared_ptr<SwsContext> img_convert_ctx_;\r
+\r
+ int64_t frame_number_;\r
\r
public:\r
ffmpeg_consumer(const std::string& filename, const core::video_format_desc& format_desc, const std::string& codec, int bitrate)\r
, format_desc_(format_desc)\r
, executor_(print())\r
, file_write_executor_(print() + L"/output")\r
+ , frame_number_(0)\r
{\r
graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
<< boost::errinfo_api_function("av_new_stream"));\r
}\r
\r
+ auto encoder = avcodec_find_encoder(codec_id);\r
+ if (!encoder)\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("codec not found"));\r
+\r
+ auto c = st->codec;\r
+\r
+ avcodec_get_context_defaults3(c, encoder);\r
+\r
bitrate *= 1000000;\r
\r
- st->codec->codec_id = codec_id;\r
- st->codec->bit_rate = bitrate > 0 ? bitrate : format_desc_.width < 1280 ? 63*1000000 : 220*1000000;\r
- st->codec->codec_type = AVMEDIA_TYPE_VIDEO;\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
-\r
- if(st->codec->codec_id == CODEC_ID_PRORES)\r
+ c->codec_id = codec_id;\r
+ c->bit_rate = bitrate > 0 ? bitrate : format_desc_.width < 1280 ? 63*1000000 : 220*1000000;\r
+ c->codec_type = AVMEDIA_TYPE_VIDEO;\r
+ c->width = format_desc_.width;\r
+ c->height = format_desc_.height;\r
+ c->time_base.den = format_desc_.time_scale;\r
+ c->time_base.num = format_desc_.duration;\r
+ c->gop_size = 25;\r
+\r
+ if(c->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
+ c->bit_rate = bitrate > 0 ? bitrate : format_desc_.width < 1280 ? 42*1000000 : 147*1000000;\r
+ c->pix_fmt = PIX_FMT_YUV422P10;\r
}\r
- else if(st->codec->codec_id == CODEC_ID_DNXHD)\r
+ else if(c->codec_id == CODEC_ID_DNXHD)\r
{\r
if(format_desc_.width < 1280 || format_desc_.height < 720)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("unsupported dimension"));\r
\r
- st->codec->bit_rate = bitrate > 0 ? bitrate : 220*1000000;\r
- st->codec->pix_fmt = PIX_FMT_YUV422P;\r
+ c->bit_rate = bitrate > 0 ? bitrate : 220*1000000;\r
+ c->pix_fmt = PIX_FMT_YUV422P;\r
}\r
- else if(st->codec->codec_id == CODEC_ID_DVVIDEO)\r
+ else if(c->codec_id == CODEC_ID_DVVIDEO)\r
{\r
- st->codec->bit_rate = bitrate > 0 ? bitrate : format_desc_.width < 1280 ? 50*1000000 : 100*1000000;\r
- st->codec->pix_fmt = PIX_FMT_YUV422P;\r
+ c->bit_rate = bitrate > 0 ? bitrate : format_desc_.width < 1280 ? 50*1000000 : 100*1000000;\r
+ c->pix_fmt = PIX_FMT_YUV422P;\r
}\r
//else if(st->codec->codec_id == CODEC_ID_H264)\r
- //{ \r
- // st->codec->pix_fmt = PIX_FMT_YUV422P;\r
- // st->codec->me_range = 16;\r
- // st->codec->max_qdiff = 4;\r
- // st->codec->qmin = 10;\r
- // st->codec->qmax = 51;\r
- // st->codec->qcompress = 0.6;\r
- // st->codec->gop_size = 25;\r
+ //{ \r
+ // c->pix_fmt = PIX_FMT_YUV422P;
+ // THROW_ON_ERROR2(av_opt_set(c->priv_data, "preset", "slow", 0), "[ffmpeg_consumer]");\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
- if (!codec)\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("codec not found"));\r
-\r
- st->codec->thread_count = boost::thread::hardware_concurrency();\r
- THROW_ON_ERROR2(avcodec_open(st->codec, codec), "[ffmpeg_consumer]");\r
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER;\r
+ \r
+ c->thread_count = boost::thread::hardware_concurrency();\r
+ THROW_ON_ERROR2(avcodec_open(c, encoder), "[ffmpeg_consumer]");\r
\r
return std::shared_ptr<AVStream>(st, [](AVStream* st)\r
{\r
std::shared_ptr<AVFrame> local_av_frame(avcodec_alloc_frame(), av_free);\r
local_av_frame->interlaced_frame = format_desc_.field_mode != core::field_mode::progressive;\r
local_av_frame->top_field_first = format_desc_.field_mode == core::field_mode::upper;\r
+ local_av_frame->pts = (frame_number_ * video_st_->time_base.den) * video_st_->time_base.num;\r
\r
picture_buf_.resize(avpicture_get_size(c->pix_fmt, format_desc_.width, format_desc_.height));\r
avpicture_fill(reinterpret_cast<AVPicture*>(local_av_frame.get()), picture_buf_.data(), c->pix_fmt, format_desc_.width, format_desc_.height);\r
av_write_frame(oc_.get(), video.get());\r
if(audio)\r
av_write_frame(oc_.get(), audio.get());\r
+ ++frame_number_;\r
graph_->update_value("write-time", write_timer_.elapsed()*format_desc_.fps*0.5);\r
});\r
});\r
if(codec_it != params.end() && codec_it++ != params.end())\r
codec = narrow(*codec_it);\r
\r
+ if(codec == "H264" || codec == "h264")\r
+ codec = "libx264";\r
+\r
int bitrate = 0; \r
auto bitrate_it = std::find(params.begin(), params.end(), L"BITRATE");\r
if(bitrate_it != params.end() && bitrate_it++ != params.end())\r