void AudioCode::ENcode(AVCodecContext *cdc_ctx, AVFrame *frame, AVPacket *pkt){
int ret=0;
/* send the frame for encoding */
ret = avcodec_send_frame(cdc_ctx, frame);
if (ret < 0) {
qDebug() << "Error sending the frame to the encoder\n";
return;
}
/* read all the available output packets (in general there may be any
* number of them */
while (ret >= 0) {
ret = avcodec_receive_packet(cdc_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
continue;
else if (ret < 0) {
qDebug() << "Error encoding audio frame\n";
continue;
}
socket->writeDatagram((char *)pkt->data,pkt->size,QHostAddress(m_strTargetIP),m_iTargetPort);
if(mp3OutFILE.isOpen())
mp3OutFILE.write((char *)pkt->data,pkt->size);
av_packet_unref(pkt);
}
return;
}
void AudioCode::PCM2MP3(){
AVFormatContext *fmtCtx = nullptr;
AVCodecContext *codecCtx =nullptr;
const AVCodec *codec = nullptr;
AVFrame *frame = nullptr;
AVPacket *pkt = nullptr;
fmtCtx = avformat_alloc_context();
frame = av_frame_alloc();
pkt = av_packet_alloc();
//==========Output information============
//查找编码器
codec = avcodec_find_encoder(AV_CODEC_ID_MP3);
if(codec==nullptr){
qInfo() <<"Cannot find audio encoder.\n";
}
codecCtx = avcodec_alloc_context3(codec);
codecCtx->bit_rate = 64000;
codecCtx->sample_fmt = AV_SAMPLE_FMT_S16P;
if (!check_sample_fmt(codec, codecCtx->sample_fmt)) {
qInfo() << "Encoder does not support sample format %s",
av_get_sample_fmt_name(codecCtx->sample_fmt);
exit(1);
}
codecCtx->sample_rate = Samplerate;
codecCtx->ch_layout =AV_CHANNEL_LAYOUT_STEREO;
//打开编码器
if(avcodec_open2(codecCtx,codec,nullptr) < 0)
qInfo() << "Open encode error!";
frame->nb_samples = codecCtx->frame_size;
frame->format = codecCtx->sample_fmt;
av_channel_layout_copy(&frame->ch_layout, &codecCtx->ch_layout);
qInfo() << "start init swr";
// MP3数不支持AV_SAMPLE_FMT_S16解码,所以将数据转化为AV_SAMPLE_FMT_S16P
struct SwrContext *swrContext = swr_alloc();
swr_alloc_set_opts2(&swrContext,
&codecCtx->ch_layout,
AV_SAMPLE_FMT_S16P,
Samplerate,
&codecCtx->ch_layout,
AV_SAMPLE_FMT_S16,// PCM源文件的采样格式
Samplerate,0,nullptr);
// 重采样初始化
swr_init(swrContext);
qInfo() << "end init swr";
/* 分配空间 */
uint8_t **convert_data = static_cast<uint8_t**>(calloc(2, static_cast<int>(sizeof(convert_data))));
av_samples_alloc(convert_data,nullptr,2,codecCtx->frame_size,
codecCtx->sample_fmt,0);
uint8_t *frameBuf = static_cast<uint8_t *>(av_malloc(sizeof(uint8_t *)));
int length = av_samples_get_buffer_size(nullptr, codecCtx->ch_layout.nb_channels, codecCtx->frame_size, codecCtx->sample_fmt, 1);
int readsize = length / (codecCtx->ch_layout.nb_channels * av_get_bytes_per_sample(codecCtx->sample_fmt));
//存储所有数据
QByteArray arrayAll;
qInfo() << "start encode";
while(che){
//输入一帧数据的长度 4608 ,使用qt从系统中读取一定长度的音频
QByteArray array = audioDevice->read(length);
//使用length有杂音,不使用length会丢失最后几帧数据
arrayAll += array;
if(arrayAll.size() > length)
{
//对数据进行处理,方便后面音频编码
array = arrayAll.left(length);
arrayAll.remove(0,length);
//读PCM:特意注意读取的长度,否则可能出现转码之后声音变快或者变慢
frameBuf = reinterpret_cast<uint8_t *>(array.data()) ;
const uint8_t *tmpframe = frameBuf;
swr_convert(swrContext,
convert_data,codecCtx->frame_size,
&tmpframe,readsize);
//输出一帧数据的长度
//双通道赋值(输出的AAC为双通道)
frame->data[0] = convert_data[0];
frame->data[1] = convert_data[1];
ENcode(codecCtx,frame,pkt);
}
}
qInfo() << "end encode";
ENcode(codecCtx,nullptr,pkt);
swr_free(&swrContext);
avcodec_free_context(&codecCtx);
av_free(frame);
avio_close(fmtCtx->pb);
avformat_free_context(fmtCtx);
return;
}
使用ffmpeg将pcm格式音频转化为mp3格式音频
最新推荐文章于 2024-09-29 10:09:58 发布