ffmpeg学习日记121-视频-各种图片转yuv

news2024/11/14 5:54:42
Author: wencoo
Blog:https://wencoo.blog.csdn.net/
Date: 24/04/2023
Details:

在这里插入图片描述

文章目录

  • 实现功能
  • 查看转换结果
  • 参考

图片的解码方式和视频解码是一样的,因为视频是由一副一副的图片组成的,只不过视频的帧会前后参考,而图片是单独的一帧的格式封装。

这其中有一个功能点需要注意,不同的图片格式封装算法不同,所以解码使用的解码器也不同,我现在不清楚什么格式对应什么解码器,所以采用通过id的方式来查找解码器,是一种靠谱的行为。

实现功能

将png图片转换为yuv数据,示例代码如下:

#include <iostream>
#include <fstream>
#include <sstream>
#include <jsoncpp/json/json.h>
#include <tuple>


extern "C"
{
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <libavcodec/avcodec.h>

#include <libavformat/avformat.h>
#include <libavformat/avio.h>

#include <libavutil/audio_fifo.h>
#include <libavutil/avassert.h>
#include <libavutil/avstring.h>
#include <libavutil/dict.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavutil/pixdesc.h>
#include <libavutil/samplefmt.h>
#include <libavutil/time.h>
#include <libavutil/timestamp.h>

#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavfilter/avfilter.h>

#include <libswresample/swresample.h>
}

int main()
{
	std::cout << "Hello World!" << std::endl;
	printf("ffmpeg version:%s\n", av_version_info());

	int ret = 0;

	// input yuv
	//打开png图片
	// png转换为yuv指令为:ffmpeg -i %4d.png -pix_fmt yuv420p -s 1984x1344 out.yuv

	FILE *inFile = NULL;
	const char *inFileName = "bg.png";
	inFile = fopen(inFileName, "rb+");
	if (!inFile)
	{
		printf("Fail to open file\n");
		return -1;
	}

	int in_width = 48;
	int in_height = 48;

	// output yuv
	FILE *outFile = NULL;
	const char *outFileName = "output.yuv";
	outFile = fopen( outFileName, "wb");
	if (!outFile)
	{
		printf("Fail to create file for output\n");
		return -1;
	}

	AVFormatContext  *pFormatCtx = NULL;
	if (avformat_open_input(&pFormatCtx, inFileName, NULL, NULL) != 0)
	{
		fprintf(stderr, "Couldn't open input filen");
		return -1;
	}

	if (avformat_find_stream_info(pFormatCtx,0) < 0){
		fprintf(stderr ,"av_find_stream_info ERRORn");
		return -1;
	}

	int videoStream = -1;
	for (int i = 0; i < pFormatCtx->nb_streams; i++)
	{
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			videoStream = i;
			fprintf(stderr ,"the first video stream index: videoStream = %d\n", videoStream);
			break;
		}
	}
	if (videoStream == -1)
		return -1; // Didn't find a video stream

	AVCodecContext *codeCtx = pFormatCtx->streams[videoStream]->codec;
	if (!codeCtx)
	{
		fprintf(stderr, "Could not allocate video codec context\n");
		exit(1);
	}

	std::cout << "pix_fmt:" << codeCtx->pix_fmt << std::endl;

	//打开mp4文件
	const AVCodec *codec = avcodec_find_decoder(codeCtx->codec_id);
	if (!codec)
	{
		fprintf(stderr, "Codec not found\n");
		exit(1);
	}

	if (avcodec_open2(codeCtx, codec, NULL) < 0)
	{
		fprintf(stderr, "Could not open codec\n");
		exit(1);
	}

	AVFrame *frame = av_frame_alloc();
	if (!frame)
	{
		fprintf(stderr, "Could not allocate video frame\n");
		exit(1);
	}

	AVPacket *pkt = av_packet_alloc();
	if (!pkt){
		fprintf(stderr, "Could not allocate video packet\n");
		exit(1);
	}

	uint8_t *video_dst_data[4] = {NULL};
	int video_dst_linesize[4] = {0};
	ret = av_image_alloc(video_dst_data, video_dst_linesize, in_width, in_height, codeCtx->pix_fmt,1);
	if (ret < 0){

	}
	int video_dst_bufsize = ret;

	int indexNum = 1;
	while (av_read_frame(pFormatCtx, pkt) >= 0)
	{
		if (pkt->stream_index == videoStream){
			ret = avcodec_send_packet(codeCtx,pkt);

			while(ret >= 0){
				ret = avcodec_receive_frame(codeCtx,frame);
				if (ret < 0 || ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
				{
					break;
				}

				if (codeCtx->codec->type == AVMEDIA_TYPE_VIDEO){
					//获取到了yuv视频帧
					av_image_copy(video_dst_data, video_dst_linesize,
								  (const uint8_t **)(frame->data), frame->linesize,
								  codeCtx->pix_fmt, in_width, in_height);
					char tmpstr[100] = {};
					sprintf(tmpstr, "yuv-%d.yuv", indexNum);
					FILE *f1;
					f1 = fopen(tmpstr, "wb");
					fwrite(video_dst_data[0], 1, video_dst_bufsize, f1);
					fclose(f1);
					indexNum++;
				}
			}
		}
		av_packet_unref(pkt);
		if (ret < 0)
			break;
	}

	fclose(inFile);
	fclose(outFile);
	return 0;
}

