2012-04-11 17 views
2

Dieser bringt mich wirklich dazu, meine Haare herauszuziehen. Ich habe einen DirectShow-Transformationsfilter geschrieben, der von CTransformFilter abgeleitet wurde. Ich habe einen Input-Pin von CTransformInputPin abgeleitet. Wenn die Receive-Methode meines Eingangspins aufgerufen wird, protokolliert sie die Darstellungszeiten des IMediaSamples in einer Datei. Das alles funktioniert gut, bis ich den Graphen stoppe und neu starte (ich benutze MS Graphedt). Die meiste Zeit, wenn man wieder läuft, gibt es keine Probleme. Aber etwa bei etwa einem Dutzend Mal, dass ich aufhöre und dann den Graphen erneut starte, ist die Startzeit der Präsentation negativ. Es steigt schließlich auf und steigt über Null an, während der Graph läuft, aber es holt nie die Stromzeit auf, mit dem Ergebnis, dass die Stromzeit für jede Abtastung signifikant über Kopf der Präsentationsstartzeit bleibt.Negative Präsentationszeit in DirectShow

Ich habe dies mit einer Logitech Webcam Pro 9000 und einer Logitech C600 Kamera beobachtet, aber nicht mit einer Winbook Kamera, also frage ich mich, ob das ein Logitech Problem ist. Hat jemand andere negative Präsentationszeiten auf Video IMediaSamples nach dem Anhalten und wieder laufen gesehen? (Ich habe in der Pre-Roll-Flag im IMediaSample sah. Es ist immer S_FALSE)

UPDATE:

Ich habe CTransformFilter die außer Kraft gesetzt (eigentlich CBaseFilter der) Run-Methode mit diesem:

STDMETHODIMP MyTransformFilter::Run(REFERENCE_TIME tStart) 
{ 
    char buff[1000]; 
    REFERENCE_TIME rTime; 

    m_pClock->GetTime(&rTime); 
    sprintf(buff, "Run tstart = %lld, rTime = %lld", tStart, rTime); 
    Trace(buff); // open my log file, add buff, close my log file 
    return CTransformFilter::Run(tStart); 
} 

Ich benutzte Graphedt, um den Graphen zu starten, 10 Sekunden lang zu laufen, 5 Sekunden zu pausieren und dann erneut zu starten. Hier ist die Ausgabe:

Run tstart = 7855978550000, rTime = 7855978450000 
Run tstart = 7856030610000, rTime = 7856126960000 

Die beiden Zeiten von 5,2 Sekunden abweichen Ausführen übergeben (über die Höhe der Zeit, die ich angehalten). Die beiden Referenzzeitpunkte unterscheiden sich um 14,6 Sekunden (etwa die Gesamtzeit zwischen Aufrufen von Run). Abgesehen von dem leichten Anstieg, den der Filtergraph-Manager zu der Zeit hinzufügt, die an Run (10 ms, im ersten Aufruf) übergeben wurde, würde ich erwarten, dass diese bei jedem Aufruf von Run nahezu identisch sind. Stattdessen ist die Zeit, die beim zweiten Aufruf an Run übergeben wird, etwa 10 Sekunden hinter dem Referenztakt. Ich wäre äußerst dankbar für Hilfe, um zu verstehen, warum die Zeit, die beim zweiten Aufruf von Run verstrichen ist, nicht (fast) die gleiche ist wie die Zeit, die die Referenzuhr beim zweiten Aufruf zurückgibt.

UPDATE 2:

Problem erscheint in der Logitech-Version 13.31.1044.0 Treiber. Siehe Antwort unten.

Antwort

1

