Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否有其他方法将ffmpeg中的帧导出到纹理2D?我的代码在Windows中工作,但在Linux中不工作_C#_Linux_Ffmpeg_Mono_Autogen - Fatal编程技术网

C# 是否有其他方法将ffmpeg中的帧导出到纹理2D?我的代码在Windows中工作,但在Linux中不工作

C# 是否有其他方法将ffmpeg中的帧导出到纹理2D?我的代码在Windows中工作,但在Linux中不工作,c#,linux,ffmpeg,mono,autogen,C#,Linux,Ffmpeg,Mono,Autogen,声音在Linux中的工作方式与在Windows中的工作方式相同。但视频只是一个黑屏,当我试图将帧保存为BMP文件时,所有帧都是损坏/空文件。我正在使用Ffmpeg.Autogen与库进行接口。该文件是MKV容器中的VP8和OGG。尽管出于某种原因,扩展是AVI 我试着稍微弄乱了一下代码的顺序。我检查以确保在Linux上构建的Ffmpeg具有VP8。我在网上搜索,但很难找到另一种方法来做我正在做的事情。这是对OpenVIII项目的贡献。我的叉子-> 这只是准备缩放器来更改像素格式,否则人们会有蓝色

声音在Linux中的工作方式与在Windows中的工作方式相同。但视频只是一个黑屏,当我试图将帧保存为BMP文件时,所有帧都是损坏/空文件。我正在使用Ffmpeg.Autogen与库进行接口。该文件是MKV容器中的VP8和OGG。尽管出于某种原因,扩展是AVI

我试着稍微弄乱了一下代码的顺序。我检查以确保在Linux上构建的Ffmpeg具有VP8。我在网上搜索,但很难找到另一种方法来做我正在做的事情。这是对OpenVIII项目的贡献。我的叉子->

这只是准备缩放器来更改像素格式,否则人们会有蓝色的脸

        private void PrepareScaler()
        {

            if (MediaType != AVMediaType.AVMEDIA_TYPE_VIDEO)
            {
                return;
            }

            ScalerContext = ffmpeg.sws_getContext(
                Decoder.CodecContext->width, Decoder.CodecContext->height, Decoder.CodecContext->pix_fmt,
                Decoder.CodecContext->width, Decoder.CodecContext->height, AVPixelFormat.AV_PIX_FMT_RGBA,
                ffmpeg.SWS_ACCURATE_RND, null, null, null);
            Return = ffmpeg.sws_init_context(ScalerContext, null, null);

            CheckReturn();
        }
将帧转换为BMP 我想这就是问题所在。因为我已经添加了bitmap.save到这个文件中,得到了空的BMP

