IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Discussion :

Problème de lecture de flux avec QHttp->read()

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Points : 58
    Points
    58
    Par défaut Problème de lecture de flux avec QHttp->read()
    Bonjour à tous,

    Je travaille sur un projet dans lequel, j'ai une caméra IP qui me transmet un flux continu de bytes quand j'envois la requete adéquate.

    Je suis supposé segmenter ce flux en fonction de délimiteurs contenus dedans, afin d'extraire une suite d'images. (le délimiteur est connu).

    J'ai finalisé le projet en Java, et je souhaitais en faire une version en C++ avec Qt, mais voila, avec Qt, une fois que j'envois la requete adéquate pour recevoir le flux, ce derniers est reçu et lu byte par byte par la méthode "read()" de QHttp.
    En fait, j'utilise un read(c, 1) avec c: tableau de un caractere, et je boucle ainsi indéfiniment (enfin... tant qu'une condition donnée n'est pas atteinte, comme l'arret manuel de la reception avec un bouton par exemple)

    Le problème est que la caméra m'envois des bytes de valeurs -1 de temps à autre à l'intérieur du flux lui meme, hors, quand read() lit un byte de valeur -1, la méthode read() retourne un 0 (valeur de retour de la méthode, c'est dire qu'elle n'a rien lu) et arrete de lire. C'est à dire que meme si apèrs un -1 envoyé par la caméra, il y a de nouveaus des bytes utiles, le read() du QHttp ne les lis plus.

    Il est a noter qu'avec Java, et l'objet InputStream, quand je boucle sur un read(), ça m'affiche toutes les valeurs reçu, meme les -1, et ça contiu de lire la suite! jusqu'a ce que la condition d'arret soit vérifié!

    Comment faire avec Qt et QHttp pour que la lecture du flux entrant ne s'interrompe pas si le byte reçu est -1?

    Merci pour toute idée permettant de regler ce problème

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Points : 58
    Points
    58
    Par défaut
    J'ai réussi a regler le problème, j'arrive a lire le flux en continu sans interruption, mais il y a quelque chose qui me semble pas du tout normal! avec le code que j'ai implementé, la lecture du flux est super lente! pour que les bytes d'une seule image (entre deux délimiteurs) soient lu, il faut un bon moment! ce n'est pas normal à mon avis. je vous met le code source de la calsse qui est supposée faire ça. Si j'ai fait une erreur quelque part, ou si vous avez une meilleure façon de faire, merci de me l'indiquer.

    Voici le code source de la classe en question (elle dérive de QThread)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    #include "Source.h"
    #include <iostream>
     
    using namespace std;
     
    void Source::run(){
     
    	string parametres="/axis-cgi/mjpg/video.cgi?resolution=352x288&compression=40&fps=10";
     
    	QString qStr(QString::fromStdString("http://192.168.0.32"));
    	QUrl qurl(qStr);
     
    	this->http=new QHttp();
    	http->setHost(qurl.host(), 80);
     
    	QEventLoop loop;
    	QObject::connect(http, SIGNAL(done(bool)), &loop, SLOT(quit()));
    	QObject::connect(http, SIGNAL(dataReadProgress (int, int)), this, SLOT(receptionFluxEnCours()));
     
    	http->get(QString::fromStdString(parametres));
     
    	loop.exec();
    }
     
    void Source::receptionFluxEnCours(){
     
    	char c[1];
    	http->read(c, 1);
    	cout << c[0];    // c'est ici que je suis l'affichage des caracteres du flux
    }
    L'affichage des caracteres lu du flux est super lente, et du coup, l'obtention d'une image dure plus de 10 secondes! ce qui n'est pas normal!
    En Java, avec InputStream et sa méthode read(), j'ai un affichage d'images en temps reel! comme une vidéo!

    Merci pour toutes vos reponses eventuelles.

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Il se peut que le signal dataReadProgress ne soit pas envoyé très souvent. Du coup cela ferai que ta lecture est lente.
    En solution, je propose le changement de la lecture de receptionFluxEnCours qui se fait actuellement byte par byte, en une fonction qui lirai tout les bytes disponible actuellement.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 667
    Points
    10 667
    Billets dans le blog
    3
    Par défaut
    Salut,

    Quelques suggestions pour ton code:
    - pas besoin d'utiliser QString::fromStdString() comme tu le fais. Par exemple, tu peux remplacer ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QString qStr(QString::fromStdString("http://192.168.0.32"));
    QUrl qurl(qStr);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QUrl qurl("http://192.168.0.32");
    et tu peux aussi definir les parametre via QUrl au lieu de les encoder en dur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    qurl.addQueryItem("resolution", "352x288");
    qurl.addQueryItem("compression", "40");
    qurl.addQueryItem("fps", "10");
    En C++, on va éviter de lire carcatère par caractère comme tu le fais avec read(1). On va préférer faire un readAll() et parcourir le résultat obtenu. Tu peux même faire directement une recherche dans le tableau renvoyé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    QByteArray data = http->readAll();
    int position = data.indexOf( "ton delimiteur d'image" );
    A part ça, il y a deux problèmes dans ton code :
    - tu te connectes à dataReadProgress() qui sert à t'informer de la progression du download() au lieu de te connecter à readyRead() qui t'informe qu'il y a des données à lire. Résultat : tu essayes de lire des données quand il n'y a rien à lire (c'est en progress...) et read() te renvoie -1...
    - il y a un problème dans ton algorithme de lecture. En effet, QHttp émet readyRead() une seule fois pour te dire qu'il y a tout un paquet d'octets à lire. Et toi, tu ne lis que un seul octet de ce paquet! Tout le reste est perdu ! En fait, tu perds certainement des dizaines d'images de ta caméra, et c'est simplement quand tu as la chance de lire un délimiteur que "ça marche". Mais il y a une grosse erreur dans le code...

    Donc, pour faire simple :
    - tu dois te connecter à readyRead() et non pas dataReadProgress()
    - tu dois appeler readAll() et non pas read(1)
    - tu dois parcourir le "tableau" QByteArray que te renvoie readAll() pour trouver ce que tu recherches

    Et ça devrait fonctionner

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Points : 58
    Points
    58
    Par défaut
    Bonjour a tous,

    Avant tout, merci à LittleWhite et à Aurelien.Regat-Barrel pour vos réponses.

    Pour ta réponse LittleWhite, effectivement, elle était bonne pour ce qui est de la lecture plus rapide du flux. en augmentant la taille du tableau de byte que je rempli a chaque lecture, l'affiche des bytes lus est beaucoup plus rapide, donc effectivement, c'est le signal "dataReadProgress" qui n'est pas envoyé souvent comme tu l'as suggéré.
    En faisant la modification pour lire des tableau plus grand, la vitesse de lecture s'est amélioré, mais j'avais toujours un problemes avec pleins de "-1" lus.

    J'avais mis de coté cet aspect de mon travail pour me concentrer sur autre chose, c'est la raison pour laquel j'ai un peu tardé a poster mes resultats ici.

    Pour ton message, Aurelien.Regat-Barrel, je viens de le lire a l'instant, et avant meme de mettre en oeuvre tes suggestion, je suis déja très d'accord avec ce que tu as dit. c'est très logique . je vais coder tout ça et je vous tiens au courant.

    Merci pour vos reponses.

    PS: Aurelien.Regat-Barrel, pour la premiere remarque:
    Quelques suggestions pour ton code:
    - pas besoin d'utiliser QString::fromStdString() comme tu le fais. Par exemple, tu peux remplacer ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    QString qStr(QString::fromStdString("http://192.168.0.32"));
    QUrl qurl(qStr);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    QUrl qurl("http://192.168.0.32");
    en fait, le code que j'ai copié sur mon post n'est pas tout a fait celui que j'ai sur mon appli. le "QString::fromStdString()" est utilisé car la fonction qui execute ce code reçoit l'adresse ip de la caméra en argument, et le type de cet argument est un simple "string" (STL). donc j'ai changé dans le code copié le nom de la variable representant l'adresse ip par "192.168.0.30" sans modifier le reste.
    Mais pour le reste, encore merci

Discussions similaires

  1. Problème de lecture properties juste avec tomcat
    Par mattrixx dans le forum Tomcat et TomEE
    Réponses: 5
    Dernier message: 03/03/2011, 16h52
  2. lecture de flux avec MagpieRSS
    Par skeut dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 1
    Dernier message: 28/05/2008, 09h52
  3. Réponses: 1
    Dernier message: 21/03/2007, 16h43
  4. [SAX] Java : problème de lecture d'XML avec SAX
    Par TheReturnOfMuton dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 22/06/2006, 18h26
  5. Réponses: 4
    Dernier message: 23/07/2003, 13h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo