ffmpeg音频编码,程序如下:

extern "C"
{
#include <libavutil/avutil.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}

#pragma warning(disable:4996)

// check sample format
int check_sample_fmt(const AVCodec *codec, AVSampleFormat sample_fmt)
{
	const AVSampleFormat *p = codec->sample_fmts;
	while (*p != AV_SAMPLE_FMT_NONE)
	{
		if (*p == sample_fmt)
		{
			return 1;
		}
		p++;
	}
	return 0;
}

int select_sample_rate(const AVCodec *codec)
{
	const int *rate = codec->supported_samplerates;
	if (!rate) {
		return 44100;
	}
	int best_samplerate = 0;
	while (*rate)
	{
		if (best_samplerate == 0 || abs(44100 - *rate) < (44100 - best_samplerate))
		{
			best_samplerate = *rate;
		}
		rate++;
	}
	return best_samplerate;
}

uint64_t select_channel_layout(const AVCodec *codec)
{
	uint64_t best_ch_layout = 0;
	int best_nb_channels = 0;
	const uint64_t *p = codec->channel_layouts;
	if (!p) 
	{
		return AV_CH_LAYOUT_STEREO;
	}
	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;
}


int main()
{
	//parameter
	int ret = 0;
	char errors[200] = { 0 };
	const char *destMedia = "out/test.mp3";

	//
	av_log_set_level(AV_LOG_INFO);
	av_register_all();
	//获取指定编解码器
	AVCodec *avCodec = avcodec_find_encoder(AV_CODEC_ID_MP2);
	//获取编解码上下文
	AVCodecContext *avCodecCtx = avcodec_alloc_context3(avCodec);
	//设置参数
	avCodecCtx->bit_rate = 64000;
	avCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
	if (!check_sample_fmt(avCodec, avCodecCtx->sample_fmt)) {
		av_log(NULL, AV_LOG_WARNING, "not support sample format==%d\n", avCodecCtx->sample_fmt);
		return -1;
	}
	avCodecCtx->sample_rate = select_sample_rate(avCodec);
	avCodecCtx->channel_layout = select_channel_layout(avCodec);
	avCodecCtx->channels = av_get_channel_layout_nb_channels(avCodecCtx->channel_layout);
	//打开编码器
	ret = avcodec_open2(avCodecCtx, avCodec, NULL);
	//初始化frame, packet
	AVFrame *avFrame = av_frame_alloc();
	avFrame->nb_samples = avCodecCtx->frame_size;
	avFrame->format = avCodecCtx->sample_fmt;
	avFrame->channel_layout = avCodecCtx->channel_layout;
	ret = av_frame_get_buffer(avFrame, 0);
	float t = 0;
	float tincr = 2.0f * M_PI * 440 / avCodecCtx->sample_rate;
	AVPacket avPacket;
	av_init_packet(&avPacket);
	int getPacket = 0;
	FILE *outFile = fopen(destMedia, "wb");
	for (int i = 0; i < 200; i++)
	{
		av_packet_unref(&avPacket);
		ret = av_frame_make_writable(avFrame);
		//自己创造音频数据
		uint8_t *samples = avFrame->data[0];
		for (int j = 0; j < avCodecCtx->frame_size; j++) 
		{
			samples[2 * j] = sin(t) * 10000;
			for (int k = 1; k < avCodecCtx->channels; k++)
			{
				samples[2 * j + k] = samples[2 * j];
			}
			t += tincr;
		}
		//编码
		ret = avcodec_encode_audio2(avCodecCtx, &avPacket, avFrame, &getPacket);
		if (ret < 0) {
			av_strerror(ret, errors, 200);
			av_log(NULL, AV_LOG_WARNING, "avcodec_encode_audio2 error: ret=%d, msg=%s\n", ret, errors);
			return ret;
		}
		if (getPacket)
		{
			fwrite(avPacket.data, 1, avPacket.size, outFile);
		}
	}

	//释放资源
	av_packet_unref(&avPacket);
	av_frame_free(&avFrame);
	avcodec_free_context(&avCodecCtx);
	if (outFile) {
		fclose(outFile);
	}

	return 0;
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