当前位置:网站首页>Ffmpeg audio coding
Ffmpeg audio coding
2022-07-23 11:56:00 【Mr.codeee】
1. brief introduction
Encode audio data , hold pcm The original data is encoded as MP3 perhaps AAC.
2. technological process

2.1 In the use of FFmpeg API Before , Need to register first API, And then you can use it API. Of course , The new version of the library does not need to call the following methods .
av_register_all()2.2 Find the encoder , This example demonstrates coding MP3
// Find the encoder
codec = avcodec_find_encoder(AV_CODEC_ID_MP3);
if (!codec)
{
fprintf(stderr, "Codec not found\n");
exit(1);
}2.3 apply AVCodecContext
// apply AVCodecContext
AVCodecContext* codec_ctx = nullptr;
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx)
{
fprintf(stderr, "Could not allocate audio codec context\n");
exit(1);
}2.4 Set audio parameters
You need to specify some parameters for configuring the encoder . Like audio , For example, its sampling rate , Track number , Coding format, etc . You also need to configure the parameters of the encoded output data , as follows , The parameter setting here is input PCM yes 48000,FLT, Bit rate 25600, The output parameters follow codec_ctx The parameters are basically similar
// Set parameters
codec_ctx->bit_rate = 256000;
codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
// Check that this format is not supported
if (!check_sample_fmt(codec, codec_ctx->sample_fmt))
{
fprintf(stderr, "Encoder does not support sample format %s",av_get_sample_fmt_name(codec_ctx->sample_fmt));
exit(1);
}
codec_ctx->sample_rate = 48000;
codec_ctx->channel_layout = select_channel_layout(codec);
codec_ctx->channels = av_get_channel_layout_nb_channels(codec_ctx->channel_layout);
frame->nb_samples = codec_ctx->frame_size;
frame->format = codec_ctx->sample_fmt;
frame->channel_layout = codec_ctx->channel_layout;
frame->channels = codec_ctx->channels;
2.5 Turn on the encoder
// Turn on the encoder
if (avcodec_open2(codec_ctx, codec, NULL) < 0)
{
fprintf(stderr, "Could not open codec\n");
exit(1);
}2.6 Allocate frame space
/* allocate the data buffers */
int ret = av_frame_get_buffer(frame, 0);
if (ret < 0)
{
fprintf(stderr, "Could not allocate audio data buffers\n");
exit(1);
}2.7 Calculate the size of audio frame data
After setting the parameters of the encoder and the parameters related to the data frame to be encoded , Audio sampling can be calculated according to several parameters buffer Size .
// Calculate audio frame information
int buffer_size = av_samples_get_buffer_size(NULL, codec_ctx->channels, codec_ctx->frame_size, codec_ctx->sample_fmt, 0);
if (buffer_size < 0)
{
exit(1);
}2.8 Read pcm file , Start coding , Write to local MP3 file .
When ready , We can start coding . The new interface of audio coding is also sent to the encoder , Then encode by receiving . The core code of the code is as follows , The encoded data is stored in AVPacket in , take pkt Write the data in to the local file .
while (!feof(fp))
{
// Read data from file
int count = fread(pcmBuffer, sizeof(char), buffer_size, fp);
// Read locally packed Data to planar
f32le_convert_to_fltp((float*)pcmBuffer, (float*)pcmBuffer2, frame->nb_samples);
ret = av_samples_fill_arrays(frame->data, frame->linesize,
(const uint8_t*)pcmBuffer2, frame->channels,
frame->nb_samples, AV_SAMPLE_FMT_FLTP, 0);
// Start coding
ret = avcodec_send_frame(codec_ctx, frame);
while (ret >= 0)
{
ret = avcodec_receive_packet(codec_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
break;
}
else if (ret < 0)
{
break;
}
// The encoded data is written to the local file
fwrite(pkt->data, 1, pkt->size, f);
av_packet_unref(pkt);
}
}3. Source code
This example demonstrates reading from local pcm file , After encoding, write to MP3 In file .
#include "pch.h"
#include <iostream>
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "libavutil/timestamp.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/imgutils.h"
};
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec* codec, enum AVSampleFormat sample_fmt)
{
const enum AVSampleFormat* p = codec->sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE)
{
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
/* just pick the highest supported samplerate */
static int select_sample_rate(const AVCodec* codec)
{
const int* p;
int best_samplerate = 0;
if (!codec->supported_samplerates)
return 44100;
p = codec->supported_samplerates;
while (*p)
{
if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
best_samplerate = *p;
p++;
}
return best_samplerate;
}
/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec* codec)
{
const uint64_t* p;
uint64_t best_ch_layout = 0;
int best_nb_channels = 0;
if (!codec->channel_layouts)
return AV_CH_LAYOUT_STEREO;
p = codec->channel_layouts;
while (*p) {
int nb_channels = av_get_channel_layout_nb_channels(*p);
if (nb_channels > best_nb_channels) {
best_ch_layout = *p;
best_nb_channels = nb_channels;
}
p++;
}
return best_ch_layout;
}
void f32le_convert_to_fltp(float* f32le, float* fltp, int nb_samples)
{
float* fltp_l = fltp; // Left channel
float* fltp_r = fltp + nb_samples; // Right channel
for (int i = 0; i < nb_samples; i++)
{
fltp_l[i] = f32le[i * 2]; // 0 1 - 2 3
fltp_r[i] = f32le[i * 2 + 1]; // You can try to annotate the left channel or the right channel to listen to the sound
}
}
int main()
{
//av_register_all();
avformat_network_init();
AVCodec* codec = nullptr;
// Find the encoder
codec = avcodec_find_encoder(AV_CODEC_ID_MP3);
if (!codec)
{
fprintf(stderr, "Codec not found\n");
exit(1);
}
// apply AVCodecContext
AVCodecContext* codec_ctx = nullptr;
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx)
{
fprintf(stderr, "Could not allocate audio codec context\n");
exit(1);
}
// Set parameters
codec_ctx->bit_rate = 256000;
codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
// Check that this format is not supported
if (!check_sample_fmt(codec, codec_ctx->sample_fmt))
{
fprintf(stderr, "Encoder does not support sample format %s",av_get_sample_fmt_name(codec_ctx->sample_fmt));
exit(1);
}
codec_ctx->sample_rate = 48000;
codec_ctx->channel_layout = select_channel_layout(codec);
codec_ctx->channels = av_get_channel_layout_nb_channels(codec_ctx->channel_layout);
// Turn on the encoder
if (avcodec_open2(codec_ctx, codec, NULL) < 0)
{
fprintf(stderr, "Could not open codec\n");
exit(1);
}
AVPacket *pkt = av_packet_alloc();
if (!pkt)
{
fprintf(stderr, "could not allocate the packet\n");
exit(1);
}
AVFrame *frame = av_frame_alloc();
if (!frame)
{
fprintf(stderr, "Could not allocate audio frame\n");
exit(1);
}
frame->nb_samples = codec_ctx->frame_size;
frame->format = codec_ctx->sample_fmt;
frame->channel_layout = codec_ctx->channel_layout;
frame->channels = codec_ctx->channels;
/* allocate the data buffers */
int ret = av_frame_get_buffer(frame, 0);
if (ret < 0)
{
fprintf(stderr, "Could not allocate audio data buffers\n");
exit(1);
}
// Calculate audio frame information
int buffer_size = av_samples_get_buffer_size(NULL, codec_ctx->channels, codec_ctx->frame_size, codec_ctx->sample_fmt, 0);
if (buffer_size < 0)
{
exit(1);
}
uint8_t* pcmBuffer = (uint8_t*)av_malloc(buffer_size);
if (!pcmBuffer)
{
exit(1);
}
uint8_t* pcmBuffer2 = (uint8_t*)av_malloc(buffer_size);
if (!pcmBuffer2)
{
exit(1);
}
// Open the output file
char fileName[20] = "output.mp3";
FILE* f = fopen(fileName, "wb");
if (!f)
{
fprintf(stderr, "Could not open %s\n", fileName);
exit(1);
}
// Open the input file
const char* inputUrl = "test.pcm";
FILE* fp = fopen(inputUrl, "rb");
if (!fp)
{
fprintf(stderr, "Could not open %s\n", inputUrl);
exit(1);
}
while (!feof(fp))
{
// Read data from file
int count = fread(pcmBuffer, sizeof(char), buffer_size, fp);
// Read locally packed Data to planar
f32le_convert_to_fltp((float*)pcmBuffer, (float*)pcmBuffer2, frame->nb_samples);
ret = av_samples_fill_arrays(frame->data, frame->linesize,
(const uint8_t*)pcmBuffer2, frame->channels,
frame->nb_samples, AV_SAMPLE_FMT_FLTP, 0);
// Start coding
ret = avcodec_send_frame(codec_ctx, frame);
while (ret >= 0)
{
ret = avcodec_receive_packet(codec_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
break;
}
else if (ret < 0)
{
break;
}
// The encoded data is written to the local file
fwrite(pkt->data, 1, pkt->size, f);
av_packet_unref(pkt);
}
}
fclose(fp);
fclose(f);
avcodec_close(codec_ctx);
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
av_packet_free(&pkt);
return 0;
}
边栏推荐
猜你喜欢

