Question

Utilisé External Lib: http://sourceforge.net/projects/directshownnet/

avec AVI, WMV, MP4, FLV, WebM Fichiers Ce code fonctionne correctement, mais avec MKV, il ne renvoie que l'image noire (testée avec le flux vidéo X264 et XVid Flux vidéo).

Alors ... Ma question est la suivante: avez-vous des idées comment obtenir le cadre du fichier MKV?(Actuellement, j'utilise 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));
        }
    }

Était-ce utile?

La solution

Vous devez construire le graphique manuellement, mieux d'utiliser votre propre filtre à récupération d'échantillons, en fonction du filtre transinplace.Raison du problème - Utilisation de la vidéoInfoHeader2 qui n'est pas prise en charge par un filtre à récupération d'échantillon standard (utilisé dans iMediadet).Vous devez effectuer votre propre filtre avec le support vidéoInfoheader / VideoFoHeader2.C'est facile.Utilisez un filtre CEZRGB24 ou GREYSCALER comme échantillons.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top