我试图在Unity中创建一个游戏,其中每个帧都渲染成纹理,然后使用FFmpeg将它们组合成一个视频。 FFmpeg创建的输出最终应通过网络发送到客户端UI。但是,我主要是抓住一个帧的部分,并作为一个字节数组传递给一个不安全的方法,它应该由FFmpeg进一步处理。我使用的包装是FFmpeg.AutoGen。
渲染到纹理方法:
private IEnumerator CaptureFrame()
{
yield return new WaitForEndOfFrame();
RenderTexture.active = rt;
frame.ReadPixels(rect, 0, 0);
frame.Apply();
bytes = frame.GetRawTextureData();
EncodeAndWrite(bytes, bytes.Length);
}
到目前为止的不安全编码方法:
private unsafe void EncodeAndWrite(byte[] bytes, int size)
{
GCHandle pinned = GCHandle.Alloc(bytes, GCHandleType.Pinned);
IntPtr address = pinned.AddrOfPinnedObject();
sbyte** inData = (sbyte**)address;
fixed(int* lineSize = new int[1])
{
lineSize[0] = 4 * textureWidth;
// Convert RGBA to YUV420P
ffmpeg.sws_scale(sws, inData, lineSize, 0, codecContext->width, inputFrame->extended_data, inputFrame->linesize);
}
inputFrame->pts = frameCounter++;
if(ffmpeg.avcodec_send_frame(codecContext, inputFrame) < 0)
throw new ApplicationException("Error sending a frame for encoding!");
pkt = new AVPacket();
fixed(AVPacket* packet = &pkt)
ffmpeg.av_init_packet(packet);
pkt.data = null;
pkt.size = 0;
pinned.Free();
...
}
sws_scale
将sbyte**
作为第二个参数,因此我首先尝试将输入字节数组转换为sbyte**
,然后先将其GCHandle
固定为if(ffmpeg.avcodec_send_frame(codecContext, inputFrame) < 0)
。之后进行显式类型转换。但是,我不知道这是否是正确的方法。
此外,条件codecContext
alwasy抛出一个ApplicationException,我也真的不知道为什么会这样。 inputFrame
和codecContext = ffmpeg.avcodec_alloc_context3(codec);
codecContext->bit_rate = 400000;
codecContext->width = textureWidth;
codecContext->height = textureHeight;
AVRational timeBase = new AVRational();
timeBase.num = 1;
timeBase.den = (int)fps;
codecContext->time_base = timeBase;
videoAVStream->time_base = timeBase;
AVRational frameRate = new AVRational();
frameRate.num = (int)fps;
frameRate.den = 1;
codecContext->framerate = frameRate;
codecContext->gop_size = 10;
codecContext->max_b_frames = 1;
codecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
分别是我的AVCodecContext和AVFrame对象,字段定义如下:
编解码器环境
inputFrame = ffmpeg.av_frame_alloc();
inputFrame->format = (int)codecContext->pix_fmt;
inputFrame->width = textureWidth;
inputFrame->height = textureHeight;
inputFrame->linesize[0] = inputFrame->width;
inputFrame
from tkinter import *
from threading import Thread
def window():
root = Tk()
Window=Frame(root)
Window.pack(side=TOP)
label = Label(Window, text="Window").grid()
root.mainloop()
def loop():
label.configure(text="Something else")
if __name__ == '__main__':
Thread(target = window).start()
Thread(target = loop).start()
非常感谢任何帮助解决问题的方法:)
答案 0 :(得分:1)
点击此处的示例:https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples
特别是scaling_video.c
。在FFmpeg缩放和像素格式转换是相同的操作(保持大小参数只是像素格式转换)。
这些例子非常容易理解。试一试。
答案 1 :(得分:0)
我认为您的演员阵容不正确dragOptions: {
cursor: 'pointer',
zIndex: 2000,
grid: [20, 20],
containment: 'notNegative'
}
因为地址是 IntPtr 对象,所以正确的转换可能应该是
sbyte** inData = (sbyte**)address;