浪漫MTN7文件怎么3d转换播放器 什么播放器能看

最简单的基于FFMPEG+SDL的音频播放器
最简单的基于FFMPEG+SDL的音频播放器
一个广院工科生的视音频技术笔记
27275人阅读
我的开源项目(66)
FFMPEG(137)
版权声明:本文为博主原创文章,未经博主允许不得转载。
=====================================================最简单的基于FFmpeg的音频播放器系列文章列表:=====================================================简介FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手。在此我把自己做项目过程中实现的一个非常简单的音频播放器(大约200行代码)源代码传上来,以作备忘,同时方便新手学习FFMPEG。该播放器虽然简单,但是几乎包含了使用FFMPEG播放一个音频所有必备的API,并且使用SDL输出解码出来的音频。并且支持流媒体等多种音频输入。程序使用了新的FFMPEG类库,和早期版本的FFMPEG类库的API函数略有不同。平台使用VC2010。SourceForge项目主页注:本版本的SDL采用了SDL1.2,采用SDL2.0的播放器可以参考:注意:1.程序输出的解码后PCM音频数据可以使用Audition打开播放2.m4a,aac文件可以直接播放。mp3文件需要调整SDL音频帧大小为4608(默认是4096),否则播放会不流畅3.也可以播放视频中的音频源代码[cpp]
//&&//FFMPEG+SDL音频解码程序&&//雷霄骅&&//中国传媒大学/数字电视技术&&//&&//&&//&&#include&&stdlib.h&&&#include&&string.h&&&extern&"C"&&{&&#include&"libavcodec/avcodec.h"&&#include&"libavformat/avformat.h"&&//SDL&&#include&"sdl/SDL.h"&&#include&"sdl/SDL_thread.h"&&};&&#include&"decoder.h"&&//#include&"wave.h"&&&&//#define&_WAVE_&&&&//全局变量---------------------&&&&&&static&&Uint8&&*audio_&&&&&&&static&&Uint32&&audio_&&&&&&&static&&Uint8&&*audio_&&&//-----------------&&&&&&/*&&The&audio&function&callback&takes&the&following&parameters:&&&&&&stream:&A&pointer&to&the&audio&buffer&to&be&filled&&&&&&len:&The&length&(in&bytes)&of&the&audio&buffer&(这是固定的4096?)&&&&&回调函数&&&&&注意:mp3为什么播放不顺畅?&&&&&len=4096;audio_len=4608;两个相差512!为了这512,还得再调用一次回调函数。。。&&&&&m4a,aac就不存在此问题(都是4096)!&&&&&*/&&&&&&&void&&fill_audio(void&*udata,Uint8&*stream,int&len){&&&&&&&&&&&/*&&Only&&play&&if&&we&&have&&data&&left&&*/&&&&&&&if(audio_len==0)&&&&&&&&&&&&&&&return;&&&&&&&&&&&/*&&Mix&&as&&much&&data&&as&&possible&&*/&&&&&&&len=(len&audio_len?audio_len:len);&&&&&&&SDL_MixAudio(stream,audio_pos,len,SDL_MIX_MAXVOLUME);&&&&&&audio_pos&+=&&&&&&&&audio_len&-=&&&&&&&&}&&&//-----------------&&&&&&int&decode_audio(char*&no_use)&&{&&&&&&AVFormatContext&*pFormatC&&&&&&int&&&&&&&&&&&&&i,&audioS&&&&&&AVCodecContext&&*pCodecC&&&&&&AVCodec&&&&&&&&&*pC&&&&&&&&char&url[300]={0};&&&&&&strcpy(url,no_use);&&&&&&//Register&all&available&file&formats&and&codecs&&&&&&av_register_all();&&&&&&&&//支持网络流输入&&&&&&avformat_network_init();&&&&&&//初始化&&&&&&pFormatCtx&=&avformat_alloc_context();&&&&&&//有参数avdic&&&&&&//if(avformat_open_input(&pFormatCtx,url,NULL,&avdic)!=0){&&&&&&if(avformat_open_input(&pFormatCtx,url,NULL,NULL)!=0){&&&&&&&&&&printf("Couldn't&open&file.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&&&&&//&Retrieve&stream&information&&&&&&if(av_find_stream_info(pFormatCtx)&0)&&&&&&{&&&&&&&&&&printf("Couldn't&find&stream&information.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&//&Dump&valid&information&onto&standard&error&&&&&&av_dump_format(pFormatCtx,&0,&url,&false);&&&&&&&&//&Find&the&first&audio&stream&&&&&&audioStream=-1;&&&&&&for(i=0;&i&&&pFormatCtx-&nb_&i++)&&&&&&&&&&//原为codec_type==CODEC_TYPE_AUDIO&&&&&&&&&&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;&&&&&&}&&&&&&&&//&Get&a&pointer&to&the&codec&context&for&the&audio&stream&&&&&&pCodecCtx=pFormatCtx-&streams[audioStream]-&&&&&&&&&//&Find&the&decoder&for&the&audio&stream&&&&&&pCodec=avcodec_find_decoder(pCodecCtx-&codec_id);&&&&&&if(pCodec==NULL)&&&&&&{&&&&&&&&&&printf("Codec&not&found.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&//&Open&codec&&&&&&if(avcodec_open(pCodecCtx,&pCodec)&0)&&&&&&{&&&&&&&&&&printf("Could&not&open&codec.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&/*********&For&output&file&******************/&&&&&&FILE&*pF&&#ifdef&_WAVE_&&&&&&pFile=fopen("output.wav",&"wb");&&&&&&fseek(pFile,&44,&SEEK_SET);&//预留文件头的位置&&#else&&&&&&pFile=fopen("output.pcm",&"wb");&&#endif&&&&&&&&//&Open&the&time&stamp&file&&&&&&FILE&*pTSF&&&&&&pTSFile=fopen("audio_time_stamp.txt",&"wb");&&&&&&if(pTSFile==NULL)&&&&&&{&&&&&&&&&&printf("Could&not&open&output&file.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&fprintf(pTSFile,&"Time&Base:&%d/%d\n",&pCodecCtx-&time_base.num,&pCodecCtx-&time_base.den);&&&&&&&&/***&Write&audio&into&file&******/&&&&&&//把结构体改为指针&&&&&&AVPacket&*packet=(AVPacket&*)malloc(sizeof(AVPacket));&&&&&&av_init_packet(packet);&&&&&&&&//音频和视频解码更加统一!&&&&&&//新加&&&&&&AVFrame&*pF&&&&&&pFrame=avcodec_alloc_frame();&&&&&&&&//---------SDL--------------------------------------&&&&&&//初始化&&&&&&if(SDL_Init(SDL_INIT_VIDEO&|&SDL_INIT_AUDIO&|&SDL_INIT_TIMER))&{&&&&&&&&&&&&printf(&"Could&not&initialize&SDL&-&%s\n",&SDL_GetError());&&&&&&&&&&&exit(1);&&&&&&}&&&&&&&&//结构体,包含PCM数据的相关信息&&&&&&SDL_AudioSpec&wanted_&&&&&&wanted_spec.freq&=&pCodecCtx-&sample_&&&&&&&wanted_spec.format&=&AUDIO_S16SYS;&&&&&&&wanted_spec.channels&=&pCodecCtx-&&&&&&&&wanted_spec.silence&=&0;&&&&&&&wanted_spec.samples&=&1024;&//播放AAC,M4a,缓冲区的大小&&&&&&//wanted_spec.samples&=&1152;&//播放MP3,WMA时候用&&&&&&wanted_spec.callback&=&fill_&&&&&&&wanted_spec.userdata&=&pCodecC&&&&&&&&&if&(SDL_OpenAudio(&wanted_spec,&NULL)&0)//步骤(2)打开音频设备&&&&&&&{&&&&&&&&&&&printf("can't&open&audio.\n");&&&&&&&&&&&return&0;&&&&&&&}&&&&&&&//-----------------------------------------------------&&&&&&printf("比特率&%3d\n",&pFormatCtx-&bit_rate);&&&&&&printf("解码器名称&%s\n",&pCodecCtx-&codec-&long_name);&&&&&&printf("time_base&&%d&\n",&pCodecCtx-&time_base);&&&&&&printf("声道数&&%d&\n",&pCodecCtx-&channels);&&&&&&printf("sample&per&second&&%d&\n",&pCodecCtx-&sample_rate);&&&&&&//新版不再需要&&//&&short&decompressed_audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE&*&3)&/&2];&&//&&int&decompressed_audio_buf_&&&&&&uint32_t&ret,len&=&0;&&&&&&int&got_&&&&&&int&index&=&0;&&&&&&while(av_read_frame(pFormatCtx,&packet)&=0)&&&&&&{&&&&&&&&&&if(packet-&stream_index==audioStream)&&&&&&&&&&{&&&&&&&&&&&&&&//decompressed_audio_buf_size&=&(AVCODEC_MAX_AUDIO_FRAME_SIZE&*&3)&/&2;&&&&&&&&&&&&&&//原为avcodec_decode_audio2&&&&&&&&&&&&&&&&&&//ret&=&avcodec_decode_audio4(&pCodecCtx,&decompressed_audio_buf,&&&&&&&&&&&&&&&&&&//&decompressed_audio_buf_size,&packet.data,&packet.size&);&&&&&&&&&&&&&&//改为&&&&&&&&&&&&&&ret&=&avcodec_decode_audio4(&pCodecCtx,&pFrame,&&&&&&&&&&&&&&&&&&&got_picture,&packet);&&&&&&&&&&&&&&if&(&ret&&&0&)&//&if&error&len&=&-1&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&printf("Error&in&decoding&audio&frame.\n");&&&&&&&&&&&&&&&&&&exit(0);&&&&&&&&&&&&&&}&&&&&&&&&&&&&&if&(&got_picture&&&0&)&&&&&&&&&&&&&&{&&#if&1&&&&&&&&&&&&&&&&&&printf("index&%3d\n",&index);&&&&&&&&&&&&&&&&&&printf("pts&%5d\n",&packet-&pts);&&&&&&&&&&&&&&&&&&printf("dts&%5d\n",&packet-&dts);&&&&&&&&&&&&&&&&&&printf("packet_size&%5d\n",&packet-&size);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//printf("test&%s\n",&rtmp-&m_inChunkSize);&&#endif&&&&&&&&&&&&&&&&&&//直接写入&&&&&&&&&&&&&&&&&&//注意:数据是data【0】,长度是linesize【0】&&#if&1&&&&&&&&&&&&&&&&&&fwrite(pFrame-&data[0],&1,&pFrame-&linesize[0],&pFile);&&&&&&&&&&&&&&&&&&//fwrite(pFrame,&1,&got_picture,&pFile);&&&&&&&&&&&&&&&&&&//len+=got_&&&&&&&&&&&&&&&&&&index++;&&&&&&&&&&&&&&&&&&//fprintf(pTSFile,&"%4d,%5d,%8d\n",&index,&decompressed_audio_buf_size,&packet.pts);&&#endif&&&&&&&&&&&&&&}&&#if&1&&&&&&&&&&&&&&//---------------------------------------&&&&&&&&&&&&&&//printf("begin....\n");&&&&&&&&&&&&&&&//设置音频数据缓冲,PCM数据&&&&&&&&&&&&&&audio_chunk&=&(Uint8*)&pFrame-&data[0];&&&&&&&&&&&&&&&//设置音频数据长度&&&&&&&&&&&&&&audio_len&=&pFrame-&linesize[0];&&&&&&&&&&&&&&//audio_len&=&4096;&&&&&&&&&&&&&&//播放mp3的时候改为audio_len&=&4096&&&&&&&&&&&&&&//则会比较流畅,但是声音会变调!MP3一帧长度4608&&&&&&&&&&&&&&//使用一次回调函数(4096字节缓冲)播放不完,所以还要使用一次回调函数,导致播放缓慢。。。&&&&&&&&&&&&&&//设置初始播放位置&&&&&&&&&&&&&&audio_pos&=&audio_&&&&&&&&&&&&&&//回放音频数据&&&&&&&&&&&&&&&SDL_PauseAudio(0);&&&&&&&&&&&&&&//printf("don't&close,&audio&playing...\n");&&&&&&&&&&&&&&&while(audio_len&0)//等待直到音频数据播放完毕!&&&&&&&&&&&&&&&&&&&SDL_Delay(1);&&&&&&&&&&&&&&&//---------------------------------------&&#endif&&&&&&&&&&}&&&&&&&&&&//&Free&the&packet&that&was&allocated&by&av_read_frame&&&&&&&&&&//已改&&&&&&&&&&av_free_packet(packet);&&&&&&}&&&&&&//printf("The&length&of&PCM&data&is&%d&bytes.\n",&len);&&&&#ifdef&_WAVE_&&&&&&fseek(pFile,&0,&SEEK_SET);&&&&&&struct&WAVE_HEADER&&&&&&&&&memcpy(wh.header.RiffID,&"RIFF",&4);&&&&&&wh.header.RiffSize&=&36&+&&&&&&&memcpy(wh.header.RiffFormat,&"WAVE",&4);&&&&&&&&memcpy(wh.format.FmtID,&"fmt&",&4);&&&&&&wh.format.FmtSize&=&16;&&&&&&wh.format.wavFormat.FormatTag&=&1;&&&&&&wh.format.wavFormat.Channels&=&pCodecCtx-&&&&&&&wh.format.wavFormat.SamplesRate&=&pCodecCtx-&sample_&&&&&&wh.format.wavFormat.BitsPerSample&=&16;&&&&&&calformat(wh.format.wavFormat);&//Calculate&AvgBytesRate&and&BlockAlign&&&&&&&&memcpy(wh.data.DataID,&"data",&4);&&&&&&wh.data.DataSize&=&&&&&&&&&fwrite(&wh,&1,&sizeof(wh),&pFile);&&#endif&&&&&&SDL_CloseAudio();//关闭音频设备&&&&&&&//&Close&file&&&&&&fclose(pFile);&&&&&&//&Close&the&codec&&&&&&avcodec_close(pCodecCtx);&&&&&&//&Close&the&video&file&&&&&&av_close_input_file(pFormatCtx);&&&&&&&&return&0;&&}&&程序会打印每一帧的信息运行截图:完整工程下载地址:更新列表更新()===============================================simplest ffmpeg audio player完整工程(更新版)下载地址:新版本中使用了最新版本的FFMPEG类库()。FFMPEG在新版本中的音频解码方面发生了比较大的变化。如果将旧版的主程序和新版的类库组合使用的话,会出现听到的都是杂音这一现象。经过研究发现,新版中avcodec_decode_audio4()解码后输出的音频采样数据格式为AV_SAMPLE_FMT_FLTP(float, planar)而不再是AV_SAMPLE_FMT_S16(signed 16 bits)。因此无法直接使用SDL进行播放。最后的解决方法是使用SwrContext对音频采样数据进行转换之后,再进行输出播放,问题就可以得到解决了。转换方面的代码如下示例:[cpp]
//输出音频数据大小,一定小于输出内存。&&int&out_&&//输出内存大小&&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);&&&&&&&&......&&}&&更新()===============================================simplest ffmpeg audio player classic完整工程(classic)下载地址:本版本使用的类库编译时间为2012年的,无需经过swr_convert()即可播放,代码简洁。重建了工程,删掉了不必要的代码,把代码修改得更规范更易懂。可以通过宏控制是否使用SDL,以及是否输出PCM。[cpp]
//Output&PCM&&#define&OUTPUT_PCM&0&&//Use&SDL&&#define&USE_SDL&1&&在解码循环中添加了一小段代码,可以根据解码后AVFrame中的nb_samples调整SDL_AudioSpec中的samples的大小。这样不用改代码就可以正常播放AAC,MP3这些每帧采样数不同的音频流了。[cpp]
//FIX:FLAC,MP3,AAC&Different&number&of&samples&&&&&&&&&&&&&&&&&&if(wanted_spec.samples!=pFrame-&nb_samples){&&&&&&&&&&&&&&&&&&&&&&SDL_CloseAudio();&&&&&&&&&&&&&&&&&&&&&&wanted_spec.samples=pFrame-&nb_&&&&&&&&&&&&&&&&&&&&&&SDL_OpenAudio(&wanted_spec,&NULL);&&&&&&&&&&&&&&&&&&}&&贴上新代码:[cpp]
/**&&*&最简单的基于FFmpeg的音频播放器&&*&Simplest&FFmpeg&Audio&Player&&*&&*&雷霄骅&Lei&Xiaohua&&*&&&*&中国传媒大学/数字电视技术&&*&Communication&University&of&China&/&Digital&TV&Technology&&*&http://blog.csdn.net/leixiaohua1020&&*&&*&本程序实现了音频的解码和播放。&&*&&*&This&software&decode&and&play&audio&streams.&&*/&&#include&"stdafx.h"&&#include&&stdio.h&&&#include&&stdlib.h&&&#include&&string.h&&&extern&"C"&&{&&#include&"libavcodec/avcodec.h"&&#include&"libavformat/avformat.h"&&//SDL&&#include&"sdl/SDL.h"&&#include&"sdl/SDL_thread.h"&&};&&&&//Output&PCM&&#define&OUTPUT_PCM&0&&//Use&SDL&&#define&USE_SDL&1&&&&//Buffer:&&//|-----------|-------------|&&//chunk-------pos---len-----|&&static&&Uint8&&*audio_&&&static&&Uint32&&audio_&&&static&&Uint8&&*audio_&&&//-----------------&&/*&callback&function&that&is&called&when&the&audio&device&needs&more&data.&&*&takes&the&following&parameters:&&&*&stream:&A&pointer&to&the&audio&buffer&to&be&filled&&&*&len:&The&length&(in&bytes)&of&the&audio&buffer&(这是固定的4096?)&&*&回调函数&&*&注意:mp3为什么播放不顺畅?&&*&len=4096;audio_len=4608;两个相差512!为了这512,还得再调用一次回调函数。。。&&*&m4a,aac就不存在此问题(都是4096)!&&*&解决方法:设置SDL_AudioSpec中的samples参数&&*/&&&void&&fill_audio(void&*udata,Uint8&*stream,int&len){&&&&&&&/*&&Only&&play&&if&&we&&have&&data&&left&&*/&&&&&&&if(audio_len==0)&&&&&&&&&&&&&&&return;&&&&&&&&&&&/*&&Mix&&as&&much&&data&&as&&possible&&*/&&&&&&&len=(len&audio_len?audio_len:len);&&&&&&&SDL_MixAudio(stream,audio_pos,len,SDL_MIX_MAXVOLUME);&&&&&&audio_pos&+=&&&&&&&&audio_len&-=&&&&}&&&//-----------------&&&&&&int&_tmain(int&argc,&_TCHAR*&argv[])&&{&&&&&&AVFormatContext&*pFormatC&&&&&&int&&&&&&&&&&&&&i,&audioS&&&&&&AVCodecContext&&*pCodecC&&&&&&AVCodec&&&&&&&&&*pC&&&&&&&&char&filename[]="WavinFlag.aac";&&&&&&&&//Register&all&available&file&formats&and&codecs&&&&&&av_register_all();&&&&&&&&//支持网络流输入&&&&&&avformat_network_init();&&&&&&//初始化&&&&&&pFormatCtx&=&avformat_alloc_context();&&&&&&//Open&&&&&&if(avformat_open_input(&pFormatCtx,filename,NULL,NULL)!=0){&&&&&&&&&&printf("Couldn't&open&file.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&&&&&//&Retrieve&stream&information&&&&&&if(av_find_stream_info(pFormatCtx)&0){&&&&&&&&&&printf("Couldn't&find&stream&information.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&//&Dump&valid&information&onto&standard&error&&&&&&av_dump_format(pFormatCtx,&0,&filename,&false);&&&&&&&&//&Find&the&first&audio&stream&&&&&&audioStream=-1;&&&&&&for(i=0;&i&&&pFormatCtx-&nb_&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;&&&&&&}&&&&&&&&//&Get&a&pointer&to&the&codec&context&for&the&audio&stream&&&&&&pCodecCtx=pFormatCtx-&streams[audioStream]-&&&&&&&&&//&Find&the&decoder&for&the&audio&stream&&&&&&pCodec=avcodec_find_decoder(pCodecCtx-&codec_id);&&&&&&if(pCodec==NULL){&&&&&&&&&&printf("Codec&not&found.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&//&Open&codec&&&&&&if(avcodec_open(pCodecCtx,&pCodec)&0){&&&&&&&&&&printf("Could&not&open&codec.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&FILE&*pFile=NULL;&&#if&OUTPUT_PCM&&&&&&pFile=fopen("output.pcm",&"wb");&&#endif&&&&&&&&//把结构体改为指针&&&&&&AVPacket&*packet=(AVPacket&*)malloc(sizeof(AVPacket));&&&&&&av_init_packet(packet);&&&&&&&&AVFrame&*pF&&&&&&pFrame=avcodec_alloc_frame();&&&&//SDL--------------------------------------&&#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;&&&&&&}&&&&&&//结构体,包含PCM数据的相关信息&&&&&&SDL_AudioSpec&wanted_&&&&&&wanted_spec.freq&=&pCodecCtx-&sample_&&&&&&&wanted_spec.format&=&AUDIO_S16SYS;&&&&&&&wanted_spec.channels&=&pCodecCtx-&&&&&&&&wanted_spec.silence&=&0;&&&&&&&//wanted_spec.samples&=&1152;&//播放MP3时候用&&&&&&wanted_spec.samples&=&1024;&//播放AAC,M4A,缓冲区的大小&&&&&&wanted_spec.callback&=&fill_&&&&&&&wanted_spec.userdata&=&pCodecC&&&&&&&&&if&(SDL_OpenAudio(&wanted_spec,&NULL)&0){&&&&&&&&&&&printf("can't&open&audio.\n");&&&&&&&&&&&return&-1;&&&&&&}&&&#endif&&&&&&printf("Bitrate:&%3d\n",&pFormatCtx-&bit_rate);&&&&&&printf("Codec&Name:&%s\n",&pCodecCtx-&codec-&long_name);&&&&&&printf("Channels:&&%d&\n",&pCodecCtx-&channels);&&&&&&printf("Sample&per&Second&&%d&\n",&pCodecCtx-&sample_rate);&&&&&&&&uint32_t&ret,len&=&0;&&&&&&int&got_&&&&&&int&index&=&0;&&&&&&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");&&&&&&&&&&&&&&&&&&exit(0);&&&&&&&&&&&&&&}&&&&&&&&&&&&&&if&(&got_picture&&&0&){&&#if&1&&&&&&&&&&&&&&&&&&printf("index&%3d\t",&index);&&&&&&&&&&&&&&&&&&printf("dts&%5d\t",&packet-&dts);&&&&&&&&&&&&&&&&&&printf("packet_size&%5d\n",&packet-&size);&&#endif&&&&&&&&&&&&&&&&&&&&//FIX:FLAC,MP3,AAC&Different&number&of&samples&&&&&&&&&&&&&&&&&&if(wanted_spec.samples!=pFrame-&nb_samples){&&&&&&&&&&&&&&&&&&&&&&SDL_CloseAudio();&&&&&&&&&&&&&&&&&&&&&&wanted_spec.samples=pFrame-&nb_&&&&&&&&&&&&&&&&&&&&&&SDL_OpenAudio(&wanted_spec,&NULL);&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&index++;&&&&&&&&&&&&&&&&&&//直接写入&&&&&&&&&&&&&&&&&&//注意:数据是data【0】,长度是linesize【0】&&#if&OUTPUT_PCM&&&&&&&&&&&&&&&&&&fwrite(pFrame-&data[0],&1,&pFrame-&linesize[0],&pFile);&&#endif&&&&&&&&&&&&&&}&&//SDL----------------------------------------&&#if&USE_SDL&&&&&&&&&&&&&&//设置音频数据缓冲,PCM数据&&&&&&&&&&&&&&audio_chunk&=&(Uint8*)&pFrame-&data[0];&&&&&&&&&&&&&&&//设置音频数据长度&&&&&&&&&&&&&&audio_len&=&pFrame-&linesize[0];&&&&&&&&&&&&&&audio_pos&=&audio_&&&&&&&&&&&&&&//回放音频数据&&&&&&&&&&&&&&&SDL_PauseAudio(0);&&&&&&&&&&&&&&while(audio_len&0)//等待直到音频数据播放完毕!&&&&&&&&&&&&&&&&&&&SDL_Delay(1);&&&#endif&&&&&&&&&&}&&&&&&&&&&av_free_packet(packet);&&&&&&}&&&&&&&&//&Close&file&&#if&OUTPUT_PCM&&&&&&fclose(pFile);&&#endif&&#if&USE_SDL&&&&&&SDL_CloseAudio();//关闭音频设备&&&&&&&SDL_Quit();&&#endif&&&&&&//&Close&the&codec&&&&&&avcodec_close(pCodecCtx);&&&&&&//&Close&the&video&file&&&&&&av_close_input_file(pFormatCtx);&&&&&&&&return&0;&&}&&更新()===============================================simplest ffmpeg audio player 1.2完整工程下载地址:本版本使用新的类库(),解码后的音频需要经过swr_convert()转换后方可播放。重建了工程,删掉了不必要的代码,把代码修改得更规范更易懂。可以通过宏控制是否使用SDL,以及是否输出PCM。此外修改了部分地方,在原先版本的基础上,支持更多种的音频格式:AAC,MP3...贴上修改后源代码:[cpp]
/**&&*&最简单的基于FFmpeg的音频播放器&&1.2&&*&Simplest&FFmpeg&Audio&Player&&1.2&&*&&*&雷霄骅&Lei&Xiaohua&&*&&&*&中国传媒大学/数字电视技术&&*&Communication&University&of&China&/&Digital&TV&Technology&&*&http://blog.csdn.net/leixiaohua1020&&*&&*&本程序实现了音频的解码和播放。&&*&&*&This&software&decode&and&play&audio&streams.&&*/&&&&#include&"stdafx.h"&&#include&&stdlib.h&&&#include&&string.h&&&extern&"C"&&{&&#include&"libavcodec/avcodec.h"&&#include&"libavformat/avformat.h"&&#include&"libswresample/swresample.h"&&//SDL&&#include&"sdl/SDL.h"&&#include&"sdl/SDL_thread.h"&&};&&&&#define&MAX_AUDIO_FRAME_SIZE&192000&//&1&second&of&48khz&32bit&audio&&&&&&//Output&PCM&&#define&OUTPUT_PCM&1&&//Use&SDL&&#define&USE_SDL&1&&&&//Buffer:&&//|-----------|-------------|&&//chunk-------pos---len-----|&&static&&Uint8&&*audio_&&&static&&Uint32&&audio_&&&static&&Uint8&&*audio_&&&&&/*&The&audio&function&callback&takes&the&following&parameters:&&&*&stream:&A&pointer&to&the&audio&buffer&to&be&filled&&&*&len:&The&length&(in&bytes)&of&the&audio&buffer&&&*&回调函数&*/&&&void&&fill_audio(void&*udata,Uint8&*stream,int&len){&&&&&&&if(audio_len==0)&&&&&&&&/*&&Only&&play&&if&&we&&have&&data&&left&&*/&&&&&&&&&&&&&&&return;&&&&&&&len=(len&audio_len?audio_len:len);&&&/*&&Mix&&as&&much&&data&&as&&possible&&*/&&&&&&&&&SDL_MixAudio(stream,audio_pos,len,SDL_MIX_MAXVOLUME);&&&&&&audio_pos&+=&&&&&&&&audio_len&-=&&&&}&&&//-----------------&&&&&&int&_tmain(int&argc,&_TCHAR*&argv[])&&{&&&&&&AVFormatContext&*pFormatC&&&&&&int&&&&&&&&&&&&&i,&audioS&&&&&&AVCodecContext&&*pCodecC&&&&&&AVCodec&&&&&&&&&*pC&&&&&&&&//char&url[]="WavinFlag.aac";&&&&&&//char&url[]="72bian.mp3";&&&&&&//char&url[]="72bian.wma";&&&&&&&&av_register_all();&&&&&&avformat_network_init();&&&&&&pFormatCtx&=&avformat_alloc_context();&&&&&&//Open&&&&&&if(avformat_open_input(&pFormatCtx,url,NULL,NULL)!=0){&&&&&&&&&&printf("Couldn't&open&input&stream.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&//&Retrieve&stream&information&&&&&&if(av_find_stream_info(pFormatCtx)&0){&&&&&&&&&&printf("Couldn't&find&stream&information.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&//&Dump&valid&information&onto&standard&error&&&&&&av_dump_format(pFormatCtx,&0,&url,&false);&&&&&&&&//&Find&the&first&audio&stream&&&&&&audioStream=-1;&&&&&&for(i=0;&i&&&pFormatCtx-&nb_&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;&&&&&&}&&&&&&&&//&Get&a&pointer&to&the&codec&context&for&the&audio&stream&&&&&&pCodecCtx=pFormatCtx-&streams[audioStream]-&&&&&&&&&//&Find&the&decoder&for&the&audio&stream&&&&&&pCodec=avcodec_find_decoder(pCodecCtx-&codec_id);&&&&&&if(pCodec==NULL){&&&&&&&&&&printf("Codec&not&found.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&//&Open&codec&&&&&&if(avcodec_open2(pCodecCtx,&pCodec,NULL)&0){&&&&&&&&&&printf("Could&not&open&codec.\n");&&&&&&&&&&return&-1;&&&&&&}&&&&&&&&FILE&*pFile=NULL;&&#if&OUTPUT_PCM&&&&&&pFile=fopen("output.pcm",&"wb");&&#endif&&&&&&&&AVPacket&*packet=(AVPacket&*)malloc(sizeof(AVPacket));&&&&&&av_init_packet(packet);&&&&&&&&//Out&Audio&Param&&&&&&uint64_t&out_channel_layout=AV_CH_LAYOUT_STEREO;&&&&&&int&out_nb_samples=1024;&&&&&&AVSampleFormat&out_sample_fmt=AV_SAMPLE_FMT_S16;&&&&&&int&out_sample_rate=44100;&&&&&&int&out_channels=av_get_channel_layout_nb_channels(out_channel_layout);&&&&&&//Out&Buffer&Size&&&&&&int&out_buffer_size=av_samples_get_buffer_size(NULL,out_channels&,out_nb_samples,out_sample_fmt,&1);&&&&&&&&uint8_t&*out_buffer=(uint8_t&*)av_malloc(MAX_AUDIO_FRAME_SIZE*2);&&&&&&&&AVFrame&*pF&&&&&&pFrame=avcodec_alloc_frame();&&//SDL------------------&&#if&USE_SDL&&&&&&//Init&&&&&&if(SDL_Init(SDL_INIT_VIDEO&|&SDL_INIT_AUDIO&|&SDL_INIT_TIMER))&{&&&&&&&&&&&&printf(&"Could&not&initialize&SDL&-&%s\n",&SDL_GetError());&&&&&&&&&&&return&-1;&&&&&&}&&&&&&//SDL_AudioSpec&&&&&&SDL_AudioSpec&wanted_&&&&&&wanted_spec.freq&=&out_sample_&&&&&&&wanted_spec.format&=&AUDIO_S16SYS;&&&&&&&wanted_spec.channels&=&out_&&&&&&&wanted_spec.silence&=&0;&&&&&&&wanted_spec.samples&=&out_nb_&&&&&&&wanted_spec.callback&=&fill_&&&&&&&wanted_spec.userdata&=&pCodecC&&&&&&&&&if&(SDL_OpenAudio(&wanted_spec,&NULL)&0){&&&&&&&&&&&printf("can't&open&audio.\n");&&&&&&&&&&&return&-1;&&&&&&&}&&&#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);&&&&&&&&uint32_t&ret,len&=&0;&&&&&&int&got_&&&&&&int&index&=&0;&&&&&&//FIX:Some&Codec's&Context&Information&is&missing&&&&&&int64_t&in_channel_layout=av_get_default_channel_layout(pCodecCtx-&channels);&&&&&&//Swr&&&&&&struct&SwrContext&*au_convert_&&&&&&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);&&#if&1&&&&&&&&&&&&&&&&&&printf("index:%5d\t&pts:%10d\t&packet&size:%d\n",index,packet-&pts,packet-&size);&&#endif&&&&&&&&&&&&&&&&&&//FIX:FLAC,MP3,AAC&Different&number&of&samples&&&&&&&&&&&&&&&&&&if(wanted_spec.samples!=pFrame-&nb_samples){&&&&&&&&&&&&&&&&&&&&&&SDL_CloseAudio();&&&&&&&&&&&&&&&&&&&&&&out_nb_samples=pFrame-&nb_&&&&&&&&&&&&&&&&&&&&&&out_buffer_size=av_samples_get_buffer_size(NULL,out_channels&,out_nb_samples,out_sample_fmt,&1);&&&&&&&&&&&&&&&&&&&&&&wanted_spec.samples=out_nb_&&&&&&&&&&&&&&&&&&&&&&SDL_OpenAudio(&wanted_spec,&NULL);&&&&&&&&&&&&&&&&&&}&&&&#if&OUTPUT_PCM&&&&&&&&&&&&&&&&&&//Write&PCM&&&&&&&&&&&&&&&&&&fwrite(out_buffer,&1,&out_buffer_size,&pFile);&&#endif&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&index++;&&&&&&&&&&&&&&}&&//SDL------------------&&#if&USE_SDL&&&&&&&&&&&&&&//Set&audio&buffer&(PCM&data)&&&&&&&&&&&&&&audio_chunk&=&(Uint8&*)&out_&&&&&&&&&&&&&&&//Audio&buffer&length&&&&&&&&&&&&&&audio_len&=out_buffer_&&&&&&&&&&&&&&&&audio_pos&=&audio_&&&&&&&&&&&&&&//Play&&&&&&&&&&&&&&SDL_PauseAudio(0);&&&&&&&&&&&&&&while(audio_len&0)//Wait&until&finish&&&&&&&&&&&&&&&&&&SDL_Delay(1);&&&#endif&&&&&&&&&&}&&&&&&&&&&av_free_packet(packet);&&&&&&}&&&&&&&&swr_free(&au_convert_ctx);&&&&#if&USE_SDL&&&&&&SDL_CloseAudio();//Close&SDL&&&&&&SDL_Quit();&&#endif&&&&&&//&Close&file&&#if&OUTPUT_PCM&&&&&&fclose(pFile);&&#endif&&&&&&av_free(out_buffer);&&&&&&//&Close&the&codec&&&&&&avcodec_close(pCodecCtx);&&&&&&//&Close&the&video&file&&&&&&av_close_input_file(pFormatCtx);&&&&&&&&return&0;&&}&&=============================================================FFMPEG相关学习资料:SDL GUIDE 中文译本ffdoc (FFMPEG的最完整教程)如何用FFmpeg编写一个简单播放器
上一篇下一篇
我的同类文章
我的开源项目(66)
FFMPEG(137)
·阅读798·阅读971·阅读1322·阅读1327·阅读3297
·阅读1058·阅读837·阅读994·阅读1241·阅读1096
你好,我在Linux用你最新版本《最简单的基于FFMPEG+SDL的音频播放器》中的代码,但是播放的音乐噪音很大,根本就听不到原声。请问这是怎么回事?45楼
感谢雷大大分享的资料,心里有种说不出来的激动。在经受折磨好多天,当看到雷大的例子编译通过,成功运行的那一刻,血都沸腾了。非常感谢。Re:
回复yzq:谢兄弟支持,互相学习!44楼
雷老师,你好,我用了swr_convert还是有杂音.播放用的是opensl es. 用没有Android这方面的音视频的demo工程发一份参考下.先谢了,经常看你的帖子Re:
回复yangchaoxun:Android这方面的还没有啊43楼
你好,我用你这个例子在linux下移植了一下,发现播放的声音一直卡卡的,而dump下来的数据播放又是正常的,一直没有查出原因来,还有个情况就是假如我播放了10s,但是dump下来的数据只有3s-4s。感觉是这个数据被一段一段的塞到了到sdl里面播放。谢谢!Re:
回复bluesky:这个音频播放器只是个简单的示例程序,其中有不少可以改进的地方,推荐有时间看下ffplay~42楼
雷老师你好,在使用simplest_ffmpeg_player2_su(加入了线程控制的)这个例子,发现视频播放变慢了,而使用simplest_ffmpeg_player2并不会出现这样的情况。当然,可以改变延迟的值来控制快慢,但是两个例子都把延迟设置为40ms,为什么会出现一个比较正常,一个比较慢的情况呢?Re:
回复weiwei9363:这个地方可能是我做Demo的时候大意了。解码出来的AVPacket不一定是视频,也有可能是音频(我之前一直用纯视频流做测试,所以没有发现这个地方)。而我在这里没有对音频帧做处理而是直接进行下一个WaitEvent(),所以导致视频变缓慢。我有时间修正一下这个地方。41楼
雷老师你好,在使用simplest_ffmpeg_player2_su(加入了线程控制的)这个例子,发现视频播放变慢了,而使用simplest_ffmpeg_player2并不会出现这样的情况。当然,可以改变延迟的值来控制快慢,但是两个例子都把延迟设置为40ms,为什么会出现一个比较正常,一个比较慢的情况呢?40楼
雷老师,使用了simplest_ffmpeg_player2_su(加入了线程的)这个例子,然后视频播放变慢了。而simplest_ffmpeg_player2并不会出现这样的情况,为什么会发生这种情况呢?当然,我可以修改延迟的时间来控制,但是两个例子设置的延迟都是40ms。39楼
雷神你好,很早之前就来咨询了关于ffmpeg的问题,我现在是把ffmpeg框架移植到IOS平台上。然而新版本加入了AV_SAMPLE_FMT_FLTP,需要使用swr_alloc_set_opts方法重新分配。但是目前不是很清楚这一步骤是在哪里执行。而且关于AAC格式的如何播放呢,貌似不能解析成PCM格式Re:
回复Stone_Zl:libswresample就是在你解码获得PCM之后才调用的。具体地说avcodec_decode_audio4()之后。AAC解码之后就是PCM,你再研究研究38楼
while&((mp3_bytes&=&fread(mp3_buf,&1,&210,&MP3File))&&&0)&&{&&&&&&samples&=&hip_decode_headers(hip,&mp3_buf,&210,&pcm_l,&pcm_r,&&mp3Header);&&&&&&if&(samples&&&0)&&&&&&{&&&&&&&&&&short&*tt&=&new&short[samples*sizeof(short)];&&&&&&&&&&memcpy((void*)tt,&(const&void*)pcm_l,&samples*sizeof(short));&&&&&&&&&&mp3Buffer.push_back(tt);&&&&&&&&&&write_bytes&+=&samples*sizeof(short);&&&&&&&&&&mp3BufferSize.push_back(samples*sizeof(short));&&&&&&}&&}&&37楼
请问大虾,播音有了,录音的有么?Re:
回复kingxwf:录音得查找libavdevice相关的技术36楼
雷老师您好,有没有Linux版本。为什么很多函数都无法被识别,该有的库文件都有啊。Re:
回复FengMang37Du:我也遇到这个问题,undefined reference to `swr_alloc()'undefined reference to `swr_init(SwrContext*)'undefined reference to `swr_convert(SwrContext*, unsigned char**, int, unsigned char const**, int)'该有的库也有,请教一下,怎么解决的?谢谢Re:
你好,我用你这个例子在linux下移植了一下,发现播放的声音一直卡卡的,而dump下来的数据播放又是正常的,一直没有查出原因来,还有个情况就是假如我播放了10s,但是dump下来的数据只有3s-4s。感觉是这个数据被一段一段的塞到了到sdl里面播放。谢谢!Re:
回复ha:可能是现在API的名称改变了?我有时间看下35楼
雷老师,您好!请问一下如果在您的程序基础上实现让音频快速或慢速播放,应该怎么做呢?Re:
回复nihaoohao:这个需要处理PCM数据吧~34楼
有个问题想请教博主我用博文里的程序播放channels = 2的音频流是正常的但是播放channels = 6的音频流直接返回了百度了一番似乎是SDL1.2不支持channels=6的?
除了换SDL还有别的解决办法吗Re:
回复fslcz:是除了换SDL2
还有别的解决办法吗
手残少打了个2Re:
回复fslcz:肯定有了。SDL2只是封装了底层的API,你要是直接用底层API比如XAudio2这些的话应该没问题的。可能代码会繁琐一些。33楼
我本地解码音频没什么问题。。但是解码网络流的。时候。。解码失败。。。肿么破。Re:
回复u:你看看FFmpeg的log输出的是什么错误32楼
我传了一个mp3进去,一直打印pack_size为0....是为啥?我下了最后一个连接的代码,把url[] == 1.mp3Re:
回复wuselll_123:这个地方有一个小错误:pts是int64_t类型的,不能用%d输出,而应该用%I64d。这么一改,后面的packet_size也就正常了。31楼
您好。使用FFmpeg Android移植音频播放遇到了问题。就是按照您所说的使用swr_convert进行重采样,然后使用android AudioTrack播放时,主唱的声音没有了。其他背景音乐都在,也很流程。au_convert_ctx = swr_alloc();
au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, 24000,
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);
}原视频解码出的格式是AV_SAMPLE_FMT_S16P,采样率是24000,然后我重采样为AV_SAMPLE_FMT_S16,采样率不变,也是24000。 Android AudioTrack播放设置是audioParam.mFrequency = 24000;
audioParam.mChannel = AudioFormat.CHANNEL_OUT_STEREO;
audioParam.mSampBit = AudioFormat.ENCODING_PCM_16BIT;可是视频中提取的音频播放没有主唱,(就是一个男人哼哈,哼哈)只有背景音乐。请问是不是什么设置错了?看到网上有说AV_SAMPLE_FMT_S16P的音频应该把解码后的Frame-》data[0]和data[1]分别保存进去。可是data[1]的size为0 。Re:
回复ai454121:如果没有主唱的话,很有可能是主唱的音频存在一个特定的声道里,而该声道没有提取出来。检查一下设置吧Re:
//恩,已经解决了,在获取audioStream的时候没有使用break、所以获取的stream不正确&&for(i=0;&i&&&pFormatCtx-&nb_&i++)&&&&&&&&&&&&if(pFormatCtx-&streams[i]-&codec-&codec_type==AVMEDIA_TYPE_AUDIO){&&&&&&&&&&&&&&&&audioStream=i;&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&}&&&}&&30楼
博主您好,我调用您的程序,编译通过并成功播放了声音,但我有几个问题想请教您:1、我该怎么去选择通道,我用MP4格式的视频,可以播放声音,输出现实的通道数为2,但换成MKV格式后,有大量杂音,隐约可以听见视频原有的声音,声道数显示为6,。2、需要创建队列吗?我在网上找了好多资料,发现都有队列,但那都是至少两年前的资料了,不知道现在需不需要。本人只是初学者,问题可能很粗浅,请不要介意,不胜感激。Re:
回复ztktct:1,这种情况不太了解,SDL_AudioSpec中可以设置声道。2,最好还是用队列,这个只是个简单的demo~Re:
回复leixiaohua1020:雷大神,感谢您的解答,我参考您的建议,试着用队列来播放音频,因为参考资料少,资料上面还是用avcodec_decode_audio2()来解码的,但我想用新版的avcodec_decode_audio4()来解码,自己试着改了下,结果不正确,您能编一份用队列来播放音频的程序吗,或者给我几个建议,非常感谢。29楼
你好,请问FFMPEG怎样实现边播放在线视频边缓冲的功能?类似于土豆网那样的边观看边缓冲。这个问题困扰了我好久,请大神可以给点思路。Re:
回复changyou0730:这个可能需要自己编程实现这个“缓冲”的缓存吧~28楼
我想问下您这问题是怎么解决的吗?我这播放WAV文件的时候返回值也是-22.Re:
回复u:嗯,这是由于播放某些格式的时候一些参数FFmpeg没有初始化导致的,随后会更新修复这个问题~27楼
博主,为什么您这工程播放不了WMA文件,而且播放MP3文件的时候有点噪音,请问怎么解决啊?26楼
if&(inBuffer_)&return&decodedDataSize_;&&&&&&AVFrame&*frame&=&avcodec_alloc_frame();&&&&&&decodedDataSize_&=&0;&&&&&&AVPacket&*packet&=&[self&readPacket];&&&&&&&&&&&&while&(packet&&&&packet-&size&&&0)&{&&&&&&&&decodedDataSize_&=&audioBufferSize_;&&&&&&&&NSInteger&len&=&avcodec_decode_audio4(audioCodecContext_,&frame,&&decodedDataSize_,&packet);&&&&&&&&&&if&(len&&&0)&{&&&&&&&&&&NSLog(@"Could&not&decode&audio&packet.");&&&&&&&&&&return&0;&&&&&&&&}&&&&&&&&&&&&&&&&&&if&(decodedDataSize_&&=&0)&{&&&&&&&&&&NSLog(@"Decoding&was&completed.");&&&&&&&&&&packet&=&NULL;&&&&&&&&&&return&0;&&&&&&&&}&&&&&&&&&&packet-&size&-=&&&&&&&&&&&packet-&data&+=&&&&&&&&&&&&&&&&&&&&//int&data_size&=&av_samples_get_buffer_size(NULL,&audioCodecContext_-&channels,&frame-&nb_samples,&audioCodecContext_-&sample_fmt,&1);&&&&&&&&&&decodedDataSize_&=&frame-&linesize[0];&&&&&&&&&&audioBuffer_&=&frame-&extended_data[0];&&&&&&&&&&&&&&&&&&&&inBuffer_&=&YES;&&&&&&&&&&break;&&&&&&}&&&&&&return&decodedDataSize_;&&解码代码但是mp3格式会播放有杂音Re:
回复Stone_Zl:解码后的PCM保存成文件播放有没有杂音?25楼
您好,你这个音频转换的代码是放在哪的。我使用ffmpeg转换pcm格式会有杂音。。。Re:
回复Stone_Zl:这个没有转换吧,只是播放。你说的是swr_convert()?Re:
NSInteger&len&=&avcodec_decode_audio4(audioCodecContext_,&frame,&&decodedDataSize_,&packet);if&(len&&&0)&{NSLog(@"Could&not&decode&audio&packet.");&return&0;&}if&(decodedDataSize_&&=&0)&{&NSLog(@"Decoding&was&completed.");packet&=&NULL;return&0;}&packet-&size&-=&&packet-&data&+=&if&(audioCodecContext_-&sample_fmt&==&AV_SAMPLE_FMT_S16P){&int&data_size&=&av_samples_get_buffer_size(NULL,&audioCodecContext_-&channels,&frame-&nb_samples,&audioCodecContext_-&sample_fmt,&1);charchar&*data&=&(charchar&*)av_malloc(data_size);shortshort&*sample_buffer&=&(shortshort&*)frame-&data[0];for&(int&i&=&0;&i&&&data_size/2;&i++){data[i*2]&=&(char)(sample_buffer[i/2]&&&0xFF);data[i*2+1]&=&(char)((sample_buffer[i/2]&&&8)&&&0xFF);&}audioBuffer_&=&(uint8_t&*)&decodedDataSize_&=&data_&av_free(data);}else{decodedDataSize_&=&frame-&linesize[0];&audioBuffer_&=&frame-&extended_data[0];}}&&您好,这是我解码的代码。不过之前也尝试过您说的SwrContext方法,我编译的ffmpeg版本是2.1。我这样写的话flac/mp3都能播放而且没有杂音,但是AAC跟M4A格式就完全不能播放,24楼
播放没有音乐那是因为没有创建一个screen,就算是只播放音乐,也要创建一个screen,另外,其实也不用专门设置wanted_spec.samples的大小,统一为1024即可,我这边测试播放mp3,wma,aac都没问题,效果也很好Re:
回复chenhao0316:哈哈,谢谢兄弟指点,以后不断改进~23楼
大神,请问您知不知道ffmpeg有没有设置UDP_MAX_PKT_SIZE这个宏的接口呢,我用ffmpeg播放rtsp地址的时候花屏,但是网上说设置这个参数就行,虽然设置完重新编译一下库就行了,但是想问下有没有这个接口呢,或者说有另外的解决办法?.Re:
回复wangjian8006:具体这个宏我不太清楚,但是你要是说需要设置参数的话,使用AVDictionary应该是可以的吧~22楼
亲,你的代码工程下载后运行可以解码播放,但是针对其他音频格式MP3有杂音,ape播放不了、mp2有杂音、ogg播放不了、FLAC播放不了、wma播放不了,怎么解决?加你QQ了。Re:
回复jtjt6868:博主理你了没有?呵呵Re:
回复qiany3wa:最上面那位仁兄的留言CSDN的“通知”竟然没有提醒我,没看见,估计是漏掉了吧~只调过AAC的,最近时间比较紧也没有继续弄,其他格式都没有测。有什么修改建议的话联系我下啊,继续完善完善~Re:
回复leixiaohua1020:博主客气了。我把这个代码在ubuntu上编译了一下,是可以用。有个问题:声音听起来有杂质。和ffplay播放的效果对比挺明显。我用的ffmpeg版本是2.2.3.SDL的版本是1.2.15.然后我把这个代码拆 成了两部分:解码存为pcm文件;然后用SDL打开这个文件直接播放。却是流畅的,声音没有什么问题。Re:
回复qiany3wa:哦,你是今天加我QQ的那位?看来应该是SDL播放的问题了21楼
代码略做修改就可以在ubuntu正常运行,但是有个疑惑au_convert_ctx = swr_alloc(); 这个申请的内存需要用swr_free()释放吗?Re:
回复dragonpic:这个我确实没有注意到,你看看有没有内存泄露?20楼
引用“ricky_pc_10”的评论:请问:为什么av_samples_get_buffer_size的结果是个固定值:-22呢?我试了几...哦,刚看了源码,原来是参数nb_samples值错误,传了0进去了。Re:
回复ricky_pc_10:我想问下您这问题是怎么解决的吗?我这播放WAV文件的时候返回值也是-22.Re:
回复ricky_pc_10:哦,刚看见~19楼
请问:为什么av_samples_get_buffer_size的结果是个固定值:-22呢?我试了几个文件,都是这样。下面是我GDB的相关参数传入的值。我是在Linux下编译运行的,而且我将SDL相关内容屏蔽了,直接输出到PCM文件了。Breakpoint 2, decode_audio (no_use=0x7fffffffeb74 "/opt/16K_adpcm.wav") at simplest_ffmpeg_audio_player.cpp:139139
int out_buffer_size=av_samples_get_buffer_size(&out_linesize, pCodecCtx-&channels,pCodecCtx-&frame_size,pCodecCtx-&sample_fmt, 1);(gdb) p out_linesize $1 = 32767(gdb) p pCodecCtx $2 = (AVCodecContext *) 0x602b60(gdb) p pCodecCtx-&channels $3 = 1(gdb) p pCodecCtx-&frame_size $4 = 0(gdb) p pCodecCtx-&sample_fmt $5 = AV_SAMPLE_FMT_S16P(gdb) n140
printf("#################out_buffer_size[%d]\n", out_buffer_size);(gdb) p out_linesize $6 = 32767(gdb) p out_buffer_size $7 = -2218楼
没有错误,但是运行的时候没有声音,输出都有信息,就是没有声音呢?Re:
回复asas:应该是SDL的问题,可以尝试换个版本,或者换个硬件驱动之类的Re:
回复leixiaohua1020:我在win7 64bit下用vc2013编译没出错,播放也有输出但就是没声音,后来在SDL_Init ()执行后,加入SDL_Surface *screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);弹出个sdl窗口就有声音了,不知道sdl内部有啥问题,这个比较奇怪Re:
回复tatu2000:嗯,确实。不过之前听别人说有种解决方法:把SDL_Init()中的SDL_INIT_VIDEO去掉,你试试行不17楼
楼主怎么把视频和音频都能实现呢,我看你都分开了Re:
回复u:都实现的话,可以参考ffplay源代码,是一个完整的播放器16楼
引用“kflxuan”的评论:这个问题已经解决,原因是新版FFMPEG解码AAC得到的sample_fmt为AV_SAMPLE_F...请问你是从哪看出来的?Re:
回复jiqiujia:单步调试,看AVCodecContext
*pCodecCtx结构体的成员15楼
这个问题已经解决,原因是新版FFMPEG解码AAC得到的sample_fmt为AV_SAMPLE_FMT_FLTP,需要转为AV_SAMPLE_FMT_S16才能播放,MP3同理。谢谢楼主在论坛及QQ上的耐心解答!Re:
回复kflxuan:你好,我按照你的方法,找了很多资料。最终发现需要 av_opt_set_channel_layout和av_opt_set_int等函数。可是这2个函数在swresample.h里面并未实现,但是在swresample.c里面有,那么是不是需要我将这2个函数从swresample.c里面移植出来啊?????Re:
回复oldmtn:不需要,av_opt_set_int()在opt.h中也有声明,重采样可以参考下/mingyuejingque/item/4c4b39a3a28dafa928ce9d66Re:
回复kflxuan:哈哈,谢谢留言补充,目前貌似有不少人有这个问题,也给大家一个参考~Re:
回复leixiaohua1020:MFC中使用SDL播放16位的PCM数据时,发现没有声音,不知道楼主找到原因没Re:
回复kflxuan:嗯,看到你在另一篇文章里的留言了,原理不明。。14楼
VS2010+ffmpeg--git-f118b41-win32-dev解码AAC音乐发现杂音很大,但若用楼主工程的ffmpeg发现能正常解码播放,跟踪发现使用两个版本的ffmpeg解码出来的数据都不一样,请问这是什么原因Re:
回复kflxuan:嗯,这个问题已经出现过好几次了。新版的ffmpeg的aac解码出现了更改。解码音频输出的格式需要转换一下才能得到可以播放的数据13楼
您好,我用您写的音频播放器的源码编译,但是使用的是SDL2的库,结果debug出来的声音全是重复的爆破音,完全听不到音乐,请问是SDL2库的问题吗?谢谢(使用的是vs2008,音乐用的是您工程中的acc音乐)PS:源码基本上没有改变,唯一的改变是将avcodec_open改为avcodec_open2,这个问题困扰我好久,谢谢!!!!Re:
回复cxm:这个不确定。有可能是SDL2的接口函数发生了变化,但是我没有用过SDL2。可以先把解码出来的PCM数据输出到文件看看播放有没有杂音Re:
回复leixiaohua1020:您好,我用您资源中的ffmpeg库试了一下,刚开始一两秒有音乐,后来就出现了噪音,噪音越来越大,打后面音乐几乎听不见了?感觉还是有问题!Re:
回复cxm:这方面没有深入研究过。。12楼
我用你上面的代码,来解码AAC文件,播放出来全是嗓音呢,怎么回事啊Re:
回复liZZZAAA:你用的是我的程序还是上面的一段代码?程序的话应该没有问题啊11楼
楼主,为什么解码不了AAC呢,可以指导一下吗.qqRe:
回复liZZZAAA:原本的工程,直接运行应该是可以的啊10楼
多谢分享。写的很好,受益了。Re:
回复jltxgcy:谢谢支持~9楼
楼主这个播放器不能播放声音啊!解码是没问题的!求解Re:
回复hl:应该是能播放的啊,在好几个环境下都试过了啊~Re:
回复leixiaohua1020:好的,谢谢!我再看一下!8楼
楼主您好,我刚接触ffmpeg。请问您这个程序的每一次while(av_read_frame(pFormatCtx, packet)&=0)循环里是不是都解码得到一个frame的数据,这个返回的packet是不是有可能包含多个frame啊?Re:
回复caohongfei881:嗯,对~视频的话一般是一帧画面,音频帧可能有好几帧Re:
回复leixiaohua1020:那这样的话,while循环如果只解码了一帧,那packet中是不是还有帧没有被解码呢?Re:
回复caohongfei881:那不是,解码的时候,AVPacket里面有几帧就解几帧,把里面的都解码完~7楼
我想知道可否不要存到文件中,直接使用解码出来的frame?Re:
回复love4Mario:可以啊,解码出来的数据,是原始的PCM采样数据,看您怎么用它了Re:
回复leixiaohua1020:直接用设备放出来啊。可以吗Re:
回复love4Mario:可以啊~这个播放器本身就是通过SDL把音频播放出来的Re:
回复leixiaohua1020:楼主可否写一个不要写入文件的,直接用sdl播放的代码示例呢?谢谢了!Re:
回复love4Mario:你把代码中的fwrite()去掉,可以不写入文件了~6楼
您用的是哪个版本的呢?谢谢Re:
回复u:2012年的,具体版本记不得了~5楼
请问有没有音频重采样的例子啊?Re:
回复u:这个没试过啊4楼
请问,能否测试一下sdl2?我试了一下,好像不行,初学者,不太会弄,谢谢Re:
回复hellthanatos:嗯,有机会的话我试试,应该是可以的~3楼
我搞错了,你这个是window的,不好意思2楼
那如果用alsa可以吗?1楼
请问,我能不能完全不用SDL来做一个简单的音频播放器?谢谢
发表评论用 户 名:wangwangzq126评论内容:
发表评论:
TA的最新馆藏

我要回帖

更多关于 播放器格式转换 的文章

 

随机推荐