MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ open()

bool MayaFlux::IO::AudioEncodeContext::open ( FFmpegMuxContext mux,
uint32_t  sample_rate,
uint32_t  channels,
AVCodecID  codec_id 
)

Open the encoder and register an audio stream in the mux context.

Selects the encoder: if codec_id is AV_CODEC_ID_NONE the container's default audio codec is used (WAV → PCM_S16LE, MP4/MKV → AAC, OGG → Vorbis, FLAC → FLAC). Allocates and opens AVCodecContext, copies parameters to the new AVStream, initialises SwrContext (AV_SAMPLE_FMT_DBL → encoder native format), and allocates AVAudioFifo sized to two encoder frames.

Must be called after FFmpegMuxContext::open() and before FFmpegMuxContext::write_header().

Parameters
muxOpen mux context that will own the output stream.
sample_ratePCM sample rate in Hz.
channelsNumber of interleaved channels.
codec_idEncoder override; AV_CODEC_ID_NONE = container default.
Returns
True on success; false sets the internal error string.

Definition at line 52 of file AudioEncodeContext.cpp.

56{
57 close();
59
60 if (!mux.is_open()) {
61 m_last_error = "AudioEncodeContext::open called on unopened mux";
62 return false;
63 }
64
65 if (codec_id == AV_CODEC_ID_NONE)
66 codec_id = mux.format_context->oformat->audio_codec;
67
68 if (codec_id == AV_CODEC_ID_NONE) {
69 m_last_error = "container has no default audio codec";
70 return false;
71 }
72
73 const AVCodec* codec = avcodec_find_encoder(codec_id);
74 if (!codec) {
75 m_last_error = std::string("avcodec_find_encoder failed for codec ")
76 + avcodec_get_name(codec_id);
77 return false;
78 }
79
80 codec_context = avcodec_alloc_context3(codec);
81 if (!codec_context) {
82 m_last_error = "avcodec_alloc_context3 failed";
83 return false;
84 }
85
86 AVSampleFormat enc_fmt = AV_SAMPLE_FMT_FLTP;
87 {
88 const AVSampleFormat* fmts = nullptr;
89 int n_fmts = 0;
90 if (avcodec_get_supported_config(nullptr, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT,
91 0, reinterpret_cast<const void**>(&fmts), &n_fmts)
92 >= 0
93 && fmts && n_fmts > 0) {
94 enc_fmt = fmts[0];
95 for (int i = 0; i < n_fmts; ++i) {
96 if (fmts[i] == AV_SAMPLE_FMT_S16) {
97 enc_fmt = AV_SAMPLE_FMT_S16;
98 break;
99 }
100 if (fmts[i] == AV_SAMPLE_FMT_FLTP) {
101 enc_fmt = AV_SAMPLE_FMT_FLTP;
102 break;
103 }
104 }
105 }
106 }
107
108 uint32_t enc_rate = sample_rate;
109 {
110 const int* rates = nullptr;
111 int n_rates = 0;
112 if (avcodec_get_supported_config(nullptr, codec, AV_CODEC_CONFIG_SAMPLE_RATE,
113 0, reinterpret_cast<const void**>(&rates), &n_rates)
114 >= 0
115 && rates && n_rates > 0) {
116 bool found = false;
117 for (int i = 0; i < n_rates; ++i) {
118 if (static_cast<uint32_t>(rates[i]) == sample_rate) {
119 found = true;
120 break;
121 }
122 }
123 if (!found)
124 enc_rate = static_cast<uint32_t>(rates[0]);
125 }
126 }
127
128 av_channel_layout_default(&codec_context->ch_layout,
129 static_cast<int>(channels));
130 codec_context->sample_rate = static_cast<int>(enc_rate);
131 codec_context->sample_fmt = enc_fmt;
132 codec_context->time_base = { .num = 1, .den = static_cast<int>(enc_rate) };
133
134 if (mux.format_context->oformat->flags & AVFMT_GLOBALHEADER)
135 codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
136
137 if (avcodec_open2(codec_context, codec, nullptr) < 0) {
138 m_last_error = "avcodec_open2 failed";
139 close();
140 return false;
141 }
142
143 stream = mux.add_stream();
144 if (!stream) {
145 m_last_error = mux.last_error();
146 close();
147 return false;
148 }
149
150 if (avcodec_parameters_from_context(stream->codecpar, codec_context) < 0) {
151 m_last_error = "avcodec_parameters_from_context failed";
152 close();
153 return false;
154 }
155
156 stream->time_base = codec_context->time_base;
157 m_stream_index = stream->index;
158 m_sample_rate = enc_rate;
159 m_channels = channels;
160
161 if (!setup_resampler() || !setup_fifo()) {
162 close();
163 return false;
164 }
165
166 return true;
167}
void close()
Release all owned resources.
AVCodecContext * codec_context
Owned; freed in destructor.
AVStream * stream
Owned by mux; pointer cached here.
static void init_ffmpeg()
Initialise FFmpeg logging level once per process.

References MayaFlux::IO::FFmpegMuxContext::add_stream(), close(), codec_context, MayaFlux::IO::FFmpegMuxContext::format_context, MayaFlux::IO::FFmpegDemuxContext::init_ffmpeg(), MayaFlux::IO::FFmpegMuxContext::is_open(), MayaFlux::IO::FFmpegMuxContext::last_error(), m_channels, m_last_error, m_sample_rate, m_stream_index, setup_fifo(), setup_resampler(), and stream.

Referenced by MayaFlux::IO::SoundFileWriter::worker_loop().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: