ffmpeg 播放音频
播放音频,设置好SDL_AudioSpec播放参数,然后由SDL回调函数进行解码和数据的拷贝,解码播放音频无需设置延迟,因为声卡播放音频是阻塞的
int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf, int buf_size)
{
  static AVPacket pkt;
    static uint8_t *audio_pkt_data = NULL;
    static int audio_pkt_size = 0;
    static AVFrame frame;
int len1, data_size = 0;
for(;;)
  {
	  //while循环解码,直到将Packet中的多个音频帧数据解码完成了,再读取下一个包,每次解码一个音频帧数据后饭后解码后的大小,如果一直未解码出数据,则直到将该packet解码完
	  //了后都没有解码出数据,则读取下一个包,一直到有数据解码成来后再返回解码成功后的数据大小
      while(audio_pkt_size > 0) 
	  {
          int got_frame = 0;
          len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);
          if(len1 < 0) 
	      {
		      //解码失败,则跳过该包数据,解码下一包数据
		      audio_pkt_size = 0;
		      break;
          }
          audio_pkt_data += len1;
          audio_pkt_size -= len1;
          data_size = 0;
          if(got_frame) 
	      {
		      data_size = av_samples_get_buffer_size(NULL, 
					                         aCodecCtx->channels,
					                         frame.nb_samples,
					                         aCodecCtx->sample_fmt,
					                         1);
		      assert(data_size <= buf_size);
		      memcpy(audio_buf, frame.data[0], data_size);
          }
          if(data_size <= 0) 
	      {
		      /* No data yet, get more frames */
		      continue;
          }
          /* We have data, return it and come back for more later */
          return data_size;
      }  
      if(pkt.data)
          av_free_packet(&pkt);
  if(quit) 
	  {
          return -1;
      }
  if(packet_queue_get(&audioq, &pkt, 1) < 0) 
	  {
          return -1;
      }
	  //静态变量保存Packet的数据
      audio_pkt_data = pkt.data;
	  //静态变量保存Packet的大小
      audio_pkt_size = pkt.size;
    }
}
SDL回调函数进行音频的播放,每次将解码的数据拷贝到SDL缓冲区,大小为len
void audio_callback(void *userdata, Uint8 *stream, int len)
{
  AVCodecContext *aCodecCtx = (AVCodecContext *)userdata;
    int len1, audio_size;
  static uint8_t audio_buf[(MAX_AUDIO_FRAME_SIZE * 3) / 2];
    static unsigned int audio_buf_size = 0;
    static unsigned int audio_buf_index = 0;
  while(len > 0) 
    {
    //如果上次拷贝后,还有数据剩余未拷贝完成,则现先将上次剩余的数据拷贝进去SDL缓冲区后,然后进行下一个包数据的解码和拷贝
        if(audio_buf_index >= audio_buf_size) 
	    {
	        //audio_size 解码的长度,audio_buf解码的缓存
            audio_size = audio_decode_frame(aCodecCtx, audio_buf, sizeof(audio_buf));
            if(audio_size < 0) 
	        {
		        //如果未解码出数据,则设置为静音
		        audio_buf_size = 1024; // arbitrary?
		        memset(audio_buf, 0, audio_buf_size);
            } 
	        else 
	        {
		        //解码后的长度
		        audio_buf_size = audio_size;
            }
	          //每次解码后从第一个位置开始拷贝数据
              audio_buf_index = 0;
        }
	    //解码后的缓存区所剩余的长度,如果解码数据大于SDL回调缓冲区的大小,则只需填充慢SDL回调缓冲区
	    //如果未能填充满SDL缓冲区,则解码下一个Packet进行填充
        len1 = audio_buf_size - audio_buf_index;
        if(len1 > len)
            len1 = len;
        memcpy(stream, (uint8_t *)audio_buf + audio_buf_index, len1);
        len -= len1;
        stream += len1;
        audio_buf_index += len1;
    }
}
ffmpeg 播放音频的更多相关文章
- FFmpeg学习3:播放音频
		参考dranger tutorial,本文将介绍如何使用FFmpeg解码音频数据,并使用SDL将解码后的数据输出. 本文主要包含以下几方面的内容: 关于播放音频的需要的一些基础知识介绍 使用SDL2播 ... 
- FFMPEG + SDL音频播放分析
		目录 [hide] 1 抽象流程: 2 关键实现: 2.1 main()函数 2.2 decode_thread()读取文件信息和音频包 2.3 stream_component_open():设置音 ... 
- FFmpeg 入门(3):播放音频
		本文转自:FFmpeg 入门(3):播放音频 | www.samirchen.com 音频 SDL 提供了播放音频的方法.SDL_OpenAudio 函数用来让设备播放音频,它需要我们传入一个包含了所 ... 
- [总结]FFMPEG视音频编解码零基础学习方法--转
		ffmpeg编解码学习 目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ... 
- FFMPEG视音频编解码零基础学习方法
		在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ... 
- FFMPEG视音频编解码零基础学习方法-b
		感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ... 
- [总结]FFMPEG视音频编解码零基础学习方法
		在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ... 
- 【转】[总结]FFMPEG视音频编解码零基础学习方法
		在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ... 
- 浏览器音频兼容和ffmpeg的音频转码使用
		浏览器对各音/视频格式的支持问题 浏览器测试效果图 ffmpeg在音频格式转换,和从视频中提取音频的简单实用 1.百度搜索浏览器对于音频文件的兼容,排在前面的文章大部分是复制粘贴很久以前的文章,容易误 ... 
随机推荐
- django页面导出excel
			from django.http import HttpResponse from xlwt import * from io import BytesIO def excel_export(requ ... 
- Maven私服Nexus详解
			maven的仓库只有两大类:1.本地仓库 2.远程仓库,在远程仓库中又分成了3种:2.1 中央仓库 2.2 私服 2.3 其它公共库. 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理 ... 
- ubuntu16 intellij idea install lombok plugin
			项目中用到lombok,idea会出现类似编译报错的红色,但并不影响运行.所以为了没有类似警告,就在idea上安装lombok插件.file-settings 安装完成之后,按照提示重启idea,问题 ... 
- 第十六篇  make中的路径搜索
			在实际的工程项目中,源文件和头文件都会组织成一定的目录结构,这样也便于项目的管理,前述我们分析的makefile,源文件和头文件大都在当前目录,没有路径搜索的问题,下面我们引入今天的演示程序的目录结 ... 
- qt5 交叉编译
			qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf 添加 QMAKE_LFLAGS += -Wl,-rpath-link,$$[QT_SYSROOT]/us ... 
- Word Embeddings
			能够充分意识到W的这些属性不过是副产品而已是很重要的.我们没有尝试着让相似的词离得近.我们没想把类比编码进不同的向量里.我们想做的不过是一个简单的任务,比如预测一个句子是不是成立的.这些属性大概也就是 ... 
- CF1142E/1143B Lynyrd Skynyrd
			CF1142E/1143B Lynyrd Skynyrd 开始读错题了,以为是连续的一段,敲完后才发现是 \(subsequence\) ... 考虑对于 \(a\) 中的每个 \(a_i\) 找到它 ... 
- 12 Factor CLI Apps
			CLIs are a fantastic way to build products. Unlike web applications, they take a small fraction of t ... 
- Android 第三方分享中遇到的问题以及解决方式
			版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/liuxian13183/article/details/36189343 ... 
- 【转】Ubuntu12.04 LTS下环境变量设置
			原文网址:http://blog.chinaunix.net/uid-26963688-id-3221439.html 1.设置当前用户环境变量(对root用户无效) 打开终端输入:light@cha ... 