查看转换结果

使用ffplay进行播放查看,需指定格式

ffplay.exe -f rawvideo -video_size 48x48 -pix_fmt rgba -i .\yuv-1.yuv

参考

  • FFmpeg开发实战(六):jpeg转换为yuv格式图像

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/689351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OCR本地搜题(无需网络)

1、先下载好所需要的软件 2、安装.NET&#xff08;必须&#xff0c;否则无法使用&#xff09; 安装步骤&#xff1a;全部默认。 3、找到ScreenshotsSearch下的狗头 4、界面如下 5、点击 题库后&#xff0c;先清空题库 6在点击下方用Excel打开题库&#xff08;选择好题库文件&a…

点击左侧 - 右侧页面对应刷新(iframe)

在工作方面的需求&#xff0c;需要实现点击左侧栏目&#xff0c;右侧的内容对应更改。 这里&#xff0c;我运用了iframe来实现这个功能&#xff01;&#xff08;布局的话,使用了flex弹性布局&#xff09; 完整效果图。 左侧导航显示代码&#xff1a; <div class"lef…

菜鸡shader:L4三色环境光原理妙用并在ue4中实现

三色环境光的拓展运用 我的上一篇博客写了关于三色环境光的原理&#xff0c;这次就来简单拓展一下。最重要的核心思想其实就是取法线向量的第二个分量&#xff0c;因为它控制方法是指向xz平面的上或者下。 所以这次要用这个原来来单独摘出上层环境光&#xff0c;乘上菲涅尔&a…

【Java项目 读写分离技术】

文章目录 Java项目 读写分离技术1 Mysql 主从复制1.1 介绍1.2 配置 2 读写分离实现2.1 背景2.2 Sharding-JDBC 介绍2.3 配置步骤 Java项目 读写分离技术 面对日益增加的系统访问量&#xff0c;数据库的吞吐量面临着巨大瓶颈。对于同一时刻有大量并发读操作和较少写操作类型的应…

el-date-picker设置今天之前的日期不可选

<el-date-pickerv-model"editForm.offlineTime"type"date"placeholder"选择日期"style"width: 150px":picker-options"{disabledDate: (time) >time.getTime() <new Date(new Date().setHours(0, 0, 0, 0))}">&…

GCDW云原生数据仓库获评“2023优秀科技成果奖”

5月26日&#xff0c;“2023中国国际大数据产业博览会”在贵阳盛大开幕&#xff0c;同日举行了“领先科技成果发布会”&#xff0c;来自国内外高校、科研机构、科技企业的357项优秀成果参与申报&#xff0c;代表了近年来国内外大数据领域最前沿的科技成果。“南大通用GCDW云原生…

原生JS实现图片裁剪功能(fixed布局)

功能介绍&#xff1a;图片通过原生input上传&#xff0c;使用canvas进行图片裁剪。 裁剪框限制不允许超出图片范围&#xff0c;图片限制了最大宽高&#xff08;自行修改要的尺寸&#xff09;&#xff0c;点击确认获取新的base64图片数据&#xff0c;大部分需求都是弹窗进行处理…

office word 2007

office word 2007 指数怎么写的

反AI来了…尼康的Natural Intelligence

a mutant_umbrella tree shaped like a nuclear bomb explosion,a photo-realism photograph, 4k, ultra realistic VS a mutant_umbrella tree shaped like a nuclear bomb explosion 尼康发起了一次名为&#xff1a;Natural Intelligence &#xff0c;“不要放弃现实世界”的…

机器学习之K-means聚类算法

