2010-10-29 3 views
2

Я работаю в небольшом приложении для базы iphone по идеям, используемым для создания приложения для Android.
Чтобы проверить, очевидно, я использую симулятор, но у симулятора нет поддержки встроенной камеры. Идея Android, чтобы протестировать это, заключается в использовании приложения Java WebCamBroadcaster на рабочем столе для захвата кадров со встроенной веб-камеры и передачи их через сокет. Затем в приложении вы просто читаете байты и конвертируете в изображение.iPhone читает изображение из сокета

Ну, я пытался сделать то же самое с iPhone Simulator. Поиск в сети нашел класс для работы с асинхронными сокетами (cocoaasyncsocket). Но я не могу заставить его работать.

Java-приложение отправить кадры, как это:

socket = ss.accept(); 

BufferedImage image = videoCapture.getNextImage(); 

if (image != null) { 
    OutputStream out = socket.getOutputStream(); 
    if (RAW) { 
     image.getWritableTile(0, 0).getDataElements(0, 0, w$ 
                image.releaseWritableTile(0, 0); 
                DataOutputStream dout = new DataOutputStream(new Bu$ 
                            out)); 
     for (int i = 0; i < data.length; i++) { 
      dout.writeInt(data[i]); 
     } 
     dout.close(); 
    } else { 
     ImageIO.write(image, "JPEG", out); 
    } 
} 

Андроида версия этого использование C кода для выполнения де сокета чтения proccess так:

long read_count, total_read = 0; 
while (total_read < readBufSize) 


{ 
    read_count = read(sockd, &readBuf[total_read], readBufSize); 
    if (read_count <= 0 || errno != 0) 
    { 
    char buffer[100]; 
    sprintf(buffer, "socket read errorno = %d", errno); 
    LOGV(buffer); 
    break; 
    } 
    total_read += read_count; 
} 

// If we read all of the data we expected, we will load the frame from the p$ 


if (total_read == readBufSize){ 
    frame = loadPixels(readBuf, width, height);} 



Where readBufsize = width*height*sizeof(int); 
readBuf = (char*)malloc(readBufSize); 

Так я пытаюсь реализовать тот же для iPhone, но у меня есть ошибка в соединении (errno = 2). Затем я нахожу cocoaasyncsocket, и я пытаюсь использовать, но у меня есть неизвестная ошибка, и ничего не читается:

#import <Foundation/Foundation.h> 
#import "AsyncSocket.h" 

@interface Captura : NSObject { 
    NSString *ipserver; 
    UInt16   port; 
    NSError *errPtr; 
    AsyncSocket *socket; 
    NSMutableData *socketData; 
} 
@property (nonatomic,retain) NSString *ipserver; 
@property (retain) AsyncSocket *socket; 
@property (retain) NSError *errPtr; 
//will contain de data read from socket 
@property (retain) NSMutableData *socketData; 

-(id)initWithIp:(NSString*)ip puerto:(UInt16)p; 
-(BOOL)open; 
-(void)close; 
-(void)beginRead; 
- (UIImage*)getImage; 
@end 

и реализация

#import "Captura.h" 

@implementation Captura 
@synthesize ipserver; 
@synthesize socket; 
@synthesize errPtr; 
@synthesize socketData; 

-(id)initWithIp:(NSString*)ip puerto:(UInt16)p{ 
    if (self = [super init]) { 
     ipserver = ip; 
     port  = p; 
     socket = [[AsyncSocket alloc] initWithDelegate:self]; 
     socketData = [[NSMutableData alloc] init]; 
    } 
    return self; 
} 

//Connect 
-(BOOL)open{ 
    return [socket connectToHost:ipserver onPort:port error:&errPtr]; 
} 

-(void)beginRead{ 
    NSLog(@"Begin Read"); 
    NSUInteger offset = [socketData length]; 
    [socket readDataWithTimeout:1 
          tag:0]; 
} 

- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ 
    NSLog(@"Conectado al servidor"); 
} 

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { 
    NSLog(@"Data leida %u",[data length]); 
    [socketData appendData:data]; 
    [self beginRead]; 
} 

- (void)onSocketDidDisconnect:(AsyncSocket *)sock{ 
    [socketData release]; 
    [ipserver release]; 
    [socket release]; 
    NSLog(@"MutableData length %u", [socketData length]); 
    NSLog(@"Socket Desconectado"); 
} 

- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err{ 
    NSLog(@"Ocurrió un error desconectando.... %@",err); 
} 

- (UIImage*)getImage{ 
    NSData *data; 
    [socketData getBytes:data length:320*480*sizeof(int)]; 
    NSLog(@"Data obtenida %@",[data length]); 
    if ([socketData length]>320*480*sizeof(int)) { 
     [socketData replaceBytesInRange:NSMakeRange(0,320*480*sizeof(int)) withBytes:NULL length:0]; 
    } 
    if (data!=nil && [data length]) { 
     UIImage *img = [[UIImage alloc] initWithData:data]; 
     [data release]; 
     return img; 
    } 
    [data release]; 
    return nil; 
} 
@end 

