40 const AVCodec* codec{};
42 AVCodecContext* enc{};
48 AVFrame* cache_input_frame{};
53 struct SwsContext* sws_ctx{};
54 std::vector<std::unique_ptr<r8b::CDSPResampler>> resamplers;
56 std::unique_ptr<AudioFrameEncoder> encoder;
59 std::vector<std::vector<double>> resample_in_buf;
60 std::vector<ossia::float_vector> resample_out_buf;
67 codec = avcodec_find_encoder_by_name(opts.codec.c_str());
70 qDebug() <<
"Could not find encoder for " << opts.codec.c_str();
74 this->tmp_pkt = av_packet_alloc();
77 qDebug() <<
"Could not allocate AVPacket";
81 this->st = avformat_new_stream(oc,
nullptr);
84 qDebug() <<
"Could not allocate stream";
87 this->st->id = oc->nb_streams - 1;
89 this->enc = avcodec_alloc_context3(codec);
92 qDebug() <<
"Could not alloc an encoding context";
98 case AVMEDIA_TYPE_AUDIO:
99 init_audio(set, this->enc);
101 case AVMEDIA_TYPE_VIDEO:
102 init_video(set, this->enc);
110 if(oc->oformat->flags & AVFMT_GLOBALHEADER)
112 this->enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
118#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 24, 100)
119 c->sample_fmt = av_get_sample_fmt(set.audio_converted_smpfmt.toStdString().c_str());
122 const int* supported_samplerates{};
123#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 19, 100)
124 avcodec_get_supported_config(
125 c, codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0, (
const void**)&supported_samplerates,
128 supported_samplerates = codec->supported_samplerates;
130 if(supported_samplerates)
132 c->sample_rate = supported_samplerates[0];
133 for(
int i = 0; supported_samplerates[i]; i++)
135 if(supported_samplerates[i] == set.audio_sample_rate)
137 c->sample_rate = set.audio_sample_rate;
144 c->sample_rate = set.audio_sample_rate;
152 av_channel_layout_default(&c->ch_layout, set.audio_channels);
153 c->thread_count = set.threads > 0 ? set.threads : 0;
154 if(set.audio_encoder_short ==
"pcm_s24le" || set.audio_encoder_short ==
"pcm_s24be")
155 c->bits_per_raw_sample = 24;
157 this->st->time_base = AVRational{1, c->sample_rate};
158 c->time_base = AVRational{1, c->sample_rate};
159 c->framerate = AVRational{c->sample_rate, 1};
160 qDebug() <<
"Opening audio encoder with: rate: " << c->sample_rate;
166 c->codec_id = codec->id;
167 c->width = set.width;
168 c->height = set.height;
171 c->thread_count = set.threads > 0 ? set.threads : 0;
172 c->thread_type = FF_THREAD_FRAME | FF_THREAD_SLICE;
177 this->st->time_base = AVRational{100000, int(100000 * set.rate)};
178 c->time_base = this->st->time_base;
179 c->framerate = AVRational{this->st->time_base.den, this->st->time_base.num};
185 c->pix_fmt = av_get_pix_fmt(set.video_converted_pixfmt.toStdString().c_str());
186 if(c->pix_fmt == AV_PIX_FMT_NONE)
189 const AVPixelFormat* fmts =
nullptr;
190#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 19, 100)
191 avcodec_get_supported_config(
192 c, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0,
193 (
const void**)&fmts,
nullptr);
195 fmts = codec->pix_fmts;
197 if(fmts && fmts[0] != AV_PIX_FMT_NONE)
198 c->pix_fmt = fmts[0];
200 c->pix_fmt = AV_PIX_FMT_YUV420P;
202 c->strict_std_compliance = FF_COMPLIANCE_NORMAL;
207 AVDictionary* opt_arg)
209#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 24, 100)
210 AVDictionary* opt =
nullptr;
212 av_dict_copy(&opt, opt_arg, 0);
213 int ret = avcodec_open2(enc, codec, &opt);
217 qDebug() <<
"Could not open audio codec: " << av_to_string(ret);
222 if(enc->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
225 nb_samples = audio_stgs.getBufferSize();
226 enc->frame_size = nb_samples;
227 qDebug() <<
"Setting frame_size: " << nb_samples;
231 nb_samples = enc->frame_size;
232 qDebug() <<
"Forcing frame_size: " << nb_samples;
235 cache_input_frame = alloc_audio_frame(
236 enc->sample_fmt, &enc->ch_layout, enc->sample_rate, nb_samples);
239 ret = avcodec_parameters_from_context(this->st->codecpar, enc);
242 qDebug() <<
"Could not copy the stream parameters";
248 = av_get_sample_fmt(set.audio_converted_smpfmt.toStdString().c_str());
249 if(conv_fmt == AV_SAMPLE_FMT_NONE)
251 qDebug() <<
"Invalid audio sample format:" << set.audio_converted_smpfmt;
257 const int input_sample_rate = ctx.getRate();
258 if(enc->sample_rate != input_sample_rate)
260 for(
int i = 0; i < set.audio_channels; i++)
261 this->resamplers.push_back(std::make_unique<r8b::CDSPResampler>(
262 input_sample_rate, enc->sample_rate, nb_samples * 2, 3.0, 206.91,
268 case AV_SAMPLE_FMT_NONE:
269 case AV_SAMPLE_FMT_U8:
270 case AV_SAMPLE_FMT_S16:
271 encoder = std::make_unique<S16IAudioFrameEncoder>(nb_samples);
273 case AV_SAMPLE_FMT_S32:
278 encoder = std::make_unique<S32IAudioFrameEncoder>(nb_samples);
280 case AV_SAMPLE_FMT_FLT:
281 encoder = std::make_unique<FltIAudioFrameEncoder>(nb_samples);
283 case AV_SAMPLE_FMT_DBL:
284 encoder = std::make_unique<DblIAudioFrameEncoder>(nb_samples);
287 case AV_SAMPLE_FMT_U8P:
288 case AV_SAMPLE_FMT_S16P:
289 encoder = std::make_unique<S16PAudioFrameEncoder>(nb_samples);
291 case AV_SAMPLE_FMT_S32P:
292 encoder = std::make_unique<S32PAudioFrameEncoder>(nb_samples);
294 case AV_SAMPLE_FMT_FLTP:
295 encoder = std::make_unique<FltPAudioFrameEncoder>(nb_samples);
297 case AV_SAMPLE_FMT_DBLP:
298 encoder = std::make_unique<DblPAudioFrameEncoder>(nb_samples);
300 case AV_SAMPLE_FMT_S64:
301 case AV_SAMPLE_FMT_S64P:
302 qDebug() <<
"64-bit integer audio sample format not supported for encoding";
313#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 24, 100)
314 static AVFrame* alloc_audio_frame(
315 enum AVSampleFormat sample_fmt,
const AVChannelLayout* channel_layout,
316 int sample_rate,
int nb_samples)
318 AVFrame* frame = av_frame_alloc();
321 qDebug() <<
"Error allocating an audio frame";
325 frame->format = sample_fmt;
326 av_channel_layout_copy(&frame->ch_layout, channel_layout);
327 frame->sample_rate = sample_rate;
328 frame->nb_samples = nb_samples;
332 if(av_frame_get_buffer(frame, 0) < 0)
334 qDebug() <<
"Error allocating an audio buffer";
335 av_frame_free(&frame);
344 static AVFrame* alloc_video_frame(
enum AVPixelFormat pix_fmt,
int width,
int height)
346 auto frame = av_frame_alloc();
350 frame->format = pix_fmt;
351 frame->width = width;
352 frame->height = height;
355 const int ret = av_frame_get_buffer(frame, 0);
358 qDebug() <<
"Could not allocate frame data.";
359 av_frame_free(&frame);
368 AVDictionary* opt_arg)
370 AVCodecContext* c = this->enc;
371 AVDictionary* opt =
nullptr;
373 av_dict_copy(&opt, opt_arg, 0);
376 int ret = avcodec_open2(this->enc, codec, &opt);
380 qDebug() <<
"Could not open video codec: " << av_to_string(ret);
385 this->cache_input_frame = alloc_video_frame(AV_PIX_FMT_RGBA, c->width, c->height);
386 if(!this->cache_input_frame)
388 qDebug() <<
"Could not allocate video frame";
392 this->tmp_frame =
nullptr;
394 auto input_fmt = av_get_pix_fmt(set.video_render_pixfmt.toStdString().c_str());
395 auto conv_fmt = av_get_pix_fmt(set.video_converted_pixfmt.toStdString().c_str());
396 if(input_fmt == AV_PIX_FMT_NONE || conv_fmt == AV_PIX_FMT_NONE)
398 qDebug() <<
"Invalid pixel format:" << set.video_render_pixfmt
399 <<
"->" << set.video_converted_pixfmt;
402 sws_ctx = sws_getContext(
403 set.width, set.height, input_fmt, set.width, set.height, conv_fmt,
404 SWS_FAST_BILINEAR,
nullptr,
nullptr,
nullptr);
407 qDebug() <<
"Could not create swscale context";
410 this->tmp_frame = alloc_video_frame(conv_fmt, c->width, c->height);
413 qDebug() <<
"Could not allocate temporary video frame";
419 ret = avcodec_parameters_from_context(this->st->codecpar, c);
422 qDebug() <<
"Could not copy the stream parameters";
431 AVDictionary* opt_arg)
435 if(codec->type == AVMEDIA_TYPE_AUDIO)
437 open_audio(set, oc, codec, opt_arg);
439 else if(codec->type == AVMEDIA_TYPE_VIDEO)
441 open_video(set, oc, codec, opt_arg);
445 void close(AVFormatContext* oc)
447 avcodec_free_context(&enc);
448 av_frame_free(&cache_input_frame);
449 av_frame_free(&tmp_frame);
450 av_packet_free(&tmp_pkt);
451 sws_freeContext(sws_ctx);
455 AVFrame* get_video_frame()
457 if(!m_valid || !this->cache_input_frame)
459 if(av_frame_make_writable(this->cache_input_frame) < 0)
462 this->cache_input_frame->pts = this->next_pts++;
463 return this->cache_input_frame;
466 AVFrame* get_audio_frame()
468 if(!m_valid || !this->cache_input_frame)
470 if(av_frame_make_writable(this->cache_input_frame) < 0)
473 this->cache_input_frame->pts = this->next_pts;
474 this->next_pts += this->enc->frame_size;
475 return this->cache_input_frame;
478 int write_video_frame(AVFormatContext* fmt_ctx, AVFrame* input_frame)
482#if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(7, 5, 100)
484 av_frame_unref(tmp_frame);
485 tmp_frame->format = enc->pix_fmt;
486 tmp_frame->width = enc->width;
487 tmp_frame->height = enc->height;
490 int ret = sws_scale_frame(sws_ctx, tmp_frame, input_frame);
493 qDebug() <<
"Error during sws_scale_frame: " << av_to_string(ret);
497 tmp_frame->pts = input_frame->pts;
500 ret = avcodec_send_frame(enc, tmp_frame);
503 qDebug() <<
"Error sending a frame to the encoder: " << av_to_string(ret);
509 ret = avcodec_receive_packet(enc, tmp_pkt);
510 if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
514 qDebug() <<
"Error encoding a frame: " << av_to_string(ret);
519 av_packet_rescale_ts(tmp_pkt, enc->time_base, st->time_base);
520 tmp_pkt->stream_index = st->index;
522 ret = av_interleaved_write_frame(fmt_ctx, tmp_pkt);
525 qDebug() <<
"Error while writing output packet: " << av_to_string(ret);
530 return ret == AVERROR_EOF ? 1 : 0;
537 int write_video_frame_direct(AVFormatContext* fmt_ctx, AVFrame* frame)
542 int ret = avcodec_send_frame(enc, frame);
545 qDebug() <<
"Error sending a frame to the encoder: " << av_to_string(ret);
551 ret = avcodec_receive_packet(enc, tmp_pkt);
552 if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
556 qDebug() <<
"Error encoding a frame: " << av_to_string(ret);
560 av_packet_rescale_ts(tmp_pkt, enc->time_base, st->time_base);
561 tmp_pkt->stream_index = st->index;
563 ret = av_interleaved_write_frame(fmt_ctx, tmp_pkt);
566 qDebug() <<
"Error while writing output packet: " << av_to_string(ret);
571 return ret == AVERROR_EOF ? 1 : 0;
574 int write_audio_frame(AVFormatContext* fmt_ctx, AVFrame* input_frame)
579 int ret = avcodec_send_frame(enc, input_frame);
582 qDebug() <<
"Error sending a frame to the encoder: " << av_to_string(ret);
588 ret = avcodec_receive_packet(enc, tmp_pkt);
589 if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
593 qDebug() <<
"Error encoding a frame: " << av_to_string(ret);
598 av_packet_rescale_ts(tmp_pkt, enc->time_base, st->time_base);
599 tmp_pkt->stream_index = st->index;
601 ret = av_interleaved_write_frame(fmt_ctx, tmp_pkt);
604 qDebug() <<
"Error while writing output packet: " << av_to_string(ret);
609 return ret == AVERROR_EOF ? 1 : 0;