ffmpeg 编程常用 pcm 转 aac aac 转 pcm mp4 h264解码
ffmpeg 是现在开源的全能编解码器,基本上全格式都支持,纯 c 语言作成,相对比其它的 VLC ,GStreamer glib2 写的,开发更简单些,文档很棒,就是 examples 比较少。
常用的功能有:
AVFrame 数据帧
AVCodecContext 编解码器
AVPacket 数据帧
swr_convert 格式转换器
ffmpeg 的使用都差不多,查找解码器,准备数据,解码,拿结果。
基本上会了一种,其它的也就能会,新版的 4.x 的代码较之前的有些变化,现在大部分之前的代码也是兼容的。有一些 定义成了 enum 。
介绍几个非常实用的例子:
1, pcm 编码 aac (aac 和 m4a 是一种类型)
需要 libfdk_aac 库自行安装配置好,使用 ubuntu 16.0.4 x64 g++ 编译
g++ -g main.cpp -lavcodec -lavformat -lswresample -lavutil -std=c++11 -o wav_to_m4a
用法 ./wav_to_m4a ../xxx.wav ,需要说明的是,有些网站下载的 wav 根本不能用,最好是用 ffmpeg 命令转换。
现实的需求中,没有人让你做一个格式转换器。可能是从 ALSA 读取原始PCM 在编码成 AAC 或通过网络发走,或保存文件。
下面的例子,仅是编码成了 AAC 但是未添加 AAC 头信息。有空在更新。但是可以用 播放器放的。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h> #ifdef __cplusplus
extern "C"
{
#endif
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#include <libavutil/mem.h>
#ifdef __cplusplus
}
#endif #ifndef WORD
#define WORD unsigned short
#endif #ifndef DWORD
#define DWORD unsigned int
#endif struct RIFF_HEADER
{
char szRiffID[]; // 'R','I','F','F'
DWORD dwRiffSize;
char szRiffFormat[]; // 'W','A','V','E'
}; struct WAVE_FORMAT
{
WORD wFormatTag;
WORD wChannels;
DWORD dwSamplesPerSec;
DWORD dwAvgBytesPerSec;
WORD wBlockAlign;
WORD wBitsPerSample;
}; struct FMT_BLOCK
{
char szFmtID[]; // 'f','m','t',' '
DWORD dwFmtSize;
struct WAVE_FORMAT wavFormat;
}; struct DATA_BLOCK
{
char szDataID[]; // 'd','a','t','a'
DWORD dwDataSize;
}; using namespace std; void read_wav(uint8_t *wav_buf, int *fs, int *channels, int *bits_per_sample, int *wav_size, int *file_size)
{
struct RIFF_HEADER *headblk;
struct FMT_BLOCK *fmtblk;
struct DATA_BLOCK *datblk; headblk = (struct RIFF_HEADER *) wav_buf;
fmtblk = (struct FMT_BLOCK *) &headblk[];
datblk = (struct DATA_BLOCK *) &fmtblk[]; *file_size = headblk->dwRiffSize; //采样频率
*fs = fmtblk->wavFormat.dwSamplesPerSec;
//通道数
*channels = fmtblk->wavFormat.wChannels;
*wav_size = datblk->dwDataSize;
//采样bit数 16 24
*bits_per_sample = fmtblk->wavFormat.wBitsPerSample;
} int main(int argc, char **argv)
{
int fd;
int ret;
struct stat stat;
int fs, channels, bits_per_sample, wav_size, file_size;
uint8_t *wav_buf;
uint8_t *audio_buf;
const char *out_file = "out.m4a";
const AVCodec *codec;
AVFrame *frame;
AVPacket *encodePacket;
AVCodecContext *codecContext; //打开文件进行 mmap
fd = open(argv[], O_RDONLY);
fstat(fd, &stat);
wav_buf = (uint8_t*)mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, );
read_wav(wav_buf, &fs, &channels, &bits_per_sample, &wav_size, &file_size);
printf("wav format: fs = %d, channels = %d, bits_per_sample = %d, wav_size = %d file_size = %d\n\r", fs, channels, bits_per_sample, wav_size, file_size); //真实wav 跳过头部
audio_buf = wav_buf + sizeof(struct RIFF_HEADER) + sizeof(struct FMT_BLOCK) + sizeof(struct DATA_BLOCK); avcodec_register_all(); //ffmpeg 4.x 已经不需要此函数 codec = avcodec_find_encoder_by_name("libfdk_aac"); if(! codec)
{
printf("avcodec_find_encoder error \n");
return -;
} codecContext = avcodec_alloc_context3(codec);
if(! codecContext)
{
printf("Could not allocate audio codec context \n");
return -;
} codecContext->bit_rate = ;
codecContext->sample_fmt = AV_SAMPLE_FMT_S16;
codecContext->sample_rate = ;
codecContext->channel_layout = AV_CH_LAYOUT_STEREO;
codecContext->channels = av_get_channel_layout_nb_channels(codecContext->channel_layout); printf("sample_fmt:%d sample_rate:%d channel_layout:%d channels:%d \n", codecContext->sample_fmt, codecContext->sample_rate, codecContext->channel_layout, codecContext->channels); /* open avcodec */
if( > avcodec_open2(codecContext, codec, NULL))
{
printf("Could not open codec \n");
return -;
} /* frame containing input raw audio */
frame = av_frame_alloc();
if(! frame)
{
printf("Could not allocate audio frame \n");
return -;
} frame->nb_samples = codecContext->frame_size;
frame->format = codecContext->sample_fmt;
frame->channel_layout = codecContext->channel_layout; printf("nb_samples:%d format:%d channel_layout:%d \n", frame->nb_samples, frame->format, frame->channel_layout); encodePacket = av_packet_alloc(); int size = av_samples_get_buffer_size(NULL, codecContext->channels,codecContext->frame_size,codecContext->sample_fmt, );
uint8_t *frame_buf = (uint8_t *)av_malloc(size);
avcodec_fill_audio_frame(frame, codecContext->channels, codecContext->sample_fmt,(const uint8_t*)frame_buf, size, ); ofstream acc_file(out_file, ios::binary | ios::out | ios::trunc); int pos = ;
while(pos <= file_size)
{
frame->data[] = audio_buf + pos; /* send the frame for encoding */
ret = avcodec_send_frame(codecContext, frame);
if( > ret)
{
printf("Error sending the frame to the encoder \n");
return -;
} /* read all the available output packets (in general there may be any
* number of them */
while( <= ret)
{
ret = avcodec_receive_packet(codecContext, encodePacket);
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if( > ret)
{
printf("Error encoding audio frame \n");
return -;
} //c++ 写文件流
acc_file.write((const char*)encodePacket->data, encodePacket->size);
av_packet_unref(encodePacket);
} pos += size;
} cout << "encode done" << endl;
return ;
} // main.cpp
2, acc 解码 pcm
3, mp4 解码 h264 acc 并调用 SDL 播放视频
更新中。。
ffmpeg 编程常用 pcm 转 aac aac 转 pcm mp4 h264解码的更多相关文章
- 最简单的基于FFMPEG的音频编码器(PCM编码为AAC)
http://blog.csdn.net/leixiaohua1020/article/details/25430449 本文介绍一个最简单的基于FFMPEG的音频编码器.该编码器实现了PCM音频采样 ...
- 基于FFmpeg的音频编码(PCM数据编码成AAC android)
概述 在Android上实现录音,并利用 FFmpeg将PCM数据编码成AAC. 详细 代码下载:http://www.demodashi.com/demo/10512.html 之前做的一个demo ...
- 爬取编程常用词汇,保存为Excel
编程常用词汇 import requests import openpyxl from lxml import etree import re url = 'https://www.runoob.co ...
- VBA编程常用词汇英汉对照表
表 20‑1到表 20‑8是VBA编程中使用频率最高的英文单词,按字母排序.词性列中,a表示形容词,n表示名词,v表示动词,p表示介词以及其他词性. 表 20‑1 VBA编程常用词汇表 单词 中文 词 ...
- UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数
UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数 gethostname() getppername() getsockname() gethostbyname() ...
- Spark—RDD编程常用转换算子代码实例
Spark-RDD编程常用转换算子代码实例 Spark rdd 常用 Transformation 实例: 1.def map[U: ClassTag](f: T => U): RDD[U] ...
- 利用ffmpeg将H264解码为RGB
因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作.在网上找了一圈,H264解码比較方便的也就是ffmpeg一系列的函数库了,原本设备中也是用这套函数库解码,但厂家不给提供,没办法,仅仅得 ...
- linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)
在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示. 420显示如 ...
- 嵌入式开发之davinci--- 8148/8168/8127 中的alsa音频pcm g711 和aac 音频格式
(1)alsa pcm (2)g711 (3)aac (4) --------------author:pkf -------------------time:2-4 ---------------- ...
随机推荐
- django框架基础-django redis-长期维护-20191220
############### django框架-django redis ############### # 学习django redis我能得到什么? # 1,项目中广泛使用到redis ...
- 经典题型-打印小星星(python)
# * # * * # * * * # * * * * # * * * * * x = 0 while x < 5: x += 1 # 每次循环需要给y赋值0.清空y中存储的值 y = 0 wh ...
- Mysql的分页查询语句的性能分析
MySql分页sql语句,如果和MSSQL的TOP语法相比,那么MySQL的LIMIT语法要显得优雅了许多.使用它来分页是再自然不过的事情了. 1.1最基本的分页方式: 在中小数据量的情况下,这样的S ...
- mongodb Map/reduce测试代码
private void AccountInfo() { ls.Clear(); DateTime dt = DateTime.Now.Date; IMongoQuery query = Query& ...
- Luogu_2878_[USACO07JAN]保护花朵Protecting the Flowers
题目描述 Farmer John went to cut some wood and left N (2 ≤ N ≤ 100,000) cows eating the grass, as usual. ...
- 一下午简单写个搭建Flutter开发环境,dome跑起来!
1.下载flutter包由于需要翻墙,国内下载会出现问题,所有需要先配置一下用户环境变量. export PUB_HOSTED_URL=https://pub.flutter-io.cn export ...
- 批量修改datafram中某一列
如要对df中列名为“values”的值做修改,大于等于50改为1,小于50改为0,可用apply函数来实现: def fun(x): if x >= 50: return 1 else: ret ...
- Hexo搭建总结
Hexo搭建过程记录 1.Hexo基本环境搭建 1.Hexo安装前提 Node.js和Git,他们的安装方法可以自行百度. 2.具体安装步骤可以参考: https://www.cnblogs.com/ ...
- AI未来如何应对人类的欺骗?
人工智能正以可预见.不可预见的种种形式无孔不入地涉足社会的各个层面,这既让人兴奋,也让人不安.我们能够预测到这样的情绪反应,但我们真的能够预测到人工智能所涉及的相关风险吗? 假若现在是2022年,你乘 ...
- 20170220-coroutine
协程 coroutine 最近频繁的听说到 "协程" 这个词,花了一段时间肤浅的研究了一下.对于 "它是一个什么东西" 有了一个大概的了解. from wiki ...