使用FFMPEG实现音频播放器

导言

因为公司项目的原因,要学习如何使用FFMPEG进行音频播放,折腾一圈发现,使用FFMPEG还真不是一件简单的事,更为可惜的是,当年在这方面的杰出人物—雷霄骅的英逝,这方面的文档愈发稀少,而FFMPEG相关代码不断更新,整理此文,算是对他的一种缅怀吧。

FFMPEG简介

Q:FFMPEG是什么?

A:FFMPEG是一个多媒体框架

Q:FFMPEG作为一个多媒体框架,有什么功能?

A:FFMEPG作为一个多媒体框架,是由多个模块组成的,每个模块都有对应的功能:

  • libavutil是一个包含简化编程功能的库,其中包括随机数生成器,数据结构,数学代码,核心多媒体工具等更多东西。
  • libavcodec是一个包含音频/视频解码器和编码器的库。
  • libavformat是一个包含了多媒体格式的分离器和混流器的库。
  • libavdevice是一个包含输入输出设备的库,用于捕捉和渲染很多来自常用的多媒体输入/输出软件框架的数据,包括Video4Linux,Video4Linux2,VfW和ALSA。
  • libavfilter是一个包含媒体过滤器的库。
  • libswscale是一个用于执行高度优化的图像缩放和颜色空间/像素格式转换操作的库。
  • libswresample是一个用于执行高度优化的音频重采样,重新矩阵和取样格式转换操作的库。

FFMPEG入门资料

  • FFMPEG视音频编解码零基础学习方法—雷霄骅
  • FFMPEG官方API手册
  • FFMPEG官方文档

安装FFMPEG

对于如何安装FFMEPG,主要可以查看官方的安装指南,简要步骤如下:

  • 安装gcc,yasm
  • 下载源码
  • 解压后运行./configure
  • 执行make & make install
  • 安装完成

编写代码

写在编码之前

在编写代码之前,请务必搞懂以下文章的内容:

  • FFMPEG中最关键的结构体之间的关系

可能在观看代码时有些不懂得地方,可以看这里:

  • FFmpeg学习4:音频格式转换

或者查看手册中的具体说明:

  • FFMPEG官方API手册

代码

