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 ---------------- ...
随机推荐
- 102)PHP,目录操作
基本的操作: 创建目录: mkdir(目录地址,权限,是否递归创建=false); 注意第二个参数在windows系统下没有作用, 递归创建,就是多级目录,要是设计不存在目录,就自动创建 删除目录 R ...
- Emgu.CV.CvInvoke的类型初始值设定项引发异常”TypeInitializationException”的问题
问题如图: 解决方案: 1.记住EmguCV的安装位置:X:\XXX\XXX… 本测试方案中EmguCV的安装位置:D:\Emgu,操作时记得用自己的EmguCV安装路径替换掉D:\Emgu. 2.添 ...
- 解决scoped 下confirm 样式问题
- vue项目中net::ERR_CONNECTION_TIMED_OUT错误
我出错的原因时network地址与我本机ip地址不一致 Network: http://192.168.13.30:8080/ 处理方法: 在vue项目中新建一个vue.config.js文件 配置上 ...
- 使用Spring AOP 实现日志管理(简单教程)
有时候,我们在做项目时会遇到这样的需求: 给XXX.java中的所有方法加上指定格式的日志输出. 针对这种指定类.或者指定方法进行共性操作的功能,我们完全可以使用Spring AOP来实现. 本文使用 ...
- Django的乐观锁与悲观锁实现
1) 事务概念 一组mysql语句,要么执行,要么全不不执行. 2) mysql事务隔离级别 Read Committed(读取提交内容) 如果是Django2.0以下的版本,需要去修改到 ...
- echo追加和覆盖
追加: echo " " >> 文件名 覆盖: echo " " > 文件名
- IIS6.0远程命令执行
0X00 漏洞信息: 漏洞编号:CVE-2017-7269 漏洞简述:开启WebDAV服务的IIS 6.0被爆存在缓存区溢出漏洞导致远程代码执行,目前针对 Windows Server2003 R2 ...
- 吴裕雄--天生自然HTML学习笔记:关闭8080端口被占用怎么办?关闭8080端口被占用
- 吴裕雄--天生自然 R语言开发学习:基本数据管理(续二)
#---------------------------------------------------------# # R in Action (2nd ed): Chapter 4 # # Ba ...