Ну этот код подключения к серверу и инициализировать процесс чтения, а затем закрыть .. сокет разъединение и приложение близко.

я не могу проверить де GetImage метод еще ...

Некоторые идеи?

Заранее спасибо ...

ответ

0

Мой новый Подход является использование традиционных сокетов C, чтобы прочитать кадры:

Интерфейс:

#import <Foundation/Foundation.h> 
#include <errno.h> 
#include <netdb.h> 
#include <unistd.h> 
#include "opencv/cv.h" 

#define IMAGE(i, x, y, n) *((unsigned char *)((i)->imageData  \ 
+ (x) * sizeof(unsigned char) * 3 \ 
+ (y) * (i)->widthStep) + (n)) 


@interface Socket : NSObject { 
    struct addrinfo *pAddrifo; 
    long readBufSize; 
    char *readBuf; 
    IplImage *frame; 

} 

-(id)initWithIp:(const char *)ipaddress port:(const char*)puerto; 
-(void)close; 
-(BOOL)grabFrame; 
-(IplImage*)retrieveFrame; 
@end 

Реализация:

#import "Socket.h" 
@implementation Socket 
-(id)initWithIp:(const char *)ipaddress port:(const char*)puerto{ 
if (self = [super init]) { 
    if(pAddrifo!=nil){ 
    freeaddrinfo(pAddrifo); 
    pAddrifo = 0; 
    return nil; 
    } 
    struct addrinfo hints; 
    memset(&hints,0,sizeof hints); 
    hints.ai_family  = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_NUMERICHOST; 
    int error = getaddrinfo(ipaddress,puerto,&hints,&pAddrifo); 
     if (error > 0) { 
     NSLog(@"Ha ocurrido un error obtiendo la información del socket %s",g $ 
     freeaddrinfo(pAddrifo); 
     pAddrifo = 0; 
     return nil; 
     } 
     readBufSize = 320*480*sizeof(int); 
     readBuf  = (char*)malloc(readBufSize); 
     if (!readBuf) { 
      NSLog(@"Out Of Memory error"); 
      freeaddrinfo(pAddrifo); 
      pAddrifo = 0; 
      return nil; 
     } 

    } 
    return self; 
} 
-(void)close{ 
    readBufSize = 0; 
    if (pAddrifo) { 
     freeaddrinfo(pAddrifo); 
     pAddrifo = 0; 
    } 
    if (readBuf) { 
     free(readBuf); 
     readBuf = 0; 
    } 
    if (frame) { 
     cvReleaseImage(&frame); 
     frame = 0; 
    } 
} 

/* return a IplImage pointer ... IplImage is a image format from OpenCV 
static IplImage* loadPixels(char* pixels, int width, int height) { 
int x, y, pos, int_size = sizeof(int); 
IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); 

for (y = 0; y < height; y++) { 
    pos = y * width * int_size; 
    for (x = 0; x < width; x++, pos += int_size) { 
     // blue 
     IMAGE(img, x, y, 0) = pixels[pos + 3] & 0xFF; 
     // green 
     IMAGE(img, x, y, 1) = pixels[pos + 2] & 0xFF; 
     // red 
     IMAGE(img, x, y, 2) = pixels[pos + 1] & 0xFF; 
    } 
} 
return img; 
} 

-(BOOL)grabFrame{ 
if(pAddrifo == 0 || readBuf == 0){ 
    NSLog(@"No se a inicializado aún"); 
    return NO; 
} 
int sockd = socket(pAddrifo->ai_family, pAddrifo->ai_socktype , pAddrifo->a$ 
if (sockd < 0 || errno!=0) { 
    NSLog(@"Fallo al crear el socket, errno = %d",errno); 
    close(sockd); 
    return NO; 
} 
if (connect(sockd, pAddrifo->ai_addr, pAddrifo->ai_addrlen) < 0 || errno!=0)$ 
    NSLog(@"Error en conección errno=%d",errno); 
    close(sockd); 
    return NO; 
} 
if (frame) { 
    cvReleaseImage(&frame); 
    frame = 0; 
} 
long read_count, total_read = 0; 
while (total_read < readBufSize) { 
    read_count = read(sockd,&readBuf[total_read],readBufSize); 
    NSLog(@"read_count %d total_read=%d readBufSize=%d",read_count,total_read$ 
    if (read_count <= 0 || errno!=0) { 
    NSLog(@"Error de lectura errno = %d read_count= %d",errno,read_count); 
    break; 
    } 
    total_read+=read_count; 
} 
if (total_read == readBufSize) { 
    frame = loadPixels(readBuf,320,480); 
} 
close(sockd); 
    return frame != 0; 
} 
-(IplImage*)retrieveFrame{ 
    return frame; 
} 
@end 

I используйте эти методы в классе ViewController. Когда пользователь нажимает кнопку запуска, я вызываю метод grabFrame.

Я использую NSOperationQueue и NSInvocationOperation для реализации «потока». Но я получаю сообщение об ошибке «errno 2» и не могу прочитать полный кадр из сокета.

Некоторые идеи?

0

Мне кажется, вам нужно позвонить -beginRead in -onSocket: didConnectToHost: port:

Смежные вопросы