SDL播放ffmpeg解码的AAC
2015-06-24 17:26
387 查看
转自雷神的博客:http://blog.csdn.net/leixiaohua1020/article/details/38979615
av_read_frame()(读一个packet)-------->
avcodec_decode_audio4()(解码)------------->
swr_convert()(转换S16)--------->
SDL_PauseAudio(0)(通过回调函数装在SDL中)------------>
SDL_Delay(1)(SDL播放)
代码很贴心,用了很多条件……
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "stdafx.h" #define __STDC_CONSTANT_MACROS #ifdef _WIN32 extern "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 1 static 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[]){ ***FormatContext *pFormatCtx; int i,audioStream; ***CodecContext *pCodecCtx; ***Codec *pCodec; ***Packet *packet; uint8_t *out_buffer; ***Frame *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==***MEDIA_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_PCM pFile = fopen("output.pcm","wb"); #endif packet = (***Packet*)av_malloc(sizeof(***Packet)); av_init_packet(packet); uint64_t out_channel_layout = ***_CH_LAYOUT_STEREO;//输出声道 int out_nb_samples=1024; ***SampleFormat out_sample_fmt = ***_SAMPLE_FMT_S16;//输出格式S16 int 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_SDL if(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"); } #endif printf("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_SDL if(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_PCM fwrite(out_buffer,1,out_buffer_size,pFile); #endif index++; } #if USE_SDL audio_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 seconds SDL_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_SDL SDL_CloseAudio(); SDL_Quit(); #endif #if OUTPUT_PCM fclose(pFile); #endif av_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播放)
代码很贴心,用了很多条件……
相关文章推荐
- 【JavaScript】程序入门(二)
- JS动态增加页面上的控件实例
- 超炫的 CSS3 页面切换动画效果
- js 的try catch应用
- iOS开发网络数据之AFNetworking使用
- Multiply Strings
- FusionCharts的使用方法
- 搞定:找不到该项目,请确认该项目的位置的办法
- cocos2dx-3.3 使用编辑框(EditBox)
- 安卓广播BroadcastReceiver
- oracle10g database vault 访问Realms相关的数据字典
- 软件测试之Web测试经典总结
- ajax读取properties资源文件数据的方法
- Cordova+ ios 插件开发
- 一些学习前端的网站(html&css&javascript等)持续更新。。。
- layout_weight 额外空间的分配
- PopupWindow中嵌套EditText不能粘贴的问题
- Error using fmincon (line 816), Hessian option set to 'on' but no Hessian function provided in optio
- SDL中的互斥量和条件变量
- poll和select的使用和差异