2015-05-02 11 views
57

Ho bisogno di riprodurre un file AVI personalizzato che contiene un flusso video classico, uno streaming audio ma anche un flusso di dati personalizzato.Riproduzione di un flusso di dati avi personalizzato utilizzando QtMultimedia

Il flusso personalizzato contiene dati visualizzati da alcuni widget personalizzati; questi widget hanno solo bisogno che ciascun frame personalizzato sia scritto in un buffer al momento giusto.

La nostra applicazione è basata su Qt, e usa già QMediaPlayer/QVideoWidget per riprodurre i video tradizionali, ma il flusso personalizzato aggiuntivo rende le cose più complicate, perché per quanto ne so QMediaPlayer riproduce solo il video/audio e ignora tutto il resto.

Vorrei evitare di reinventare l'intero qt-multimedia, ma non sono sicuro di come sfruttare al meglio le classi Qt disponibili.


Le mie idee finora sono:

  1. Scrivi un supporto personalizzato giocatore classe che demultiplexa e decodifica il video utilizzando ffmpeg, implementa i tempi, utilizza QAudioOutput per la riproduzione di audio, produce un flusso di QVideoFrame s da riprodurre sul video e scrivere i dati personalizzati su un buffer per la visualizzazione.

    Il problema: Al fine di evitare di scrivere il codice per ridimensionare/convertire i fotogrammi video, vorrei riutilizzare QVideoWidget, ma sembra funzionare solo con il "vero" QMediaPlayer.

  2. Demi il file di input e feed QMediaPlayer con i flussi AV. Demi l'input con ffmpeg (probabilmente lasciando la decodifica al backend Qt), avere uno QIODevice per recuperare solo i flussi video/audio dal file di input e un altro per recuperare il flusso di dati. Riproduci il video/audio con QMediaPlayer.

       +-------+       
           | QFile |       
           +---^---+       
            |        
           inherits       
            |        
         +--------------------+ 
         | MyAviDemuxer | 
         |     | 
         | holds a queue of | 
         | demuxed packets | 
         +--------------------+ 
         |     | 
        readDataPacket  readVideoPacket 
         |     | 
    +-------v--------+ +--------v-----------+   +-----------+ 
    | MyCustomReader | | MyVideoAudioStream +--inherits--> QIODevice | 
    +----------------+ +--------+-----------+   +-----------+ 
              |  
              setMedia     
              |     
            +-------v-------+   
            | QMediaPlayer |   
            +---------------+   
    

    Il problema: sincronizza la temporizzazione del flusso di dati con QMediaPlayer, gestire intestazioni e metadati in modo corretto.


Sono leggermente inclinato all'opzione 1, proprio perché mi dà più controllo, ma mi chiedo se ho perso una soluzione più facile (anche solo per Windows).

+3

Perché, in nome dei stai ancora utilizzando AVI nel 2015? –

+2

@StevenPenny Bozza, motivi legacy e cosa no. Lo cambieremo. La domanda si applica comunque a qualsiasi formato di contenitore multimediale. – sbabbi

+0

Qualsiasi motivo preferisci FFmpeg su GStreamer? – karlphillip

risposta

1

Capisco che tu abbia abbastanza la struttura di classe personalizzata, ma forse potresti usare qualche consiglio da un principiante di codifica. Penso che dovresti utilizzare alcuni tipi di dati esistenti di base insieme alle tue classi personalizzate.

Soluzione: sincronizzare la temporizzazione del flusso di dati con QMediaPlayer:
Prova utilizzando alcuni fili timer (combinazione di Thread e timer).Creane uno che usi qualunque sia l'indice del flusso di MyVideoAudioStream (utilizzando il tempo come variabile nell'indice) e "Mycustomreader" (utilizzando una serie di pacchetti con il tempo come variabile nell'indice) come se fosse un corpo. Aggiungi al corpo una logica che passa attraverso la posizione (@param: time) in QMediaPlayer. Da questo, è possibile analizzare il codice di esecuzione di entrambi allo stesso tempo. Con l'aumentare del tempo, la posizione in QMediaPlayer e l'indice del tuo stream aumenterebbero.

Se non si dispone di un indice o posizione nel flusso personalizzato, consiglio vivamente di crearne uno.

+0

Il flusso personalizzato è incorporato nel file passato a QMediaPlayer. Questa soluzione richiederebbe di aprire lo stesso file due volte e fondamentalmente caricare l'indice due volte (una volta per il flusso personalizzato e una volta all'interno del codice qt). È un modo semplice, ma non molto pulito. Dipende anche dal presupposto che qmediaplayer (o più propriamente il backend che sta usando) non si blocchi immediatamente quando vede uno stream nel file AVI che non può capire. – sbabbi

+0

Come ho detto, sono un novellino di programmazione. So che questa risposta non è pulita, ma è ancora l'unica risposta qui ... Se hai una soluzione migliore, postala! –

1

Sembra che Qt supporti già in qualche misura il concetto di flussi di dati - http://doc.qt.io/qt-5/qmediastreamscontrol.html#details mostra che è tra i tipi di flussi selezionabili per un controllo di qmediastreams.

Altri documenti tra cui http://doc.qt.io/qt-5/qmediaserviceproviderplugin.html suggeriscono che si potrebbe creare un QMediaServiceProviderPlugin che implementa il video e interfacce QMediaControl audio (possibilmente da sottoclasse un fornitore di servizi di media esistente), un creare anche la propria sottoclasse QMediaControl interfaccia per creare un controllo per gestire i dati grezzi .

Si spera che l'implementazione in questo modo consenta di utilizzare le strutture esistenti per suddividere i flussi, gestire le intestazioni e funzionalità simili.

Sfortunatamente le specifiche relative alla creazione di un QMediaService sembrano essere "al di fuori degli scopi di questa documentazione e il supporto sulle mailing list o canali IRC pertinenti". (http://doc.qt.io/qt-5/qmediaservice.html#details). La fonte (http://code.qt.io/cgit/qt/qtmultimedia.git/tree/src/multimedia) potrebbe essere utile, tuttavia, oltre a, forse, la sorgente su http://code.qt.io/cgit/qt/qtmultimedia.git/tree/src/plugins, che include i plugin directshow/gstreamer/coreaudio.

In ogni caso vorrei provare a creare una sottoclasse e ri-implementare il meno possibile

Problemi correlati