public Bitmap FrameToBMP()
        {
            Bitmap bitmap = null;
            BitmapData bitmapData = null;

            try
            {
                bitmap = new Bitmap(Decoder.CodecContext->width, Decoder.CodecContext->height, PixelFormat.Format32bppArgb);
                AVPixelFormat v = Decoder.CodecContext->pix_fmt;

                // lock the bitmap
                bitmapData = bitmap.LockBits(new Rectangle(0, 0, Decoder.CodecContext->width, Decoder.CodecContext->height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

                byte* ptr = (byte*)(bitmapData.Scan0);

                byte*[] srcData = { ptr, null, null, null };
                int[] srcLinesize = { bitmapData.Stride, 0, 0, 0 };

                // convert video frame to the RGB bitmap
                ffmpeg.sws_scale(ScalerContext, Decoder.Frame->data, Decoder.Frame->linesize, 0, Decoder.CodecContext->height, srcData, srcLinesize); //sws_scale broken on linux?
            }
            finally
            {
                if (bitmap != null && bitmapData != null)
                {
                    bitmap.UnlockBits(bitmapData);
                }
            }
            return bitmap;

        }
得到位图后,我们将其转换为纹理2D,以便绘制

 public Texture2D FrameToTexture2D()
        {
            //Get Bitmap. there might be a way to skip this step.
            using (Bitmap frame = FrameToBMP())
            {
                //string filename = Path.Combine(Path.GetTempPath(), $"{Path.GetFileNameWithoutExtension(DecodedFileName)}_rawframe.{Decoder.CodecContext->frame_number}.bmp");

                //frame.Save(filename);
                BitmapData bmpdata = null;
                Texture2D frameTex = null;
                try
                {
                    //Create Texture
                    frameTex = new Texture2D(Memory.spriteBatch.GraphicsDevice, frame.Width, frame.Height, false, SurfaceFormat.Color); //GC will collect frameTex
                                                                                                                                        //Fill it with the bitmap.
                    bmpdata = frame.LockBits(new Rectangle(0, 0, frame.Width, frame.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);// System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    byte[] texBuffer = new byte[bmpdata.Width * bmpdata.Height * 4]; //GC here
                    Marshal.Copy(bmpdata.Scan0, texBuffer, 0, texBuffer.Length);

                    frameTex.SetData(texBuffer);


                }
                finally
                {
                    if (bmpdata != null)
                    {
                        frame.UnlockBits(bmpdata);
                    }
                }
                return frameTex;

            }
        }
如果你想的话,我可以发更多的。这几乎全在我的叉子上


视频将像在Windows中一样播放。可达到15 fps的平滑度。:)

我最终删除了代码中的位图部分。成功了!所以之前我会将帧转换为位图,它会将位图中的像素复制到纹理2D中。我仔细看了看,意识到我可以跳过位图的这一步。很抱歉,我的问题不够清楚

        /// <summary>
        /// Converts Frame to Texture
        /// </summary>
        /// <returns>Texture2D</returns>
        public Texture2D FrameToTexture2D()
        {
            Texture2D frameTex = new Texture2D(Memory.spriteBatch.GraphicsDevice, Decoder.CodecContext->width, Decoder.CodecContext->height, false, SurfaceFormat.Color);
            const int bpp = 4;
            byte[] texBuffer = new byte[Decoder.CodecContext->width * Decoder.CodecContext->height * bpp]; 
            fixed (byte* ptr = &texBuffer[0])
            {
                byte*[] srcData = { ptr, null, null, null };
                int[] srcLinesize = { Decoder.CodecContext->width * bpp, 0, 0, 0 };
                // convert video frame to the RGB data
                ffmpeg.sws_scale(ScalerContext, Decoder.Frame->data, Decoder.Frame->linesize, 0, Decoder.CodecContext->height, srcData, srcLinesize);
            }
            frameTex.SetData(texBuffer);
            return frameTex;
        }
//
///将帧转换为纹理
/// 
///纹理2d
公共纹理2D FrameToTexture2D()
{
Texture2D frameTex=新的Texture2D(Memory.spriteBatch.GraphicsDevice,Decoder.CodecContext->width,Decoder.CodecContext->height,false,SurfaceFormat.Color);
常数int bpp=4;
byte[]texBuffer=新字节[Decoder.CodecContext->width*Decoder.CodecContext->height*bpp];
已修复(字节*ptr=&texBuffer[0])
{
字节*[]srcData={ptr,null,null,null};
int[]srcLinesize={Decoder.CodecContext->width*bpp,0,0,0};
//将视频帧转换为RGB数据
ffmpeg.sws_scale(ScalerContext,Decoder.Frame->data,Decoder.Frame->linesize,0,Decoder.CodecContext->height,srcData,srcLinesize);
}
frameTex.SetData(texBuffer);
返回frameTex;
}

那么你的问题是什么?对不起,我想知道是否有其他方法可以完成我正在做的事情。以防万一,这在不起作用的地方会起作用。类似于从帧填充位图的另一种方法,或者跳过位图,一步转到帧到纹理2D。或者ffmpeg I中的一个函数可以更好地实现这一点。主要是它最终只能在linux中工作。我需要想法。显示ffmpeg的日志。我会查看日志。我见过使用日志的代码,但我还没见过。也许这会显示发生了什么。我把loglevel设置为恐慌,但它没有输出任何东西。无论如何,我找到了一个补丁,所以我会发布它。