Problème affichage flux video MJPEG camera IP

Zim513201Zim513201 Membre
février 2015 modifié dans API UIKit #1
Bonjour, je suis entrain d'essayer d'afficher le flux video de mes cam ip dans une webview, cependant , l'image s'affiche mais c'est tout , il n'y a pas de flux , c'est uniquement une seule image.

Par contre dans safari, tout fonctionne parfaitement.

Voici mon code , mais où est mon erreur

[code=auto:0]

- (void)viewDidLoad {



//Chargement de l'URL

NSString *urlAddress = @"http://154.235.83.19:8081/videostream.cgi?user=admin&pwd=513201";

NSURL *url = [NSURL URLWithString:urlAddress];

NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];

webView.delegate=self;

[webView loadRequest:requestObj];

}

Réponses

  • LarmeLarme Membre
    février 2015 modifié #2

    De mémoire :


    Une des versions d'iOS6 qui coà¯ncidait avec une mise à  jour de Safari Mac OS X a bloqué tout ça (aussi bien sur iOS et que OS X)

    Le MJPEG, c'est du MotionJPEG, c'est à  dire que ça envoie en continue un JPEG. Et avant, Safari (Mac OS X/iOS) et les UIWebView s'occupaient de l'auto-refresh.


    Vu que ça ne marchait plus, j'avais décidé pour le projet d'utiliser des NSStreams, et de décoder les images (il suffit de trouver quels sont les bytes annonçant le début d'une image et ceux d'une fin, de les mettre dans un buffer et de recomposer le tout, UIImage pouvant être initWithData: (ou un truc du genre)).


    J'avais trouvé sur le net un code source qui le faisait, mais j'avais préféré utiliser ma solution maison.


     


    Avec un peu de recul, je vois autrement deux possibles pistes :


    - faire un auto-refresh manuel (et regarder si peut-être des delegates de UIWebView ne sont pas triggers d'ailleurs par défaut et retourne non sur l'auto-refresh habituel), mais ça veut dire potentiellement un NSTimer.

    - peut-être essayer de "surcharger" le code de la page via un script (JavaScript) qui s'occuperait de faire le refresh.


     


    Si jamais tu veux mon code avec la solution des NSStreams, je peux potentiellement te le filer en début de semaine prochaine.


  • Merci larme, oui, la solution des NSStreams est peut être la meilleur, et oui je voudrais volontier ton code , mais je vais chercher encore de moi même .
  • LarmeLarme Membre
    mars 2015 modifié #4

    Alors, désolé pour la réponse tardive.


     


    J'ai retrouvé mon code.


    C'est pas zoli zoli, j'ai essayé de cleaner un peu (comme j'ai pu, en 5 minutes), mais je n'ai pas la possibilité de tester si tout marche encore.


    Avec l'expérience que j'ai gagné depuis, je n'aurais certainement pas laissé un code aussi sale.


    Donc je déconseillerais de laisser ça ainsi. Si tu as besoin, je veux bien essayer de m'y replonger encore un peu pour essayer de trouver des erreurs possibles. 


    Mais par exemple, si c'était à  refaire, j'utiliserais sûrement rangeOfData:options:range: plutôt que de faire ce que j'ai fait avec tous ces ifs étranges. Je trouve étrange ce Byte byte[2]; à  un moment par exemple.


    Y'avait aussi des release, mais je pense m'en être débarrassé.



    typedef enum : NSUInteger {
    L4StateImageRetrieveWaiting,
    L4StateImageRetrievePossibleStart,
    L4StateImageRetrieveCurrentlyReading,
    } L4StateImageRetrieve;



    @property(nonatomic, strong) NSInputStream *inputStreamVideo; //Flux input (à  envoyer)
    @property(nonatomic, strong) NSOutputStream *outputStreamVideo; //Flux output (à  recevoir)
    @property(nonatomic) int debut; //Marqueur début d'image
    @property(nonatomic) int fin; //Marqueur fin d'image
    @property(nonatomic) int lastByte; //Sauvegarde dernier octet

    @property (nonatomic, weak) IBOutlet UIImageView *renderImageView;
    @property (nonatomic, strong) NSMutableData *imageData;
    @property (nonatomic) CFReadStreamRef readStream;
    @property (nonatomic) CFWriteStreamRef writeStream;



    -(void)startNetworkVideo
    {
    NSLog(@Starting Videos Network);

    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@192.168.11.123, 8080, &_readStream, &_writeStream);

    CFReadStreamSetProperty(_readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
    CFWriteStreamSetProperty(_writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);//Useful?

    _inputStreamVideo = (__bridge NSInputStream *)_readStream;
    _outputStreamVideo = (__bridge NSOutputStream *)_writeStream;//Useful?
    [_inputStreamVideo setDelegate:self];
    [_outputStreamVideo setDelegate:self];//Useful?
    [_inputStreamVideo scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [_outputStreamVideo scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];//Useful?
    [_inputStreamVideo open];
    [_outputStreamVideo open]; //Useful?
    }



    -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
    {
    switch (eventCode)
    {
    case NSStreamEventOpenCompleted:
    NSLog(@NSStreamEventOpenCompleted);
    break;
    case NSStreamEventHasBytesAvailable:
    //Flux Vidéo
    if (aStream == _inputStreamVideo)
    {
    uint8_t buffer[64];
    int length;
    while ([_inputStreamVideo hasBytesAvailable])
    {
    //Start JPG : FFD8 " End JPG : FFD9
    length = (int)[(NSInputStream *) aStream read:buffer maxLength:64]; //GetSize
    if (length > 0)
    {
    for (int i = 0; i < length ; i++) //Lecture du buffer
    {
    if (_debut == L4StateImageRetrieveCurrentlyReading) //On est en train de lire un image
    {
    [_imageData appendBytes:&buffer[i] length:1]; //Add to _imageData the byte

    //We found the end of the image we can render
    if (_lastByte == 0xFF /*255*/ && buffer[i] == 0xD9/*217*/)
    {
    //Show Image
    [_renderImageView setImage:[UIImage imageWithData:_imageData]];
    _debut = L4StateImageRetrieveWaiting;
    }
    _lastByte = buffer[i]; //Sauvegarde du dernier octet. NSData ne permettant pas de regarder le dernier octet //Ce qui est faut si on fait un subdataWithRange:
    }
    if (_debut == L4StateImageRetrieveWaiting || _debut == L4StateImageRetrievePossibleStart) //On n'a pas encore détecté le début d'une image
    {
    if (buffer[i] == 0xFF/*255*/) //Si on détecte le FF
    {
    _debut = L4StateImageRetrievePossibleStart;
    }
    if (_debut == L4StateImageRetrievePossibleStart && buffer[i] == 0xD8/*216*/) //Si on a détecté le FF et qu'on trouve D8
    {
    [_imageData setLength:0]; //Remove all the data

    //Bytes de début d'un .jpg
    Byte byte[2];
    byte[0] = 0xFF;
    byte[1] = 0xD8;
    [_imageData appendBytes:&byte[0] length:1];
    [_imageData appendBytes:&byte[1] length:1];
    _debut = L4StateImageRetrieveCurrentlyReading;
    }
    }
    }
    }
    }
    }
    break;
    case NSStreamEventErrorOccurred:
    NSLog(@NSStreamEventErrorOccurred);
    break;
    case NSStreamEventEndEncountered:
    NSLog(@NSStreamEventEndEncountered);
    break;
    case NSStreamEventNone:
    NSLog(@NSStreamEventNone);
    break;
    default:
    break;
    }
    }


  • Merci Larme
Connectez-vous ou Inscrivez-vous pour répondre.