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

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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ffmpeg sdl是一种基于ffmpegsdl开发视频播放器。ffmpeg是一个开源的跨平台音视频解决方案,支持包括视频采集、编码、解码、转码、播放等功能,被广泛应用于视频处理和视频播放领域。而sdl是一种跨平台开放源代码的多媒体库,提供了音频、视频、事件等处理功能,它是一个适合于游戏和媒体应用的库。 ffmpeg sdl视频播放器利用ffmpeg库解码文件,将视频数据解码成RGB格式的图片数据,然后使用sdl库将图片数据渲染到屏幕上。通过这种方式,可以实现基于CPU的视频播放。 ffmpeg sdl视频播放器具有以下特性: 1. 支持多种视频格式:ffmpeg支持的视频格式非常丰富,几乎可以处理所有常见的视频格式,例如MP4、AVI、FLV等。因此,ffmpeg sdl视频播放器可以播放多种格式的视频。 2. 良好的兼容性:ffmpeg sdl视频播放器可以运行在多个平台上,例如Windows、Linux、Android等平台。 3. 可扩展性强:ffmpegsdl都是开源的项目,可以方便地进行开发和扩展。同时,ffmpeg sdl视频播放器还支持自定义音频和视频渲染。 4. 轻量级:ffmpeg sdl视频播放器采用的是CPU进行解码,因此不需要额外的硬件加速。同时,ffmpegsdl都是轻量级的库,不会占用过多的系统资源。 总之,ffmpeg sdl视频播放器是一种非常方便的视频播放解决方案,具有兼容性强、支持视频格式多、可扩展性强等优点。它可以为视频处理和视频播放提供极佳的支持,并且可以适用于多种平台和应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值