Reputation: 11
I use ffmpeg.av_hwframe_transfer_data to sent decoded frames into GPU, but i can not get them again in another good format. I try to change my shaders, use av_hwframe_transfer_get_formats but it is not working!dfghkdsfiuhsgiherghoeirughoighweroigjoiwejgoiwrjgjeoijgoiewgoheroighoieqfgoihqeoigheiogieiqrhgihergh2eouirghou2rerhg My code:
{
private static bool _readingComplete = false;
private static bool _decodingComplete = false;
private static readonly object _lock = new object();
private static Queue<AVPacket> packets = new Queue<AVPacket>();
private static readonly object _fileLock = new object();
public static MyWindow myWindow;
public static SKBitmap myBitmap;
public static async unsafe Task Main(string[] args)
{
FFmpegBinariesHelper.RegisterFFmpegBinaries();
DynamicallyLoadedBindings.Initialize();
Console.WriteLine($"FFmpeg version info: {ffmpeg.av_version_info()}");
Directory.Delete("frames", true);
Directory.CreateDirectory("frames");
var url = "rtsp://admin:[email protected]:554/stream0?username=admin&password=E10ADC3949BA59ABBE56E057F20";
AVDictionary* opts = null;
ffmpeg.av_dict_set(&opts, "-rtsp_transport", "tcp", 0);
var vsr = new VideoStreamReader(url, opts);
var vsd = new VideoStreamDecoder(*vsr.GetCodecParameters(), AVHWDeviceType.AV_HWDEVICE_TYPE_D3D11VA);
Task readerTask = Task.Factory.StartNew(() => ReadPackets(vsr), TaskCreationOptions.LongRunning);
Task decoderTask = Task.Factory.StartNew(() => DecodeFrames(vsd), TaskCreationOptions.LongRunning);
var nativeWindowSettings = new NativeWindowSettings()
{
ClientSize = new Vector2i(800, 600),
Title = "My first OpenTK program!"
};
using (var myWindow = new MyWindow(GameWindowSettings.Default, nativeWindowSettings))
{
myWindow.Run();
}
}
private static unsafe void ReadPackets(VideoStreamReader vsr)
{
while (!_readingComplete)
{
vsr.TryReadNextPacket(out var packet);
lock (_lock)
{
packets.Enqueue(packet);
}
}
_readingComplete = true;
}
private static unsafe void DecodeFrames(VideoStreamDecoder vsd)
{
Console.WriteLine($"codec name: {vsd.CodecName}");
//var sourceSize = vsd.FrameSize;
//var sourcePixelFormat = vsd.PixelFormat;
//var destinationSize = sourceSize;
//var destinationPixelFormat = AVPixelFormat.AV_PIX_FMT_RGBA;
//using var vfc = new VideoFrameConverter(sourceSize, sourcePixelFormat, destinationSize, destinationPixelFormat);
var frameNumber = 0;
while (true)
{
AVPacket packet;
lock (_lock)
{
if (packets.Count == 0)
{
if (_readingComplete)
{
break;
}
else
{
continue;
}
}
packet = packets.Dequeue();
}
vsd.TryDecodeNextFrame(out var frame, packet);
//var convertedFrame = vfc.Convert(frame);
//var bitmap = new SKBitmap(convertedFrame.width, convertedFrame.height, SKColorType.Bgra8888, SKAlphaType.Opaque);
//bitmap.InstallPixels(new SKImageInfo(convertedFrame.width, convertedFrame.height, SKColorType.Bgra8888, SKAlphaType.Opaque), (IntPtr)convertedFrame.data[0]);
//myBitmap = bitmap;
var bitmap = new SKBitmap(frame.width, frame.height, SKColorType.Bgra8888, SKAlphaType.Opaque);
bitmap.InstallPixels(new SKImageInfo(frame.width, frame.height, SKColorType.Bgra8888, SKAlphaType.Opaque), (IntPtr)frame.data[0]);
myBitmap = bitmap;
Console.WriteLine($"frame: {frameNumber}");
frameNumber++;
}
_decodingComplete = true;
}
//private static unsafe void WriteFrame(AVFrame convertedFrame, int frameNumber)
//{
// var imageInfo = new SKImageInfo(convertedFrame.width, convertedFrame.height, SKColorType.Bgra8888, SKAlphaType.Opaque);
// using var bitmap = new SKBitmap();
// bitmap.InstallPixels(imageInfo, (IntPtr)convertedFrame.data[0]);
// string filePath;
// lock (_fileLock)
// {
// filePath = $"frames/frame.{frameNumber:D8}.jpg";
// }
// using var stream = File.Create(filePath);
// bitmap.Encode(stream, SKEncodedImageFormat.Jpeg, 90);
//}
}
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using SkiaSharp;
namespace OpenTKTask;
public class MyWindow : GameWindow
{
private Shader shader;
private int vertexBufferHandle;
private int elementBufferHandle;
private int vertexArrayHandle;
private int texture;
//float[] vertices =
//{
// 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
// 1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
// -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
// -1.0f, 1.0f, 0.0f, 0.0f, 1.0f
//};
float[] vertices =
{
//Position | Texture coordinates
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // top right
1.0f, -1.0f, 0.0f, 1.0f, 1.0f, // bottom right
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, // bottom left
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f // top left
};
uint[] indices =
{
0, 1, 3,
1, 2, 3
};
float[] texCoords =
{
0.0f, 0.0f,
1.0f, 0.0f,
0.5f, 1.0f,
};
public MyWindow(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings)
{
this.CenterWindow(new Vector2i(1280, 760));
}
protected override void OnResize(ResizeEventArgs e)
{
GL.Viewport(0, 0, e.Width, e.Height);
base.OnResize(e);
}
protected override void OnLoad()
{
base.OnLoad();
shader = new Shader("C:\\Users\\1\\Desktop\\7h3_C0d3r\\OpenTKTask\\vertexShader.vert", "C:\\Users\\1\\Desktop\\7h3_C0d3r\\OpenTKTask\\fragShader.frag");
shader.Use();
vertexArrayHandle = GL.GenVertexArray();
GL.BindVertexArray(vertexArrayHandle);
vertexBufferHandle = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferHandle);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
elementBufferHandle = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBufferHandle);
GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(uint), indices, BufferUsageHint.StaticDraw);
var positionLocation = shader.GetAttribLocation("aPosition");
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0);
GL.EnableVertexAttribArray(positionLocation);
var texCoordLocation = shader.GetAttribLocation("aTexCoord");
GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
GL.EnableVertexAttribArray(texCoordLocation);
texture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, 800, 600, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.BindTexture(TextureTarget.Texture2D, 0);
}
protected override void OnUnload()
{
base.OnUnload();
GL.DeleteBuffer(vertexBufferHandle);
GL.DeleteVertexArray(vertexArrayHandle);
GL.DeleteProgram(shader.Handle);
GL.DeleteTexture(texture);
}
protected override void OnUpdateFrame(FrameEventArgs args)
{
base.OnUpdateFrame(args);
}
protected override void OnRenderFrame(FrameEventArgs args)
{
base.OnRenderFrame(args);
UpdateTexture(Program.myBitmap);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.BindTexture(TextureTarget.Texture2D, texture);
shader.Use();
GL.BindVertexArray(vertexArrayHandle);
GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0);
SwapBuffers();
}
public void UpdateTexture(SKBitmap bitmap)
{
GL.BindTexture(TextureTarget.Texture2D, texture);
if (bitmap != null)
{
//byte[] pixels = bitmap.Bytes;
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bitmap.Width, bitmap.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, 0);
}
}
public SKBitmap LoadBitmap(string path)
{
using (var stream = File.OpenRead(path))
{
return SKBitmap.Decode(stream);
}
}
}
using FFmpeg.AutoGen;
using System.Drawing;
namespace OpenTKTask;
public sealed unsafe class VideoStreamDecoder : IDisposable
{
private readonly AVCodecContext* _pCodecContext;
private readonly AVPacket* _pPacket;
private readonly AVFrame* _pFrame;
private readonly AVFrame* _receivedFrame;
private AVFrame* _pSwFrame;
private AVBufferRef* _pHWDeviceCtx;
public VideoStreamDecoder(AVCodecParameters parameter, AVHWDeviceType HWDeviceType = AVHWDeviceType.AV_HWDEVICE_TYPE_D3D12VA)
{
_receivedFrame = ffmpeg.av_frame_alloc();
AVCodec* codec = ffmpeg.avcodec_find_decoder(parameter.codec_id);
if (codec == null)
throw new InvalidOperationException("Codec not found.");
_pCodecContext = ffmpeg.avcodec_alloc_context3(codec);
ffmpeg.av_hwdevice_ctx_create(&_pCodecContext->hw_device_ctx, HWDeviceType, null, null, 0).ThrowExceptionIfError();
ffmpeg.avcodec_parameters_to_context(_pCodecContext, ¶meter)
.ThrowExceptionIfError();
ffmpeg.avcodec_open2(_pCodecContext, codec, null).ThrowExceptionIfError();
CodecName = ffmpeg.avcodec_get_name(codec->id);
FrameSize = new Size(_pCodecContext->width, _pCodecContext->height);
PixelFormat = _pCodecContext->pix_fmt;
_pFrame = ffmpeg.av_frame_alloc();
_pPacket = ffmpeg.av_packet_alloc();
}
public string CodecName { get; }
public Size FrameSize { get; }
public AVPixelFormat PixelFormat { get; }
public bool TryDecodeNextFrame(out AVFrame frame, AVPacket packet)
{
ffmpeg.av_frame_unref(_pFrame);
ffmpeg.av_frame_unref(_receivedFrame);
int error;
do
{
ffmpeg.avcodec_send_packet(_pCodecContext, &packet).ThrowExceptionIfError();
error = ffmpeg.avcodec_receive_frame(_pCodecContext, _pFrame);
} while (error == ffmpeg.AVERROR(ffmpeg.EAGAIN));
error.ThrowExceptionIfError();
if (_pCodecContext->hw_device_ctx != null)
{
ffmpeg.av_hwframe_transfer_data(_receivedFrame, _pFrame, 0).ThrowExceptionIfError();
Console.WriteLine((AVPixelFormat)171);
frame = *_receivedFrame; // AV_PIX_FMT_NV11
//Console.WriteLine((AVPixelFormat)frame.format);
}
else
frame = *_pFrame; // AV_PIX_FMT_NV11
//Console.WriteLine((AVPixelFormat)frame.format);
return true;
}
public void Dispose()
{
var pFrame = _pFrame;
ffmpeg.av_frame_free(&pFrame);
var pCodecContext = _pCodecContext;
ffmpeg.avcodec_free_context(&pCodecContext);
if (_pHWDeviceCtx != null)
{
var pHWDeviceCtx = _pHWDeviceCtx;
ffmpeg.av_buffer_unref(&pHWDeviceCtx);
}
if (_pSwFrame != null)
{
var pSwFrame = _pSwFrame;
ffmpeg.av_frame_free(&pSwFrame);
}
}
}````
Upvotes: 0
Views: 70