Nach einigem Experimentieren bin ich zu dem Schluss gekommen, dass das Problem sehr wahrscheinlich auf den Logitech 13.31.1044.0 Kameratreiber zurückzuführen ist. Mit dem früheren Logitech 12.10.1110 Treiber, mit der Winbook DC-6120 Kamera (und ihrem Treiber) und der Chicony USB 2.0 Kamera (und ihrem Treiber) konnte ich das Problem nicht wiederholen.Ohne ersichtlichen Grund wird der Logitech 13-Treiber Proben liefern, die mit negativen Präsentationszeiten beginnen, in etwa einem von etwa einem Dutzend Mal, einschließlich eines Neustarts (dh nachdem ich es in grafischer Form gestoppt und dann erneut gestartet habe)). Ein Vergleich dieser Zeiten mit der Streamzeit liefert nicht die Informationen, die MSDN beschreibt, ob die Probe zur Anzeige in der Vergangenheit, Gegenwart oder Zukunft geplant ist oder nicht, da die Streamzeit nicht beeinträchtigt scheint. Bei jedem Neustart beginnt die Stream-Zeit wie erwartet wieder bei Null, unabhängig davon, zu welcher Zeit die Präsentationszeiten der Kamera beginnen. (Beachten Sie, dass der Logitech im RGB24-Subtyp ohne komprimierte Frames streamt.)

Ich arbeite an einem Multithread-Pass-Through-Filter, der die Darstellungszeiten möglicherweise anhand der Streamzeit neu zuweisen kann. und tun so schnell genug, um korrekte Werte zu "fälschen", und werde hier posten, wenn ich ein bedeutungsvolles Ergebnis bekomme. Außerdem werde ich meine Tests dokumentieren und Logitech mitteilen. Wenn sie antworten, poste ich das auch hier.

Wenn jemand anderes mit den Logitech-Produkten arbeitet, die den oben genannten Treiber verwenden (oder das beschriebene Verhalten anderweitig beobachten), kommentieren Sie bitte hier. Ich würde Ihnen gerne eine Kopie meines Filters schicken, der die Zeiten, Rahmen und so weiter protokolliert. Wir könnten vielleicht zusammenarbeiten, um einen guten Weg zu finden, damit umzugehen.

UPDATE

mit möglichst einfachen TRANFORM Filter zu schreiben, die ich könnte (eine, die einfach kopiert ein negatives Bild des Eingangs IMediaSample mit dem Ausgang), konnte ich dieses Verhalten ziemlich konsequent reproduzieren. Etwa alle fünf oder sechs Mal starte ich einen Graphen neu, der aus Kamera-> Filter-> Renderer besteht, die ersten paar Samples werden mit negativen Frame-Zeiten ausgeliefert, die weit hinter der Stream-Zeit liegen und niemals aufholen. (Das heißt, die Stream-Zeit bleibt den Präsentationszeiten der Samples dauerhaft voraus). Auch das passiert weder mit anderen Kameras noch mit dem älteren Logitech-Treiber.

Hier ist der interessante Teil: Wenn ich der Run-Methode des Filters etwas Verzögerung hinzufüge (nach dem Überschreiben von CTransformFilter :: Run), verschwindet das Problem. Hier ist der Code:

STDMETHODIMP DLPassThrough::Run(REFERENCE_TIME tStart) 
{ 
    Sleep(10); 

    return CTransformFilter::Run(tStart); 
} 

Ich kann das Problem kommen und gehen durch Kommentieren oder Wiederherstellen der "Sleep (10)" Anruf. Alles was ich erraten kann ist, dass der Kameracode Multi-Threaded ist und einige Zeit zwischen dem "Pause" -Aufruf, der immer einem "Run" -Ruf vorausgeht, und dem nächsten "Run" -Aufruf benötigt, um aufzuräumen, was er macht. Wie ich die MSDN-Dokumentation verstehe, ruft der Graph-Manager auf dem Renderer "Pause", dann meinen Filter und dann die Kamera auf, bevor er zurückgeht und "Run" auf dem Renderer, meinem Filter und dann der Kamera aufruft. Ich glaube, dass jeder dieser Aufrufe synchron ist, aber wenn der Kameracode Multithread ist, kann er immer noch an seinem letzten "Pause" -Aufruf vom Graph-Manager arbeiten, wenn seine "Run" -Methode aufgerufen wird. Wenn ich der "Run" -Methode meines Filters eine Verzögerung hinzufüge, gibt es eine längere Verzögerung zwischen dem letzten "Pause" -Aufruf an die Kamera und dem nächsten "Run" -Aufruf an die Kamera.

