2023-05-04:用go语言重写ffmpeg的scaling_video.c示例,用于实现视频缩放(Scaling)功能。

2023-05-04:用go语言重写ffmpeg的scaling_video.c示例,用于实现视频缩放(Scaling)功能。

答案2023-05-04:

这段代码实现了使用 libswscale 库进行视频缩放的功能。下面是程序的主要流程:

1.获取命令行参数,包括输出文件名和目标图像大小。

2.解析目标图像大小,生成指定大小的输出文件。

3.创建缩放上下文(scaling context)并分配输入和输出图像数据的内存空间。

4.循环生成合成图像、将输入图像转换为输出图像并将输出图像写入输出文件中,重复该操作若干次。

5.释放内存空间并关闭输出文件。

具体步骤如下:

1.获取命令行参数。首先检查命令行参数是否符合要求,如果不符合则打印使用说明并退出程序。否则,解析输出文件名和目标图像大小。

2.解析目标图像大小。调用 libavutil.AvParseVideoSize() 函数解析目标图像大小,并根据解析结果生成一个指定大小的输出文件。

3.创建缩放上下文并分配内存空间。调用 libswscale.SwsGetContext() 函数创建一个缩放上下文,并使用 libavutil.AvImageAlloc() 函数分配输入和输出图像数据的内存空间。

4.循环处理图像。在循环中,首先生成一个 YUV420P 格式的合成图像。然后,调用 libswscale.SwsScale() 函数将输入图像转换为输出图像。最后,将输出图像写入输出文件中。在本程序中,处理图像的循环次数为 100 次。

5.释放内存空间并关闭输出文件。在程序结束时,需要释放输入和输出图像数据的内存空间,并关闭输出文件。

整个程序的主要目的是演示如何使用 libswscale 库进行视频缩放。它通过调用 libswscale 库的函数 SwsGetContext()SwsScale() 实现了将一系列输入图像转换为指定大小的输出图像的功能。

代码见github/moonfdd/ffmpeg-go库。

命令如下:

go run ./examples/internalexamples/scaling_video/main.go ./out/big_buck_bunny.mp4 640*480

./lib/ffplay -f rawvideo -pix_fmt rgb24 -video_size 640x480 ./out/big_buck_bunny.mp4

golang代码如下:

package main

import (
	"fmt"
	"os"
	"unsafe"

	"github.com/moonfdd/ffmpeg-go/ffcommon"
	"github.com/moonfdd/ffmpeg-go/libavutil"
	"github.com/moonfdd/ffmpeg-go/libswscale"
)

