2023-02-28:moonfdd/ffmpeg-go是用go语言绑定ffmpeg的库,目前是github上最好用的库。请用go语言将yuv文件编码为h264文件。

答案2023-02-28:

使用 github.com/moonfdd/ffmpeg-go 库。

命令如下:

go run ./examples/a12.video_encode_yuv2h264/main.go

参考了12:yuv编码为h264,代码用golang编写。代码如下:

package main

import (
"fmt"
"os"
"os/exec"
"unsafe" "github.com/moonfdd/ffmpeg-go/ffcommon"
"github.com/moonfdd/ffmpeg-go/libavcodec"
"github.com/moonfdd/ffmpeg-go/libavformat"
"github.com/moonfdd/ffmpeg-go/libavutil"
) 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-56.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
}
} //是否存在yuv文件
_, err = os.Stat("./out/result.yuv")
if err != nil {
if os.IsNotExist(err) {
fmt.Println("create yuv file")
exec.Command("./lib/ffmpeg", "-i", "./resources/big_buck_bunny.mp4", "-pix_fmt", "yuv420p", "./out/result.yuv", "-y").CombinedOutput()
}
} ret := int32(0) //默认返回值
//需要的变量名并初始化
var fmtCtx *libavformat.AVFormatContext
var outFmt *libavformat.AVOutputFormat
var vStream *libavformat.AVStream
pkt := libavcodec.AvPacketAlloc()
var codecCtx *libavcodec.AVCodecContext
var codec *libavcodec.AVCodec
var picture_buf uintptr
var picFrame *libavutil.AVFrame
var size ffcommon.FSizeT //[1]!打开视频文件
in_file, err := os.Open("./out/result.yuv")
if err != nil {
fmt.Printf("can not open file!\n")
return
}
defer in_file.Close() for {
//[2]!打开输出文件,并填充fmtCtx数据
in_w := int32(640)
in_h := int32(360)
frameCnt := 1440
outFile := "./out/result.h264"
os.Remove(outFile)
if libavformat.AvformatAllocOutputContext2(&fmtCtx, nil, "", outFile) < 0 {
fmt.Printf("Cannot alloc output file context.\n")
break
}
outFmt = fmtCtx.Oformat
//[2]! //[3]!打开输出文件
if libavformat.AvioOpen(&fmtCtx.Pb, outFile, libavformat.AVIO_FLAG_READ_WRITE) < 0 {
fmt.Printf("output file open failed.\n")
break
} //[3]! //[4]!创建h264视频流,并设置参数
vStream = fmtCtx.AvformatNewStream(codec)
if vStream == nil {
fmt.Printf("failed create new video stream.\n")
break
}
vStream.TimeBase.Den = 25
vStream.TimeBase.Num = 1
//[4]! //[5]!编码参数相关
codecPara := fmtCtx.GetStream(uint32(vStream.Index)).Codecpar
codecPara.CodecType = libavutil.AVMEDIA_TYPE_VIDEO
codecPara.Width = in_w
codecPara.Height = in_h
//[5]! //[6]!查找编码器
codec = libavcodec.AvcodecFindEncoder(outFmt.VideoCodec)
if codec == nil {
fmt.Printf("Cannot find any endcoder.\n")
break
}
//[6]! //[7]!设置编码器内容
codecCtx = codec.AvcodecAllocContext3()
codecCtx.AvcodecParametersToContext(codecPara)
if codecCtx == nil {
fmt.Printf("Cannot alloc context.")
break
}
codecCtx.CodecId = outFmt.VideoCodec
codecCtx.CodecType = libavutil.AVMEDIA_TYPE_VIDEO
codecCtx.PixFmt = libavutil.AV_PIX_FMT_YUV420P
codecCtx.Width = in_w
codecCtx.Height = in_h
codecCtx.TimeBase.Num = 1
codecCtx.TimeBase.Den = 25
codecCtx.BitRate = 400000
codecCtx.GopSize = 12 if codecCtx.CodecId == libavcodec.AV_CODEC_ID_H264 {
codecCtx.Qmin = 10
codecCtx.Qmax = 51
codecCtx.Qcompress = 0.6
}
if codecCtx.CodecId == libavcodec.AV_CODEC_ID_MPEG2VIDEO {
codecCtx.MaxBFrames = 2
}
if codecCtx.CodecId == libavcodec.AV_CODEC_ID_MPEG1VIDEO {
codecCtx.MbDecision = 2
}
//[7]! //[8]!打开编码器
if codecCtx.AvcodecOpen2(codec, nil) < 0 {
fmt.Printf("Open encoder failed.\n")
break
}
//[8]! fmtCtx.AvDumpFormat(0, outFile, 1) //输出 输出文件流信息 //初始化帧
picFrame = libavutil.AvFrameAlloc()
picFrame.Width = codecCtx.Width
picFrame.Height = codecCtx.Height
picFrame.Format = codecCtx.PixFmt
size = uint64(libavutil.AvImageGetBufferSize(codecCtx.PixFmt, codecCtx.Width, codecCtx.Height, 1))
picture_buf = libavutil.AvMalloc(size)
libavutil.AvImageFillArrays((*[4]*byte)(unsafe.Pointer(&picFrame.Data)), (*[4]int32)(unsafe.Pointer(&picFrame.Linesize)), (*byte)(unsafe.Pointer(picture_buf)), codecCtx.PixFmt,
codecCtx.Width, codecCtx.Height, 1) //[9] --写头文件
ret = fmtCtx.AvformatWriteHeader(nil)
//[9] y_size := codecCtx.Width * codecCtx.Height
pkt.AvNewPacket(int32(size * 3))
buf := make([]byte, size)
//picture_buf = uintptr(unsafe.Pointer(&buf[0])) //[10] --循环编码每一帧
for i := 0; i < frameCnt; i++ {
//读入YUV
n, err := in_file.Read(buf)
if err != nil {
fmt.Println("read end")
break
}
if n <= 0 {
break
} for i := 0; i < n; i++ {
*(*byte)(unsafe.Pointer(picture_buf + uintptr(i))) = buf[i]
} picFrame.Data[0] = (*byte)(unsafe.Pointer(picture_buf)) //亮度Y
picFrame.Data[1] = (*byte)(unsafe.Pointer(picture_buf + uintptr(y_size))) // U
picFrame.Data[2] = (*byte)(unsafe.Pointer(picture_buf + uintptr(y_size*5/4))) // V
// AVFrame PTS
picFrame.Pts = int64(i) //编码
if codecCtx.AvcodecSendFrame(picFrame) >= 0 {
for codecCtx.AvcodecReceivePacket(pkt) >= 0 {
fmt.Printf("encoder success!\n")
// parpare packet for muxing
pkt.StreamIndex = uint32(vStream.Index)
pkt.AvPacketRescaleTs(codecCtx.TimeBase, vStream.TimeBase)
pkt.Pos = -1
ret = fmtCtx.AvInterleavedWriteFrame(pkt)
if ret < 0 {
fmt.Printf("error is: %s.\n", libavutil.AvErr2str(ret))
}
pkt.AvPacketUnref() //刷新缓存
}
}
}
//[10] //[11] --Flush encoder
ret = flush_encoder(fmtCtx, codecCtx, vStream.Index)
if ret < 0 {
fmt.Printf("flushing encoder failed!\n")
break
}
//[11] //[12] --写文件尾
fmtCtx.AvWriteTrailer()
//[12] break
} // //===========================释放所有指针===============================//
libavcodec.AvPacketFree(&pkt)
codecCtx.AvcodecClose()
libavutil.AvFree(uintptr(unsafe.Pointer(picFrame)))
libavutil.AvFree(picture_buf) if fmtCtx != nil {
fmtCtx.Pb.AvioClose()
fmtCtx.AvformatFreeContext()
} _, err = exec.Command("./lib/ffplay.exe", "./out/result.h264").Output()
if err != nil {
fmt.Println("play err = ", err)
}
} //刷新编码器
func flush_encoder(fmtCtx *libavformat.AVFormatContext, codecCtx *libavcodec.AVCodecContext, vStreamIndex int32) int32 {
var ret int32
enc_pkt := libavcodec.AvPacketAlloc()
enc_pkt.Data = nil
enc_pkt.Size = 0 if codecCtx.Codec.Capabilities&libavcodec.AV_CODEC_CAP_DELAY == 0 {
return 0
} fmt.Printf("Flushing stream #%d encoder\n", vStreamIndex)
ret = codecCtx.AvcodecSendFrame(nil)
if ret >= 0 {
for codecCtx.AvcodecReceivePacket(enc_pkt) >= 0 {
fmt.Printf("success encoder 1 frame.\n") // parpare packet for muxing
enc_pkt.StreamIndex = uint32(vStreamIndex)
enc_pkt.AvPacketRescaleTs(codecCtx.TimeBase, fmtCtx.GetStream(uint32(vStreamIndex)).TimeBase)
ret = fmtCtx.AvInterleavedWriteFrame(enc_pkt)
if ret < 0 {
break
}
}
} return ret
}

