ffmpeg之PCM转AAC

AAC是一种常见的音频格式,今天尝试使用ffmpeg把pcm压缩成AAC编码。

第一步:初始化编码相关变量

寻找AAC的编码器

codec = avcodec_find_encoder(AV_CODEC_ID_AAC);

 初始化编码器上下文,主要通道数,采样率,采样格式

	c = avcodec_alloc_context3(codec);
	if (!c) {
		fprintf(stderr, "Could not allocate audio codec context\n");
		return false;
	}
	c->channels = m_PcmChannel;
	c->channel_layout = av_get_default_channel_layout(m_PcmChannel);
	c->sample_rate = m_PcmSampleRate;
	c->sample_fmt = AV_SAMPLE_FMT_FLTP;//AV_SAMPLE_FMT_FLTP;
	c->bit_rate = 64000;
	/* Allow the use of the experimental AAC encoder. */
	c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;

 打开编码器

	if (avcodec_open2(c, codec, NULL) < 0) {
		fprintf(stderr, "Could not open codec\n");
		return false;
	}

 设置格式转换,主要是AAC需要的采样格式位AV_SAMPLE_FMT_FLTP,而PCM格式位AV_SAMPLE_FMT_S16,所以需要进行格式的转换。

	resample_context = swr_alloc_set_opts(NULL, c->channel_layout, c->sample_fmt,
		c->sample_rate, c->channel_layout, m_PcmFormat, c->sample_rate, 0, NULL);
if (swr_init(resample_context) < 0)
	{
		fprintf(stderr, "Could not open resample context\n");
		return false;
	}

第二步:初始化相关工作做完之后,可以进行转码工作,首先丢进。

对PCM进行重新采样,转换成AAC需要的PCM格式

if (swr_convert(resample_context, frame->extended_data, frame->nb_samples, (const uint8_t**)m_PcmPointer, 1024)<0)
	{
		fprintf(stderr, "Could not convert input samples (error )\n");
		if (NULL != frame)
		{
			av_frame_free(&frame);
		}
		return ;
	}

 放进编码器

ret = avcodec_send_frame(c, frame);

第三步:从编码器取出编码完的数据

int  ret = avcodec_receive_packet(c, packet);

第四步:由于编码后的AAC文件没有头,导致写成文件无法识别,所以需要手动写入AAC头

	// fill in ADTS data  
	m_pOutData[0] = 0xFF;
	m_pOutData[1] = 0xF1;
	m_pOutData[2] = ((profile) << 6) + (freqIdx << 2) + (chanCfg >> 2);
	m_pOutData[3] = (((chanCfg & 3) << 6) + (packetLen >> 11));
	m_pOutData[4] = ((packetLen & 0x7FF) >> 3);
	m_pOutData[5] = (((packetLen & 7) << 5) + 0x1F);
	m_pOutData[6] = 0xFC;

 

至此,PCM转成AAC的格式流程结束。

这里对AVSampleFormat格式进行一下介绍,

如果是以下格式:

    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16,         ///< signed 16 bits
    AV_SAMPLE_FMT_S32,         ///< signed 32 bits
    AV_SAMPLE_FMT_FLT,         ///< float
    AV_SAMPLE_FMT_DBL,         ///< double

只能保存再AVFrame的uint8_t *data[0];

音频保持格式如下:

LRLRLR。。。。

如果是以下格式

    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP,        ///< float, planar
    AV_SAMPLE_FMT_DBLP,        ///< double, planar

plane 0: LLLLLLLLLLLLLLLLLLLLLLLLLL...
plane 1: RRRRRRRRRRRRRRRRRRRR....

plane 0对于uint8_t *data[0];

plane 1对于uint8_t *data[1];

 

为了便于大家学习和研究, 工程采用VS2017开发,地址如下:

https://download.csdn.net/download/g0415shenw/10599101

你可能感兴趣的:(ffmpeg)