23 #ifndef GUIVideoEncoder_h 24 #define GUIVideoEncoder_h 40 #define __STDC_CONSTANT_MACROS 44 #pragma warning(disable: 4244) // do not warn about integer conversions 47 #pragma GCC diagnostic push 48 #pragma GCC diagnostic ignored "-Wpedantic" 49 #pragma GCC diagnostic ignored "-Wvariadic-macros" 53 #include <libavutil/opt.h> 54 #include <libavutil/imgutils.h> 55 #include <libavcodec/avcodec.h> 56 #include <libavformat/avformat.h> 57 #include <libswscale/swscale.h> 63 #pragma GCC diagnostic pop 69 GUIVideoEncoder(
const char*
const out_file,
const int width,
const int height,
double frameDelay) {
71 AVFormatContext*
const pFormatCtx =
myFormatContext = avformat_alloc_context();
74 pFormatCtx->oformat = av_guess_format(NULL, out_file, NULL);
75 if (pFormatCtx->oformat == 0) {
76 throw std::runtime_error(
"Unknown format!");
80 if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {
81 throw std::runtime_error(
"Failed to open output file!");
86 if (frameDelay > 0.) {
87 framerate = (int)(1000. / frameDelay);
92 AVStream*
const video_st = avformat_new_stream(pFormatCtx, 0);
93 video_st->time_base.num = 1;
94 video_st->time_base.den = framerate;
97 AVCodecContext*
const pCodecCtx = video_st->codec;
99 pCodecCtx->codec_id = pFormatCtx->oformat->video_codec;
100 pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
101 pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
102 pCodecCtx->width = width;
104 pCodecCtx->height = (height / 2) * 2;
105 pCodecCtx->time_base.num = 1;
106 pCodecCtx->time_base.den = framerate;
107 pCodecCtx->bit_rate = 4000000;
108 pCodecCtx->gop_size = 250;
113 pCodecCtx->qmin = 10;
114 pCodecCtx->qmax = 51;
117 pCodecCtx->max_b_frames = 3;
120 AVDictionary* param = 0;
122 if (pCodecCtx->codec_id == AV_CODEC_ID_H264) {
123 av_dict_set(¶m,
"preset",
"slow", 0);
124 av_dict_set(¶m,
"tune",
"zerolatency", 0);
128 if (pCodecCtx->codec_id == AV_CODEC_ID_HEVC) {
129 av_dict_set(¶m,
"preset",
"ultrafast", 0);
130 av_dict_set(¶m,
"tune",
"zero-latency", 0);
136 AVCodec*
const pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
138 throw std::runtime_error(
"Can not find encoder!");
140 if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0) {
141 throw std::runtime_error(
"Failed to open encoder!");
145 myFrame->format = pCodecCtx->pix_fmt;
146 myFrame->width = pCodecCtx->width;
147 myFrame->height = pCodecCtx->height;
148 av_image_alloc(
myFrame->data,
myFrame->linesize, pCodecCtx->width, pCodecCtx->height,
149 pCodecCtx->pix_fmt, 32);
151 mySwsContext = sws_getContext(pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGBA,
152 pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,
155 avformat_write_header(pFormatCtx, NULL);
164 if (!(fmt_ctx->streams[0]->codec->codec->capabilities &
171 av_init_packet(&enc_pkt);
172 ret = avcodec_encode_video2(fmt_ctx->streams[0]->codec, &enc_pkt,
183 ret = av_write_frame(fmt_ctx, &enc_pkt);
188 av_write_trailer(fmt_ctx);
191 if (fmt_ctx->streams[0]) {
192 avcodec_close(fmt_ctx->streams[0]->codec);
196 avio_close(fmt_ctx->pb);
197 avformat_free_context(fmt_ctx);
203 AVCodecContext*
const pCodecCtx = video_st->codec;
205 uint8_t* inData[1] = { buffer };
206 int inLinesize[1] = { 4 * pCodecCtx->width };
207 sws_scale(
mySwsContext, inData, inLinesize, 0, pCodecCtx->height,
210 av_init_packet(&
myPkt);
217 int ret = avcodec_encode_video2(pCodecCtx, &
myPkt,
myFrame, &got_picture);
219 throw std::runtime_error(
"Failed to encode!");
221 if (got_picture == 1) {
222 myPkt.stream_index = video_st->index;
224 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