SDL播放ffmpeg解码的AAC

来源:互联网 发布:隐藏应用的软件 编辑:程序博客网 时间:2024/05/29 19:48

转自雷神的博客:http://blog.csdn.net/leixiaohua1020/article/details/38979615


#include <stdio.h>#include <stdlib.h>#include <string.h>#include "stdafx.h"#define __STDC_CONSTANT_MACROS#ifdef _WIN32extern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswresample/swresample.h"#include "SDL/SDL.h"};#endif#define MAX_AUDIO_FRAME_SIZE 19200#define OUTPUT_PCM 0#define USE_SDL 1static Uint8 *audio_chunk;static Uint32 audio_len;static Uint8 *audio_pos;void fill_audio(void *udata,Uint8 *stream,int len){SDL_memset(stream,0,len);if(audio_len ==0){return;}len=(len>audio_len?audio_len:len);SDL_MixAudio(stream,audio_pos,len,SDL_MIX_MAXVOLUME);audio_pos+=len;audio_len-=len;}int _tmain(int argc, _TCHAR* argv[]){AVFormatContext *pFormatCtx;int i,audioStream;AVCodecContext *pCodecCtx;AVCodec *pCodec;AVPacket *packet;uint8_t *out_buffer;AVFrame *pFrame;SDL_AudioSpec wanted_spec;int ret;int m=1;uint32_t len=0;int got_picture;int index=0;int64_t in_channel_layout;struct SwrContext *au_convert_ctx;FILE *pFile=NULL;char url[]="test1.aac";av_register_all();avformat_network_init();pFormatCtx= avformat_alloc_context();if(avformat_open_input(&pFormatCtx,url,NULL,NULL)!=0){printf("Couldn't open input stream\n");return -1;}if(avformat_find_stream_info(pFormatCtx,NULL)<0){printf("Couldn't find the info of stream\n");return -1;}av_dump_format(pFormatCtx,0,url,false);audioStream =-1;for(i=0;i < pFormatCtx->nb_streams;i++){if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){audioStream=i;break;}}if(audioStream==-1){printf("Couldn't find a audio stream\n");return -1;}pCodecCtx= pFormatCtx->streams[audioStream]->codec;pCodec = avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec==NULL){printf("Codec not found\n");return -1;}if(avcodec_open2(pCodecCtx,pCodec,NULL)<0){printf("Could not open codec \n");return -1;}#if OUTPUT_PCMpFile = fopen("output.pcm","wb");#endifpacket = (AVPacket*)av_malloc(sizeof(AVPacket));av_init_packet(packet);uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;//输出声道int out_nb_samples=1024;AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;//输出格式S16int out_sample_rate = 44100;int out_channels =av_get_channel_layout_nb_channels(out_channel_layout);int out_buffer_size = av_samples_get_buffer_size(NULL,out_channels,out_nb_samples,out_sample_fmt,1);out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE*2);pFrame = av_frame_alloc();#if USE_SDLif(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)){printf("Could not initialize SDL - %s\n",SDL_GetError());return -1;}wanted_spec.freq = out_sample_rate;wanted_spec.format = AUDIO_S16SYS;wanted_spec.channels=out_channels;wanted_spec.silence =0;wanted_spec.samples = out_nb_samples;wanted_spec.callback =fill_audio;wanted_spec.userdata = pCodecCtx;if(SDL_OpenAudio(&wanted_spec,NULL)<0){printf("cann't open audio\n");return -1;}else{printf("whether loop in SDL_OpenAudio()\n");}#endifprintf("Bitrate:\t %3d\n",pFormatCtx->bit_rate);printf("Decoder Name:\t %s\n",pCodecCtx->codec->long_name);printf("Channels:\t %d\n",pCodecCtx->channels);printf("Sample per Second \t %d \n",pCodecCtx->sample_rate);in_channel_layout = av_get_default_channel_layout(pCodecCtx->channels);printf("in_channel_layout --->%d\n",in_channel_layout);au_convert_ctx = swr_alloc();au_convert_ctx= swr_alloc_set_opts(au_convert_ctx,out_channel_layout,out_sample_fmt,out_sample_rate,in_channel_layout,pCodecCtx->sample_fmt,pCodecCtx->sample_rate,0,NULL);swr_init(au_convert_ctx);while(av_read_frame(pFormatCtx,packet)>=0){if(packet->stream_index==audioStream){ret = avcodec_decode_audio4(pCodecCtx,pFrame,&got_picture,packet);if(ret < 0){printf("Error in decoding audio frame\n");return -1;}if(got_picture > 0){swr_convert(au_convert_ctx,&out_buffer,MAX_AUDIO_FRAME_SIZE,(const uint8_t **)pFrame->data,pFrame->nb_samples);printf("index:%5d\t pts:%12d\t packet size:%d\n",index,packet->pts,packet->size);#if USE_SDLif(wanted_spec.samples!=pFrame->nb_samples){//MP3、AAC不同的samples,重定位SDL_CloseAudio();out_nb_samples = pFrame->nb_samples;out_buffer_size=av_samples_get_buffer_size(NULL,out_channels,out_nb_samples,out_sample_fmt,1);wanted_spec.samples=out_nb_samples;SDL_OpenAudio(&wanted_spec,NULL);}#endif#if OUTPUT_PCMfwrite(out_buffer,1,out_buffer_size,pFile);#endifindex++;}#if USE_SDLaudio_chunk = (Uint8 *)out_buffer;audio_len = out_buffer_size;audio_pos =audio_chunk;/**SDL_PauseAudio(1);  // audio callback is stopped when this returns.SDL_Delay(5000);  // audio device plays silence for 5 secondsSDL_PauseAudio(0);  // audio callback starts running again.*/SDL_PauseAudio(0); //将解码并转换过的数据装在SDL中while(audio_len>0){SDL_Delay(1);//播放}#endif}av_free_packet(packet);}swr_free(&au_convert_ctx);#if USE_SDLSDL_CloseAudio();SDL_Quit();#endif#if OUTPUT_PCMfclose(pFile);#endifav_free(out_buffer);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0;}
雷神的这篇博客,从本地读取AAC文件avformat_open_input()   ------>

av_read_frame()(读一个packet)-------->

avcodec_decode_audio4()(解码)------------->

swr_convert()(转换S16)--------->

SDL_PauseAudio(0)(通过回调函数装在SDL中)------------>

SDL_Delay(1)(SDL播放)


代码很贴心,用了很多条件……


0 0
原创粉丝点击