【问题标题】:IMediaDet::GetBitmapBits returns zeroes - black image from mkv video fileIMediaDet::GetBitmapBits 返回零 - mkv 视频文件中的黑色图像
【发布时间】:2013-11-30 05:29:03
【问题描述】:

使用的外部库:http://sourceforge.net/projects/directshownet/

对于 avi、wmv、mp4、flv、webm 文件,此代码可以正常工作,但对于 mkv,它仅返回黑色图像(使用 x264 视频流和 xvid 视频流测试)。

所以...我的问题是:您有任何想法如何从 mkv 文件中获取框架吗? (目前我使用的是Hali Media Splitter)

public string FileName
{
        get
        {
            return fileName;
        }

        set
        {
            mediaDet = null;
            fileName = value;

            if (File.Exists(fileName))
            {
                AMMediaType mediaType = null;

                try
                {
                    mediaDet = (IMediaDet)new MediaDet();
                    DsError.ThrowExceptionForHR(mediaDet.put_Filename(fileName));

                    // find the video stream in the file
                    int index = 0;
                    Guid type = Guid.Empty;
                    while (type != MediaType.Video)
                    {
                        mediaDet.put_CurrentStream(index++);
                        mediaDet.get_StreamType(out type);
                    }

                    // retrieve some measurements from the video
                    mediaDet.get_FrameRate(out frameRate);

                    mediaType = new AMMediaType();
                    mediaDet.get_StreamMediaType(mediaType);
                    videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));
                    DsUtils.FreeAMMediaType(mediaType);
                    mediaType = null;
                    width = videoInfo.BmiHeader.Width;
                    height = videoInfo.BmiHeader.Height;

                    mediaDet.get_StreamLength(out mediaLength);
                    frameCount = (int)(frameRate * mediaLength);
                }
                catch (Exception e)
                {
                    if (mediaType != null)
                    {
                        DsUtils.FreeAMMediaType(mediaType);
                    }

                    fileName = "";

                    throw new ArgumentException(String.Format("unable to open the file \"{0}\", DirectShow reported the following error: {1}", value, e.Message));
                }
            }
        }
    }

public Bitmap GetImageAtTime(double seconds)
    {
        if (seconds <= mediaLength)
        {
            if (mediaDet != null)
            {
                IntPtr bufferPtr = IntPtr.Zero;
                Bitmap returnValue = null;

                try
                {
                    // create a buffer to hold the image data from the MediaDet
                    int bufferSize;
                    mediaDet.GetBitmapBits(seconds, out bufferSize, IntPtr.Zero, width, height);
                    bufferPtr = Marshal.AllocHGlobal(bufferSize);
                    mediaDet.GetBitmapBits(seconds, out bufferSize, bufferPtr, width, height);

                    // compose a bitmap from the data in the managed buffer 
                    unsafe
                    {
                        returnValue = new Bitmap(width, height, this.PixelFormat);
                        BitmapData imageData = returnValue.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, this.PixelFormat);
                        int* imagePtr = (int*)imageData.Scan0;

                        int bitmapHeaderSize = Marshal.SizeOf(videoInfo.BmiHeader);
                        int* sourcePtr = (int*)((byte*)bufferPtr.ToPointer() + bitmapHeaderSize);

                        for (int i = 0; i < (bufferSize - bitmapHeaderSize) / 4; i++)
                        {
                            *imagePtr = *sourcePtr;
                            imagePtr++;
                            sourcePtr++;
                        }

                        returnValue.UnlockBits(imageData);
                        returnValue.RotateFlip(RotateFlipType.Rotate180FlipX); // DirectShow stores pixels in a different order than Bitmaps do
                    }

                    Marshal.FreeHGlobal(bufferPtr);

                    return returnValue;
                }
                catch
                {
                    if (bufferPtr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(bufferPtr);
                    }

                    if (returnValue != null)
                    {
                        returnValue.Dispose();
                    }

                    throw;
                }
            }
            else
            {
                throw new InvalidOperationException("cannot retrieve the frame because the FileName property has not been set yet");
            }
        }
        else
        {
            throw new ArgumentException(String.Format("seconds must be between 0 and {0} inclusive, value was \"{1}\"", mediaLength, seconds));
        }
    }

【问题讨论】:

  • 为什么你更喜欢 DirectShow 而不是 Haali?
  • 我不明白你的意思。 Haali 是一个分离器,DirectShow 是一个 API/框架。

标签: c# video directshow directshow.net mkv


【解决方案1】:

您必须手动构建图形,最好使用您自己的基于 TransInPlace 过滤器的样本采集器过滤器。问题原因 - 标准 Sample Grabber 过滤器(在 IMediaDet 中使用)不支持的 VideoInfoHeader2 用法。您必须使用 VideoInfoHeader/VideoInfoHeader2 支持制作自己的过滤器。这很容易。使用 CEzRGB24 或灰度过滤器作为样本。

【讨论】:

  • 好的,所以我试过了,但是 var m_FilterGraph = (IFilterGraph2)new FilterGraph(); int hr = m_FilterGraph.AddSourceFilter(file, "Ds.NET FileFilter", out capFilter);正在给我 System.Runtime.InteropServices.COMException (0x80040241):无法加载此文件的源过滤器。而这个前。为我拥有的任何视频文件(avi、mp4、mkv 等)抛出请帮助:-\
  • sourceforge.net/projects/directshownet/files/DirectShowSamples/… in this sample (Samples\Editing\DxScan) 我在类似的地方有类似的错误(Capture.cs,SetupGraph(字符串文件)函数)
  • ok xD 所以我设法通过一些编辑 Samples\Editing\DxScan 从 MKV :D 获取帧。但是 - 我必须在 x86 下编译这个项目才能使其工作 - x64 有机会吗? x64 是错误 COMException 的原因
  • 是的,你可以。检查您是否有 x64 拆分器等,都必须工作。 DirectShowLib 也必须是 AnyCPU 或 x64 版本。
  • 当我使用 codeproject.com/Articles/21105/… 并单击(文件->渲染媒体文件)时,会显示类似的消息(无法加载文件的源过滤器 - 即使使用 .avi)但是当我我自己构建图表(文件源异步。-> LavSplitter -> 一些解码器 -> 增强的视频渲染)它正在工作......
猜你喜欢
  • 1970-01-01
  • 2012-09-30
  • 2014-04-27
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 2011-08-08
  • 1970-01-01
  • 2015-09-12
相关资源
最近更新 更多