播放器,Android万能音频播放器03"/>
pcm格式android播放器,Android万能音频播放器03
1、基本概念
采样率:每秒对音频数据采样的个数(44100hz)
采样位数:存储采样数据的位数(16bit 2字节)
输出声道(声道布局):单声道、立体声(左右声道)等
2、重采样
就是把目标音频按照一定的格式重新采样编码成新的音频数据,
方便统一处理,一般的采样标准是:44100HZ、16bit、双声道
3、采样对象:解码出来的音频帧(AVframe)
使用函数:SwrContext
swr_ctx = swr_alloc_set_opts(
struct SwrContext *s, // 传NULL
int64_t out_ch_layout, // 输出声道布局
enum AVSampleFormat out_sample_fmt, //输出采样位数格式
int out_sample_rate, //输出采样率
int64_t in_ch_layout, // 输入声道布局
enum AVSampleFormat in_sample_fmt, //输入采样位数格式
int in_sample_rate, //输入采样率
int log_offset, // NULL
void *log_ctx); // NULL
4、
前两篇已经实现了将AVPacket存储到队列中及从队列中取出AVPacket,
在JfAudio中进行重采样
新建一个用于采样的线程
void JfAudio::play() {
pthread_create(&playThread,NULL,decodePlay,this);
}
线程回调decodePlay
void *decodePlay(void *data){
JfAudio *jfAudio = (JfAudio *)(data);
jfAudio->resampleAudio();
pthread_exit(&jfAudio->playThread);
}
音频重采样方法
int JfAudio::resampleAudio() {
while (playStatus != NULL && !playStatus->exit){
avPacket = av_packet_alloc();
if (queue->getAVPacket(avPacket) != 0){
av_packet_free(&avPacket);
av_free(avPacket);
avPacket = NULL;
continue;
}
ret = avcodec_send_packet(pACodecCtx,avPacket);
if (ret != NULL){
av_packet_free(&avPacket);
av_free(avPacket);
avPacket = NULL;
continue;
}
avFrame = av_frame_alloc();
ret = avcodec_receive_frame(pACodecCtx,avFrame);
if (ret == 0) {//进行重采样
if (avFrame->channels > 0 && avFrame->channel_layout == 0){//有声道数没有声道布局,所以要设置声道布局
avFrame->channel_layout = av_get_default_channel_layout(avFrame->channels);//设置声道布局
} else if (avFrame->channels == 0 && avFrame->channel_layout > 0){//有声道布局没有声道数,所以要设置声道数
avFrame->channels = av_get_channel_layout_nb_channels(avFrame->channel_layout);
}
SwrContext *swr_ctx = NULL;
swr_ctx = swr_alloc_set_opts(NULL,
AV_CH_LAYOUT_STEREO,// 输出声道布局:立体声
AV_SAMPLE_FMT_S16,//输出采样位数格式
avFrame->sample_rate,//输出的采样率
avFrame->channel_layout,//输入声道布局
(AVSampleFormat)(avFrame->format),//输入采样位数格式
avFrame->sample_rate,//输入采样率
NULL,
NULL);
if (!swr_ctx || swr_init(swr_ctx) < 0){
av_packet_free(&avPacket);
av_free(avPacket);
avPacket = NULL;
av_frame_free(&avFrame);
av_free(avFrame);
avFrame = NULL;
if (swr_ctx != NULL){
swr_free(&swr_ctx);
swr_ctx = NULL;
}
if (LOG_DEBUG){
LOGE("!swr_ctx || swr_init(swr_ctx) < 0");
}
continue;
}
//返回的是采样的个数
int nb = swr_convert(swr_ctx,
&buffer,//转码后输出的PCM数据大小
avFrame->nb_samples,//输出采样个数
(const uint8_t **)(avFrame->data),
avFrame->nb_samples);
int out_channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
data_size = nb * out_channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
fwrite(buffer,1,data_size,outFile);
LOGD("DATA SIZE == %d",data_size);
av_packet_free(&avPacket);
av_free(avPacket);
avPacket = NULL;
av_frame_free(&avFrame);
av_free(avFrame);
avFrame = NULL;
swr_free(&swr_ctx);
swr_ctx = NULL;
} else {
av_packet_free(&avPacket);
av_free(avPacket);
avPacket = NULL;
av_frame_free(&avFrame);
av_free(avFrame);
avFrame = NULL;
continue;
}
}
fclose(outFile);
return data_size;
}
更多推荐
pcm格式android播放器,Android万能音频播放器03
发布评论