VMware uses wireless network card NAT to access the Internet under Windows

NFT digital collection platform development and construction, source code development digital collection

UE4解决WebBrowser无法播放H.264的问题

1、MySQL初体验

8、 Collection framework and generics
![[doris] configure and basically use the contents system (continue to add content when you have time)](/img/74/21c5c0866ed6b1bb6f9a1e3755b61e.png)
[doris] configure and basically use the contents system (continue to add content when you have time)

Mosaic the face part of the picture

Data warehouse 4.0 notes - user behavior data collection III
![[hudi]hudi compilation and simple use of Hudi & spark and Hudi & Flink](/img/6f/e6f5ef79c232d9b27a8334cd8ddaa5.png)
[hudi]hudi compilation and simple use of Hudi & spark and Hudi & Flink

Gerrit operation manual
随机推荐
方法的定义应用
UE4.24版本VR项目打包后,未出现手柄控制器
1. Initial experience of MySQL
Ten year structure five year life-01 at the beginning of graduation
[doris] configure and basically use the contents system (continue to add content when you have time)
[system problems] Net Framework 3.5 installation error
Cuda10.0 configuration pytorch1.7.0+monai0.9.0
NFT digital collection platform development and construction, source code development digital collection
查看真机APP里面沙盒文件
IP地址是什么
[untitled]
Data warehouse 4.0 notes - business data collection
Stage 1 Review
数仓4.0笔记——用户行为数据采集一
抽象类和接口有什么区别?
Customized development of ant chain NFT digital collection DAPP mall system
MySQL password free login settings
Accumulate SQL by date
规范数据库设计
Development of digital collection system: what are the main features of NFT?