func main0() (ret ffcommon.FInt) {
	var src_data, dst_data [4]*ffcommon.FUint8T
	var src_linesize, dst_linesize [4]ffcommon.FInt
	var src_w ffcommon.FInt = 320
	var src_h ffcommon.FInt = 240
	var dst_w ffcommon.FInt
	var dst_h ffcommon.FInt
	var src_pix_fmt libavutil.AVPixelFormat = libavutil.AV_PIX_FMT_YUV420P
	var dst_pix_fmt libavutil.AVPixelFormat = libavutil.AV_PIX_FMT_RGB24
	var dst_size string
	var dst_filename string
	var dst_file *os.File
	var dst_bufsize ffcommon.FInt
	var sws_ctx *libswscale.SwsContext
	var i ffcommon.FInt

	if len(os.Args) != 3 {
		fmt.Printf("Usage: %s output_file output_size\nAPI example program to show how to scale an image with libswscale.\nThis program generates a series of pictures, rescales them to the given output_size and saves them to an output file named output_file\n.\n", os.Args[0])
		os.Exit(1)
	}
	dst_filename = os.Args[1]
	dst_size = os.Args[2]

	if libavutil.AvParseVideoSize(&dst_w, &dst_h, dst_size) < 0 {
		fmt.Printf("Invalid size '%s', must be in the form WxH or a valid size abbreviation\n",
			dst_size)
		os.Exit(1)
	}

	dst_file, _ = os.Create(dst_filename)
	if dst_file == nil {
		fmt.Printf("Could not open destination file %s\n", dst_filename)
		os.Exit(1)
	}

	/* create scaling context */
	sws_ctx = libswscale.SwsGetContext(src_w, src_h, src_pix_fmt,
		dst_w, dst_h, dst_pix_fmt,
		libswscale.SWS_BILINEAR, nil, nil, nil)
	if sws_ctx == nil {
		fmt.Printf(
			"Impossible to create scale context for the conversion fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n",
			libavutil.AvGetPixFmtName(src_pix_fmt), src_w, src_h,
			libavutil.AvGetPixFmtName(dst_pix_fmt), dst_w, dst_h)
		ret = -libavutil.EINVAL
		goto end
	}

	/* allocate source and destination image buffers */
	ret = libavutil.AvImageAlloc(&src_data, &src_linesize,
		src_w, src_h, src_pix_fmt, 16)
	if ret < 0 {
		fmt.Printf("Could not allocate source image\n")
		goto end
	}

	/* buffer is going to be written to rawvideo file, no alignment */
	ret = libavutil.AvImageAlloc(&dst_data, &dst_linesize,
		dst_w, dst_h, dst_pix_fmt, 1)
	if ret < 0 {
		fmt.Printf("Could not allocate destination image\n")
		goto end
	}
	dst_bufsize = ret

	for i = 0; i < 100; i++ {
		// /* generate synthetic video */
		fill_yuv_image(&src_data, &src_linesize, src_w, src_h, i)

		/* convert to destination format */
		sws_ctx.SwsScale((**byte)(unsafe.Pointer(&src_data)),
			(*int32)(unsafe.Pointer(&src_linesize)), 0, uint32(src_h), (**byte)(unsafe.Pointer(&dst_data)), (*int32)(unsafe.Pointer(&dst_linesize)))

		// /* write scaled image to file */
		dst_file.Write(ffcommon.ByteSliceFromByteP(dst_data[0], int(dst_bufsize)))
	}

	fmt.Printf("Scaling succeeded. Play the output file with the command:\nffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n",
		libavutil.AvGetPixFmtName(dst_pix_fmt), dst_w, dst_h, dst_filename)

end:
	dst_file.Close()
	libavutil.AvFreep(uintptr(unsafe.Pointer(&src_data[0])))
	libavutil.AvFreep(uintptr(unsafe.Pointer(&dst_data[0])))
	sws_ctx.SwsFreeContext()
	if ret < 0 {
		return 1
	} else {
		return 0
	}
}

func fill_yuv_image(data *[4]*ffcommon.FUint8T, linesize *[4]ffcommon.FInt, width, height, frame_index ffcommon.FInt) {
	var x, y ffcommon.FInt

	/* Y */
	for y = 0; y < height; y++ {
		for x = 0; x < width; x++ {
			//data[0][y*linesize[0]+x] = x + y + frame_index*3
			*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(data[0])) + uintptr(y*linesize[0]+x))) = byte((x + y + frame_index*3) % 256)
		}
	}

	/* Cb and Cr */
	for y = 0; y < height/2; y++ {
		for x = 0; x < width/2; x++ {
			// data[1][y * linesize[1] + x] = 128 + y + frame_index * 2;
			// data[2][y * linesize[2] + x] = 64 + x + frame_index * 5;
			*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(data[1])) + uintptr(y*linesize[1]+x))) = byte((128 + y + frame_index*2) % 256)
			*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(data[2])) + uintptr(y*linesize[2]+x))) = byte((64 + x + frame_index*5) % 256)
		}
	}
}

