2010-03-05 12 views
3

J'ai créé un serveur Java, qui prend des captures d'écran, les redimensionne, et les envoie sur TCP/IP à mon application iPhone. L'application utilise ensuite NSInputStream pour collecter les données d'image entrantes, créer une instance NSMutableData avec le tampon d'octets, puis créer un objet UIImage à afficher sur l'iPhone. Screenshare, essentiellement. Mon code iPhone pour recueillir les données d'image est actuellement comme suit:Streaming JPEG, détecter la fin de JPEG

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent{ 


if(streamEvent == NSStreamEventHasBytesAvailable && [iStream hasBytesAvailable]){ 
     uint8_t buffer[1024]; 

    while([iStream hasBytesAvailable]){ 
     NSLog(@"New Data"); 

     int len = [iStream read:buffer maxLength:sizeof(buffer)]; 

     [imgdata appendBytes:buffer length:len]; 
     fullen=fullen+len; 

     /*Here is where the problem lies. What should be in this 
     if statement in order to make it test the last byte of 
     the incoming buffer, to tell if it is the End of Image marker 
     for the end of incoming JPEG file? 
     */ 
     if(buffer[len]=='FFD9'){ 
     UIImage *img = [[UIImage alloc] initWithData:imgdata]; 
     NSLog(@"NUMBER OF BYTES: %u", len); 

     image.image = img; 
     } 
    } 

} 
} 

Mon problème, comme indiqué par le commentaire en code, est de déterminer quand arrêter la collecte de données dans l'objet NSMutableData, et utiliser les données créer un UIImage. Il semble logique de rechercher le marqueur Fin de fichier JPEG (EOI) - dans les octets entrants, car l'image sera prête à être affichée lors de l'envoi. Comment puis-je tester pour cela? Il me manque quelque chose sur la façon dont les données sont stockées, ou sur le marqueur dans le fichier JPEG, mais toute aide pour tester cela serait grandement appréciée!

James

+0

1) 'buffer [len]' est passé la fin du morceau qu'il a lu, qui n'est long que de 'lte' octets (donc le dernier index est' len-1', et 2) ''FFD9'' est pas un octet, c'est 4 octets; vous voulez probablement dire '0xFFD9', qui est de 2 octets, mais vous devrez en quelque sorte lire les 2 derniers octets, au lieu du dernier octet; et puis vous devez tester les octets individuellement, ou avoir à vous soucier de l'endianness – user102008

Répondre

3

Vous ne voulez évidemment pas fermer le flux parce que cela tue la performance.

Étant donné que vous contrôlez la connexion du serveur client, envoyez le nombre d'octets dans l'image avant d'envoyer les données d'image. Mieux encore, envoyez un nombre d'octets dans l'image, les données d'image, et un numéro de série facilement identifiable à la fin afin que vous puissiez vérifier rapidement que les données sont effectivement arrivées.

Beaucoup plus facile et plus efficace que la vérification du marqueur de fin de fichier. Bien sûr, vous pouvez aussi vérifier juste après que le nombre d'octets a été reçu, aussi. Assez facile. Bien sûr, tout cela va être très inefficace pour le style de partage d'écran dans tous les cas sauf les cas inhabituels. Dans la plupart des cas, seule une petite partie de l'écran à refléter change avec chaque image. Si vous essayez d'envoyer l'intégralité de l'écran à chaque image, vous allez rapidement saturer votre connexion et le côté client sera horriblement léthargique et ne répondra pas. Etant donné qu'il s'agit d'un marché extrêmement mature, il existe des tonnes de solutions et de nombreux bits open source à partir desquels vous pouvez dériver une solution adaptée à vos besoins (voir VNC, par exemple).

+0

Toutes les bonnes suggestions, merci! – James