Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione Zenfone 11 Ultra: il flagship ASUS ritorna a essere un 'padellone'
Recensione Zenfone 11 Ultra: il flagship ASUS ritorna a essere un 'padellone'
Zenfone 11 Ultra ha tantissime qualità interessanti, fra cui potenza da vendere, un display di primissimo livello, un comparto audio potente e prestazioni di connettività fra le migliori della categoria. Manca però dell'esclusività del predecessore, che in un settore composto da "padelloni" si distingueva per le sue dimensioni compatte. Abbiamo provato il nuovo flagship ASUS, e in questa recensione vi raccontiamo com'è andata.
Appian: non solo low code. La missione è l’ottimizzazione dei processi con l'IA
Appian: non solo low code. La missione è l’ottimizzazione dei processi con l'IA
Abbiamo partecipato ad Appian World 2024, evento dedicato a partner e clienti che si è svolto recentemente nei pressi di Washington DC, vicino alla sede storica dell’azienda. Nel festeggiare il 25mo anniversario, Appian ha annunciato diverse novità in ambito intelligenza artificiale
Lenovo ThinkVision 3D 27, la steroscopia senza occhialini
Lenovo ThinkVision 3D 27, la steroscopia senza occhialini
Primo contatto con il monitor Lenovo ThinkVision 3D 27 che grazie a particolari accorgimenti tecnici riesce a ricreare l'illusione della spazialità tridimensionale senza che sia necessario utilizzare occhialini
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


Recensione Zenfone 11 Ultra: il flagship ASUS ritorna a essere un 'padellone' Recensione Zenfone 11 Ultra: il flagship ASUS ri...
Appian: non solo low code. La missione è l’ottimizzazione dei processi con l'IA Appian: non solo low code. La missione è ...
Lenovo ThinkVision 3D 27, la steroscopia senza occhialini Lenovo ThinkVision 3D 27, la steroscopia senza o...
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...
La Cina ha lanciato la missione Shenzhou...
La sonda spaziale NASA Psyche comunica v...
Dacia Duster, prima guida: con le versio...
Google Pixel 8 Pro 256 GB a 928€ (minimo...
Arriva l'ok da Parlamento europeo sul di...
RISC-V: l'uso dell'ISA open-source da pa...
Amazon scatenata: iPad a 399€, airfryer ...
SK hynix, costruzione della Fab M15X ai ...
Oggi 459€ per utenti Prime il portatile ...
Sta per succedere! La prima gara a guida...
Parthenope: un nuovo RPG investigativo t...
Urbanista Malibu: ecco come va la cassa ...
Gas Station Simulator è costato 1...
AOC Graphic Pro U3, tre nuovi monitor pe...
Wacom Movink: per la prima volta il disp...
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: 23:15.


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