Frage

Ich möchte eine kleine Videodatei öffnen und alle Bilder im Speicher zuordnen (um einen benutzerdefinierten Filter anzuwenden).Ich möchte mich nicht um den Video-Codec kümmern, das würde ich lieber der Bibliothek überlassen.

Ich habe versucht, Direct Show mit dem SampleGrabber-Filter zu verwenden (unter Verwendung dieses Beispiels). http://msdn.microsoft.com/en-us/library/ms787867(VS.85).aspx), aber ich habe es nur geschafft, einige Frames zu ergattern (nicht alle Frames!).Ich bin ziemlich neu in der Programmierung von Videosoftware, vielleicht verwende ich nicht die beste Bibliothek, oder ich mache es falsch.

Ich habe einen Teil meines Codes eingefügt (hauptsächlich ein modifiziertes Kopieren/Einfügen aus dem MSDN-Beispiel), leider werden die ersten 25 Frames nicht wie erwartet erfasst ...

[...]

hr = pGrabber->SetOneShot(TRUE);
hr = pGrabber->SetBufferSamples(TRUE);

pControl->Run(); // Run the graph.
pEvent->WaitForCompletion(INFINITE, &evCode); // Wait till it's done.

// Find the required buffer size.
long cbBuffer = 0;
hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);

for( int i = 0 ; i < 25 ; ++i )
{
    pControl->Run(); // Run the graph.
    pEvent->WaitForCompletion(INFINITE, &evCode); // Wait till it's done.

    char *pBuffer = new char[cbBuffer];
    hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);

    AM_MEDIA_TYPE mt;
    hr = pGrabber->GetConnectedMediaType(&mt);
    VIDEOINFOHEADER *pVih;
    pVih = (VIDEOINFOHEADER*)mt.pbFormat;

    [...]
}

[...]

Gibt es jemanden mit Erfahrung in Videosoftware, der mir Ratschläge zu Code oder anderen einfacheren Bibliotheken geben kann?

Danke

Bearbeiten:Msdn-Links scheinen nicht zu funktionieren (siehe den Fehler)

War es hilfreich?

Lösung

Derzeit sind dies die beliebtesten Video-Frameworks, die auf Win32-Plattformen verfügbar sind:

  1. Video für Windows:altes Windows-Framework aus der Zeit von Win95, aber immer noch weit verbreitet, da es sehr einfach zu verwenden ist.Leider werden nur AVI-Dateien unterstützt, für die der richtige VFW-Codec installiert wurde.

  2. Direkt zeigen:Standard-WinXP-Framework, es kann grundsätzlich alle Formate laden, die Sie mit dem Windows Media Player abspielen können.Eher schwierig zu bedienen.

  3. Ffmpeg:Genauer gesagt libavcodec und libavformat, die mit dem Open-Source-Multimedia-Dienstprogramm Ffmpeg geliefert werden.Es ist extrem leistungsstark und kann viele Formate lesen (fast alles, mit dem Sie spielen können). VLC), auch wenn Sie den Codec nicht auf dem System installiert haben.Die Verwendung ist ziemlich kompliziert, aber Sie können sich jederzeit vom mitgelieferten ffplay-Code oder von anderen Implementierungen in Open-Source-Software inspirieren lassen.Ich denke jedenfalls, dass es immer noch viel einfacher zu bedienen ist als DS (und viel schneller).Es muss von MinGW unter Windows kompiliert werden, aber alle Schritte werden sehr gut erklärt Hier (In diesem Moment ist der Link unterbrochen, ich hoffe, er ist nicht tot).

  4. Schnelle Zeit:Das Apple-Framework ist nicht die beste Lösung für die Windows-Plattform, da die Installation der QuickTime-App und des richtigen QuickTime-Codecs für jedes Format erforderlich ist.Es unterstützt nicht viele Formate, ist aber im professionellen Bereich weit verbreitet (einige Codecs sind daher eigentlich nur für QuickTime geeignet).Die Umsetzung sollte nicht allzu schwierig sein.

  5. Gstreamer:neuestes Open-Source-Framework.Ich weiß nicht viel darüber, ich vermute, dass es einige der anderen Systeme überdeckt (aber ich bin mir nicht sicher).

Alle diese Frameworks wurden als Backend in OpenCv Highgui implementiert, mit Ausnahme von DirectShow.Das Standard-Framework für Win32 OpenCV verwendet VFW (und kann daher nur einige AVI-Dateien öffnen). Wenn Sie die anderen verwenden möchten, müssen Sie das CVS anstelle der offiziellen Version herunterladen und trotzdem ein wenig am Code herumhacken, aber das ist sowieso nicht der Fall zu vollständig, zum Beispiel erlaubt das FFMPEG-Backend keine Suche im Stream.Wenn Sie QuickTime mit OpenCV verwenden möchten Das kann dir helfen.

Andere Tipps

Ich habe benutzt OpenCV um Videodateien zu laden und zu verarbeiten.Es ist auch praktisch für viele Arten der Videoverarbeitung, einschließlich solcher, die für Computer Vision nützlich sind.

Die Verwendung des „Callback“-Modells von SampleGrabber kann zu besseren Ergebnissen führen.Siehe das Beispiel unter Samples\C++\DirectShow\Editing\GrabBitmaps.

Viele Informationen finden Sie auch in Samples\C++\DirectShow\Filters\Grabber2\grabber_text.txt und readme.txt.

Ich weiß, dass es in C++ sehr verlockend ist, die Videodateien richtig aufzuschlüsseln und es einfach selbst zu machen.Aber obwohl die Informationen vorhanden sind, ist es ein so langwieriger Prozess, Klassen zu erstellen, um jedes Dateiformat zu verwalten und es leicht änderbar zu machen, um zukünftige Strukturänderungen zu berücksichtigen, dass es sich ehrlich gesagt einfach nicht lohnt.

