当前位置:网站首页>ffmpeg RGB raw数据H264编码写mp4
ffmpeg RGB raw数据H264编码写mp4
2022-08-06 05:26:00 【音视频开发老舅】
时间戳基本概念
时间戳:计算的单位不是秒,时间戳的单位采用的是采样频率的倒数,这样做的目的就是为了时间戳单位更精准。比如说一个音频的采样频率为8000Hz,那么我们可以把时间戳单位设为1 / 8000。
时间戳增量:相邻两帧之间的时间差(以时间戳单位为基准)。ORTP库中根据负载类型直接给定了时间戳的单位(音频负载1/8000,视频负载1/90000)。如果采样频率为90000Hz,则由上面讨论可知,时间戳单位为1/90000,我们就假设1秒钟被划分了90000个时间块,那么,如果每秒发送25帧,那么,每一个帧的发送占多少个时间块呢?当然是 90000/25 = 3600。因此,我们根据定义“时间戳增量是发送第二个RTP包相距发送第一个RTP包时的时间间隔”,故时间戳增量应该为3600。如果fps=50,那么pts增量就是1800。本人此处踩坑,设置fps=50,h264编码始终是25.
采样频率: 也叫时钟频率,即每秒钟抽取样本的次数,例如音频的采样率8000Hz,48k Hz等。
code:
时间戳基本概念
时间戳:计算的单位不是秒,时间戳的单位采用的是采样频率的倒数,这样做的目的就是为了时间戳单位更精准。比如说一个音频的采样频率为8000Hz,那么我们可以把时间戳单位设为1 / 8000。
时间戳增量:相邻两帧之间的时间差(以时间戳单位为基准)。ORTP库中根据负载类型直接给定了时间戳的单位(音频负载1/8000,视频负载1/90000)。如果采样频率为90000Hz,则由上面讨论可知,时间戳单位为1/90000,我们就假设1秒钟被划分了90000个时间块,那么,如果每秒发送25帧,那么,每一个帧的发送占多少个时间块呢?当然是 90000/25 = 3600。因此,我们根据定义“时间戳增量是发送第二个RTP包相距发送第一个RTP包时的时间间隔”,故时间戳增量应该为3600。如果fps=50,那么pts增量就是1800。本人此处踩坑,设置fps=50,h264编码始终是25.
采样频率: 也叫时钟频率,即每秒钟抽取样本的次数,例如音频的采样率8000Hz,48k Hz等。
code:
extern "C"
{
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
#include <iostream>
using namespace std;
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
int main()
{
char infile[] = "out.rgb";
char outfile[] = "rgb.mp4";
//新版ffmpeg 不用注册
FILE *fp = fopen(infile,"rb");
if (!fp)
{
cout << infile << " open failed!" << endl;
getchar();
return -1;
}
int width = 848;
int height = 480;
int fps = 25;
//1 创建编码器
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec)
{
cout << " avcodec_find_encoder AV_CODEC_ID_H264 failed!" << endl;
getchar();
return -1;
}
//编码器上下文
AVCodecContext *c = avcodec_alloc_context3(codec);
if (!c)
{
cout << " avcodec_alloc_context3 failed!" << endl;
getchar();
return -1;
}
//设置视频编码相关参数
//比特率
c->bit_rate = 400000000;
c->width = width;
c->height = height;
//把1秒钟分成fps个单位
c->time_base = { 1,fps };
c->framerate = { fps,1 };
c->gop_size = 50;
c->max_b_frames = 0;
c->pix_fmt = AV_PIX_FMT_YUV420P;
c->codec_id = AV_CODEC_ID_H264;
c->thread_count = 8;
//全局的编码信息
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
//h264编码器
AVDictionary* param = 0;
if (avcodec_context->codec_id == AV_CODEC_ID_H264)
{
av_dict_set(¶m, "preset", "fast", 0);
av_dict_set(¶m, "tune", "zerolatency", 0);
}
//打开编码器
int ret = avcodec_open2(c,codec,NULL);
if (ret < 0)
{
cout << " avcodec_open2 failed!" << endl;
getchar();
return -1;
}
cout << "avcodec_open2 success!" << endl;
//2 create out context
AVFormatContext *oc = NULL;
avformat_alloc_output_context2(&oc, 0, 0, outfile);
//3 add video stream
AVStream *st = avformat_new_stream(oc,NULL);
st->id = 0;
st->codecpar->codec_tag = 0;
avcodec_parameters_from_context(st->codecpar,c);
cout << "===============================================" << endl;
av_dump_format(oc, 0, outfile, 1);
cout << "===============================================" << endl;
//4 rgb to yuv
//改变视频尺寸
SwsContext *ctx= NULL;
ctx = sws_getCachedContext(ctx,
width,height,AV_PIX_FMT_BGRA,
width,height,AV_PIX_FMT_YUV420P,SWS_BICUBIC,
NULL,NULL,NULL);
//输入空间
unsigned char *rgb = new unsigned char[width*height*4];
//输出空间
AVFrame *yuv = av_frame_alloc();
yuv->format = AV_PIX_FMT_YUV420P;
yuv->width = width;
yuv->height = height;
//分配空间
ret = av_frame_get_buffer(yuv,32);
if (ret < 0)
{
cout << " av_frame_get_buffer failed!" << endl;
getchar();
return -1;
}
//5 write mp4 head
ret = avio_open(&oc->pb,outfile,AVIO_FLAG_WRITE);
if (ret < 0)
{
cout << " avio_open failed!" << endl;
getchar();
return -1;
}
ret = avformat_write_header(oc, NULL);
if (ret < 0)
{
cout << " avformat_write_header failed!" << endl;
getchar();
return -1;
}
int p = 0;
for (;;)
{
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
//ptr -- 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
//size -- 这是要读取的每个元素的大小,以字节为单位。
//nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
//stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。
int len = fread(rgb,1,width*height*4,fp);
if (len<=0)
{
break;
}
uint8_t *indata[AV_NUM_DATA_POINTERS] = { 0 };
indata[0] = rgb;
int inlinesize[AV_NUM_DATA_POINTERS] = { 0 };
inlinesize[0] = width * 4;
int h = sws_scale(ctx,indata,inlinesize,0,height,yuv->data,yuv->linesize);
if (h<=0)
{
break;
}
//6 encode frame
yuv->pts = p;
p = p + 3600;
//发送到编码器
ret = avcodec_send_frame(c,yuv);
if (ret != 0)
{
continue;
}
AVPacket pkt;
av_init_packet(&pkt);
//接收编码结果
ret = avcodec_receive_packet(c,&pkt);
if (ret != 0)
continue;
//将编码后的帧写入文件
av_interleaved_write_frame(oc,&pkt);
cout << "<" << pkt.size << ">";
}
//写文件尾
av_write_trailer(oc);
//关闭视频输出IO
avio_close(oc->pb);
//清理封装输出上下文
avformat_free_context(oc);
//关闭编码器
avcodec_close(c);
//清理编码器上下文
avcodec_free_context(&c);
//清理视频重采样上下文
sws_freeContext(ctx);
cout << "======================end=========================" << endl;
delete rgb;
getchar();
return 0;
}
原文链接:ffmpeg RGB raw数据H264编码写mp4 - 资料 - 我爱音视频网 - 构建全国最权威的音视频技术交流分享论坛
本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击领取↓↓
边栏推荐
- MacOS下 Qt6编译及链接MySQL
- 十、 一起学习Lua 数组
- ELK日志分析系统(二)之ELK搭建部署
- 【R语言】在Jupyter Notebook中使用conda管理的R语言
- 关于Warning:Implicit declaration of function “xxx” is invalid in C99警告!
- Qt 5.14.2 connect to Mysql database
- SourceTree 常用技巧
- MySQL复习
- R_文字识别(OCR)
- pip命令安装工具包时出现ReadTimeoutError或者THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE问题解决
猜你喜欢

