=====================================================

最简单的基于FFmpeg的音频播放器系列文章列表:

《最简单的基于FFMPEG+SDL的音频播放器》

《最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)》

《最简单的基于FFMPEG+SDL的音频播放器:拆分-解码器和播放器》

=====================================================

本文补充记录《最简单的基于FFMPEG+SDL的音频播放器》中的两个例子:FFmpeg音频解码器和SDL音频采样数据播放器。这两个部分是从音频播放器中拆分出来的两个例子。FFmpeg音频解码器实现了视频数据到PCM采样数据的解码,而SDL音频采样数据播放器实现了PCM数据到音频设备的播放。简而言之,原先的FFmpeg+SDL音频播放器实现了:

音频数据->PCM->音频设备

FFmpeg音频解码器实现了:

音频数据->PCM

SDL音频采样数据播放器实现了:

PCM->音频设备

FFmpeg音频解码器

源代码

/** * 最简单的基于FFmpeg的音频解码器 * Simplest FFmpeg Audio Decoder * * 雷霄骅 Lei Xiaohua * leixiaohua1020@126.com * 中国传媒大学/数字电视技术 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程序可以将音频码流(mp3,AAC等)解码为PCM采样数据。 * 是最简单的FFmpeg音频解码方面的教程。 * 通过学习本例子可以了解FFmpeg的解码流程。 * * This software decode audio streams (AAC,MP3 ...) to PCM data. * Suitable for beginner of FFmpeg. * */#include <stdio.h>#include <stdlib.h>#include <string.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32//Windowsextern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libswresample/swresample.h"};#else//Linux...#ifdef __cplusplusextern "C"{#endif#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include <libswresample/swresample.h>#ifdef __cplusplus};#endif#endif#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audioint main(int argc, char* argv[]){ AVFormatContext *pFormatCtx; int    i, audioStream; AVCodecContext *pCodecCtx; AVCodec   *pCodec; AVPacket  *packet; uint8_t   *out_buffer; AVFrame   *pFrame;    int ret; uint32_t len = 0; int got_picture; int index = 0; int64_t in_channel_layout; struct SwrContext *au_convert_ctx; FILE *pFile=fopen("output.pcm", "wb"); char url[]="skycity1.mp3"; 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(avformat_find_stream_info(pFormatCtx,NULL)<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_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; } // Get a pointer to the codec context for the audio stream pCodecCtx=pFormatCtx->streams[audioStream]->codec; // 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; } packet=(AVPacket *)av_malloc(sizeof(AVPacket)); av_init_packet(packet); //Out Audio Param uint64_t out_channel_layout=AV_CH_LAYOUT_STEREO; //nb_samples: AAC-1024 MP3-1152 int out_nb_samples=pCodecCtx->frame_size; 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); out_buffer=(uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE*2); pFrame=av_frame_alloc(); //FIX:Some Codec's Context Information is missing in_channel_layout=av_get_default_channel_layout(pCodecCtx->channels); //Swr 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:%lld\t packet size:%d\n",index,packet->pts,packet->size);    //Write PCM    fwrite(out_buffer, 1, out_buffer_size, pFile);    index++;   }  }  av_free_packet(packet); } swr_free(&au_convert_ctx); fclose(pFile); av_free(out_buffer); // Close the codec avcodec_close(pCodecCtx); // Close the video file avformat_close_input(&pFormatCtx); return 0;}

运行结果

程序运行后,会解码下面的音频文件。

解码后的PCM采样数据被保存成了一个文件。使用Adobe Audition设置采样率等信息后可以查看PCM的内容。

SDL音频采样数据播放器

源代码

/** * 最简单的SDL2播放音频的例子(SDL2播放PCM) * Simplest Audio Play SDL2 (SDL2 play PCM)  * * 雷霄骅 Lei Xiaohua * leixiaohua1020@126.com * 中国传媒大学/数字电视技术 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程序使用SDL2播放PCM音频采样数据。SDL实际上是对底层绘图 * API(Direct3D,OpenGL)的封装,使用起来明显简单于直接调用底层 * API。 * * 函数调用步骤如下:  * * [初始化] * SDL_Init(): 初始化SDL。 * SDL_OpenAudio(): 根据参数(存储于SDL_AudioSpec)打开音频设备。 * SDL_PauseAudio(): 播放音频数据。 * * [循环播放数据] * SDL_Delay(): 延时等待播放完成。 * * This software plays PCM raw audio data using SDL2. * SDL is a wrapper of low-level API (DirectSound). * Use SDL is much easier than directly call these low-level API. * * The process is shown as follows: * * [Init] * SDL_Init(): Init SDL. * SDL_OpenAudio(): Opens the audio device with the desired  *     parameters (In SDL_AudioSpec). * SDL_PauseAudio(): Play Audio. * * [Loop to play data] * SDL_Delay(): Wait for completetion of playback. */#include <stdio.h>#include <tchar.h>extern "C"{#include "sdl/SDL.h"};//Buffer://|-----------|-------------|//chunk-------pos---len-----|static  Uint8  *audio_chunk; static  Uint32  audio_len; static  Uint8  *audio_pos; /* Audio Callback * 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){  //SDL 2.0 SDL_memset(stream, 0, 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 += len;  audio_len -= len; } int main(int argc, char* argv[]){ //Init if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)) {    printf( "Could not initialize SDL - %s\n", SDL_GetError());   return -1; } //SDL_AudioSpec SDL_AudioSpec wanted_spec; wanted_spec.freq = 44100;  wanted_spec.format = AUDIO_S16SYS;  wanted_spec.channels = 2;  wanted_spec.silence = 0;  wanted_spec.samples = 1024;  wanted_spec.callback = fill_audio;  if (SDL_OpenAudio(&wanted_spec, NULL)<0){   printf("can't open audio.\n");   return -1;  }  FILE *fp=fopen("NocturneNo2inEflat_44.1k_s16le.pcm","rb+"); if(fp==NULL){  printf("cannot open this file\n");  return -1; } int pcm_buffer_size=4096; char *pcm_buffer=(char *)malloc(pcm_buffer_size); int data_count=0; //Play SDL_PauseAudio(0); while(1){  if (fread(pcm_buffer, 1, pcm_buffer_size, fp) != pcm_buffer_size){   // Loop   fseek(fp, 0, SEEK_SET);   fread(pcm_buffer, 1, pcm_buffer_size, fp);   data_count=0;  }  printf("Now Playing %10d Bytes data.\n",data_count);  data_count+=pcm_buffer_size;  //Set audio buffer (PCM data)  audio_chunk = (Uint8 *) pcm_buffer;   //Audio buffer length  audio_len =pcm_buffer_size;  audio_pos = audio_chunk;  while(audio_len>0)//Wait until finish   SDL_Delay(1);  } free(pcm_buffer); SDL_Quit(); return 0;}

