Преобразование входящего NSStream в представление

Я успешно отправляю поток NSData. Метод делегата ниже получает этот поток и добавляет к NSMutableData self.data. Как мне взять эти данные и превратить их в UIView/AVCaptureVideoPreviewLayer (который должен показывать видео)? Я чувствую, что пропускаю еще одно преобразование, AVCaptureSession > NSStream > MCSession > NSStream > ?

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
    switch(eventCode) {
        case NSStreamEventHasBytesAvailable:
        {
            if(!self.data) {
                self.data = [NSMutableData data];
            }
            uint8_t buf[1024];
            unsigned int len = 0;
            len = [(NSInputStream *)stream read:buf maxLength:1024];
            if(len) {
                [self.data appendBytes:(const void *)buf length:len];
            } else {
                NSLog(@"no buffer!");
            }

// Code here to take self.data and convert the NSData to UIView/Video
}

Я отправляю поток с этим:

-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
{

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(imageBuffer,0);

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
//    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    void *src_buff = CVPixelBufferGetBaseAddress(imageBuffer);

    NSData *data = [NSData dataWithBytes:src_buff length:bytesPerRow * height];

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);


    NSError *error;
    self.oStream = [self.mySession startStreamWithName:@"videoOut" toPeer:[[self.mySession connectedPeers]objectAtIndex:0] error:&error];
    self.oStream.delegate = self;
    [self.oStream scheduleInRunLoop:[NSRunLoop mainRunLoop]
                            forMode:NSDefaultRunLoopMode];
    [self.oStream open];

    [self.oStream write:[data bytes] maxLength:[data length]];






//    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer( sampleBuffer );

    CGSize imageSize = CVImageBufferGetEncodedSize( imageBuffer );
    // also in the 'mediaSpecific' dict of the sampleBuffer

    NSLog( @"frame captured at %.fx%.f", imageSize.width, imageSize.height );
}

person Eric    schedule 13.03.2014    source источник
comment
Возможно, вы захотите посмотреть, сможете ли вы использовать Open GL. Возьмите свои данные, преобразуйте их в текстуры GL, а затем используйте GL, чтобы показать их. Вероятно, для этого есть API более высокого уровня. Данные не в каком-либо стандартном формате?   -  person nielsbot    schedule 14.03.2014
comment
Какой формат видео? UIView? Какая связь с видео?   -  person Larme    schedule 14.03.2014
comment
Формат видео — AVCaptureSession.   -  person Eric    schedule 14.03.2014
comment
Вам нужно блокировать/разблокировать пиксели в каждом кадре? Интересно, будет ли это дорого с точки зрения времени.   -  person nielsbot    schedule 17.03.2014
comment
Я не знал, что я делаю. Где вы это видите в коде?   -  person Eric    schedule 18.03.2014
comment
Если ваша идея состоит в том, чтобы транслировать видео, это, вероятно, очень удачный подход. Поймите, что CMSampleBufferGetImageBuffer() возвращает необработанные данные, составляющие изображение (4 байта на пиксель RGBA). Поэтому, если вы транслируете это, вам все равно не хватает информации о времени и описании (и звука), из которых состоит видео. Кроме того, имейте в виду, что вам потребуется не менее 20 кадров (изображений) в секунду, чтобы все выглядело плавно. если вы намерены следовать этому пути, вы можете либо создать новый файл в приемнике с помощью AVAssetWriter, либо визуализировать каждое изображение с помощью OpenGL.   -  person MDB983    schedule 21.03.2014
comment
Проблема с созданием файла заключается в записи всего файла перед его отображением. Я хочу транслировать видео через MCSession. Я не могу поверить, что мне нужен собственный API для этого. AVCaptureSession › NSStream › MCSession › NSStream › ? Я не могу вернуть поток обратно на AV   -  person Eric    schedule 21.03.2014
comment
Опять же, вы передаете только необработанные данные изображения... Вот аналогичный вопрос. stackoverflow.com/questions/20150337 /. Он содержит ссылку на репозиторий github, где автор начал работу над аналогичным проектом. Опять же, бегло взглянув на код, он не отображает видео, а отображает изображения. Добавить отсутствующий код OpenGL Render несложно.   -  person MDB983    schedule 22.03.2014


Ответы (2)


Я думаю, вам нужно AVCaptureManager, посмотрите, работает ли приведенный ниже код для вас..

AVCamCaptureManager *manager = [[AVCamCaptureManager alloc] init];
[self setCaptureManager:manager];

[[self captureManager] setDelegate:self];

if ([[self captureManager] setupSession]) {
     // Create video preview layer and add it to the UI
    AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:[[self captureManager] session]];
    UIView *view = self.videoPreviewView;//Add a view in XIB where you want to show video
    CALayer *viewLayer = [view layer];
    [viewLayer setMasksToBounds:YES];
    CGRect bounds = [view bounds];

    [newCaptureVideoPreviewLayer setFrame:bounds];

    [newCaptureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    [viewLayer insertSublayer:newCaptureVideoPreviewLayer below:[[viewLayer sublayers] objectAtIndex:0]];

    [self setCaptureVideoPreviewLayer:newCaptureVideoPreviewLayer];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [[[self captureManager] session] startRunning];
    });
}

Управление делегатами

- (void)captureManager:(AVCamCaptureManager *)captureManager didFailWithError:(NSError *)error
{

}

- (void)captureManagerRecordingBegan:(AVCamCaptureManager *)captureManager
{

}

- (void)captureManagerRecordingFinished:(AVCamCaptureManager *)captureManager outputURL:(NSURL *)url
{



}

- (void)captureManagerStillImageCaptured:(AVCamCaptureManager *)captureManager
{



}

- (void)captureManagerDeviceConfigurationChanged:(AVCamCaptureManager *)captureManager
{

}

Я надеюсь, что это помогает.

person iphonic    schedule 21.03.2014
comment
Ни один из методов делегата CaptureManager не может обрабатывать видео. Я что-то упускаю? - person Eric; 23.03.2014
comment
@Eric См. это developer.apple.com/library/ios/samplecode/AVCam/Introduction/, если это поможет.. - person iphonic; 24.03.2014

Вы можете создать UIImageView для вашего события дескриптора следующим образом:

UIImageView * iv = [[UIImageView alloc] initWithImage: [UIImage imageWithData: self.data];

Также вы можете выделить только один раз и просто вызвать init.

Каждый раз, когда вы получаете из сокета, вы инициализируете UIImageView и можете показать его, добавив этот UIImageView в UIView.

Извините за мой английский, я не знаю, понял ли я вас

person Rievo    schedule 21.03.2014