2023-02-28:moonfdd/ffmpeg-go是用go语言绑定ffmpeg的库,目前是github上最好用的库。请用go语言将yuv文件编码为h264文件。的更多相关文章

  1. mac 查看文件编码及转换文件编码

    方法是用vim , vim 打开相应文件, :set fileencoding即可显示文件编码格式 将文件编码转换为utf-8 :set fileencoding=utf-8

  2. 2018-4-25 1.如何在GitHub上新建一个新的项目并下载该项目及如何提交新的文件

  3. Linux查看文件编码格式及文件编码转换

    Linux查看文件编码格式及文件编码转换   如果你需要在Linux 中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中默认的文件格式是GBK(gb2312),而L ...

  4. linux文件编码

    linux下新建一个文件,或采用fopen新建,那么文件的编码是什么? 怎么查看文件编码格式: 查看文件编码file命令file ip.txt ip.txt: UTF-8 Unicode text, ...

  5. iconv 文件编码相互转换

    iconv 文件编码相互转换 示例: iconv -f utf-8 -t gbk ~/a.txt > ~/b.txt -f 从哪种格式转换 -t 要转换到哪种格式 a.txt要转换的文件 b.t ...

  6. 在Linux中查看文件的编码及对文件进行编码转换

    如果你需要在Linux中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中默认的文件格式是GBK(gb2312),而Linux一般都是UTF-8.下面介绍一下,在Li ...

  7. linux下查看文件编码及修改编码

    http://blog.csdn.net/jnbbwyth/article/details/6991425 查看文件编码在Linux中查看文件编码可以通过以下几种方式:1.在Vim中可以直接查看文件编 ...

  8. [转] linux下查看文件编码及修改编码

    如果无法识别文件编码,可能是文件中已有乱码,此时需要去掉乱码 查看文件编码 在Linux中查看文件编码可以通过以下几种方式: 1.在Vim中可以直接查看文件编码 :set fileencoding 即 ...

  9. 在Vim中查看文件编码

    :set fileencoding 即可显示文件编码格式. 如果你只是想查看其它编码格式的文件或者想解决 用Vim查看文件乱码的问题,那么在 ~/.vimrc 文件中添加以下内容: set encod ...

  10. (转载)Linux查看文件编码格式及文件编码转换

    Linux查看文件编码格式及文件编码转换 时间:2011-04-08作者:woyoo分类:linux评论:0 我友分享: 新浪微博 腾讯微博 搜狐微博 网易微博 开心网 QQ空间 msn 如果你需要在 ...

