2023-05-04:用go語言重寫ffmpeg的scaling_video.c示例,用于實現(xiàn)視頻縮放(Scaling)
2023-05-04:用go語言重寫ffmpeg的scaling_video.c示例,用于實現(xiàn)視頻縮放(Scaling)功能。
答案2023-05-04:
這段代碼實現(xiàn)了使用 libswscale 庫進行視頻縮放的功能。下面是程序的主要流程:
1.獲取命令行參數(shù),包括輸出文件名和目標(biāo)圖像大小。
2.解析目標(biāo)圖像大小,生成指定大小的輸出文件。
3.創(chuàng)建縮放上下文(scaling context)并分配輸入和輸出圖像數(shù)據(jù)的內(nèi)存空間。
4.循環(huán)生成合成圖像、將輸入圖像轉(zhuǎn)換為輸出圖像并將輸出圖像寫入輸出文件中,重復(fù)該操作若干次。
5.釋放內(nèi)存空間并關(guān)閉輸出文件。
具體步驟如下:
1.獲取命令行參數(shù)。首先檢查命令行參數(shù)是否符合要求,如果不符合則打印使用說明并退出程序。否則,解析輸出文件名和目標(biāo)圖像大小。
2.解析目標(biāo)圖像大小。調(diào)用?libavutil.AvParseVideoSize()
?函數(shù)解析目標(biāo)圖像大小,并根據(jù)解析結(jié)果生成一個指定大小的輸出文件。
3.創(chuàng)建縮放上下文并分配內(nèi)存空間。調(diào)用?libswscale.SwsGetContext()
?函數(shù)創(chuàng)建一個縮放上下文,并使用?libavutil.AvImageAlloc()
?函數(shù)分配輸入和輸出圖像數(shù)據(jù)的內(nèi)存空間。
4.循環(huán)處理圖像。在循環(huán)中,首先生成一個 YUV420P 格式的合成圖像。然后,調(diào)用?libswscale.SwsScale()
?函數(shù)將輸入圖像轉(zhuǎn)換為輸出圖像。最后,將輸出圖像寫入輸出文件中。在本程序中,處理圖像的循環(huán)次數(shù)為 100 次。
5.釋放內(nèi)存空間并關(guān)閉輸出文件。在程序結(jié)束時,需要釋放輸入和輸出圖像數(shù)據(jù)的內(nèi)存空間,并關(guān)閉輸出文件。
整個程序的主要目的是演示如何使用 libswscale 庫進行視頻縮放。它通過調(diào)用 libswscale 庫的函數(shù)?SwsGetContext()
?和?SwsScale()
?實現(xiàn)了將一系列輸入圖像轉(zhuǎn)換為指定大小的輸出圖像的功能。
代碼見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()
}


福大大架構(gòu)師每日一題
java當(dāng)死,golang當(dāng)立。最新面試題,涉及golang,rust,mysql,redis,云原生,算法,分布式,網(wǎng)絡(luò),操作系統(tǒng)。
公眾號