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 ---------------- ...
随机推荐
- 二、RabbitMQ简介及AMQP协议
RabbitMQ简介 RabbitMQ是开源的消息代理和队列服务器,是由Erlang语言开发的,基于AMQP协议(Advanced Message Queuing Protocol高级消息队列协议)的 ...
- jsonp和callback的使用
这两天用 Jquery 跨域取数据的时候,经常碰到 invalid label 这个错误,十分的郁闷,老是取不到服务器端发送回来的 json 值, 一般跨域用到的两个方法为:$.ajax 和$.get ...
- 吴裕雄--天生自然Android开发学习:1.2.1 使用Eclipse + ADT + SDK开发Android APP
1.前言 这里我们有两条路可以选,直接使用封装好的用于开发Android的ADT Bundle,或者自己进行配置 因为谷歌已经放弃了ADT的更新,官网上也取消的下载链接,这里提供谷歌放弃更新前最新版本 ...
- 吴裕雄--天生自然python学习笔记:Python3 OS 文件/目录方法
os 模块提供了非常丰富的方法用来处理文件和目录.常用的方法如下表所示: 序号 方法及描述 1 os.access(path, mode) 检验权限模式 2 os.chdir(path) 改变当前工作 ...
- 2018湖南省赛B题“2018”
题面懒得敲了,反正看这篇博客的肯定知道题面. 比赛时想按约数的一些性质分情况讨论出公式然后在合并,结果单考虑矩阵里出现2018和1009(与2互质,1009出现次数等于2)出现的情况就写了一长串公式, ...
- linux系统下rpm包的安装、删除、效验、查询
详细课程 使用 RPM RPM 有五个基本的操作 模式(不包括包的编译): 安装,卸载,升级,查询,校验.本节将对它们一一介绍.要了解完整的细节和选项,可以使用 rpm --help, 或转到 the ...
- Day learn,day up
前言 忽略我这个中文式英语的标题. 身为一个记性不咋地的前端渣渣,觉得平时看的一些文章太散了,特开此文作为一种记录,可谓好记性不如烂笔头,也算是逼自己要经常学习.文章的日期为最后更新时间,题目顺序不分 ...
- Python【map、reduce、filter】内置函数使用说明
题记 介绍下Python 中 map,reduce,和filter 内置函数的方法 一:map map(...) map(function, sequence[, sequence, ...]) -& ...
- Promise 的含义
Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Pro ...
- Ubuntu环境下的iptables的端口转发配置实例
打开转发开关要让iptables的端口转发生效,首先需要打开转发开关方法一:临时打开,重启后失效$sudo su#echo 1 >/proc/sys/net/ipv4/ip_forward 方法 ...