运行结果

程序运行后,会读取程序文件夹下的一个PCM采样数据文件,内容如下所示。

接下来会将PCM数据输出到系统的音频设备上(音响、耳机)。

下载

Simplest FFmpeg Audio Player

SourceForge:https://sourceforge.net/projects/simplestffmpegaudioplayer/

Github:https://github.com/leixiaohua1020/simplest_ffmpeg_audio_player

开源中国:http://git.oschina.net/leixiaohua1020/simplest_ffmpeg_audio_player

CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8924329

本程序实现了音频的解码和播放。是最简单的FFmpeg音频解码方面的教程。
通过学习本例子可以了解FFmpeg的解码流程。
项目包含3个工程:

simplest_ffmpeg_audio_player:基于FFmpeg+SDL的音频解码器
simplest_ffmpeg_audio_decoder:音频解码器。使用了libavcodec和libavformat。
simplest_audio_play_sdl2:使用SDL2播放PCM采样数据的例子。

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

最简单的基于FFMPEG+SDL的音频播放器 拆分-解码器和播放器相关推荐

  1. 最简单的基于FFMPEG+SDL的音频播放器

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  2. 最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  3. 最简单的基于FFMPEG SDL的音频播放器

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! ==== ...

  4. 最简单的基于FFMPEG+SDL的音频播放器:拆分-解码器和播放器

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  5. 100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)

    ===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...

  6. 最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...

  7. 最简单的基于FFMPEG+SDL的视频播放器:拆分-解码器和播放器

    ===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...

  8. 最简单的基于FFmpeg的移动端例子:IOS 视频转码器

    ===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子:A ...

  9. 最简单的基于FFmpeg的移动端例子:Android 视频转码器

    ===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子:A ...

最新文章

  1. CNN网络优化加速开源代码汇总
  2. 多态及其内部原理剖析
  3. vscode 安装包_VS Code的下载与安装(更改插件的安装位置)
  4. linux的用户及权限管理,用户及权限管理
  5. 8 年经验面试官解读程序员的技能瓶颈,以及突破瓶颈的忠告 | CSDN 博文精选
  6. python机器学习案例系列教程——推荐系统
  7. 微软邀请IT管理人员及开发人员参加用户体验在线调研
  8. android soundpool 播放音效,Android使用SoundPool播放短音效
  9. 深入linux设备驱动程序内核机制(第三章) 读书笔记
  10. matlab 关于interpreter的使用
  11. could not initialize proxy - the owning Session was closed解决方法!
  12. AndroidStudio输入生日计算星座
  13. java什么时候触发gc_什么时候触发 GC
  14. python实现mysql二叉树_python环境下使用mysql数据及数据结构和二叉树算法(图)...
  15. 四舍六入五留双与四舍五入之间的差别
  16. Lua string.split
  17. 艾美捷重组蛋白酶K,无动物源/AF化学性质介绍
  18. 腾讯:互联网金融行业HBase实践与创新
  19. UnityShader水体渲染
  20. 上海某大型游戏公司Unity3D基础面试题

热门文章

  1. java的格式输入语句是_java输入输出语句是什么
  2. matlab 伽马波带片,菲涅尔波带片
  3. 柯马机器人型号_柯马机器人的六大常见问题大盘点!——柯马机器人
  4. 搜索指定期刊内的文章
  5. MATLAB中函数find的使用方法概述,简单易懂+例子
  6. 【VisualBasicApplication】Excel编程 快速入门
  7. ABOV(15)SPI
  8. 802.11协议标准介绍
  9. 详解!卡车自动装卸系统及其应用
  10. hbase在海量用户日志中快速查询访问路径的使用场景