/*********************************Author: ToudsourCreated Time: 一  3/20 15:15:26 2017File Name:player.c
*********************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<avcodec.h>
#include<avformat.h>
#include<swresample.h>#define MAX_AUDIO_FRAME_SIZE  192000#define LOG(str) printf("Line %d:  %s  \n", __LINE__, str)const char *url = "WavinFlag.aac";
const char *output_path = "WavingFlag.pcm";
int main()
{//注册所有的工具av_register_all();//初始化网络相关工具avformat_network_init();AVFormatContext *fmt_ctx = NULL;AVCodecContext  *cod_ctx = NULL;AVCodec         *cod   = NULL;//分配一个avformatfmt_ctx = avformat_alloc_context();if (fmt_ctx == NULL)LOG("alloc fail");//打开文件,解封装if (avformat_open_input(&fmt_ctx, url, NULL, NULL) != 0)LOG("open fail");//查找文件的相关流信息if (avformat_find_stream_info(fmt_ctx, NULL) < 0)LOG("find stream fail");//输出格式信息av_dump_format(fmt_ctx, 0, url, 0);//查找解码信息int stream_index = -1;for (int i = 0; i < fmt_ctx->nb_streams; i++)if (fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {stream_index = i;break;}if (stream_index == -1)LOG("find stream fail");//保存解码器cod_ctx = fmt_ctx->streams[stream_index]->codec;cod = avcodec_find_decoder(cod_ctx->codec_id);if (cod == NULL)LOG("find codec fail");if (avcodec_open2(cod_ctx, cod, NULL) < 0)LOG("can't open codec");FILE *file = NULL;file = fopen(output_path, "wb");//创建packet,用于存储解码前的数据AVPacket *packet = malloc(sizeof(AVPacket));av_init_packet(packet);//设置转码后输出相关参数//采样的布局方式uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;//采样个数int out_nb_samples = 1024;//采样格式enum AVSampleFormat  sample_fmt = AV_SAMPLE_FMT_S16;//采样率int out_sample_rate = 44100;//通道数int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);//创建bufferint buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, sample_fmt, 1);//注意要用av_mallocuint8_t *buffer = av_malloc(MAX_AUDIO_FRAME_SIZE * 2);//创建Frame,用于存储解码后的数据AVFrame *frame = av_frame_alloc();printf("Bitrate :\t %3lld\n", fmt_ctx->bit_rate);printf("Decoder Name :\t %s\n", cod_ctx->codec->long_name);printf("Cannels:\t %d\n", cod_ctx->channels);printf("Sample per Second:\t %d\n", cod_ctx->sample_rate);uint32_t ret,len = 0;int got_picture;int64_t in_channel_layout = av_get_default_channel_layout(cod_ctx->channels);//打开转码器struct SwrContext *convert_ctx = swr_alloc();//设置转码参数convert_ctx = swr_alloc_set_opts(convert_ctx, out_channel_layout, sample_fmt, out_sample_rate, \in_channel_layout, cod_ctx->sample_fmt, cod_ctx->sample_rate, 0, NULL);//初始化转码器swr_init(convert_ctx);int index = 0;//while循环,每次读取一帧,并转码while (av_read_frame(fmt_ctx, packet) >= 0) {printf("index : %d\n", index);if (packet->stream_index == stream_index) {//解码声音if (avcodec_decode_audio4(cod_ctx, frame, &got_picture, packet) < 0) {LOG("decode error");return -1;}if (got_picture > 0) {//转码swr_convert(convert_ctx, &buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)frame->data, frame->nb_samples);printf("index: %5d\t pts:%10lld\t packet size:%d\n", index, packet->pts, packet->size);fwrite(buffer, 1, buffer_size, file);}}index ++;av_free_packet(packet);}swr_free(&convert_ctx);fclose(file);LOG("safe exit");return 0;
}

编译

FFMPEG编译也不是一件容易的事情,在这里我建议使用pkg-config来给出相关编译信息。
废话不多说,这是下边是MakeFile的内容:

player : player.cgcc -g -Wall player.c -o player -std=c99 \
-I/usr/local/include/libavformat \
-I/usr/local/include/libavcodec \
-I/usr/local/include/libswresample \
`pkg-config --libs libavformat`

运行

从代码中可以看出,我们需要一个*.acc音频文件作为我们播放源,这需要大家自己去各大音频网站上自己去获取,最后生成的*.pcm如何打开呢?

这里我们需要下载工具Audition,下载安装后,在打开是选择双声道,44100HZ采样然后点击播放就可以播放啦。

祝大家编码顺利。

使用FFMPEG实现音频播放器相关推荐

  1. ffmpeg提取音频播放器总结

    ffmpeg提取音频播放器总结:  一:简介  从编写音频播放器代码到完成播放器编写,测试,整整5天的时间,这时间还不算之前对 ffmpeg熟悉的时间,可以说是历经千辛万苦,终于搞出来了,虽然最终效果 ...

  2. FFmpeg+SDL2音频播放器

    基于雷神最简单的音频播放器修改. /** * 最简单的基于FFmpeg的音频播放器 2 * Simplest FFmpeg Audio Player 2 * * 雷霄骅 Lei Xiaohua * l ...

  3. Android media ---- 1.7.ffmpeg 简单音频播放器

    哎,喜欢偷懒,这边直接抄袭下雷神的代码.雷神是个值得敬佩的程序员. vs代码下载链接: https://pan.baidu.com/s/1c2dIuYk 密码:ld4b /* *最简单的基于FFmpe ...

  4. ffmpeg+sdl音频播放器

    主机环境:Windows XP SDL版本:SDL2-2.0.3 ffmpeg版本:ffmpeg.2.4 ffmpeg库版本:ffmpeg-20140916-git-b76d613-win32-dev ...

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

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

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

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

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

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

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

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

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

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

最新文章

  1. 怎样实现基于Trie树和字典的分词功能
  2. Dos批处理中符号作用大全
  3. python多线程的作用_Python多线程中三个函数的强大功能简介
  4. 如何将pdf导出html,如何导出PDF版、导出EXE版、导出HTML离线版?
  5. 使用transform实现手风琴布局
  6. 帆软报表插件开发之fine-decision中的LogInOutEventProvider扩展
  7. Bailian2798 2进制转化为16进制【进制】
  8. 10截图时屏幕变大_解锁电脑更多的截屏姿势:Win 10中自带的七种截图方法
  9. linux实现普通用户只允许使用部分命令
  10. 矩阵快速幂 超详细介绍
  11. c51单片机流水灯程序汇编语言,基于51单片机的流水灯程序
  12. .NET 开源项目概览
  13. AAAI-2021-RE-Progressive Multitask Learning with Controlled Information Flow for Joint Entity and Re
  14. 【渝粤教育】国家开放大学2018年秋季 1326T社区护理学(本) 参考试题
  15. 主板上的jrgb接口干什么用_主板vdg接口是什么
  16. 相册照片直播小程序开发
  17. SQL查询-查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
  18. 单页面SPA和多页面MPA应用的区别
  19. 小白都能看懂!Python机器学习预测乳腺癌疾病案例剖析!
  20. 12- 降维算法 (PCA降维/LDA分类/NMF) (数据处理)

热门文章

  1. 对抗网络之目标检测应用:A-Fast-RCNN
  2. 基于RTT压缩包C基础-不明白的接口PRF_ENV_GET __attribute__
  3. 一文带你彻底搞懂Docker中的cgroup
  4. Ruby 字符串操作(和 Python3 字符串操作进行对比)
  5. 【智能物流】一文读懂自动化立体仓库
  6. html如何冻结字段,html表格中的冻结字段
  7. WOW地名中英文对照联盟版
  8. OKR案例:GROW教练模型的训练方法
  9. 学长教你学C-day12-C语言函数
  10. CoreGraphics 画图,(转燕羽天空)