目录 K-means聚类算法 算法流程 优点 缺点 随机点聚类 人脸聚类 旋转物体聚类 K-means聚类算法 K-means聚类算法是一种无监督的学习方法&#xff0c;通过对样本数据进行分组来发现数据内在的结构。K-means的基本思想是将n个实例分成k个簇&#xff0c;使得同一簇内数据相…

Java性能权威指南-总结18

Java性能权威指南-总结18 线程与同步的性能线程同步避免同步伪共享 线程与同步的性能 线程同步 避免同步 如果同步可以完全避免&#xff0c;那加锁的损失就不会影响应用的性能。 有两种一般性的方式可以应对。其一是在每个线程中使用不同的对象&#xff0c;这样访问对象时就…

Selenium教程__界面的刷新、后退、前进操作(4)

本文将介绍如何使用Selenium来实现界面的刷新、后退和前进操作&#xff0c;以便于测试、开发人员能够更好地控制和管理用户界面的交互行为。 通过学习本文内容&#xff0c;您将能够掌握Selenium中相关API的使用方法&#xff0c;并能够灵活地应用到您的项目中&#xff0c;从而提…

机器学习-搭建轻量级机器人模型

在自己的机器上部署一个机器人简直太酷啦&#xff0c;因为模型数据缘故&#xff0c;可能有时候回复会有一点点怪&#xff0c;不过不影响我们探索机器模型的学习&#xff0c;搭建安装完毕&#xff0c;大家就可自行学习源码啦。 这是启动后台的图片。 需要安装环境&#xff1a;p…

vue监听鼠标与键盘事件

mounted () {window.addEventListener(mousedown, this.handleMousedown)//监听鼠标按下window.addEventListener(mouseup, this.handleMouseup)//监听鼠标抬起window.addEventListener(keydown, this.handlekeydown)//监听键盘按下},methods: {// 鼠标按下事件handleMousedown…

GDAL 标记图像连接区域

文章目录 一、简介1.1原始算法1.2修改标记算法二、实现代码三、实现效果参考资料一、简介 1.1原始算法 标记图像连接区域的算法有很多,这里主要实现了一种基于扫描线的改进算法(Suzuki算法),原始算法使用了一种决策树策略,即对二进制图像b(x,y)进行重复传递,在前向和后向…

chatgpt赋能python:Python要点:从入门到精通

Python要点&#xff1a;从入门到精通 Python是一门高级编程语言&#xff0c;是一种解释型、面向对象、动态数据类型的语言。它的设计思想是“代码易读易写”&#xff0c;在数据科学、人工智能、自动化测试、Web开发等领域广泛应用。本文将从入门到精通的角度来介绍Python的要点…

模拟电路系列分享-电阻的选则

目录 概要 整体架构流程 技术名词解释 技术细节 1.阻值的选择 2.不能太小的原因 3.不能太大的原因 4.E系列选择 小结 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; 电阻(Resistor]是我们的老朋友了&#xff0c;从初中就认识。但到目前为止&#xff0c;我们却…

chatgpt赋能python:Python获取电脑IP:教你简单又快速的实现方式

Python获取电脑IP&#xff1a;教你简单又快速的实现方式 如果你是一名网络工程师或者Web开发者&#xff0c;那么获得电脑IP地址对你来说是一个常见的任务。而Python作为一种流行的脚本语言&#xff0c;也提供了多种方法来获取电脑的IP地址。下面我们将介绍三种Python获取电脑I…

深度生成模型系统的实现原理有哪些?未来的挑战是什么?

由于计算机性能的快速提升, 学习可观测样本的概率密度并随机生成新样本的生成模型成为热点。相比于需要学习条件概率分布的判别模型生成模型的训练难度大、模型结构复杂, 但除了能够生成新样本外, 生成模型在图像重构、缺失数据填充、密度估计、风格迁移和半监督学习等应用领域…

【因果图法和决策表】某软件的一个模块的需求规格说明书中描述:(1)年薪制员工:严重过失,扣年终风险金的4%;过失,扣年终风险金的2%。(2)非年薪制员工:严重过失,扣当月薪资的8%;过失,扣当月薪

题目&#xff1a; 某软件的一个模块的需求规格说明书中描述&#xff1a; &#xff08;1&#xff09;年薪制员工&#xff1a;严重过失&#xff0c;扣年终风险金的4%&#xff1b;过失&#xff0c;扣年终风险金的2%。 &#xff08;2&#xff09;非年薪制员工&#xff1a;严重过…