Stattdessen empfehle ich ffmpeg.Es wurde oben erwähnt, aber es heißt, es sei schwierig, es sei nicht schwierig.Es gibt viel mehr Optionen, als die meisten Leute brauchen würden, was es schwieriger erscheinen lässt, als es ist.Die meisten Vorgänge können Sie ffmpeg einfach selbst erledigen lassen.

Beispiel

Entscheiden Sie von Anfang an, dass Sie ffmpeg-Operationen in einem Thread, genauer gesagt einer Thread-Bibliothek, ausführen lassen.Aber lassen Sie es von Ihrer eigenen Thread-Klasse umschließen, damit Sie über eigene EventAgs und Methoden verfügen können, um zu überprüfen, ob der Thread fertig ist.Etwas wie :-

ThreadLibManager()
{
  List<MyThreads> listOfActiveThreads;
  public AddThread(MyThreads);
}
Your thread class is something like:-
class MyThread
{
 public Thread threadForThisInstance { get; set; }
 public MyFFMpegTools mpegTools { get; set; }
}
MyFFMpegTools performs many different video operations, so you want your own event  
args to tell your parent code precisely what type of operation has just raised and 
event.
enum MyFmpegArgs
{
public int thisThreadID { get; set; } //Set as a new MyThread is added to the List<>
public MyFfmpegType operationType {get; set;}
//output paths etc that the parent handler will need to find output files
}
enum MyFfmpegType
{
  FF_CONVERTFILE = 0, FF_CREATETHUMBNAIL, FF_EXTRACTFRAMES ...
}

Hier ist ein kleiner Ausschnitt meiner ffmpeg-Tool-Klasse, dieser Teil sammelt Informationen über ein Video.Ich habe FFmpeg an einem bestimmten Ort abgelegt und beim Starten der Software wird sichergestellt, dass es dort vorhanden ist.Für diese Version habe ich es auf den Desktop verschoben. Ich bin mir ziemlich sicher, dass ich den Pfad für Sie richtig geschrieben habe (ich hasse das spezielle Ordnersystem von MS wirklich, deshalb ignoriere ich es so gut ich kann).

Auf jeden Fall ist es ein Beispiel für die Verwendung von fensterlosem ffmpeg.

        public string GetVideoInfo(FileInfo fi)
    {
        outputBuilder.Clear();
        string strCommand = string.Concat(" -i \"", fi.FullName, "\"");
        string ffPath =   
  System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\ffmpeg.exe";
        string oStr = "";

        try
        {
            Process build = new Process();
            //build.StartInfo.WorkingDirectory = @"dir";
            build.StartInfo.Arguments = strCommand;
            build.StartInfo.FileName = ffPath;

            build.StartInfo.UseShellExecute = false;
            build.StartInfo.RedirectStandardOutput = true;
            build.StartInfo.RedirectStandardError = true;
            build.StartInfo.CreateNoWindow = true;
            build.ErrorDataReceived += build_ErrorDataReceived;
            build.OutputDataReceived += build_ErrorDataReceived;
            build.EnableRaisingEvents = true;
            build.Start();
            build.BeginOutputReadLine();
            build.BeginErrorReadLine();
            build.WaitForExit();


            string findThis = "start";
            int offset = 0;
            foreach (string str in outputBuilder)
            {
                if (str.Contains("Duration"))
                {
                    offset = str.IndexOf(findThis);
                    oStr = str.Substring(0, offset);
                }
            }
        }
        catch
        {
            oStr = "Error collecting file information";
        }

        return oStr;
    }
    private void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        string strMessage = e.Data;
        if (outputBuilder != null && strMessage != null)
        {
            outputBuilder.Add(string.Concat(strMessage, "\n"));
        }
    } 

Versuchen Sie es mit dem OpenCV Bibliothek.Es verfügt auf jeden Fall über die Fähigkeiten, die Sie benötigen.

Dieser Leitfaden enthält einen Abschnitt über den Zugriff auf Frames aus einer Videodatei.

Wenn es sich um AVI-Dateien handelt, würde ich die Daten selbst aus der AVI-Datei lesen und die Frames extrahieren.Verwenden Sie nun den Videokomprimierungsmanager, um es zu dekomprimieren.

Das AVI-Dateiformat ist sehr einfach, siehe: http://msdn.microsoft.com/en-us/library/dd318187(VS.85).aspx (und Google verwenden).

Sobald Sie die Datei geöffnet haben, extrahieren Sie einfach jeden Frame und übergeben ihn an ICDecompress(), um ihn zu dekomprimieren.

Es scheint eine Menge Arbeit zu sein, aber es ist der zuverlässigste Weg.

Wenn das zu viel Arbeit ist oder Sie mehr als AVI-Dateien möchten, verwenden Sie ffmpeg.

OpenCV ist die beste Lösung, wenn das Video in Ihrem Fall nur zu einer Bildfolge führen soll.Wenn Sie bereit sind, echte Videoverarbeitung durchzuführen, sodass ViDeo „Visual Audio“ entspricht, müssen Sie mit den von „martjno“ angebotenen Schritten Schritt halten.Neue Windows-Lösungen auch für Win7 beinhalten zusätzlich 3 neue Möglichkeiten:

  1. Windows Media Foundation:Nachfolger von DirectShow;bereinigte Schnittstelle
  2. Windows Media Encoder 9:Es enthält nicht nur das Programm, sondern auch Bibliotheken zum Codieren
  3. Windows-Ausdruck 4:Nachfolger von 2.

Die letzten beiden sind reine kommerzielle Lösungen, die erste ist jedoch kostenlos.Um WMF zu codieren, müssen Sie das Windows SDK installieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top