OBS外放声音重采样,用sdl播放

来源:互联网 发布:linux pwd命令 编辑:程序博客网 时间:2024/04/29 17:12

obs读取视频文件添加声音到外放,搞了好几天,不是有杂音就是声音卡顿,或者不同步,现在终于搞好了,把重采样部分代码贴出来

int ff_audio_resample(struct ff_decoder *decoder, AVFrame *frame)

{  


int dst_linesize = 0;
int wanted_nd_samples=0;
int sample_size=0;
int64_t dec_channel_layout;
char **out = &decoder->out_buffer;
if (!frame || decoder->isSdlClose || !decoder->isSdlOpen || !decoder->visable || decoder->muted)
return -1;
wanted_nd_samples = frame->nb_samples;
dec_channel_layout = 
(frame->channel_layout && av_frame_get_channels(frame) == av_get_channel_layout_nb_channels(frame->channel_layout))?
frame->channel_layout:av_get_default_channel_layout(av_frame_get_channels(frame));

if(decoder->fmt != frame->format ||decoder->sample_rate != frame->sample_rate ||  
decoder->channel_layout != dec_channel_layout || wanted_nd_samples !=  frame->nb_samples){
if(decoder->convert_ctx){
swr_free(&decoder->convert_ctx);
}
decoder->convert_ctx= swr_alloc_set_opts(NULL,
AV_CH_LAYOUT_STEREO, 
AV_SAMPLE_FMT_S16,
44100,
dec_channel_layout,
frame->format, 
frame->sample_rate,
0, NULL);


if(!decoder->convert_ctx || swr_init(decoder->convert_ctx)< 0){
swr_free(&decoder->convert_ctx);
return -1;
}
decoder->fmt = frame->format;
decoder->sample_rate = frame->sample_rate;
decoder->channel_layout = dec_channel_layout;

}



if(decoder->convert_ctx){
const uint8_t **in = (const uint8_t **)frame->extended_data;
uint8_t **out = &decoder->out_buffer;
int out_count = (int64_t)wanted_nd_samples*44100/frame->sample_rate+256;
int out_size=av_samples_get_buffer_size(NULL,2,out_count,AV_SAMPLE_FMT_S16, 0);
if(out_size<0)
return -1;
if(wanted_nd_samples != frame->nb_samples){
if(swr_set_compensation(decoder->convert_ctx,(wanted_nd_samples-frame->nb_samples)*44100/frame->sample_rate,
wanted_nd_samples*44100/frame->sample_rate)<0){
return -1;
}
}
av_fast_malloc(&decoder->out_buffer, &decoder->listen_outsize, out_size);
if(!decoder->out_buffer)
return -1;

int len = swr_convert(decoder->convert_ctx, out, out_count, in, frame->nb_samples);
if(len < 0)
return -1;
if(len == out_count){
if(swr_init(decoder->convert_ctx) < 0)
swr_free(&decoder->convert_ctx);
}

decoder->audioData = (uint8_t *)decoder->out_buffer;
sample_size = len*2*av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
}
else {
sample_size = av_samples_get_buffer_size(NULL,av_frame_get_channels(frame),
frame->nb_samples,frame->format, 1);
decoder->audioData = (uint8_t *)frame->data[0];

}
return sample_size;

}

static int ff_audio_decode_frame(struct ff_decoder *decoder)
{
int data_size=0;
struct ff_frame *ff_frame;
AVFrame *frame;
while(1) {
ff_frame = NULL;
if (decoder->frame_queue.size == 0)
av_usleep(1000);
else {
ff_frame = ff_circular_queue_peek_read(
&decoder->frame_queue);

if (!ff_frame || !ff_frame->frame)
av_usleep(1);
else{
frame = av_frame_clone(ff_frame->frame);
break;
}
}
}
data_size = ff_audio_resample(decoder,frame);
if(frame)
av_frame_free(&frame);
return data_size;
}


void  ff_fill_audio_callback(void *udata, uint8_t *stream, int len){
struct ff_decoder *decoder = (struct ff_decoder *)udata;


if (!decoder)
return;
if (!stream  || decoder->isSdlClose || !decoder->isSdlOpen || !decoder->visable || decoder->muted)
return;
while(len>0) {
if(decoder->audio_buf_index >= decoder->audioDataLen) {
int audio_size = ff_audio_decode_frame( decoder);
if(audio_size <= 0){
decoder->audioDataLen = sizeof(decoder->silence_buffer);
decoder->audioData = decoder->silence_buffer;
} else {
decoder->audioDataLen = audio_size;
}
decoder->audio_buf_index = 0;
}
int len1 = decoder->audioDataLen - decoder->audio_buf_index;
if(len1 > len)
len1 = len;
if(decoder->audioData ){

if(decoder->volume == 1.0)
memcpy(stream,(uint8_t*)decoder->audioData + decoder->audio_buf_index,len1);
else {
int volume = 256*decoder->volume;
memset(stream,decoder->silence_buffer[0],len1);
SDL_MixAudio(stream,(uint8_t*)decoder->audioData+decoder->audio_buf_index,len1,volume);
}
}
len -= len1;
stream += len1;
decoder->audio_buf_index +=len1;
}
return;
}

0 0
原创粉丝点击