FFmpeg+SDL 学习笔记3,视频编码(RGB to MP4)

2023-05-16

1,步骤

1. 读取RGB文件转换为yuv
2. 压缩为h264
3. 封装为MP4

3X3RGB图像存放方式(连续)

在这里插入图片描述
每一个颜色放入一个字节,一个像素点称为一个RGB

YUV

“Y”表示明亮度,也就是灰度值
“U”和“V”表示色度
在这里插入图片描述

code

#include <iostream>
using namespace std;

extern "C"
{
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}

#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"/swscale.lib")
int p = 0;

int main()
{
	const char* iPath = "./file/test.rgb";
	const char* oPath = "./file/rgb.mp4";

	//注册所有的封装器解封装器
	av_register_all();
	//注册所有的编码器和解码器
	avcodec_register_all();
	
	//打开输入文件
	FILE* fp = fopen(iPath, "rb");
	if (!fp)
	{
		cout << "fopen" << endl;
		return -1;
	}

	int width = 848;
	int height = 480;
	int fps = 25;

	//1,create codec
	AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
	if (!codec)
	{
		cout << "avcodec_find_encoder" << endl;
		return -1;
	}
	//2,,创建编码上下文
	AVCodecContext* c = avcodec_alloc_context3(codec);
	if (!c)
	{
		cout << "avcodec_alloc_context3" << endl;
		return -1;
	}
	//设置压缩比特率(对应的视频压缩比例)
	c->bit_rate = 4000000000;
	c->width = width;
	c->height = height;
	//时间基准
	c->time_base = { 1,fps };
	c->framerate = { fps,1 };
	//画面组的大小,关键帧
	c->gop_size = 50;
	//b帧,越大,压缩率越高,视频越不清晰
	c->max_b_frames = 0;
	//像素格式
	c->pix_fmt = AV_PIX_FMT_YUV420P;
	c->codec_id = AV_CODEC_ID_H264;
	//全局的编码信息
	c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
	//多线程
	c->thread_count = 4;

	//2,打开编码器
	int ret = avcodec_open2(c, codec, NULL);
	if (ret < 0)
	{
		cout << "avcodec_open2" << endl;
	}
	cout << "avcodec_open success!" << endl;

	//3,创建输出上下文
	AVFormatContext* oc = NULL;
	avformat_alloc_output_context2(&oc, 0, 0, oPath);

	//添加视频的流信息
	AVStream* st = avformat_new_stream(oc, NULL);
	//st->codec = c;
	st->id = 0;
	st->codecpar->codec_tag = 0;
	avcodec_parameters_from_context(st->codecpar, c);

	cout << ".//" << endl;
	av_dump_format(oc, 0, oPath,1);


	//4,rgb to yuv
	SwsContext* ctx = NULL;
	sws_getCachedContext(ctx,
		width, height, AV_PIX_FMT_BGRA,		//输入的宽度、高度、格式
		width, height, AV_PIX_FMT_YUV420P,	//输出的宽度、高度、格式(可以一致,也可不一致)
		SWS_BICUBIC, NULL, NULL, NULL);		//SWS_BICUBIC转换时所用的算法

	//输入的空间
	unsigned char* rgb = new unsigned char[width * height * 4];//存放视频数据 *4是bgra(a无数据)
	//输出的空间
	AVFrame* yuv = av_frame_alloc();	//存放编码前的原始数据
	yuv->format = AV_PIX_FMT_YUV420P;
	yuv->width = width;
	yuv->height = height;
	//知道高度宽度像素格式之后,分配空间
	ret = av_frame_get_buffer(yuv,32);	//右32,对齐方式
	if (ret < 0)
	{
		cout << "av_frame_get_buffer" << endl;
		return -1;
	}


	//5,写入MP4的头文件
	ret = avio_open(&oc->pb, oPath, AVIO_FLAG_WRITE);
	if (ret < 0)
	{
		cout << "avio_open" << endl;
		return - 1;
	}
	ret = avformat_write_header(oc, NULL);
	if (ret < 0)
	{
		cout << "avformat_write_header" << endl;
		return -1;
	}

	cout << "测试" << endl;

	for (;;)
	{
		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)
		{
			cout << "avcodec_send_frame" << endl;
			return -1;
		}
		AVPacket pkt;
		av_init_packet(&pkt);
		ret = avcodec_receive_packet(c, &pkt);
		if (ret != 0)
		{
			cout << "avcodec_receive_packet" << endl;
			continue;
		}

		cout << "《" << pkt.size << "》" << endl;
		//写入
		//av_write_frame(oc, &pkt);
		//av_packet_unref(&pkt);//释放pkt中的某些资源
		av_interleaved_write_frame(oc, &pkt);

	}
	//写入视频索引
	av_write_trailer(oc);
	//关闭视频输出io
	avio_close(oc->pb);
	//清理封装输出上下文
	avformat_free_context(oc);
	//关闭编码器
	avcodec_close(c);
	//清理编码器上下文
	avcodec_free_context(&c);
	//清理视频重采样上下文

	cout << "---------------------end----------------" << endl;


	//6,encode frame(编码)
	delete rgb;
	getchar();
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FFmpeg+SDL 学习笔记3,视频编码(RGB to MP4) 的相关文章

  • GitHub第三方资源库整理(OC篇)

    http www jianshu com p a1c3b7d5bab1 随着GitHub star 的项目越来越多 xff0c 而且之前也没有整理 xff0c 所以找起来特别麻烦 xff0c 于是就有了这篇文章 xff0c 一是方便我自己查
  • 整理的一些swift开源项目,仅供学习交流!!

    1 swift3 0开发的自学英语社区app 2 https github com netyouli 3 六阿哥的开源项目 xff0c 均已上架 新版剑三壁纸库app xff0c 使用swift开发 使用swift语言写的一款新闻资讯类的a
  • 令世人惊叹的服务器端 Swift!

    转自 xff1a http www code4app com blog 822721 634 html 时至今日 xff0c Swift 已然演变成了一门开源 跨平台的编程语言 xff0c 有许多个团队正在竞相利用 Swift 语言能够用于
  • 33 个 2017 年必须了解的 iOS 开源库

    http www cocoachina com ios 20170208 18647 html 本文翻译自Medium xff0c 原作者为Pawe Bia ecki 照片版权 xff1a xff08 Unsplash Markus Pe
  • 整理的一些iOS 开源框架

    1 一个拥有多种优雅风格的搜索控制器 https github com iphone5solo PYSearch
  • Windows端通过Vscode或PowerShell连接linux服务器,打开图形界面的程序

    问题 Windows主机不进行任何配置ssh连接到linux服务器上 xff0c 打开图形界面软件 xff0c 会出现下面的错误 xff1a gedit 46927 Gtk WARNING cannot open display 解决Win
  • 循环依赖问题终极解决方案

    今天下午给师兄抽云图数据的时候 xff0c 报错了 说到底还是C 43 43 太菜了 xff0c 调试了一会才发现是写了个循环依赖 xff0c 这四个字是这篇文章的重点 这个不是头文件重复包含的问题 xff0c 看下面的图可能一下就明白了菜
  • Linux ln命令、软链接和硬链接的区别

    前些天发现了一个巨牛的人工智能学习网站 xff0c 通俗易懂 xff0c 风趣幽默 xff0c 忍不住分享一下给大家 点击跳转到教程 Linux ln命令是一个非常重要命令 xff0c 它的功能是为某一个文件在另外一个位置建立一个同步的链接
  • mysql 查找配置文件 my.ini 位置方法

    前些天发现了一个巨牛的人工智能学习网站 xff0c 通俗易懂 xff0c 风趣幽默 xff0c 忍不住分享一下给大家 点击跳转到教程 个人备注 xff1a 不显示文件类型时 xff0c my ini 文件名就叫作 my xff0c 文件属性
  • VS2019 + CUDA10.1 安装和配置

    VS2019 43 CUDA10 1 安装和配置 1 CUDA 10 1 安装 1 cuda官方下载网址 xff0c 找到cuda版本为cuda10 1 xff0c 选择自己系统对应的版本下载安装程序 2 运行cuda 10 1 243 4
  • pip使用清华镜像下载

    pip使用清华镜像下载 在国内使用pip安装python第三方包时 xff0c 可能会出现下载速度较慢的情况 xff0c 这时可以尝试从国内的pip镜像源下载这些包 xff0c 大大加快下载速度 xff1a 我们常用清华源 xff0c 在p
  • windows10安装Ubuntu20.04及界面图形化

    这里写自定义目录标题 windows10安装Ubuntu20 04及界面图形化一 安装前windows的配置二 ubuntu20 04系统安装三 ubuntu 20 04更换清华大学源四 中文汉化五 安装图形界面 xff0c VcXsrv的
  • opencv 获取rtsp原始码流代码

    opencv不仅可以获取解码后的图片数据 xff0c 还可以获取未经解码的原始码流数据 这样为使用其他硬解码器提供方便 在编译opencv cmake时需要指定 D WITH FFMPEG 61 ON python 代码如下 xff0c 需
  • 通过Launchpad查找PPA仓库

    我们通常会通过查找安装命令得知一些仓库名 xff0c 我们还可以通过Ubuntu Launchpad网站查询更多信息 首先登录https launchpad net 然后搜索自己关心的ppa xff0c 例如我们搜索得到了ppa jonat
  • ffmpeg 中 rtsp相关源码解析(五)

    lt lt ffmpeg 中 rtsp相关源码解析 四 gt gt 简单介绍了rtp包是通过ff rtsp fetch packet来获取的 我们更深入地问一个问题 xff0c 那么对于vp8 h264等音视频编解码标准 xff0c 这些p
  • 庆祝博客访问量即将突破20万

    2018年开始更新博客 xff0c 到现在已有3年 博客访问量预计这周就突破20万 本来写这博客并没有特别的目的 xff0c 只是想记录在工作学习过程中遇到的问题 也没想到会有这么多的访问 从南京到无锡再到上海 xff0c 一次次突破 从0
  • ffmpeg 源码分析 解码流程

    以ffmpeg 3 4 中的ffplay 来举例 全局初始化 av register all avformat network init AVFORMAT 设置过程 avformat alloc context avformat open
  • post传数组

    业务中涉及批量删除 xff0c 就需要传多个id xff0c 用数组吧 在post中 xff0c 参数都是键值对的形式 xff0c 键和值都是string类型 xff0c 那么就需要把数组序列化为string的形式 Array toStri
  • 基于OpenCV+QT的实时视频传输显示工具(一)

    时常会找一些比较有趣的东西来看 xff0c 但一般都是看完尝试了事 xff0c 没怎么做出总结过 现在想想真是可惜 xff0c 这么多年来 xff0c 看得东西也不少 xff0c 但是留下的印记却很少 xff0c 结果就是找工作时 xff0
  • Gstreamer基础知识介绍

    由于deepstream是基于gstreamer的 xff0c 所以要想在deepstream上做拓展 xff0c 需要对gstreamer有一定的认识 以下主要介绍Gstreamer整体框架和Gstreamer基础概念 一 Gstream

随机推荐