Torna indietro   Hardware Upgrade Forum > Software > Programmazione

La Formula E può correre su un tracciato vero? Reportage da Misano con Jaguar TCS Racing
La Formula E può correre su un tracciato vero? Reportage da Misano con Jaguar TCS Racing
Abbiamo visto ancora una volta la Formula E da vicino, ospiti di Jaguar TCS Racing. In questa occasione però curve e rettilinei erano quelli di un circuito permanente, molto diverso dagli stretti passaggi delle strade di Roma
Lenovo LEGION e LOQ: due notebook diversi, stessa anima gaming
Lenovo LEGION e LOQ: due notebook diversi, stessa anima gaming
Lenovo ha puntato forte sul gaming negli ultimi anni e lo testimoniano i marchi LEGION e LOQ, il primo per gli amanti delle massime prestazioni e dell'assenza di compromessi, il secondo per chi desidera soluzioni dal buon rapporto tra prestazioni e prezzo. Abbiamo provato due esponenti dell'offerta, così da capire l'effettiva differenza prestazionale.
Nothing Ear e Ear (a): gli auricolari per tutti i gusti! La ''doppia'' recensione
Nothing Ear e Ear (a): gli auricolari per tutti i gusti! La ''doppia'' recensione
Nothing propone sul mercato non uno ma ben due auricolari nuovi: Ear di terza generazione e Ear (a) ossia un nuovo modello a basso costo pronto a ritagliarsi una fetta di mercato. Entrambi rimangono fedeli al marchio per il design ancora trasparente ma fanno un balzo in avanti notevole per qualità e soppressione del rumore.  
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 14-11-2018, 10:21   #1
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
Qt 5.6.1 / Linux Streaming MJPEG in plug browser

Ho un problema che mi sta davvero facendo impazzire... ho una telecamera tipo "video sorveglianza" che mi invia via HTTP uno stream mjpeg che qualsiasi browser del mondo sa leggere semplicemente aprendo la pagina, ma ovviamente QWebkit no! Il meglio che ho ottenuto è che lo stampasse come testo

La cosa più ovvia visto che sto "browser" a stento supporta HTML4 era di usare un plugin, ma Flash no perché la gente ha paura di lui (?), così avevo pensato al plugin di VLC, ma tutto quello che ho ottenuto era un cubetto con un bel '?' dentro!

Ora sto provando a fare il mio plugin ed ero tutto contento perché questo funziona pure: http://doc.qt.io/archives/qt-4.8/qt-...n-example.html!

Così ho pensato di usare QMediaplayer, ma sembra la solita cosa non finita... come plugin va addirittura in SIGABORT (!), l'applicazione standalone mi mostrava uno schermo nero

I codec credo di averceli ho messo gstreamer-ffmpeg che dovrebbe supportare qualunque cosa, ma nulla!

Come ultimo tentativo ho deciso di farlo "a mano", in fondo uno stream MJPEG è piuttosto semplice da gestire sono tante JPEG una dietro l'altra e infatti l'applicazione standalone funziona!

Così stamane mi appropinquo a trasformarla in un plugin e... NON appare nulla!
Peggio ancora il segnale readyRead di QNetworkReply manco avviene!

Questo è il plugin factory, molto simile all'esempio di fatto:

Codice:
QObject *mediaPlayerFactory::create(const QString &mimeType, const QUrl &url,
                                    const QStringList &argumentNames,
                                    const QStringList &argumentValues) const
{
    if (mimeType != "video/mjpeg")
        return 0;

    mediaPlayerView *view = new mediaPlayerView(url);

    QNetworkRequest request(url);
    QNetworkReply *reply = manager->get(request);
    connect(reply, SIGNAL(readyRead()), view, SLOT(onReadyRead(reply)));
    connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),
            view,SLOT(onError(QNetworkReply::NetworkError)));

    //connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));

    return view;
}
E questo è il costruttore di mediaPlayerView:

Codice:
mediaPlayerView::mediaPlayerView(const QUrl &url, QWidget *parent)
    : QWidget(parent)
{
    this->url = url;

    Log("Getting MJPEG stream from url: " + url.toString());

    label = new QLabel(this);

    label->setWindowFlags(label->windowFlags() | Qt::FramelessWindowHint);
    label->show();

    Log("Ready to stream!");
}
onReadyRead() è relativamente banale legge tutto il pacchetto vede se è un'immagine completa e lo disegna... sono sicuro al 100% che se venisse chiamato funzionerebbe pure!