func main() {

	os.Setenv("Path", os.Getenv("Path")+";./lib")
	ffcommon.SetAvutilPath("./lib/avutil-56.dll")
	ffcommon.SetAvcodecPath("./lib/avcodec-58.dll")
	ffcommon.SetAvdevicePath("./lib/avdevice-58.dll")
	ffcommon.SetAvfilterPath("./lib/avfilter-56.dll")
	ffcommon.SetAvformatPath("./lib/avformat-58.dll")
	ffcommon.SetAvpostprocPath("./lib/postproc-55.dll")
	ffcommon.SetAvswresamplePath("./lib/swresample-3.dll")
	ffcommon.SetAvswscalePath("./lib/swscale-5.dll")

	genDir := "./out"
	_, err := os.Stat(genDir)
	if err != nil {
		if os.IsNotExist(err) {
			os.Mkdir(genDir, 0777) //  Everyone can read write and execute
		}
	}

	main0()
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL事务

1、事务的概念 事务是一种机制、一个操作序列&#xff0c;包含了一组数据库操作命令&#xff0c;并且把所有的命令作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这一组数据库命令要么都执行&#xff0c;要么都不执行。 事务是一个不可分割的工作逻辑单元&#xff…

推荐一些非常好用的DNS服务器

推荐一些非常好用的DNS服务器 1、114公共DNS服务器 1&#xff09; 老牌的114DNS&#xff0c;全国三网通用高速&#xff0c;纯净无劫持无需再忍受被强扭去看广告或粗俗网站之痛苦 DNS地址为&#xff1a;114.114.114.114 和 114.114.115.115 2&#xff09;拦截 钓鱼病毒木马网…

【目标检测论文阅读笔记】Dynamic Head: Unifying Object Detection Heads with Attentions

Abstract 在目标检测中结合定位和分类的复杂性导致了方法的蓬勃发展。以前的工作试图提高各种目标检测头的性能&#xff0c;但未能提出统一的观点。在本文中&#xff0c;我们提出了一种新颖的动态头部框架 来统一目标检测头部和注意力。通过在用于尺度感知的特征级别之间、用于…

SpringCloud学习笔记06

九十五、Cloud Alibaba简介 0、why会出现SpringCloud alibaba Spring Cloud Netflix项目进入维护模式 1、是什么 官网&#xff1a;spring-cloud-alibaba/README-zh.md at 2.2.x alibaba/spring-cloud-alibaba GitHub 2、能干嘛 3、去哪下 spring-cloud-alibaba/README-…

【软考高项笔记】第3章 信息系统治理(针对甲方)3.1 IT治理

第3章 信息系统治理&#xff08;针对甲方&#xff09; 3.1 IT治理 不同于管理&#xff0c;角度更高3.1.1 IT治理基础 目标价值 与业务目标一致 有效利用信息与数据资源 风险管理 管理层次 最高管理层 &#xff08;定目标&#xff0c;战略&#xff09; 执行管理层 &#xff08…

【BingChat】Microsoft Edge/Bing Chat 注册使用完全指南

欢迎关注【youcans的学习笔记】原创作品&#xff0c;火热更新中 【BingChat】Microsoft Edge/Bing Chat 注册使用完全指南 1. BingChat 简介2. BingChat 用户注册2.1 下载微软浏览器 Edge 预览版2.2 申请微软账户2.3 登录 Bing.com2.4 手机/平板使用 BingChat 3. BingChat 的聊…

4.shell函数

文章目录 shell函数shell函数的作用函数返回值函数传参函数变量作用范围递归阶乘使用函数递归目录/var/log&#xff0c;如果是文件直接输出文件名&#xff0c;如果是目录则输出目录名且输出此目录下的所有目录和文件名通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录…

【Jmeter快速入门】

Jmeter快速入门 Jmeter快速入门1.安装Jmeter1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 Jmeter快速入门 1.安装Jmeter Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0c;并且配置了环境变量。 1.1.下载 可以Apache Jm…

SSM整合详细教学(上)

SSM整合详细教学&#xff08;上&#xff09; 一、SSM整合1. SSM整合配置1.1 SSM整合流程1.2 SSM整合配置1.2.1 创建工程&#xff0c;添加依赖和插件1.2.2 Spring整合Mybatis1.2.3 Spring整合SpringMVC 2. 功能模块开发2.1 数据层开发(BookDao)2.2 业务层开发(BookService/BookS…

TIM编码器接口

一、知识点 1、Encoder Interface 编码器接口的工作流程 编码器接口可接收增量&#xff08;正交&#xff09;编码器的信号&#xff0c;根据编码器旋转产生的正交信号脉冲&#xff0c;自动控制CNT自增或自减&#xff0c;从而指示编码器的位置、旋转方向和旋转速度 2、编码器接口…

「领域驱动设计」DDD,六边形架构,洋葱架构,整洁架构和CQRS的整合

这篇文章是软件架构编年史的一部分&#xff0c;一系列关于软件架构的文章。在这些文章中&#xff0c;我写了我对软件架构的了解&#xff0c;我如何看待它&#xff0c;以及我如何使用这些知识。如果您阅读了本系列以前的文章&#xff0c;那么本文的内容可能更有意义。 今天的帖子…

【多任务学习】Multi-task Learning 手把手编码带数据集, 一文吃透多任务学习

文章目录 前言1.多任务学习1.1 定义1.2 原理 2. 多任务学习code2.1 数据集初探2.2 预处理2.3 网络结构2.4 训练 3. 总结 前言 我们之前讲过的模型通常聚焦单个任务,比如预测图片的类别等,在训练的时候,我们会关注某一个特定指标的优化. 但是有时候,我们需要知道一个图片,从它身…

PostgreSQL 基础知识:psql 提示和技巧

对于积极使用和连接到 PostgreSQL 数据库的任何开发人员或 DBA 来说&#xff0c;能够访问psql命令行工具是必不可少的。在我们的第一篇文章中&#xff0c;我们讨论了 psql的简要历史&#xff0c;并演示了如何在您选择的平台上安装它并连接到 PostgreSQL 数据库。 在本文中&…

HTTPS协议介绍

文章目录 一、HTTPS协议的认识二、常见的加密方式1.对称加密2.非对称加密 三、数据摘要四、HTTPS的工作过程探究1.只使用对称加密2.只使用非对称加密3.双方都使用非对称加密4.非对称加密对称加密5.中间人攻击6.引入证书7.非对称加密对称加密证书认证 一、HTTPS协议的认识 HTTP…

HTTP的method方法 GET POST PUT DELETE HEAD OPTIONS CONNECT PATCH TRACE

HTTP的method方法 GET POST PUT DELETE HEAD OPTIONS CONNECT PATCH TRACE GET 向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据&#xff0c;而不应当被用于产生“副作用”的操作中&#xff0c;例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意…

Docker 持久化存储 Bind mounts

Docker 持久化存储 Bind mounts Bind mounts 的 -v 与 --mount 区别启动容器基于bind mount挂载到容器中的非空目录只读 bind mountcompose 中使用 bind mount 官方文档&#xff1a;https://docs.docker.com/storage/bind-mounts/ Bind mounts 的 -v 与 --mount 区别 如果使用…

ePWM模块(1)

ePWM模块 ePWM模块内部包含有7个子模块,分别是时间基准子模块TB、比较功能子模块CC,动作限定子模块AQ、死区控制子模块DB、斩波控制子模块PC、事件触发子模块ET和故障捕获子模块TZ。 每个ePWM模块都具有以下功能: 可以输出两路PWM,EPWMxA和EPWMxB两路PWM可以独立输出,也可…

大二一个学期学这么点内容,没有概念,只有实操

如何查看所有的数据库&#xff1a; Show databases; 如何进入某个数据库&#xff1a; use xxx; 如何新进数据库&#xff1a; Create database jx; 如何删除数据库&#xff1a; Drop database jx; 如何查看所有的表格&#xff1a; Show tables; 如何创建数据表&#xf…

【Flink】DataStream API使用之执行环境

1. 执行环境 Flink 程序可以在各种上下文环境中运行&#xff1a;我们可以在本地 JVM 中执行程序&#xff0c;也可以提交 到远程集群上运行。不同的环境&#xff0c;代码的提交运行的过程会有所不同。这就要求我们在提交作业执行计算时&#xff0c;首先必须获取当前 Flink 的运…

(异或相消)猫猫数字异或和

E - Red Scarf (atcoder.jp) 刚入坑写的一道题被我拉出来对比分析了 我的思路&#xff1a; 垃圾运气选手凭借直觉乱搞猜出来的&#xff0c;没有思路。 题解思路&#xff1a; 由问题陈述中XOR的定义&#xff0c;我们可以看出计算3个或更多整数的XOR可以以任意顺序进行&#…