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解码的更多相关文章

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

    http://blog.csdn.net/leixiaohua1020/article/details/25430449 本文介绍一个最简单的基于FFMPEG的音频编码器.该编码器实现了PCM音频采样 ...

  2. 基于FFmpeg的音频编码(PCM数据编码成AAC android)

    概述 在Android上实现录音,并利用 FFmpeg将PCM数据编码成AAC. 详细 代码下载:http://www.demodashi.com/demo/10512.html 之前做的一个demo ...

  3. 爬取编程常用词汇,保存为Excel

    编程常用词汇 import requests import openpyxl from lxml import etree import re url = 'https://www.runoob.co ...

  4. VBA编程常用词汇英汉对照表

    表 20‑1到表 20‑8是VBA编程中使用频率最高的英文单词,按字母排序.词性列中,a表示形容词,n表示名词,v表示动词,p表示介词以及其他词性. 表 20‑1 VBA编程常用词汇表 单词 中文 词 ...

  5. UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数

    UNIX环境高级编程——TCP/IP网络编程   常用网络信息检索函数 gethostname()   getppername()   getsockname()   gethostbyname() ...

  6. Spark—RDD编程常用转换算子代码实例

    Spark-RDD编程常用转换算子代码实例 Spark rdd 常用 Transformation 实例: 1.def map[U: ClassTag](f: T => U): RDD[U]  ...

  7. 利用ffmpeg将H264解码为RGB

    因为公司买到了一个不提供解码器的设备,我不得已还要做解码的工作.在网上找了一圈,H264解码比較方便的也就是ffmpeg一系列的函数库了,原本设备中也是用这套函数库解码,但厂家不给提供,没办法,仅仅得 ...

  8. linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)

    在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示. 420显示如 ...

  9. 嵌入式开发之davinci--- 8148/8168/8127 中的alsa音频pcm g711 和aac 音频格式

    (1)alsa pcm (2)g711 (3)aac (4) --------------author:pkf -------------------time:2-4 ---------------- ...

随机推荐

  1. K3CLOUD表关联

    销售订单关联发货通知单 销售订单表 T_SAL_ORDER A T_SAL_ORDERENTRY B T_SAL_ORDERENTRY_LK C 发货通知单表 T_SAL_DELIVERYNOTICE ...

  2. 奇点云数据中台技术汇(四)| DataSimba系列之流式计算

    你是否有过这样的念头:如果能立刻马上看到我想要的数据,我就能更好地决策?   市场变化越来越快,企业对于数据及时性的需求,也越来越大,另一方面,当下数据容量呈几何倍暴增,数据的价值在其产生之后,也将随 ...

  3. [LC] 429. N-ary Tree Level Order Traversal

    Given an n-ary tree, return the level order traversal of its nodes' values. Nary-Tree input serializ ...

  4. [LC] 23. Merge k Sorted Lists

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. E ...

  5. 76)PHP,session数据区的使用

    (1)session数据区: 在我们的session会话结束之前,会有一个seeeion的文件,存储着session序列化的数据,在会话没有结束之前,我们都是操作$_SESSION的,但是在会话结束后 ...

  6. Jumpserver 一键部署(支持离线安装)

    1.教程介绍1.1::通过本教程起到抛砖引玉效果,希望各位喜爱Jumpserver堡垒机的朋友受益良多. 1.2::以下提供的任何软件仅供学习交流使用. 2.下载链接2.1::centos_1810最 ...

  7. Django ORM单表查询必会13条

    必知必会13条 操作下面的操作之前,我们实现创建好了数据表,这里主要演示下面的操作,不再细讲创建准备过程 <1> all(): 查询所有结果 <2> filter(**kwar ...

  8. [LC] 152. Maximum Product Subarray

    Given an integer array nums, find the contiguous subarray within an array (containing at least one n ...

  9. [LC] 71. Simplify Path

    Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the ca ...

  10. JDBC原理之层次结构

    目录 JDBC的层次结构 前言 Collection角色 Statement角色 ResultSet角色 JDBC工作的基本流程 JDBC的层次结构 前言 JDBC API提供了以下接口和类: Dri ...