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

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

时间:2023-05-04 22:03:14浏览次数:49  
标签:src 04 示例 dst 缩放 ffcommon libavutil data fmt

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()
}

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

标签:src,04,示例,dst,缩放,ffcommon,libavutil,data,fmt
From: https://blog.51cto.com/u_14891145/6244589

相关文章

  • [oeasy]python0048_注释_comment_设置默认编码格式
    注释Comment回忆上次内容使用了版本控制git制作备份进行回滚 尝试了嵌套的控制结构层层控制 不过除非到不得以尽量不要太多层次的嵌套 这样从顶到底含义明确而且还扁平 扁平也能含义明确......
  • 实例046 数组的下标界限
    以下是使用Java文本框控件实现Java数组的下标界限完整代码,包括详细注释:importjavax.swing.*;importjava.awt.*;importjava.awt.event.*;publicclassTestextendsJFrameimplementsActionListener{//定义窗口中需要用到的组件privateJTextFieldtextField......
  • linux模块驱动编写示例
    2023-05-04关键字:该驱动可通过dts配置属性,可在/dev创建节点,支持对/dev下的节点进行标准IO读写以及ioctl读写。dts如下:ir_cut{status="okay";compatible="chorm,ir-cut";gpios=<&gpf0GPIO_ACTIVE_HIGH>,<&gpf1GPIO_ACTIVE_LOW>;}; ......
  • 实例 042 获取一维数组最小值
      你可以使用以下代码来获取一维数组中的最小值:int[]arr={5,3,9,1,7};intmin=arr[0];for(inti=1;i<arr.length;i++){if(arr[i]<min){min=arr[i];}}System.out.println("最小值为:"+min);  在上面的代码中,我们首先初始......
  • 【2023-04-28】连岳摘抄
    23:59在这个过程中,我算是饱尝了人间的辛酸,但回过头去想想,当伙计的那六年是非常宝贵的,尽管那六年我一直重复地干着几乎没有多少技术含量的活儿,但我很清楚,那就是我的工作,是需要我认真对待、努力实践的工作。这个觉悟影响了我一生,让我无论做什么,都能百分百地投入、去实践,而不是空想......
  • C++获取阿里巴巴1688中国站店铺详情 API 接口返回值示例说明
    ​C++(cplusplus)是一种计算机高级程序设计语言,由C语言扩展升级而产生,最早于1979年由本贾尼·斯特劳斯特卢普在AT&T贝尔工作室研发。C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。......
  • Ubuntu22.04 rc-local 配置开机自启动脚本
    1.rc-local服务简介Linux中的rc-local服务是一个开机自动启动的,调用开发人员或系统管理员编写的可执行脚本或命令的,它的启动顺序是在系统所有服务加载完成之后执行。ubuntu22.04系统已经默认安装了rc-local.service服务,但是不知什么原因系统把这个服务给“隐蔽”了,所以如果不做......
  • 【2023.05.04】幸运的猫(下)
    本次博客主要写黑猫回家后的故事未到家前我打电话和我父亲开玩笑说要带女朋友回家过年我爹还蛮激动的,问是哪里的女孩子,我说是福州的忘记了带回家后他是什么心情了哈哈果然还是要多写日记啊,不然什么都忘记了可太糟糕了初到家中初到家里的时候是还关在笼子里的,因为想把猫养......
  • LeetCode 双周赛 103(2023/04/29)区间求和的树状数组经典应用
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。大家好,我是小彭。这场周赛是LeetCode双周赛第103场,难得在五一假期第一天打周赛的人数也没有少太多。这场比赛前3题比较简单,我们把篇幅留给最后一题。往期周赛回顾:LeetCode单周赛第342场·容......
  • ubuntu 2204换源
    update2022.04.23:Ubuntu22.04的稳定版已经于2022年4月21日发布,Ubuntu22.04稳定版下载地址:https://ubuntu.com/download/desktopUbuntu22.04的稳定版计划于2022年4月21日发布。开发工作已经在紧锣密鼓地进行,它将遵循如下发布时间表:2022年2月24日:功能......