Ho settato ovviamente che i plugin siano abilitati e che possano accedere alla rete:

Codice:
    QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,
                                                 true);

     QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
Qualche idea?

Il prossimo tentativo sarebbe qualcosa di davvero troppo anche per Linux: far partire VLC frameless ed embeddare la sua finestra dentro la pagina web
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!
fano è offline   Rispondi citando il messaggio o parte di esso
Old 14-11-2018, 11:25   #2
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
L'ho trovato! ... ed è imbarazzante quello che Qt fa...

Per chi non conosce come funziona l'animale Qt per nascondere l'indubbio casino che sono i thread in C++ usa un meccanismo di segnali / slot così - per esempio - quando il thread che si occupa di leggere dal socket ha il buffer pieno mi notifica con readyRead() che ha qualcosa da leggere ed io mi "aggancio" ad esso con il mio slot onReadyRead().

Peccato che per far questo - in realtà - non si usa "realmente" C++ ma una sorta di dialetto, infatti file .cpp Qt è compilato in un'equivalente .moc in cui le "orrende" macchine a stati / switch appaiono robe orride tipo:

Codice:
void mediaPlayerView::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    if (_c == QMetaObject::InvokeMetaMethod) {
        mediaPlayerView *_t = static_cast<mediaPlayerView *>(_o);
        Q_UNUSED(_t)
        switch (_id) {
        case 0: _t->notifyLog((*reinterpret_cast< BrowserApp::LogLevel(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 1: _t->onReadyRead(); break;
        case 2: _t->onError((*reinterpret_cast< QNetworkReply::NetworkError(*)>(_a[1]))); break;
        case 3: _t->onFinished(); break;
        default: ;
Bello vero?

Peccato che io avevo fatto un piccolo errorino... gli slot devono essere definiti esattamente con lo stesso prototipo dei segnali, ma ci volevo passare "reply"!!!
Tutto compilava perfettamente, i moc erano creati e compilati e l'applicazione girava perfettamente peccato che non si vedeva una favonza...

Finché non ho letto cosa era scritto sullo stderr e sorpresona:

Codice:
QObject::connect: No such slot mediaPlayerView:onReadyRead(reply) in src/mediaPlayerFactory.cpp:25
vedete? Come fosse javascript un errore di "sintassi" e ce ne accorgiamo a runtime

Cambiato onReadyRead() per non prendere argomenti e fatto un'orrido "dynamic cast" con oggetto che esiste per "miracolo" chiamato sender e...

Codice:
void mediaPlayerView::onReadyRead()
{
    QNetworkReply *reply = static_cast<QNetworkReply *>(sender());

    if (reply->error() != QNetworkReply::NoError) {
        Log(BrowserApp::Error, "reply is an Error!");
        return;
    }
  
    [...]
Mah... a me pare che async di C# sia un po' meglio!
Anche se devo dire che se qualcuno ha mai programmato in BeOS la loro soluzione al problema dei "thread" era migliore avevano inventato un tipo BMessage e semplicemente per ricevere i messaggi uno doveva implementare un metodo MessageReceived() e poi
se li "puppava" con il classico switch e via...

A volte quando le cose sono troppo "magiche" è molto difficile ragionarci sopra

Voi cosa ne pensate?
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!
fano è offline   Rispondi citando il messaggio o parte di esso
Old 15-11-2018, 09:22   #3
carsco
Senior Member
 
L'Avatar di carsco
 
Iscritto dal: Oct 2009
Messaggi: 519
Nel 99% dei casi quella camera invia anche uno stream RTP o RTSP: perche' non lo apri con VLC direttamente conoscendo indirizzo, nome stream e porta?

Perche' scomodare uno strato in piu'?
carsco è offline   Rispondi citando il messaggio o parte di esso
Old 16-11-2018, 08:57   #4
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
Perché lo devo mostrare dentro la pagina web... sono ancora in HTML4 (QWebKit non supporta HTML5 o almeno non supporta tutti i tag) e comunque il tag video non supporta MJPEG.

Avevo provato - infatti - ad usare VLC plugin, ma non c'è stato verso... ottenevo un cubetto con dentro '?', la cosa strana è che Flash funzionava! Credo che alla fine supporti solo i "suoi" e Flash (c'è un bel hardcoding da qualche parte?)...

Comunque ora sto impazzendo con sto meccanismo dei segnali... si sconnette mi arriva il segnale "finished()", fai abort() (close del socket?) e poi mi arriva di nuovo il segnale finished()? Ed io mi inlooppo a stecca...
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!
fano è offline   Rispondi citando il messaggio o parte di esso
Old 16-11-2018, 09:03   #5
mally
Senior Member
 
Iscritto dal: Mar 2016
Messaggi: 2061
io sono vincolato ad usare ancora Qt 4.7 e non vedo l'ora di fare il salto a versioni 5.xxx proprio per migliorare alcuni strati a thread ma vedo che la soluzione non funziona alla grandissima...
__________________
fanboy del mio portafoglio...
mally è offline   Rispondi citando il messaggio o parte di esso
Old 16-11-2018, 23:58   #6
carsco
Senior Member
 
L'Avatar di carsco
 
Iscritto dal: Oct 2009
Messaggi: 519
Quote:
Originariamente inviato da fano Guarda i messaggi
Credo che alla fine supporti solo i "suoi" e Flash
Ma secondo te, dentro lo stream che ti manda sul browser, cosa c'e'? C'e' lo stream MJPEG (o H264 se la camera e' piu' recente)!

La camera potrebbe anche mettere a disposizione un indirizzo con una JPG che si aggiorna svariate volte al secondo (quindi, M-Jpeg, ma che lo dico a fare?).

Sappiamo marca e modello della camera?
Non andiamoci a caso.
Ti posso aiutare.
carsco è offline   Rispondi citando il messaggio o parte di esso
Old 17-11-2018, 15:34   #7
pabloski
Senior Member
 
Iscritto dal: Jan 2008
Messaggi: 8406
Comunque, siccome si sta parlando di Qt 5, faccio notare che QtWebkit è deprecato ed è stato sostituito da QtWebEngine.

Riguardo il meccanismo degli slot/signals ( che vista l'epoca era rivoluzionario e ha dato vita ai framework basati su bindings ), in qml sono stati sostituiti dai bindings.
pabloski è offline   Rispondi citando il messaggio o parte di esso
Old 20-11-2018, 12:01   #8
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
Purtroppo il lavoro che sto facendo deve anche funzionare su un Centos 5.4 (!) quindi Qt 4.6 (o 4.8) dove sicuramente QtWebEngine non esiste... e sinceramente visto che l'applicazione esiste da più di 10 anni ho paura a cambiare Engine chissà quante incompatibilità ci saranno

La telecamera è una HIK e ha 2 modi per fornire lo streaming MJPEG:

1. Via HTPP...funziona benissimo con Firefox... il nostro browser basato su QWebKit ovviamente non è in grado. Stranamente anche VLC non è in grado di aprirlo
2. Via RSTP questo lo apre VLC, ma non Firefox... bah!

Il mio mediaplayer "fatto a mano" funziona pure, il problema è che il modo per disegnare 30 immagini / s su una QLabel, X mi occupa il 95% di CPU (+25% imputabili al mio software)!

vlc chiamato da terminale ovviamente occupa solo il 14%

Le performance sono proprie pietose... non credo se l'avessi potuto scrivere in C# sarebbe stato così lento.

Questo è il codice che uso per disegnare:

Codice:
    QImage image;
    bool isValid;

    isValid = image.loadFromData(data, "JPG");

    if (!isValid) {
        Log(BrowserApp::Error, "Error image is not valid");
        return;
    }

    QPixmap pix = QPixmap();
    pix = pix.fromImage(image);
    pix = pix.scaled(this->size(), Qt::KeepAspectRatio);
    label->setPixmap(pix);
La mia impressione è che questo codice faccia una marea di memcpy(), ma credo sia il modo "consigliato" in Qt...

C'è un modo più efficiente per disegnare?
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!

Ultima modifica di fano : 20-11-2018 alle 12:04.
fano è offline   Rispondi citando il messaggio o parte di esso
Old 20-11-2018, 12:20   #9
pabloski
Senior Member
 
Iscritto dal: Jan 2008
Messaggi: 8406
Il metodo consigliato e' usare Phonon. In alternativa e' possibile sfruttare FFMPEG che e' pure cross-platform. Oppure piu' semplicemente si puo' usare OpenCV, trasformando i frame contenuti in una matrice OpenCV in immagine QImage. Si taglia la testa al toro e si usa pure la GPU se presente.
pabloski è offline   Rispondi citando il messaggio o parte di esso
Old 28-11-2018, 14:17   #10
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
Phonon non sembra più supportato da Qt5, le altre soluzioni sembrano davvero troppo complesse per risolvere un problema così banale come visualizzare uno stream MJPEG.

Alla fine visto che VLC era in grado di farlo (usando solo il 10% di CPU) ho usato la libvlc, l'API rigorosamente in C permette abbastanza semplicemente di farsi il "proprio" VLC:

https://wiki.videolan.org/LibVLC_Tut...le_LibVLC_Code

da quell'esempio è "banale" ottenere il famoso plugin VLC / QT che finalmente piace a QWebkit

Attenzione perché non è così banale ci sono 2 trappole:

1. Il pacchetto rpm VLC-Core della Centos 6 è - ovviamente - toppato e non include tra i video "plugins" quello che permette di sbattere VLC dentro una finestra X (ho passato 2 giorni prima di capirlo!). La "menata" è che si deve installare l'intero VLC che si porta dietro anche Qt4 ed altra bratta... dovrò fare un "RPM" a mano per mettere solo i plugins
2. Mentre il vero "VLC" ritenta se lo stream s'interrompe (banalmente si può simularlo staccando il cavo di rete dalla TLC), libVLC è "bacata" e semplicemente scrive che lo stream è finito! Per farlo correttamente si deve usare una callback per esempio nel posto dove viene gestito il "play":

Codice:
    libvlc_event_manager_t *event_manager = libvlc_media_player_event_manager 	(vlcPlayer); 	
    libvlc_event_attach(event_manager, libvlc_MediaPlayerEndReached, (libvlc_callback_t )&media_is_ended, this);
    libvlc_event_attach(event_manager, libvlc_MediaPlayerEncounteredError, (libvlc_callback_t )&media_is_ended, this);
In "media_is_ended()" fai semplicemente stop() / play(), se si vede qualcosa siete a cavallo altrimenti media_is_ended() sarà richiamato. Non preoccupatevi di non "stressare" la rete, vlc genera l'evento "libvlc_MediaPlayerEndReached" già a timeout.

Usando VLC ottengo altri 2 vantaggi:
  1. Se volessi potrei anche usare lo stream H264 in full HD!
  2. In caso di microinterruzioni lo stream continua ininterrotto perché - ovviamente - VLC fa buffering, con l'altra soluzione fatta "a mano" dovevo gestirmi anche questo caso...

Spero questo sarà utile a qualche altro povero sfigato che si trovi in questa situazione... imbarazzante
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!
fano è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


La Formula E può correre su un tracciato vero? Reportage da Misano con Jaguar TCS Racing La Formula E può correre su un tracciato ...
Lenovo LEGION e LOQ: due notebook diversi, stessa anima gaming Lenovo LEGION e LOQ: due notebook diversi, stess...
Nothing Ear e Ear (a): gli auricolari per tutti i gusti! La ''doppia'' recensione Nothing Ear e Ear (a): gli auricolari per tutti ...
Sony FE 16-25mm F2.8 G: meno zoom, più luce Sony FE 16-25mm F2.8 G: meno zoom, più lu...
Motorola edge 50 Pro: design e display al top, meno il prezzo! Recensione Motorola edge 50 Pro: design e display al top, m...
Kingdom Come Deliverance II: il seguito ...
Logitech M750 Signature AI Edition: il p...
Cisco presenta Hypershield, una soluzion...
Arriva Mastercard For Fintechs, il perco...
TSMC avverte il mondo: i chip fabbricati...
Auricolari economici CMF by Nothing Buds...
Fallout, la serie TV: la Stagione 2 &egr...
L'assistente virtuale Meta AI diventa pi...
iPhone 15 Pro 1 TB è sceso a 1.442€. Il ...
LastPass, campagna di phishing ai danni ...
ECOVACS DEEBOT T30 PRO OMNI è ancora dis...
Apple Watch Series 9 GPS + Cellular 45mm...
Apple verso la sostenibilità con ...
SK hynix e TSMC insieme per realizzare l...
Vi siete persi l'Antologia di Fallout in...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 12:49.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Served by www1v