Ich warte immer noch darauf, von Logitech zu hören. In der Zwischenzeit habe ich einen Multithread-Transform-In-Place-Filter geschrieben, der einfach einen Verweis auf das neueste Sample hinzufügt, seine Präsentationszeiten durch die aktuelle Stream-Zeit ersetzt, speichert sie für den Downstream-Filter, um das nächste Mal den Downstream zu verwenden Der Filter ist bereit, ihn zu empfangen und kehrt dann zum Warten auf das nächste eingehende Sample zurück. (Wenn mehr als ein Sample kommt, bevor der Downstream-Filter einen Sample aufnimmt, wird das vorherige Sample freigegeben und durch das letzte Sample ersetzt.) Scheint soweit zu arbeiten.

UPDATE 2

Hier ist Logitechs Antwort:

Ich mag möchte Sie informieren, dass das Gerät in erster Linie gemacht wurde für IM-Anwendungen für Video-Streaming zu arbeiten und nicht als Thema für die Entwicklung von Software oder Filter.

3

Negative Zeit ist keine große Sache. Im Wesentlichen heißt das: "Die Medienprobe sollte schon vor einer Weile präsentiert worden sein". Sie könnten also denken, dass die Medienprobe verworfen werden könnte? Manchmal ist dies richtig, manchmal nicht: Stellen Sie sich eine Sequenz von zeitlich komprimierten Videoframes mit einem Schlüsselframe gefolgt von 10 Delta-Frames vor. Sie möchten, dass die Präsentation mit Frame 5 beginnt, wie können Sie das tun? Sie müssen vom Schlüsselrahmen aus durchschalten, damit der Dekodierer den Spleißpunkt effektiv dekodieren kann, andernfalls kann er nicht mit dem Deltarahmen beginnen. Ein Decoder liefert möglicherweise den Ausgabe-Frame unabhängig davon, ob der Frame zu spät ist oder nicht, und so gelangen diese Frames schließlich zu Ihnen.

Ein anderes Szenario, das zu einer negativen Zeit führt, wird durch die Racebedingung von Threads, Streaming und Steuerung verursacht. Der Erfassungsthread startet möglicherweise seine Operation, hat aber noch keine Basis- "Startzeit" auf Händen.

+0

Ich würde das verstehen, wenn die Stream-Zeit auf dem neugestarteten Graph nicht bei Null neu gestartet wurde. Jedes Mal, wenn ich den Graphen stoppe und starte, beginnt die Stream-Zeit wieder bei Null. Aber bei etwa einem von 12 Malen beginnt der Capture-Filter (wenn es eine Logitech-Kamera ist) davor (-15.000.000 oder mehr REFERENCE_TIME-Einheiten) davor. Wenn nichts anderes, würde ich erwarten, dass der Capture-Filter konsistent über die Beziehung zwischen seinen Darstellungszeiten und der Stream-Zeit des Graphen ist. –

+0

-15M ist -1,5 Sekunden - ziemlich viel aber fällt immer noch in den zweiten Absatz oben. –

+0

Kann ich irgendetwas tun, um dies zu korrigieren? Ich versuche, die Präsentationszeit mit der Streamzeit zu vergleichen, damit ich entscheiden kann, ob ich ein Sample löschen soll oder nicht, anstatt es in meinem Transformationsfilter zu verarbeiten. Wenn der Capture-Filter mit einem negativen Wert beginnt, bleibt er von da an so weit hinter dem Stream-Team und lässt mir keine Möglichkeit, zu entscheiden, ob das Sample so weit hinter der Stream-Zeit liegt, die ich fallen lassen sollte es. –