哪位高手有新版ffmpeg解码音频流的例子
谁有新版ffmpeg解码音频流的例子?
如题,我根据网上的例子修改了一下,代码如下:
可是还是出现爆破音,怎么办??
------解决思路----------------------
没时间调试楼主的代码,但是这里似乎有矛盾吧,你源素材是什么采样频率,播放设置成素材的采样频率,怎么还要重采样?
wanted_spec.freq = audioCodecCtx->sample_rate;
AudioResampling(audioCodecCtx, audioFrame, AV_SAMPLE_FMT_S16, 2, 44100, out_buf);
------解决思路----------------------
我已经解决了,在音频回调函数里面加个SDL_memset(stream, 0, len);应该就行了
详情请看http://blog.****.net/jiqiujia/article/details/22449131
如题,我根据网上的例子修改了一下,代码如下:
#include <stdio.h>
#include <tchar.h>
#include <io.h>
#include <direct.h>
#include <math.h>
extern "C"
{
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "sdl/SDL.h"
#include "sdl/SDL_thread.h"
};
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"swscale.lib")
#pragma comment(lib,"swresample.lib")
#pragma comment(lib,"sdl2.lib")
static Uint8 *audio_data;
static Uint32 audio_len;
double round(double r)
{
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}
void sdl_audio_callback( void *udata, Uint8 *stream, int len ) {
static int nTest = 0;
printf("nTest: %d\n", nTest ++);
if( audio_len == 0 ) { return; }
len = (len > audio_len ? audio_len : len);
SDL_MixAudio(stream, audio_data, len, SDL_MIX_MAXVOLUME);
audio_data += len;
audio_len -= len;
}
int AudioResampling(AVCodecContext * audio_dec_ctx,
AVFrame * pAudioDecodeFrame,
int out_sample_fmt,
int out_channels,
int out_sample_rate,
uint8_t * out_buf)
{
SwrContext * swr_ctx = NULL;
int data_size = 0;
int ret = 0;
int64_t src_ch_layout = AV_CH_LAYOUT_STEREO;
int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO;
int dst_nb_channels = 0;
int dst_linesize = 0;
int src_nb_samples = 0;
int dst_nb_samples = 0;
int max_dst_nb_samples = 0;
uint8_t **dst_data = NULL;
int resampled_data_size = 0;
if (swr_ctx)
{
swr_free(&swr_ctx);
}
swr_ctx = swr_alloc();
if (!swr_ctx)
{
printf("swr_alloc error \n");
return -1;
}
src_ch_layout = (audio_dec_ctx->channel_layout &&
audio_dec_ctx->channels ==
av_get_channel_layout_nb_channels(audio_dec_ctx->channel_layout)) ?
audio_dec_ctx->channel_layout :
av_get_default_channel_layout(audio_dec_ctx->channels);
if (out_channels == 1)
{
dst_ch_layout = AV_CH_LAYOUT_MONO;
}
else if(out_channels == 2)
{
dst_ch_layout = AV_CH_LAYOUT_STEREO;
}
else
{
}
if (src_ch_layout <= 0)
{
printf("src_ch_layout error \n");
return -1;
}
src_nb_samples = pAudioDecodeFrame->nb_samples;
if (src_nb_samples <= 0)
{
printf("src_nb_samples error \n");
return -1;
}
av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", audio_dec_ctx->sample_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0);
av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", out_sample_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", (AVSampleFormat)out_sample_fmt, 0);
swr_init(swr_ctx);
max_dst_nb_samples = dst_nb_samples =
av_rescale_rnd(src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate, AV_ROUND_UP);
if (max_dst_nb_samples <= 0)
{
printf("av_rescale_rnd error \n");
return -1;
}
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, (AVSampleFormat)out_sample_fmt, 0);
if (ret < 0)
{
printf("av_samples_alloc_array_and_samples error \n");
return -1;
}
dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, audio_dec_ctx->sample_rate) +
src_nb_samples, out_sample_rate, audio_dec_ctx->sample_rate,AV_ROUND_UP);
if (dst_nb_samples <= 0)
{
printf("av_rescale_rnd error \n");
return -1;
}
if (dst_nb_samples > max_dst_nb_samples)
{
av_free(dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, (AVSampleFormat)out_sample_fmt, 1);
max_dst_nb_samples = dst_nb_samples;
}
data_size = av_samples_get_buffer_size(NULL, audio_dec_ctx->channels,
pAudioDecodeFrame->nb_samples,
audio_dec_ctx->sample_fmt, 1);
if (data_size <= 0)
{
printf("av_samples_get_buffer_size error \n");
return -1;
}
resampled_data_size = data_size;
if (swr_ctx)
{
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
(const uint8_t **)pAudioDecodeFrame->data, pAudioDecodeFrame->nb_samples);
if (ret <= 0)
{
printf("swr_convert error \n");
return -1;
}
resampled_data_size = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
ret, (AVSampleFormat)out_sample_fmt, 1);
if (resampled_data_size <= 0)
{
printf("av_samples_get_buffer_size error \n");
return -1;
}
}
else
{
printf("swr_ctx null error \n");
return -1;
}
memcpy(out_buf, dst_data[0], resampled_data_size);
if (dst_data)
{
av_freep(&dst_data[0]);
}
av_freep(&dst_data);
dst_data = NULL;
if (swr_ctx)
{
swr_free(&swr_ctx);
}
return resampled_data_size;
}
int _tmain(int argc, _TCHAR* argv[])
{
char filename[] = "WavinFlag.aac";
av_register_all();
avformat_network_init();
AVFormatContext* pFormatCtx = avformat_alloc_context();
if( avformat_open_input(&pFormatCtx,filename,NULL,NULL) != 0 ) {
printf("Couldn't open file.\n");
return -1;
}
if( av_find_stream_info(pFormatCtx) < 0 ) {
printf("Couldn't find stream information.\n");
return -1;
}
av_dump_format(pFormatCtx, 0, filename, false);
int audioStream = -1;
for(int i=0; i < pFormatCtx->nb_streams; i++) {
if( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) {
audioStream = i;
break;
}
}
if( audioStream == -1 ) {
printf("Didn't find a audio stream.\n");
return -1;
}
AVCodecContext* audioCodecCtx = pFormatCtx->streams[audioStream]->codec;
AVCodec* pCodec = avcodec_find_decoder(audioCodecCtx->codec_id);
if( pCodec == NULL ) {
printf("Codec not found.\n");
return -1;
}
AVDictionary* options = NULL;
if( avcodec_open2(audioCodecCtx, pCodec, &options) < 0 ) {
printf("Could not open codec.\n");
return -1;
}
AVPacket *packet = (AVPacket *)malloc(sizeof(AVPacket));
av_init_packet(packet);
AVFrame* audioFrame = avcodec_alloc_frame();
if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) ) {
printf( "Could not initialize SDL - %s\n", SDL_GetError());
exit(1);
}
SDL_AudioSpec wanted_spec;
wanted_spec.freq = audioCodecCtx->sample_rate;
wanted_spec.format = AUDIO_S16SYS;
wanted_spec.channels = audioCodecCtx->channels;
wanted_spec.silence = 0;
wanted_spec.samples = 1024;
wanted_spec.callback = sdl_audio_callback;
wanted_spec.userdata = audioCodecCtx;
if( SDL_OpenAudio(&wanted_spec, NULL) < 0 ) {
printf("can't open audio.\n");
return 0;
}
uint32_t len = 0;
while( av_read_frame(pFormatCtx, packet) >= 0 ) {
if( packet->stream_index == audioStream ) {
int got_picture;
int ret = avcodec_decode_audio4( audioCodecCtx, audioFrame, &got_picture, packet);
if( ret < 0 ) {
printf("Error in decoding audio frame.\n");
exit(0);
}
if( got_picture ) {
int data_size = 0;
data_size = av_samples_get_buffer_size(NULL, audioCodecCtx->channels,
audioFrame->nb_samples,
audioCodecCtx->sample_fmt, 1);
uint8_t * out_buf = new uint8_t[data_size];
AudioResampling(audioCodecCtx, audioFrame, AV_SAMPLE_FMT_S16, 2, 44100, out_buf);
audio_len = data_size;
audio_data = out_buf;
}
SDL_PauseAudio(0);
while( audio_len > 0 ) {
SDL_Delay(1);
}
}
av_free_packet(packet);
}
SDL_CloseAudio();
avcodec_close(audioCodecCtx);
av_close_input_file(pFormatCtx);
return 0;
}
可是还是出现爆破音,怎么办??
------解决思路----------------------
没时间调试楼主的代码,但是这里似乎有矛盾吧,你源素材是什么采样频率,播放设置成素材的采样频率,怎么还要重采样?
wanted_spec.freq = audioCodecCtx->sample_rate;
AudioResampling(audioCodecCtx, audioFrame, AV_SAMPLE_FMT_S16, 2, 44100, out_buf);
------解决思路----------------------
我已经解决了,在音频回调函数里面加个SDL_memset(stream, 0, len);应该就行了
详情请看http://blog.****.net/jiqiujia/article/details/22449131