12# define _USE_MATH_DEFINES
25# include <AUD_Device.h>
26# include <AUD_Special.h>
42static bool request_float_audio_buffer(
int codec_id)
44 return ELEM(codec_id, AV_CODEC_ID_AAC, AV_CODEC_ID_AC3, AV_CODEC_ID_VORBIS);
49static int write_audio_frame(MovieWriter *context)
51 AVFrame *frame =
nullptr;
52 AVCodecContext *c =
context->audio_codec;
57 frame = av_frame_alloc();
58 frame->pts =
context->audio_time / av_q2d(c->time_base);
59 frame->nb_samples =
context->audio_input_samples;
60 frame->format = c->sample_fmt;
61# ifdef FFMPEG_USE_OLD_CHANNEL_VARS
62 frame->channels = c->channels;
63 frame->channel_layout = c->channel_layout;
64 const int num_channels = c->channels;
66 av_channel_layout_copy(&frame->ch_layout, &c->ch_layout);
67 const int num_channels = c->ch_layout.nb_channels;
70 if (
context->audio_deinterleave) {
74 for (channel = 0; channel < num_channels; channel++) {
75 for (
i = 0;
i < frame->nb_samples;
i++) {
76 memcpy(
context->audio_deinterleave_buffer +
77 (
i + channel * frame->nb_samples) *
context->audio_sample_size,
79 (num_channels *
i + channel) *
context->audio_sample_size,
84 temp =
context->audio_deinterleave_buffer;
86 context->audio_input_buffer = temp;
89 avcodec_fill_audio_frame(frame,
93 context->audio_input_samples * num_channels *
99 char error_str[AV_ERROR_MAX_STRING_SIZE];
100 int ret = avcodec_send_frame(c, frame);
103 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
108 AVPacket *pkt = av_packet_alloc();
112 ret = avcodec_receive_packet(c, pkt);
113 if (
ret == AVERROR(EAGAIN) ||
ret == AVERROR_EOF) {
117 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
118 CLOG_ERROR(&
LOG,
"Error encoding audio frame: %s", error_str);
122 pkt->stream_index =
context->audio_stream->index;
123 av_packet_rescale_ts(pkt, c->time_base,
context->audio_stream->time_base);
124# ifdef FFMPEG_USE_DURATION_WORKAROUND
128 pkt->flags |= AV_PKT_FLAG_KEY;
130 int write_ret = av_interleaved_write_frame(
context->outfile, pkt);
131 if (write_ret != 0) {
132 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
133 CLOG_ERROR(&
LOG,
"Error writing audio packet: %s", error_str);
139 av_packet_free(&pkt);
140 av_frame_free(&frame);
146bool movie_audio_open(MovieWriter *context,
154# ifdef WITH_AUDASPACE
156 AVCodecContext *c =
context->audio_codec;
158 AUD_DeviceSpecs specs;
159# ifdef FFMPEG_USE_OLD_CHANNEL_VARS
160 specs.channels = AUD_Channels(c->channels);
162 specs.channels = AUD_Channels(c->ch_layout.nb_channels);
165 switch (av_get_packed_sample_fmt(c->sample_fmt)) {
166 case AV_SAMPLE_FMT_U8:
167 specs.format = AUD_FORMAT_U8;
169 case AV_SAMPLE_FMT_S16:
170 specs.format = AUD_FORMAT_S16;
172 case AV_SAMPLE_FMT_S32:
173 specs.format = AUD_FORMAT_S32;
175 case AV_SAMPLE_FMT_FLT:
176 specs.format = AUD_FORMAT_FLOAT32;
178 case AV_SAMPLE_FMT_DBL:
179 specs.format = AUD_FORMAT_FLOAT64;
187 specs.rate = mixrate;
189 context->audio_mixdown_device = BKE_sound_mixdown(scene, specs, start_frame, volume);
193 UNUSED_VARS(context, scene, start_frame, mixrate, volume, reports);
198void movie_audio_close(MovieWriter *context,
bool is_autosplit)
200# ifdef WITH_AUDASPACE
202 if (
context->audio_mixdown_device) {
203 AUD_Device_free(
context->audio_mixdown_device);
204 context->audio_mixdown_device =
nullptr;
212AVStream *alloc_audio_stream(MovieWriter *context,
221 const AVCodec *codec;
225 st = avformat_new_stream(of,
nullptr);
231 codec = avcodec_find_encoder(codec_id);
234 context->audio_codec =
nullptr;
238 context->audio_codec = avcodec_alloc_context3(codec);
239 AVCodecContext *c =
context->audio_codec;
240 c->thread_count = MOV_thread_count();
241 c->thread_type = FF_THREAD_SLICE;
243 c->sample_rate = audio_mixrate;
244 c->bit_rate =
context->ffmpeg_audio_bitrate * 1000;
245 c->sample_fmt = AV_SAMPLE_FMT_S16;
247 int channel_layout_mask = 0;
248 switch (audio_channels) {
250 channel_layout_mask = AV_CH_LAYOUT_MONO;
253 channel_layout_mask = AV_CH_LAYOUT_STEREO;
256 channel_layout_mask = AV_CH_LAYOUT_QUAD;
259 channel_layout_mask = AV_CH_LAYOUT_5POINT1_BACK;
262 channel_layout_mask = AV_CH_LAYOUT_7POINT1;
267# ifdef FFMPEG_USE_OLD_CHANNEL_VARS
268 c->channels = audio_channels;
269 c->channel_layout = channel_layout_mask;
271 av_channel_layout_from_mask(&c->ch_layout, channel_layout_mask);
274 if (request_float_audio_buffer(codec_id)) {
276 c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
277 c->sample_fmt = AV_SAMPLE_FMT_FLT;
287 const enum AVSampleFormat *p = sample_fmts;
288 for (; *p != -1; p++) {
289 if (*p == c->sample_fmt) {
295 c->sample_fmt = sample_fmts[0];
300 if (supported_samplerates) {
301 const int *p = supported_samplerates;
303 int best_dist = INT_MAX;
305 int dist =
abs(c->sample_rate - *p);
306 if (dist < best_dist) {
312 c->sample_rate = best;
315 if (of->oformat->flags & AVFMT_GLOBALHEADER) {
316 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
319 int ret = avcodec_open2(c, codec,
nullptr);
322 char error_str[AV_ERROR_MAX_STRING_SIZE];
323 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
324 CLOG_ERROR(&
LOG,
"Couldn't initialize audio codec: %s", error_str);
326 avcodec_free_context(&c);
327 context->audio_codec =
nullptr;
333 c->time_base.num = 1;
334 c->time_base.den = c->sample_rate;
336 if (c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) {
341 context->audio_input_samples = 1024;
344 context->audio_input_samples = c->frame_size;
347 context->audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
349 context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
352 audio_channels *
context->audio_sample_size);
353 if (
context->audio_deinterleave) {
355 context->audio_input_samples * audio_channels *
context->audio_sample_size);
360 avcodec_parameters_from_context(st->codecpar, c);
365void write_audio_frames(MovieWriter *context,
double to_pts)
367# ifdef WITH_AUDASPACE
368 AVCodecContext *c =
context->audio_codec;
370 while (
context->audio_stream) {
371 if ((
context->audio_time_total >= to_pts) || !write_audio_frame(context)) {
374 context->audio_time_total += double(
context->audio_input_samples) / double(c->sample_rate);
375 context->audio_time += double(
context->audio_input_samples) / double(c->sample_rate);
void BKE_report(ReportList *reports, eReportType type, const char *message)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define CLOG_ERROR(clg_ref,...)
@ FFM_CHANNELS_SURROUND51
@ FFM_CHANNELS_SURROUND71
FFMPEG_INLINE enum AVSampleFormat * ffmpeg_get_sample_fmts(struct AVCodecContext *context, const AVCodec *codec)
FFMPEG_INLINE const int * ffmpeg_get_sample_rates(struct AVCodecContext *context, const AVCodec *codec)
FFMPEG_INLINE void my_guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt)
static void error(const char *str)
int context(const bContext *C, const char *member, bContextDataResult *result)