Audio Video Development - (D) audio coding

Based on the development of audio and video QT + FFMPEG (D) - encoded audio


Most of my learning comes from Raytheon, Raytheon is no basis to blog around, always a lot of harvest.
https://blog.csdn.net/leixiaohua1020/article/details/42658139

An encoding step of the general

avformat_alloc_output_context2();                //初始化输出码流
avio_open();                                     //打开输出文件
av_new_stream();                                 //创建输出码流
avcodec_find_encoder();                          //寻找解码器
avcodec_alloc_context3();                        //打开解码器上下文
avcodec_open2();                                 //打开解码器
avformat_write_header();                         //写文件头
avcodec_send_frame();               
avcodec_receive_packet();                        //两步为编码
av_interleaved_write_frame();                   //将编码后压缩包写入文件
av_write_trailer();                             //写文件尾

Raytheon main flow chart can go there to see, for a beginner like me very helpful.

Second, coding

2.1 Creating encoder (herein creates AAC)

AVCodec *avcodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (avcodec == NULL) 
{
	//创建失败
    return -1;
}
AVCodecContext *avcodec_context = avcodec_alloc_context3(avcodec);
avcodec_context->bit_rate = 64000;
avcodec_context->sample_rate = 44100;
avcodec_context->sample_fmt = AV_SAMPLE_FMT_FLTP;
avcodec_context->channel_layout = AV_CH_LAYOUT_STEREO;
avcodec_context->channels = 2;
avcodec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

//打开编码器
int ret = avcodec_open2(avcodec_context,avcodec,NULL);
if (ret < 0)
{
    //打开失败
    return -1;
}

2.2 core coding

Two things to note:

1. Since the PCM format S16, AAC format FLTP, it requires resampling before encoding audio, converts the format to a desired format.
2.PCM size is 1152, but only AAC 1024, so it should be noted that nb_samples settings.

len = swr_convert(actx, frame->data, frame->nb_samples,
                      data, frame->nb_samples);
AVPacket pkt;
av_init_packet(&pkt);

// 音频编码
ret = avcodec_send_frame(avcodec_context,frame);
if (ret != 0) continue;
ret = avcodec_receive_packet(avcodec_context,&pkt);
if (ret != 0) continue;

// 音频封装成aac文件
pkt.stream_index = 0;
pkt.pts = 0;
pkt.dts = 0;
ret = av_interleaved_write_frame(oc,&pkt);
cout << "[" << len << "]";
av_packet_unref(&pkt);

Third, the source

int main(int argc, char *argv[])
{
	char infile[] = "out.pcm";
	char outfile[] = "out.aac";
	
	av_register_all();
	avcodec_register_all();

	AVCodec *avcodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
	if (!codec)
	{
    	cout << "avcodec_find_encoder error" << endl;
    	return -1;
	}
	
	AVCodecContext *avcodec_context = avcodec_alloc_context3(avcodec);
	if (!avcodec_context)
	{
    	cout << "avcodec_alloc_context3 error" << endl;
    	return -1;
	}
	avcodec_context->bit_rate = 64000;
	avcodec_context->sample_rate = 44100;
	avcodec_context->sample_fmt = AV_SAMPLE_FMT_FLTP;
	avcodec_context->channel_layout = AV_CH_LAYOUT_STEREO;
	avcodec_context->channels = 2;
	avcodec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

	//打开编码器
	int ret = avcodec_open2(avcodec_context,avcodec,NULL);
	if (ret < 0)
	{
    	cout << "avcodec_open2 error" << endl;
    	return -1;
	}
	cout << "avcodec_open2 success!" << endl;

	AVFormatContext *oc = NULL;
	avformat_alloc_output_context2(&oc,NULL,NULL,outfile);
	if (!oc)
	{
    	cout << "avformat_alloc_output_context2 error" << endl;
    	return -1;
	}

	AVStream *st = avformat_new_stream(oc,NULL);
	st->codecpar->codec_tag = 0;
	avcodec_parameters_from_context(st->codecpar,c);

	ret = avio_open(&oc->pb,outfile,AVIO_FLAG_WRITE);
	if (ret < 0)
	{
    	cout << "avio_open error" << endl;
    	return -1;
	}
	
	ret = avformat_write_header(oc,NULL);

	SwrContext *actx = NULL;
	actx = swr_alloc_set_opts(actx, avcodec_context->channel_layout,
							avcodec_context->sample_fmt,avcodec_context->sample_rate,
                          	AV_CH_LAYOUT_STEREO,AV_SAMPLE_FMT_S16,44100, 0,0);
	if (!actx)
	{
    	cout << "swr_alloc_set_opts error" << endl;
    	return -1;
	}
	ret = swr_init(actx);
	if (ret < 0)
	{
    	cout << "swr_init error" << endl;
    	return -1;
	}
	
	AVFrame *frame = av_frame_alloc();
	frame->format = AV_SAMPLE_FMT_FLTP;
	frame->channels = 2;
	frame->channel_layout = AV_CH_LAYOUT_STEREO;
	frame->nb_samples = 1024;
	ret = av_frame_get_buffer(frame,0);
	if (ret < 0)
	{
    	cout << "av_frame_get_buffer error" << endl;
    	return -1;
	}

	int readSize = frame->nb_samples * 2 * 2;
	char *pcm = new char[readSize];
	FILE *fp = fopen(infile,"rb");

	for (;;)
	{
    	int len = fread(pcm,1,readSize,fp);
    	if (len<=0)
    	{
        	break;
    	}
    	const uint8_t *data[1];
    	data[0] = (uint8_t*)pcm;

    	len = swr_convert(actx, frame->data, frame->nb_samples,
        	              data, frame->nb_samples );
    	if (len <= 0) 
    	{
        	break;
    	}

    	AVPacket pkt;
    	av_init_packet(&pkt);

    	//音频编码
    	ret = avcodec_send_frame(avcodec_context,frame);
    	if (ret != 0) continue;
    	ret = avcodec_receive_packet(avcodec_context,&pkt);
    	if (ret != 0) continue;

    	// 音频封装成aac文件
    	pkt.stream_index = 0;
    	pkt.pts = 0;
    	pkt.dts = 0;
    	ret = av_interleaved_write_frame(oc,&pkt);
    	cout << "[" << len << "]";
    	av_packet_unref(&pkt);
	}

	AVPacket pkt;
	av_init_packet(&pkt);

	ret = avcodec_send_frame(avcodec_context, NULL);
	cout << "ret1 = " << ret << endl;
	ret = avcodec_receive_packet(avcodec_context, &pkt);
	cout << "ret2 = " << ret << endl;

	pkt.stream_index = 0;
	pkt.pts = 0;
	pkt.dts = 0;
	ret = av_interleaved_write_frame(oc,&pkt);
	av_packet_unref(&pkt);

	delete pcm;
	pcm = NULL;
	av_write_trailer(oc);

	avio_close(oc->pb);
    avformat_free_context(oc);
	avcodec_close(c);
	avcodec_free_context(&c);
	fclose(fp);
}

Guess you like

Origin blog.csdn.net/Mr__Hu/article/details/91795842