24 #ifndef GUIVideoEncoder_h 25 #define GUIVideoEncoder_h 41 #define __STDC_CONSTANT_MACROS 45 #include <libavutil/opt.h> 46 #include <libavutil/imgutils.h> 47 #include <libavcodec/avcodec.h> 48 #include <libavformat/avformat.h> 49 #include <libswscale/swscale.h> 55 GUIVideoEncoder(
const char*
const out_file,
const int width,
const int height,
double frameDelay) {
57 AVFormatContext*
const pFormatCtx =
myFormatContext = avformat_alloc_context();
60 pFormatCtx->oformat = av_guess_format(NULL, out_file, NULL);
61 if (pFormatCtx->oformat == 0) {
62 throw std::runtime_error(
"Unknown format!");
66 if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {
67 throw std::runtime_error(
"Failed to open output file!");
72 if (frameDelay > 0.) {
73 framerate = (int)(1000. / frameDelay);
78 AVStream*
const video_st = avformat_new_stream(pFormatCtx, 0);
79 video_st->time_base.num = 1;
80 video_st->time_base.den = framerate;
83 AVCodecContext*
const pCodecCtx = video_st->codec;
85 pCodecCtx->codec_id = pFormatCtx->oformat->video_codec;
86 pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
87 pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
88 pCodecCtx->width = width;
90 pCodecCtx->height = (height / 2) * 2;
91 pCodecCtx->time_base.num = 1;
92 pCodecCtx->time_base.den = framerate;
93 pCodecCtx->bit_rate = 4000000;
94 pCodecCtx->gop_size = 250;
100 pCodecCtx->qmax = 51;
103 pCodecCtx->max_b_frames = 3;
106 AVDictionary* param = 0;
108 if (pCodecCtx->codec_id == AV_CODEC_ID_H264) {
109 av_dict_set(¶m,
"preset",
"slow", 0);
110 av_dict_set(¶m,
"tune",
"zerolatency", 0);
114 if (pCodecCtx->codec_id == AV_CODEC_ID_H265) {
115 av_dict_set(¶m,
"preset",
"ultrafast", 0);
116 av_dict_set(¶m,
"tune",
"zero-latency", 0);
122 AVCodec*
const pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
124 throw std::runtime_error(
"Can not find encoder!");
126 if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0) {
127 throw std::runtime_error(
"Failed to open encoder!");
131 myFrame->format = pCodecCtx->pix_fmt;
132 myFrame->width = pCodecCtx->width;
133 myFrame->height = pCodecCtx->height;
134 av_image_alloc(
myFrame->data,
myFrame->linesize, pCodecCtx->width, pCodecCtx->height,
135 pCodecCtx->pix_fmt, 32);
137 mySwsContext = sws_getContext(pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGBA,
138 pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,
141 avformat_write_header(pFormatCtx, NULL);
150 if (!(fmt_ctx->streams[0]->codec->codec->capabilities &
157 av_init_packet(&enc_pkt);
158 ret = avcodec_encode_video2(fmt_ctx->streams[0]->codec, &enc_pkt,
169 ret = av_write_frame(fmt_ctx, &enc_pkt);
174 av_write_trailer(fmt_ctx);
177 if (fmt_ctx->streams[0]) {
178 avcodec_close(fmt_ctx->streams[0]->codec);
182 avio_close(fmt_ctx->pb);
183 avformat_free_context(fmt_ctx);
189 AVCodecContext*
const pCodecCtx = video_st->codec;
191 uint8_t* inData[1] = { buffer };
192 int inLinesize[1] = { 4 * pCodecCtx->width };
193 sws_scale(
mySwsContext, inData, inLinesize, 0, pCodecCtx->height,
196 av_init_packet(&
myPkt);
203 int ret = avcodec_encode_video2(pCodecCtx, &
myPkt,
myFrame, &got_picture);
205 throw std::runtime_error(
"Failed to encode!");
207 if (got_picture == 1) {
208 myPkt.stream_index = video_st->index;
210 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