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 ---------------- ...
随机推荐
- python中字典以key排序,以value排序。以及通过value找key的方式
1.sorted函数首先介绍sorted函数,sorted(iterable,key,reverse),sorted一共有iterable,key,reverse这三个参数. 其中iterable表示 ...
- Java IO: 字符流的Piped和CharArray
作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 本章节将简要介绍管道与字符数组相关的reader和writer,主要涉及PipedReader.Pip ...
- JavaScript学习总结(八)正则表达式
转自:http://segmentfault.com/a/1190000000699097 基本概念 正则表达式是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”) ...
- python3下scrapy爬虫(第三卷:初步抓取网页内容之抓取网页里的指定数据)
上一卷中我们抓取了网页的所有内容,现在我们抓取下网页的图片名称以及连接 现在我再新建个爬虫文件,名称设置为crawler2 做爬虫的朋友应该知道,网页里的数据都是用文本或者块级标签包裹着的,scrap ...
- ionic2踩坑之兼容android4.3及以下版本
一个命令就行了 ionic plugin add cordova-plugin-crosswalk-webview --save 执行完之后重新打包. 但是如果要兼容4.0及以下的话.... 帮不了你 ...
- 写了个通作的分页存储过程,top,加入了排序
USE [WebDB_TradeOrder]GO/****** Object: StoredProcedure [dbo].[Boss_Proc_PagingWithOrder] Script ...
- Python-多任务复制文件夹
import multiprocessing import os import time def copy_file(queue, file_name, old_folder_name, new_fo ...
- upper_bound()函数使用方法
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end.通过返回的地址减去起始地址beg ...
- Catch That Cow (BFS)
题目: Farmer John has been informed of the location of a fugitive cow and wants to catch her immediate ...
- .NET Core 获取程序运行环境信息与反射的应用
目录 RuntimeInformation.Environment 获取信息 反射获取信息 获取某个属性的值以及别名 反射获取信息 使用 总结 笔者的九篇反射系统文章已经完结,但是笔者会持续更新反射在 ...