首先:音频的解码和视频的解码流程是一样的。
1.找到音频流:
audioStream = -1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && audioStream < 0) { audioStream = i; } } if (audioStream == -1) return -1;2.找到音频编解码器:
aCodecCtx=pFormatCtx->streams[audioStream]->codec;
SDL_AudioSpec是包含音频输出格式的结构体:
typedef struct{ int freq; Uint16 format; Uint8 channels; Uint8 silence; Uint16 samples; Uint32 size; void (*callback)(void *userdata, Uint8 *stream, int len); void *userdata; } SDL_AudioSpec;
int |
freq |
采样率。可选为11025(11.025KHZ), 22050(22.05KHZ) 和44100(44.1KHZ)。数值越高越好。44.1KHZ是理论上的CD音质界限。 |
SDL_AudioFormat |
format |
音频数据格式;format 告诉SDL我们将要给的格式。在“S16SYS”中的S表示有符号的signed,16表示每个样本是16位长的,SYS表示大小头的顺序是与使用的系统相同的。这些格式是由avcodec_decode_audio2为我们给出来的输入音频的格式。 |
Uint8 |
channels |
声音的通道数 1 单声道, 2 立体声; |
Uint8 |
silence |
表示静音的值。因为声音采样是有符号的,所以0当然就是这个值。 |
Uint16 |
samples |
audio buffer size in samples (power of 2); 详情参考“讨论” |
Uint32 |
size |
音频缓存区大小(字节数),当我们想要更多声音的时候,我们想让SDL给出来的声音缓冲区的尺寸。一个比较合适的值在512到8192之间;ffplay使用1024。 |
SDL_AudioCallback |
callback |
当音频设备需要更多数据时调用的回调函数; |
void* |
userdata |
这个是SDL供给回调函数运行的参数。我们将让回调函数得到整个编解码的上下文信息; |
4.打开音频设备:
if (SDL_OpenAudio(&wanted_spec, &spec) < 0) { fprintf(stderr, "SDL_OpenAudio: %s/n", SDL_GetError()); return -1; }5.avcodec_decode_audio4()解码输出后的音频采样数据格式为AV_SAMPLE_FMT_FLTP,但是SDL能直接识别的格式为AV_SAMPLE_FMT_S16。解决方式是:
int out_linesize; //输出内存大小 int out_buffer_size=av_samples_get_buffer_size(&out_linesize, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1); uint8_t *out_buffer=new uint8_t[out_buffer_size]; ... au_convert_ctx = swr_alloc(); au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, 44100, pCodecCtx->channel_layout,pCodecCtx->sample_fmt , pCodecCtx->sample_rate,0, NULL); swr_init(au_convert_ctx); while(av_read_frame(pFormatCtx, packet)>=0){ ...... swr_convert(au_convert_ctx,&out_buffer, out_linesize,(const uint8_t **)pFrame->data , pFrame->nb_samples); ...... }可以参考这篇文章:
ffmpeg音频解码
int |
freq |
采样率 |
SDL_AudioFormat |
format |
音频数据格式;format 告诉SDL我们将要给的格式。在“S16SYS”中的S表示有符号的signed,16表示每个样本是16位长的,SYS表示大小头的顺序是与使用的系统相同的。这些格式是由avcodec_decode_audio2为我们给出来的输入音频的格式。 |
Uint8 |
channels |
声音的通道数 1 单声道, 2 立体声; |
Uint8 |
silence |
表示静音的值。因为声音采样是有符号的,所以0当然就是这个值。 |
Uint16 |
samples |
audio buffer size in samples (power of 2); 详情参考“讨论” |
Uint32 |
size |
音频缓存区大小(字节数),当我们想要更多声音的时候,我们想让SDL给出来的声音缓冲区的尺寸。一个比较合适的值在512到8192之间;ffplay使用1024。 |
SDL_AudioCallback |
callback |
当音频设备需要更多数据时调用的回调函数; |
void* |
userdata |
这个是SDL供给回调函数运行的参数。我们将让回调函数得到整个编解码的上下文信息; |