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

◆ send_fifo_frame()

bool MayaFlux::IO::AudioEncodeContext::send_fifo_frame ( FFmpegMuxContext mux,
bool  pad_to_frame_size 
)
private

Pull one frame from the FIFO and send it to the encoder.

If the FIFO has fewer samples than frame_size, pads with silence. Drains all output packets into the mux after sending.

Definition at line 310 of file AudioEncodeContext.cpp.

311{
312 int frame_size = codec_context->frame_size > 0
313 ? codec_context->frame_size
314 : av_audio_fifo_size(fifo);
315
316 AVFrame* frame = av_frame_alloc();
317 if (!frame) {
318 m_last_error = "av_frame_alloc failed";
319 return false;
320 }
321
322 frame->nb_samples = frame_size;
323 frame->format = codec_context->sample_fmt;
324 frame->sample_rate = codec_context->sample_rate;
325 av_channel_layout_copy(&frame->ch_layout, &codec_context->ch_layout);
326
327 if (av_frame_get_buffer(frame, 0) < 0) {
328 m_last_error = "av_frame_get_buffer failed";
329 av_frame_free(&frame);
330 return false;
331 }
332
333 if (av_frame_make_writable(frame) < 0) {
334 m_last_error = "av_frame_make_writable failed";
335 av_frame_free(&frame);
336 return false;
337 }
338
339 int available = av_audio_fifo_size(fifo);
340 int to_read = std::min(available, frame_size);
341
342 int read = av_audio_fifo_read(fifo,
343 reinterpret_cast<void**>(frame->data), to_read);
344
345 if (read < to_read) {
346 m_last_error = "av_audio_fifo_read returned fewer samples than expected";
347 av_frame_free(&frame);
348 return false;
349 }
350
351 if (pad_to_frame_size && read < frame_size) {
352 int pad_samples = frame_size - read;
353 int bytes_per_sample = av_get_bytes_per_sample(codec_context->sample_fmt);
354 bool is_planar = av_sample_fmt_is_planar(codec_context->sample_fmt);
355 int planes = is_planar ? static_cast<int>(m_channels) : 1;
356 int samples_per_plane = is_planar ? pad_samples : pad_samples * static_cast<int>(m_channels);
357
358 for (int p = 0; p < planes; ++p) {
359 std::memset(
360 frame->data[p] + static_cast<ptrdiff_t>(read) * bytes_per_sample * (is_planar ? 1 : static_cast<int>(m_channels)),
361 0,
362 static_cast<size_t>(samples_per_plane) * static_cast<size_t>(bytes_per_sample));
363 }
364 frame->nb_samples = frame_size;
365 } else {
366 frame->nb_samples = read;
367 }
368
369 frame->pts = m_pts;
370 m_pts += frame->nb_samples;
371
372 int ret = avcodec_send_frame(codec_context, frame);
373 av_frame_free(&frame);
374
375 if (ret < 0) {
376 char errbuf[AV_ERROR_MAX_STRING_SIZE];
377 av_strerror(ret, errbuf, sizeof(errbuf));
378 m_last_error = std::string("avcodec_send_frame failed: ") + errbuf;
379 return false;
380 }
381
382 return drain_packets(mux);
383}
bool drain_packets(FFmpegMuxContext &mux)
Drain all packets currently available from the encoder into mux.
AVCodecContext * codec_context
Owned; freed in destructor.
AVAudioFifo * fifo
Owned; freed in destructor.

References codec_context, drain_packets(), fifo, m_channels, m_last_error, and m_pts.

Referenced by drain(), and encode_frames().

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