24 #ifndef GUIVideoEncoder_h 25 #define GUIVideoEncoder_h 41 #define __STDC_CONSTANT_MACROS 45 #pragma warning(disable: 4244) // do not warn about integer conversions 48 #pragma GCC diagnostic push 49 #pragma GCC diagnostic ignored "-Wpedantic" 50 #pragma GCC diagnostic ignored "-Wvariadic-macros" 54 #include <libavutil/opt.h> 55 #include <libavutil/imgutils.h> 56 #include <libavcodec/avcodec.h> 57 #include <libavformat/avformat.h> 58 #include <libswscale/swscale.h> 64 #pragma GCC diagnostic pop 70 GUIVideoEncoder(
const char*
const out_file,
const int width,
const int height,
double frameDelay) {
72 AVFormatContext*
const pFormatCtx =
myFormatContext = avformat_alloc_context();
75 pFormatCtx->oformat = av_guess_format(NULL, out_file, NULL);
76 if (pFormatCtx->oformat == 0) {
77 throw std::runtime_error(
"Unknown format!");
81 if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {
82 throw std::runtime_error(
"Failed to open output file!");
87 if (frameDelay > 0.) {
88 framerate = (int)(1000. / frameDelay);
93 AVStream*
const video_st = avformat_new_stream(pFormatCtx, 0);
94 video_st->time_base.num = 1;
95 video_st->time_base.den = framerate;
98 AVCodecContext*
const pCodecCtx = video_st->codec;
100 pCodecCtx->codec_id = pFormatCtx->oformat->video_codec;
101 pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
102 pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
103 pCodecCtx->width = width;
105 pCodecCtx->height = (height / 2) * 2;
106 pCodecCtx->time_base.num = 1;
107 pCodecCtx->time_base.den = framerate;
108 pCodecCtx->bit_rate = 4000000;
109 pCodecCtx->gop_size = 250;
114 pCodecCtx->qmin = 10;
115 pCodecCtx->qmax = 51;
118 pCodecCtx->max_b_frames = 3;
121 AVDictionary* param = 0;
123 if (pCodecCtx->codec_id == AV_CODEC_ID_H264) {
124 av_dict_set(¶m,
"preset",
"slow", 0);
125 av_dict_set(¶m,
"tune",
"zerolatency", 0);
129 if (pCodecCtx->codec_id == AV_CODEC_ID_HEVC) {
130 av_dict_set(¶m,
"preset",
"ultrafast", 0);
131 av_dict_set(¶m,
"tune",
"zero-latency", 0);
137 AVCodec*
const pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
139 throw std::runtime_error(
"Can not find encoder!");
141 if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0) {
142 throw std::runtime_error(
"Failed to open encoder!");
146 myFrame->format = pCodecCtx->pix_fmt;
147 myFrame->width = pCodecCtx->width;
148 myFrame->height = pCodecCtx->height;
149 av_image_alloc(
myFrame->data,
myFrame->linesize, pCodecCtx->width, pCodecCtx->height,
150 pCodecCtx->pix_fmt, 32);
152 mySwsContext = sws_getContext(pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGBA,
153 pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,
156 avformat_write_header(pFormatCtx, NULL);
165 if (!(fmt_ctx->streams[0]->codec->codec->capabilities &
172 av_init_packet(&enc_pkt);
173 ret = avcodec_encode_video2(fmt_ctx->streams[0]->codec, &enc_pkt,
184 ret = av_write_frame(fmt_ctx, &enc_pkt);
189 av_write_trailer(fmt_ctx);
192 if (fmt_ctx->streams[0]) {
193 avcodec_close(fmt_ctx->streams[0]->codec);
197 avio_close(fmt_ctx->pb);
198 avformat_free_context(fmt_ctx);
204 AVCodecContext*
const pCodecCtx = video_st->codec;
206 uint8_t* inData[1] = { buffer };
207 int inLinesize[1] = { 4 * pCodecCtx->width };
208 sws_scale(
mySwsContext, inData, inLinesize, 0, pCodecCtx->height,
211 av_init_packet(&
myPkt);
218 int ret = avcodec_encode_video2(pCodecCtx, &
myPkt,
myFrame, &got_picture);
220 throw std::runtime_error(
"Failed to encode!");
222 if (got_picture == 1) {
223 myPkt.stream_index = video_st->index;
225 av_free_packet(&
myPkt);
AVFormatContext * myFormatContext
void writeFrame(uint8_t *buffer)
GUIVideoEncoder(const char *const out_file, const int width, const int height, double frameDelay)
SwsContext * mySwsContext