随机推荐

  1. Matlab - 在Figure界面去掉图像的坐标刻度

    Matlab版本:2018b 经过一番尝试,发现有两种方法 第一种:修改坐标轴的Visible属性,去掉坐标轴数字和坐标轴标签 第二种:删除Tick,只去掉坐标轴数字 第一种 ①原图 ②如果有多个子图 ...

  2. AI 脸部美容,一键让你变瘦变美变老变年轻

    目录 项目效果 项目安装 安装环境 项目使用 项目效果 随着 AI 技术的发展,你不仅随时可以看到自己的老了之后的样子,还能看到自己童年的样子 随着这部分技术的开源,会有越来越多的应用,当然我觉得前景 ...

  3. Spring--案例:百度网盘密码数据兼容处理

    案例再度来袭 也就是说,在百度网盘的密码复制时,后面即使有空格也能提取成功(trim方法) 案例的实现: 也就是实现存在空格时,也能输出true: 现在的话: 那么,我们应该如何使得它忽略空格呢? 这 ...

  4. 使用MyBatis时需要注意到的事情------执行添加、修改和删除操作时,一定要记得提交事务

    今天在重写添加操作代码时,发现自己写的代码没有任何报错,使用断点进行查询,发现一切正常,但是注册使用的数据就是无法添加到数据库里面 然后就去之前看过的视频里面去找错误,就发现这样一个小细节: 在视频里 ...

  5. Mybatis数据库驱动

    Mybatis数据库驱动 最近在学习mybatis的源码,有一个databaseIdProvider根据不同数据库执行不同sql的功能,我正好有一个mysql还有一个瀚高数据库,就去试了一下,使用如下 ...

  6. 20张图说清楚 IP 协议

    大家好,我是风筝 轻解网络系列又来了,今天咱们说说 IP 协议,这可是网络协议中最最核心的一个协议了,还记得我们刚刚知道什么是IP地址.怎么给电脑修改 IP 的时候吗?今天我们就来探究一下 IP 协议 ...

  7. Windows10绿色植物主题Kemikal

    给大家分享一个Windows10的主题,Kemikal主题,内置8张绿色植物树木的壁纸.使用这个主题前需要破解系统主题文件. 想要完整的使用这个主题,需要下载安装下方的三个文件: Windows10主 ...

  8. 异步注解@Async使用及其部分调优

    对于spring异步注解@Async的使用: 对于异步方法调用,从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调用该方法.调用者将在调用时立即返回,方法的实际执行将提 ...

  9. Java设计模式 —— 原型模式

    7 原型模式 7.1 原型模式概述 Prototype Pattern:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象. 原型模式的工作原理:将一个原型对象传给创建者,该创建者通 ...

  10. Nvidia GPU热迁移-Singularity

    1 背景 在GPU虚拟化和池化的加持下,可以显著提高集群的GPU利用率,同时也可以较好地实现弹性伸缩.但有时会遇到需要GPU资源再分配的场景,此时亟需集群拥有GPU任务热迁移的能力.举个简单的例子,比 ...