专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > 多媒体/流媒体开发

哪位高手有新版ffmpeg解码音频流的例子

发布时间:2011-06-27 19:03:54 文章来源:www.iduyao.cn 采编人员:星星草
谁有新版ffmpeg解码音频流的例子?
如题,我根据网上的例子修改了一下,代码如下:

#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;
}



可是还是出现爆破音,怎么办??
------解决思路----------------------
引用:
Quote: 引用:

请问楼主问题解决了没有?


暂时还木有啊。。

没时间调试楼主的代码,但是这里似乎有矛盾吧,你源素材是什么采样频率,播放设置成素材的采样频率,怎么还要重采样?
wanted_spec.freq = audioCodecCtx->sample_rate;
AudioResampling(audioCodecCtx, audioFrame, AV_SAMPLE_FMT_S16, 2, 44100, out_buf);

------解决思路----------------------
我已经解决了,在音频回调函数里面加个SDL_memset(stream, 0, len);应该就行了
详情请看http://blog.csdn.net/jiqiujia/article/details/22449131
友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: