前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >最简单的基于FFMPEG的音频编码器(PCM编码为AAC)

最简单的基于FFMPEG的音频编码器(PCM编码为AAC)

作者头像
全栈程序员站长
发布于 2022-07-08 10:07:55
发布于 2022-07-08 10:07:55
1.3K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是全栈君。

本文介绍一个最简单的基于FFMPEG的音频编码器。该编码器实现了PCM音频採样数据编码为AAC的压缩编码数据。编码器代码十分简单,可是每一行代码都非常重要。通过看本编码器的源码。能够了解FFMPEG音频编码的流程。

本程序使用最新版的类库(编译时间为2014.5.6)。开发平台为VC2010。全部的配置都已经做好,仅仅须要执行就能够了。

流程(2014.9.29更新)

以下附一张使用FFmpeg编码音频的流程图。

使用该流程。不仅能够编码AAC的音频,并且能够编码MP3,MP2等等各种FFmpeg支持的音频。图中蓝色背景的函数是实际输出数据的函数。

浅绿色的函数是音频编码的函数。

简介一下流程中各个函数的意义:

av_register_all():注冊FFmpeg全部编解码器。 avformat_alloc_output_context2():初始化输出码流的AVFormatContext。 avio_open():打开输出文件。 av_new_stream():创建输出码流的AVStream。 avcodec_find_encoder():查找编码器。 avcodec_open2():打开编码器。 avformat_write_header():写文件头(对于某些没有文件头的封装格式,不须要此函数。比方说MPEG2TS)。 avcodec_encode_audio2():编码音频。即将AVFrame(存储PCM採样数据)编码为AVPacket(存储AAC,MP3等格式的码流数据)。 av_write_frame():将编码后的视频码流写入文件。 av_write_trailer():写文件尾(对于某些没有文件头的封装格式。不须要此函数。比方说MPEG2TS)。

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 *最简单的基于FFmpeg的音频编码器
 *Simplest FFmpeg Audio Encoder
 *
 *雷霄骅 Lei Xiaohua
 *leixiaohua1020@126.com
 *中国传媒大学/数字电视技术
 *Communication University of China / Digital TV Technology
 *http://blog.csdn.net/leixiaohua1020
 *
 *本程序实现了音频PCM採样数据编码为压缩码流(MP3。WMA,AAC等)。 *是最简单的FFmpeg音频编码方面的教程。 *通过学习本样例能够了解FFmpeg的编码流程。 *This software encode PCM data to AAC bitstream. *It's the simplest audio encoding software based on FFmpeg.  *Suitable for beginner of FFmpeg  */#include <stdio.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32//Windowsextern "C"{#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"};#else//Linux...#ifdef __cplusplusextern "C"{#endif#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#ifdef __cplusplus};#endif#endifint flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){	int ret;	int got_frame;	AVPacket enc_pkt;	if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &		CODEC_CAP_DELAY))		return 0;	while (1) {		enc_pkt.data = NULL;		enc_pkt.size = 0;		av_init_packet(&enc_pkt);		ret = avcodec_encode_audio2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,			NULL, &got_frame);		av_frame_free(NULL);		if (ret < 0)			break;		if (!got_frame){			ret=0;			break;		}		printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);		/* mux encoded frame */		ret = av_write_frame(fmt_ctx, &enc_pkt);		if (ret < 0)			break;	}	return ret;}int main(int argc, char* argv[]){	AVFormatContext* pFormatCtx;	AVOutputFormat* fmt;	AVStream* audio_st;	AVCodecContext* pCodecCtx;	AVCodec* pCodec;	uint8_t* frame_buf;	AVFrame* pFrame;	AVPacket pkt;	int got_frame=0;	int ret=0;	int size=0;	FILE *in_file=NULL;	                        //Raw PCM data	int framenum=1000;                          //Audio frame number	const char* out_file = "tdjm.aac";          //Output URL	int i;	in_file= fopen("tdjm.pcm", "rb");	av_register_all();	//Method 1.	pFormatCtx = avformat_alloc_context();	fmt = av_guess_format(NULL, out_file, NULL);	pFormatCtx->oformat = fmt;	//Method 2.	//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);	//fmt = pFormatCtx->oformat;	//Open output URL	if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){		printf("Failed to open output file!\n");		return -1;	}	audio_st = avformat_new_stream(pFormatCtx, 0);	if (audio_st==NULL){		return -1;	}	pCodecCtx = audio_st->codec;	pCodecCtx->codec_id = fmt->audio_codec;	pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;	pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;	pCodecCtx->sample_rate= 44100;	pCodecCtx->channel_layout=AV_CH_LAYOUT_STEREO;	pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);	pCodecCtx->bit_rate = 64000;  	//Show some information	av_dump_format(pFormatCtx, 0, out_file, 1);	pCodec = avcodec_find_encoder(pCodecCtx->codec_id);	if (!pCodec){		printf("Can not find encoder!\n");		return -1;	}	if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){		printf("Failed to open encoder!\n");		return -1;	}	pFrame = av_frame_alloc();	pFrame->nb_samples= pCodecCtx->frame_size;	pFrame->format= pCodecCtx->sample_fmt;		size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1);	frame_buf = (uint8_t *)av_malloc(size);	avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1);		//Write Header	avformat_write_header(pFormatCtx,NULL);	av_new_packet(&pkt,size);	for (i=0; i<framenum; i++){		//Read PCM		if (fread(frame_buf, 1, size, in_file) <= 0){			printf("Failed to read raw data! \n");			return -1;		}else if(feof(in_file)){			break;		}		pFrame->data[0] = frame_buf;  //PCM Data		pFrame->pts=i*100;		got_frame=0;		//Encode		ret = avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame);		if(ret < 0){			printf("Failed to encode!\n");			return -1;		}		if (got_frame==1){			printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size);			pkt.stream_index = audio_st->index;			ret = av_write_frame(pFormatCtx, &pkt);			av_free_packet(&pkt);		}	}		//Flush Encoder	ret = flush_encoder(pFormatCtx,0);	if (ret < 0) {		printf("Flushing encoder failed\n");		return -1;	}	//Write Trailer	av_write_trailer(pFormatCtx);	//Clean	if (audio_st){		avcodec_close(audio_st->codec);		av_free(pFrame);		av_free(frame_buf);	}	avio_close(pFormatCtx->pb);	avformat_free_context(pFormatCtx);	fclose(in_file);	return 0;}

结果

程序执行完毕后。会将一个PCM採样数据文件(*.pcm)编码为AAC码流文件(*.aac)。

下载

simplest ffmpeg audio encoder

项目主页

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

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

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

CSDNproject下载地址:

http://download.csdn.net/detail/leixiaohua1020/7324091

PUDNproject下载地址:

http://www.pudn.com/downloads644/sourcecode/multimedia/detail2605236.html

更新-1.1 (2015.2.13)=========================================

这次考虑到了跨平台的要求,调整了源码。经过这次调整之后,源码能够在以下平台编译通过:

VC++:打开sln文件就可以编译,无需配置。

cl.exe:打开compile_cl.bat就可以命令行下使用cl.exe进行编译,注意可能须要依照VC的安装路径调整脚本里面的參数。编译命令例如以下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
::VS2010 Environment
call "D:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
::include
@set INCLUDE=include;%INCLUDE%
::lib
@set LIB=lib;%LIB%
::compile and link
cl simplest_ffmpeg_audio_encoder.cpp /link avcodec.lib avformat.lib avutil.lib ^
avdevice.lib avfilter.lib postproc.lib swresample.lib swscale.lib /OPT:NOREF

MinGW:MinGW命令行下执行compile_mingw.sh就可以使用MinGW的g++进行编译。 编译命令例如以下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
g++ simplest_ffmpeg_audio_encoder.cpp -g -o simplest_ffmpeg_audio_encoder.exe \
-I /usr/local/include -L /usr/local/lib -lavformat -lavcodec -lavutil

GCC:Linux或者MacOS命令行下执行compile_gcc.sh就可以使用GCC进行编译。编译命令例如以下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
gcc simplest_ffmpeg_audio_encoder.cpp -g -o simplest_ffmpeg_audio_encoder.out \
-I /usr/local/include -L /usr/local/lib -lavformat -lavcodec -lavutil

PS:相关的编译命令已经保存到了project目录中

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

SourceForge上已经更新。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116024.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年1月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
嵌入式Qt-FFmpeg设计一个RTSP播放器
上篇文章,介绍了FFmpeg的交叉编译,以及在嵌入式Linux平台,运行ffmpeg指令来播放视频。
xxpcb
2022/10/04
1.4K0
嵌入式Qt-FFmpeg设计一个RTSP播放器
最简单的基于FFMPEG的视频编码器(YUV编码为H.264)
=====================================================
全栈程序员站长
2022/09/13
6220
最简单的基于FFMPEG的视频编码器(YUV编码为H.264)
C++ ffmpeg+dxva2实现硬解码「建议收藏」
0.前言 参考博客:ffmpeg实现dxva2硬件加速 下载源码:GitHub:https://github.com/Yacov-lu/ffmpeg-DXVA-decode
全栈程序员站长
2022/11/16
2.1K0
C++ ffmpeg+dxva2实现硬解码「建议收藏」
Android FFmpeg音视频编码(十六)
上一章,我们了解ffmpeg的解封装,解码过程,这一章我们来了解一下ffmpeg是怎样进行编码,和封装工作的,工作流程如下图所示:
PengJie
2021/01/17
1.9K0
ffmpeg的H.264解码
FFmpeg_allluckly.cn.png 新建工程,导入由Mac编译ffmpeg获取FFmpeg-iOS编译好的FFmpeg-iOS,然后导入系统依赖的库 AudioToolbox.framework CoreMedia.framework VideoToolbox.framework libiconv.tbd libbz2.tbd libz.tbd 编译的时候报错: 'libavcodec/avcodec.h' file not found ,修改Header search paths 里的路径:
Bison
2018/07/04
1.8K0
2023-03-19:使用Go语言和FFmpeg库实现pcm编码为mp3。
本文将介绍如何使用Go语言和FFmpeg库实现PCM音频文件编码为MP3格式。我们将使用moonfdd/ffmpeg-go库,并在Windows 10 64位操作系统下完成本次实验。
福大大架构师每日一题
2023/03/19
6540
2023-03-19:使用Go语言和FFmpeg库实现pcm编码为mp3。
最简单的基于FFmpeg的直播系统开发移动端例子:IOS 视频解码器
本文记录IOS平台下基于FFmpeg的视频解码器。该示例C语言的源代码来自于《最简单的基于FFMPEG+SDL的视频播放器》。相关的概念就不再重复记录了。
云豹kj的晨曦
2020/09/04
4500
最简单的基于FFmpeg的直播系统开发移动端例子:IOS 视频解码器
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
福大大架构师每日一题
2023/03/23
3680
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
FFMPEG视频开发:Linux使用FFMPEG采集摄像头数据保存为MP4文件存储(采集摄像头数据方式使用ffmpeg本身的接口)
关于Linux下X264和FFMPEG库的编译安装方法参考这里:https://blog.csdn.net/xiaolong1126626497/article/details/104919095
DS小龙哥
2022/01/12
2.5K1
FFMPEG视频开发:Linux使用FFMPEG采集摄像头数据保存为MP4文件存储(采集摄像头数据方式使用ffmpeg本身的接口)
Android平台RTSP|RTMP播放器高效率如何回调YUV或RGB数据?
我们在做Android平台RTSP、RTMP播放器的时候,经常遇到这样的技术诉求,开发者希望拿到播放器解码后的YUV或RGB数据,投递给视觉算法,做AI分析,本文以ffmpeg和大牛直播SDK的SmartPlayer为例,介绍下相关的技术实现。
音视频牛哥
2024/10/30
1730
Android平台RTSP|RTMP播放器高效率如何回调YUV或RGB数据?
基于最简单的FFmpeg采样读取内存读写:存储转
=====================================================
全栈程序员站长
2022/07/11
9210
基于最简单的FFmpeg采样读取内存读写:存储转
音频编码(一)——FFmpeg编码
这里为啥讲到了声波,讲到了我们的中学物理上的知识,因为我想大家能从根本理解后面音频编码的各种参数以及原因。当然这些知识网上都能搜到,我只是整合一下。
用户2929716
2018/08/23
5.8K0
音频编码(一)——FFmpeg编码
QT应用编程: 基于FFMPEG设计的流媒体播放器(播放rtmp视频流)
使用的FFMPEG库版本下载地址:https://download.csdn.net/download/xiaolong1126626497/12304729
DS小龙哥
2022/01/07
4.2K2
QT应用编程: 基于FFMPEG设计的流媒体播放器(播放rtmp视频流)
2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现。
2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现。
福大大架构师每日一题
2023/03/10
4210
2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现。
2023-03-14:读取摄像头,并且显示视频。代码用go语言编写。
释放所有资源,包括关闭 SDL 窗口、释放 AVFrame 和 AVPacket、删除 SwsContext 结构体、关闭解码器、关闭视频流、关闭摄像头。
福大大架构师每日一题
2023/03/14
8490
2023-03-14:读取摄像头,并且显示视频。代码用go语言编写。
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
福大大架构师每日一题
2023/06/08
2610
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
FFMPEG音视频开发指南(一)
FFmpeg是一款开源软件,用于生成处理多媒体数据的各类库和程序。FFmpeg可以转码、处理视频和图 片(调整视频、图片大小,去噪等)、打包、传输及播放视频。作为最受欢迎的视频和图像处理软件, 早已经被各行各业的不同公司所广泛使用。
DS小龙哥
2022/10/06
3.2K0
FFMPEG音视频开发指南(一)
安卓ffmpeg_有什么好用的视频解码
将封装格式解压后可以得到压缩过的音视频等. 将压缩过的视频解压后可以得到 视频像素数据(RGB,YUV等).常见的视频压缩格式有H.264, MPEG4等…
全栈程序员站长
2022/11/08
1.6K0
安卓ffmpeg_有什么好用的视频解码
wireshark视频流播放_ffmpeg无缝推流多个视频
使用QT+FFMPEG实现了RTSP视频流播放的基础操作,点击按钮后,将拉取指定地址的RTSP流,并在QT界面中通过Label显示
全栈程序员站长
2022/11/02
1.4K0
最简单的FFmpeg YUV420P图像拼接实例
在项目中需要将解码出来的l两个YUV420P格式的图像合并在一起,然后重新编码为H264,最后封装为mp4文件。主要说明一下两个YUV420P使用FFmpeg合并的过程,需要提前理解YUV420P格式图像的存储结构,然后依次将Y、U、V数据分别写进去就可以了。 举例:将两张相同大小的图片合并为一张大图片 640*320 640*320 合并为1280*320 假设YUV420P的宽度为FRAMEWITH 高度为FRAMEHEIGTH, Y存储在 FRAMEWITH*2/3 U存储在 FRAMEWITH*2/3—FRAMEWITH*5/6 V存储在 FRAMEWITH*5/6—FRAMEWITH 本实例主要将FFmpeg解码出来的YUV420P数据进行合并,然后写为一个YUV文件。
望天
2019/05/26
2.9K0
推荐阅读
相关推荐
嵌入式Qt-FFmpeg设计一个RTSP播放器
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文