Zero foundation to build their own famine Don 't Starve server, get rid of the online caton and happy friend online

简易数据库管理系统(DBMS)设计与实现

【多传感器融合】技术学习路线一篇全

Qt教程(2) : Qt元对象系统

R软件的下载与更新

【图像处理】RGB、YUV (YCbCr) 图像表示详解

WebRTC之RTP封装与解封装

Ad Hoc Query - Kylin

【R语言】环境配置Anaconda + R4.1.3 + Pycharm

SemEval 2022 | 将知识引入NER系统,阿里达摩院获最佳论文奖
随机推荐
一起了解分层架构&SOA架构
新朋老友齐聚首,共话「图形学」未来 | 将门行动派特别直播企划,就在7月6日晚!
R_文字识别(OCR)
【多传感器融合】激光雷达与相机前融合
多线程:定时器
SourceTree Common Tips
CW008A 铜合金
Files遍历子文件、遍历目录树方法
NAACL 2022 | 字节和加州大学提出ConST模型,探讨对比学习如何助力语音翻译?
CW008A Copper alloy
R数据分类汇总
Qt智能指针
AMPCOLOY940 high thermal conductivity beryllium-free copper alloy imported from the United States
Vs2019编译OpenCv3
泊松回归R语言实例
斐波那契序列,数组排序,在数组中查找对应元素Objects类的equals方法的作用,将26个英文字母用逗号分隔,组成字符串打印出来,矩阵的转置,找出1~1000之间的全部同构数,用随机数生成语句
KDD 2022 | 中科院计算所提出STABLE:一种无监督高鲁棒性图结构学习框架
十五、一起学习Lua 协同程序(coroutine)
(中)苹果有开源,但又怎样呢?
QT5.14 实现简单用户登录系统