2012-06-18 7 views
8

Ich erhalte eine H.264 stream von einem DVR mit seinem SDK. Es gab Speicherverluste und ich dachte, dass es das SDK war, das alle Lecks verursachte. Aber als ich den Stream aufzeichnete und die Frames eins nach dem anderen von der Festplatte abspielte (ohne irgendwelche Drittanbieter-DLLs), bemerkte ich, dass das Problem nicht die DLL ist, sondern der Stream selbst.H.264 Frames Speicher Leck mit einigen Decodern

Seltsamerweise ist DivX H264 Decoder der einzige Codec, der keinen Speicherverlust verursacht, aber wenn der Stream für eine lange Zeit läuft, stürzt manchmal auch der DivX-Dekoder ab. Ich würde lieber Microsoft DTV-DVD Video Decoder verwenden, aber es verursacht große Speicherverluste und lässt viele Frames fallen. Viele andere H.264-Decoder, die ich ausprobiert habe, verhalten sich genauso.

Ich untersuchte die h.264 frames mit einigen h.264 parsers Vergleich mit einigen anderen problemlosen Streams, aber ich habe nichts offensichtlich aus den Protokollen bemerkt.

Da mein Problem über die h.264 Frames Struktur ist, habe ich einen Quellfilter namens FramesFromFileSourceFilter vorbereitet, den Sie unten herunterladen können.

http://www.akaydin.com/directshow/FramesFromFileSourceFilter.zip

Es ist ein Visual Studio 2008 Projekt und alle Abhängigkeiten werden in der ZIP-Datei in relativ befindet Ordner (einschließlich der h.264 Frames) enthalten. Alles, was Sie tun müssen, ist, das Projekt zu kompilieren, die Ausgabe mit regsvr32.exe zu registrieren und den Filter mit jedem gewünschten h.264-Decoder von GraphEdit oder GraphStudio auszuführen. Beispielgrafiken sind unten.

FramesFromFileSourceFilter with DivX

FramesFromFileSourceFilter with Microsoft DTV-DVD Video Decoder

Auch h264 Rahmen sind als einzelne raw h264 Datei auf dem Link, unter dem von VLC spielbar ist (mit falschem FPS seit Original war 12 FPS).

http://www.akaydin.com/directshow/stream.zip

Frage:

Was könnte die Speicherleck Probleme mit vielen bekannten H264 Decoder außer DivX-Decoder verursachen. Was ist los mit diesem Stream?

aktualisieren 1

wird Lesedaten Gewinde entfernt und Funktionalität bewegt in FillBuffer ohne Puffer und Flags zu verwenden. Das Problem bleibt gleich.

http://www.akaydin.com/directshow/FramesFromFileSourceFilterUpdate1.zip

aktualisieren 2

Update1 wurde mit Sleep() in FillBuffer() Funktion, die einige Probleme verursachte. Jetzt entfernte ich die Sleep() und benutzte SetTime(), um ~ 12 FPS zu haben. Dies löste auch die Droprahmenprobleme, löste jedoch keine Speicherprobleme.

http://www.akaydin.com/directshow/FramesFromFileSourceFilterUpdate2.zip

Speichererhöhung bei Working Set tritt nur. Virtual Bytes und Private Bytes scheinen stabil zu sein.Was könnte fortlaufende Working Set Speicherinkremente verursachen, die nur mit passiert?

Antwort

3

Sie noch keine Synchronisation um Ihre Variablen

BYTE* m_buffer; 
DWORD m_bufferSize; 
bool isFrameReady; 

Und sie werden aus zwei gleichzeitigen Threads verwendet. Sie verlieren nur Ihren Speicher durch diese ungenaue Zuordnung/Freigabe AND/ODER lassen Sie Ihren Code bei Zugriffsverletzung abstürzen. Der Debug-Build Ihrer DLL zeigt dies an, indem Sie beim Ausführen des Tests die Warnung "Heap-Fehler" anzeigen. Das Laufzeitverhalten kann mit den Decodern und der Umgebung variieren, dies ist jedoch definitiv ein schwerwiegender Fehler, der behoben werden muss.

Zum Beispiel können Sie CAutoLock cAutoLock(m_pLock); in Ihrem Thread verwenden, der Puffer füllt, um Streaming-Thread-Zugriff zu verhindern, während Sie Daten aus der Datei lesen.

Beachten Sie, dass Sie den nächsten Frame in den gleichen Pufferzeiger lesen, ohne zu überprüfen, ob zuvor zugewiesener Speicher freigegeben wurde oder nicht, Sie überschreiben den Zeiger möglicherweise und hinterlassen ein Leck.

Speicherleck/Working Set Update: Jetzt, wenn Code-Probleme aussortiert werden, ist das unerwünschte Laufzeitverhalten eine Zunahme in Working Set Größe. Dies ist kein Leck. Es ist ein Hinweis darauf, dass Windows den Prozess als eine Art Priorität betrachtet (warum nicht? Er ist aktiv und arbeitet mit Speicher) und wirft mehr echte Seiten in diesen Prozess, um seine Leistung zu erleichtern. Unter this answer finden Sie eine gute Erklärung, wie Prozessspeichermetriken Speicherlecks in einer Anwendung entsprechen.

Der Unterschied zwischen den Decodern, die Sie sehen könnten, wird wahrscheinlich durch die Tatsache verursacht, dass einige Decoder mit einer kleineren Menge an Puffern gut sind, oder sie aktiver wiederverwenden, z. ziehen es vor, den gleichen Puffer aus einem Pool zu nehmen, anstatt nacheinander durch alle verfügbaren zu picken.

+0

Eigentlich hat mein echter Filter einen besseren Mechanismus, das ist der vereinfachte. Da es zwischen den Bildern jedoch einen Zeitraum von 83 Millisekunden gibt, sollte die Nebenläufigkeit nicht der Fall sein. Außerdem verursacht DivX Decoder keine Speicherlecks. Ich glaube immer noch, dass Streams dieses Problem verursachen. Außerdem funktioniert derselbe Filter gut mit anderen h.264-Streams von anderen Geräten ohne Speicherlecks mit denselben Decodern. –

+0

Vielleicht macht es Ihr echter Filter besser, aber dieser Code verursacht Heap-Korruption. Auf einem anderen Lauf, als es durchkam, bemerkte ich kein Leck (mit MS DTV-DVD Decoder), wie sagt man, ob das Leck stattgefunden hat? –

+0

Speicher nimmt während des Prozesses weiter zu, solange der Filter läuft. natürlich gibt es in diesem Beispiel eine begrenzte Anzahl von Frames. Wenn Sie jedoch mit einem Livestream arbeiten, erreicht die Speicherbelegung nach einigen Stunden Gigabytes. Haben Sie bei der Ausführung des Filters mit MS DTV-DVD Video Decoder keine Speichererhöhung von GraphEdit/GraphStudio bemerkt? Wenn ja, was ist dein Betriebssystem? Ich habe dies auf Win7 32 Bits. –