Audio 在linux上用c语言中的libav转换音频格式
我正在尝试编写一个应用程序,其中一部分将音频文件转换为不同的格式。但是输出是垃圾(好吧,这就是它在audacity中的样子) 在尝试了许多不同的东西之后,我最终得到了这样一个结果:一个原始音频文件,我试图将其转换成MP3文件。我知道原始音频还可以(通过audacity)。但是MP3又是垃圾 下面是我正在使用的代码(我从libav示例拼凑而成):Audio 在linux上用c语言中的libav转换音频格式,audio,mp3,encode,libav,resampling,Audio,Mp3,Encode,Libav,Resampling,我正在尝试编写一个应用程序,其中一部分将音频文件转换为不同的格式。但是输出是垃圾(好吧,这就是它在audacity中的样子) 在尝试了许多不同的东西之后,我最终得到了这样一个结果:一个原始音频文件,我试图将其转换成MP3文件。我知道原始音频还可以(通过audacity)。但是MP3又是垃圾 下面是我正在使用的代码(我从libav示例拼凑而成): /* *flac2m3.cpp * *创建日期:2014年8月20日 *作者:肯 */ #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括
/*
*flac2m3.cpp
*
*创建日期:2014年8月20日
*作者:肯
*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#include//std::exception
#包括
#包括
#包括
#包括
#包括
#ifndef\uU STDC\u格式\u宏
#定义\u STDC\u格式\u宏
#包括
#恩迪夫
#ifndef INT64_C
#定义INT64_C(C)(C#LL)
#定义UINT64_C(C)(C#ULL)
#恩迪夫
外部“C”
{
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#ifdef CPP_W_LITERAL_后缀
#undef CPP_W_LITERAL_后缀
#包括
#定义CPP_W_LITERAL_后缀
#恩迪夫
#ifdef av_err2str
#undef av_err2str
#恩迪夫
#定义av_err2str(errnum)\
av生成错误字符串((字符*)((av生成错误最大字符串大小))\
AV\u错误\u最大\u字符串大小,errnum)
#ifdef av_ts2timestr
#未定义av_ts2timestr
#恩迪夫
#定义av_ts2timestr(ts,tb)\
av_ts_make_time_string((字符*)(_内置_alloca(av_ts_MAX_string_SIZE)),ts,tb)
}
typedef无符号字符字节;
#包括
#包括
静态AVFormatContext*encfmt_ctx=NULL;
静态AVcodeContext*音频加密ctx;
静态AVStream*audio_encstream=NULL;
静态整数音频帧计数=0,音频帧计数=0;
静态SwrContext*swr;
静态字节**输出;
静态常量字节**inpb;
#定义MP3\u示例\u FMT AV\u示例\u FMT\u S16P
#定义MP3_比特率256000
#定义MP3_采样率44100
#定义FLAC_样本\u FMT AV_样本\u FMT_S16
#定义FLAC_比特率256000
#定义FLAC_样本率44100
#定义样本到CB(stc,cs)(av获取每个样本的字节数(stc->编解码器->样本fmt)*stc->编解码器->频道*cs)
#从(stc,CB)CB定义样本/(每个样本(stc->codec->sample\u fmt)*stc->codec->channels)
#定义字节\u至\u读取2048
布尔编码_缓冲区(字节*buff,int-cbdec,布尔刷新)
{
int ret;
int-got_框架;
内线尺寸;
AVPacket epkt={0};
AVFrame*eframe=avcodec_alloc_frame();
av_初始_数据包(&epkt);
/*
*转换音频
*/
长整数c_样本=cbdec/(4);
//长整数延迟=swr\U get\U延迟(swr,(长整数)44100);
长整数延迟=0;
int c_outsamples=av_rescale_rnd(延迟+c_insamples,
(长整数)MP3_采样率,
(长整数)FLAC_采样率、AV_取整率);
ret=av样本分配(输出和线尺寸,2,
c_样本数,MP3_样本数_FMT,0);
av_资产0(ret>=0);
inpb[0]=buff;
ret=swr_转换(swr、outpb、c_外采样、inpb、c_内采样);
av_资产0(ret>=0);
/*
*编码
*/
音频帧计数+=(cbdec/4);
printf(“cbdec=%d,deccount=%d\n”,cbdec,音频\帧\ deccount);
eframe->nb_样本=cbdec/(4);
eframe->pts=(音频帧计数*(av重新缩放q(1,音频加密流->编解码器->时基,音频加密流->时基));
avcodec_fill_audio_frame(eframe,2,MP3_SAMPLE_FMT,outpb[0],cbdec,1);
epkt.stream\u index=音频流->索引;
eframe->nb\u samples=音频加密ctx->帧大小;
ret=avcodec\U encode\U audio 2(音频加密、ctx和epkt、eframe和got\U帧);
av_资产0(ret>=0);
如果(!得到了_帧)
{
//无AVU(输出B[0]);
返回false;
}
epkt.stream\u index=音频流->索引;
音频_帧_enccount++;
/*将压缩帧写入媒体文件*/
ret=av交织写入帧(encfmt、ctx和epkt);
无AVU(输出B[0]);
avcodec_free_帧(&eframe);
返回true;
}
int open_encodec_上下文(AVFormatContext*fmt_ctx,枚举AVMediaType类型)
{
int ret;
AVStream*st;
AVCodec*enc=NULL;
enc=avcodec\u find\u编码器(fmt\u ctx->oformat->audio\u codec);
av_资产0(enc!=NULL);
st=AVU格式新流(fmt ctx,enc);
/*查找流的编码器*/
st->codec->sample\u fmt=MP3\u sample\u fmt;
st->编解码器->比特率=MP3比特率;
st->codec->sample\u rate=MP3\u sample\u rate;
st->codec->channels=2;
ret=avcodec_open2(st->codec,enc,NULL);
av_资产0(ret>=0);
返回1;
}
int main(int argc,字符**argv)
{
常量字符*fn_out=argv[1];
int ret;
av_寄存器_all();
ret=avformat\u alloc\u output\u context2(&encfmt\u ctx,NULL,NULL,fn\u out);
av_资产0(ret>=0);
如果(打开编码上下文(encfmt\u ctx,AVMEDIA\u TYPE\u AUDIO)>=0)
{
音频_encstream=encfmt_ctx->streams[0];
音频加密ctx=音频加密流->编解码器;
av_转储_格式(encfmt_ctx,0,fn_out,1);
}
字节pbo[sizeof(BYTE*)*av_sample_fmt_是平面的(MP3_sample_fmt)?2:1];
outpb=(字节**)pbo;
outpb[0]=NULL;
字节pbi[sizeof(BYTE*)*2];
inpb=(常量字节**)pbi;
inpb[0]=NULL;
swr=swr_alloc();
av_资产0(swr);
/*设置选项*/
av_opt_set_int(swr,“通道内布局”,2,0);
av_opt_set_int(swr,“通道内计数”,2,0);
av_opt_set_int(swr,“进样率”,FLAC_采样率,0);
av选择集样本fmt(swr,“入样本fmt”,FLAC样本fmt,0);
av_opt_set_int(swr,“输出通道布局”,2,0);
av_opt_set_int(swr,“输出采样率”,MP3采样率,0);
av_opt_set_sample_fmt(swr,“out_sample_fmt”,MP3_sample_fmt,0);
ret=swr_初始值(swr);
av_资产0(ret>=0);
if(!(encfmt_ctx->oformat->flags&AVFMT_NOFILE))
{
ret=avio_打开(&encfmt_ctx->pb,fn_输出,avio_标志_写入);
如果(ret<0)
{
fprintf(stderr,“无法打开“%s”:%s\n”,fn\u out,
av_err2str(ret));
返回1;
}
}
ret=avformat\U write\U头(encfmt\U ctx,NU
/*
* flac2mp3.cpp
*
* Created on: Aug 20, 2014
* Author: ken
*/
#include <stddef.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <exception> // std::exception
#include <cerrno>
#include <assert.h>
#include <time.h>
#include <fcntl.h>
#include <linux/types.h>
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif
extern "C"
{
#include <libavutil/avassert.h>
#include <libavutil/channel_layout.h>
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#ifdef CPP_W_LITERAL_SUFFIX
#undef CPP_W_LITERAL_SUFFIX
#include <libavutil/timestamp.h>
#define CPP_W_LITERAL_SUFFIX
#endif
#ifdef av_err2str
#undef av_err2str
#endif
#define av_err2str(errnum) \
av_make_error_string((char*)(__builtin_alloca(AV_ERROR_MAX_STRING_SIZE)),\
AV_ERROR_MAX_STRING_SIZE, errnum)
#ifdef av_ts2timestr
#undef av_ts2timestr
#endif
#define av_ts2timestr(ts, tb) \
av_ts_make_time_string((char*)(__builtin_alloca(AV_TS_MAX_STRING_SIZE)), ts, tb)
}
typedef unsigned char BYTE;
#include <algorithm>
#include <fcntl.h>
static AVFormatContext *encfmt_ctx = NULL;
static AVCodecContext *audio_enc_ctx;
static AVStream *audio_encstream = NULL;
static int audio_frame_deccount = 0, audio_frame_enccount = 0;
static SwrContext *swr;
static BYTE **outpb;
static const BYTE **inpb;
#define MP3_SAMPLE_FMT AV_SAMPLE_FMT_S16P
#define MP3_BITRATE 256000
#define MP3_SAMPLE_RATE 44100
#define FLAC_SAMPLE_FMT AV_SAMPLE_FMT_S16
#define FLAC_BITRATE 256000
#define FLAC_SAMPLE_RATE 44100
#define SAMPLES_TO_CB(stc, cs) (av_get_bytes_per_sample(stc->codec->sample_fmt) * stc->codec->channels * cs)
#define SAMPLES_FROM_CB(stc, cb) cb/(av_get_bytes_per_sample(stc->codec->sample_fmt) * stc->codec->channels)
#define BYTES_TO_READ 2048
bool encode_buffer(BYTE* buff, int cbdec, bool flush)
{
int ret;
int got_frame;
int line_size;
AVPacket epkt = {0};
AVFrame *eframe = avcodec_alloc_frame();
av_init_packet(&epkt);
/*
* convert audio
*/
long int c_insamples = cbdec/(4);
// long int delay = swr_get_delay(swr,(long int) 44100);
long int delay = 0;
int c_outsamples = av_rescale_rnd(delay + c_insamples,
(long int) MP3_SAMPLE_RATE,
(long int) FLAC_SAMPLE_RATE, AV_ROUND_UP);
ret = av_samples_alloc(outpb, &line_size, 2,
c_outsamples,MP3_SAMPLE_FMT, 0);
av_assert0(ret >= 0);
inpb[0] = buff;
ret = swr_convert(swr, outpb, c_outsamples, inpb, c_insamples);
av_assert0(ret >= 0);
/*
* encode
*/
audio_frame_deccount +=(cbdec/4);
printf("cbdec=%d, deccount=%d\n", cbdec, audio_frame_deccount);
eframe->nb_samples = cbdec/(4);
eframe->pts = (audio_frame_deccount * ( av_rescale_q(1, audio_encstream->codec->time_base, audio_encstream->time_base)));
avcodec_fill_audio_frame(eframe, 2, MP3_SAMPLE_FMT, outpb[0], cbdec, 1);
epkt.stream_index = audio_encstream->index;
eframe->nb_samples = audio_enc_ctx->frame_size;
ret = avcodec_encode_audio2(audio_enc_ctx, &epkt, eframe, &got_frame);
av_assert0(ret >= 0);
if (!got_frame)
{
// av_free(outpb[0]);
return false;
}
epkt.stream_index = audio_encstream->index;
audio_frame_enccount ++ ;
/* Write the compressed frame to the media file. */
ret = av_interleaved_write_frame(encfmt_ctx, &epkt);
av_free(outpb[0]);
avcodec_free_frame(&eframe);
return true;
}
int open_encodec_context(AVFormatContext *fmt_ctx, enum AVMediaType type)
{
int ret;
AVStream *st;
AVCodec *enc = NULL;
enc = avcodec_find_encoder(fmt_ctx->oformat->audio_codec);
av_assert0(enc != NULL);
st = avformat_new_stream(fmt_ctx, enc);
/* find encoder for the stream */
st->codec->sample_fmt = MP3_SAMPLE_FMT;
st->codec->bit_rate = MP3_BITRATE;
st->codec->sample_rate = MP3_SAMPLE_RATE;
st->codec->channels = 2;
ret = avcodec_open2(st->codec, enc, NULL);
av_assert0(ret >= 0);
return 1;
}
int main(int argc, char **argv)
{
const char *fn_out = argv[1];
int ret;
av_register_all();
ret = avformat_alloc_output_context2(&encfmt_ctx, NULL, NULL, fn_out);
av_assert0(ret >= 0);
if (open_encodec_context(encfmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0)
{
audio_encstream = encfmt_ctx->streams[0];
audio_enc_ctx = audio_encstream->codec;
av_dump_format(encfmt_ctx, 0, fn_out, 1);
}
BYTE pbo[sizeof(BYTE*) * av_sample_fmt_is_planar(MP3_SAMPLE_FMT) ? 2 : 1];
outpb = (BYTE**) pbo;
outpb[0] = NULL;
BYTE pbi[sizeof(BYTE*) * 2];
inpb = (const BYTE**) pbi;
inpb[0] = NULL;
swr = swr_alloc();
av_assert0(swr);
/* set options */
av_opt_set_int(swr, "in_channel_layout", 2, 0);
av_opt_set_int(swr, "in_channel_count", 2, 0);
av_opt_set_int(swr, "in_sample_rate", FLAC_SAMPLE_RATE,0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", FLAC_SAMPLE_FMT, 0);
av_opt_set_int(swr, "out_channel_layout",2, 0);
av_opt_set_int(swr, "out_sample_rate", MP3_SAMPLE_RATE, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt",MP3_SAMPLE_FMT, 0);
ret = swr_init(swr);
av_assert0(ret >= 0);
if (!(encfmt_ctx->oformat->flags & AVFMT_NOFILE))
{
ret = avio_open(&encfmt_ctx->pb, fn_out, AVIO_FLAG_WRITE);
if (ret < 0)
{
fprintf(stderr, "Could not open '%s': %s\n", fn_out,
av_err2str(ret));
return 1;
}
}
ret = avformat_write_header(encfmt_ctx, NULL);
av_assert0(ret >= 0);
int cbread = 0;
int fd = open("/nas/temp/flac.raw", O_RDONLY);
assert(fd > 0);
int cb2read = BYTES_TO_READ;
BYTE b[cb2read];
int c_reads = 0;
while ((cbread = read(fd, b, cb2read)) > 0)
{
c_reads++;
encode_buffer(b, cbread, false);
}
close(fd);
ret = av_interleaved_write_frame(encfmt_ctx, NULL);
av_assert0(ret >= 0);
av_write_trailer(encfmt_ctx);
avio_close(encfmt_ctx->pb);
avcodec_close(audio_enc_ctx);
avformat_free_context(encfmt_ctx);
exit(1);
}