1

现在我正在研究通过MultipeerConnectivity框架实现视频流的可能性。为此,我使用NSInputStream和NSOutputStream。通过NSInputStream和NSOutputStream进行视频流传输

问题是:到目前为止我无法收到任何图片。现在我试图通过简单的图片并在接收器上显示它。下面是我的一小段代码:

发送图片通过NSOutputStream:

- (void)sendMessageToStream 
{ 
    NSData *imgData = UIImagePNGRepresentation(_testImage); 

    int img_length = (int)[imgData length]; 
    NSMutableData *msgData = [[NSMutableData alloc] initWithBytes:&img_length length:sizeof(img_length)]; 
    [msgData appendData:imgData]; 
    int msg_length = (int)[msgData length]; 

    uint8_t *readBytes = (uint8_t *)[msgData bytes]; 

    uint8_t buf[msg_length]; 
    (void)memcpy(buf, readBytes, msg_length); 

    int stream_len = [_stream writeData:(uint8_t*)buf maxLength:msg_length]; 

    //int stream_len = [_stream writeData:(uint8_t *)buf maxLength:data_length]; 
    //NSLog(@"stream_len = %d", stream_len); 

    _tmpCounter++; 
    dispatch_async(dispatch_get_main_queue(), ^{ 

     _lblOperationsCounter.text = [NSString stringWithFormat:@"Sent: %ld", (long)_tmpCounter]; 
    }); 
} 

上面的代码工作完全正常。写入后的stream_len参数等于预期值为29627字节,因为图像的大小约为25-26 kb。

通过NSinputStream接收图片:

- (void)readDataFromStream 
{ 
    UInt32 length; 
    if (_currentFrameSize == 0) { 

     uint8_t frameSize[4]; 
     length = [_stream readData:frameSize maxLength:sizeof(int)]; 
     unsigned int b = frameSize[3]; 
     b <<= 8; 
     b |= frameSize[2]; 
     b <<= 8; 
     b |= frameSize[1]; 
     b <<= 8; 
     b |= frameSize[0]; 

     _currentFrameSize = b; 
    } 
    uint8_t bytes[1024]; 

    length = [_stream readData:bytes maxLength:1024]; 

    [_frameData appendBytes:bytes length:length]; 
    if ([_frameData length] >= _currentFrameSize) { 
     UIImage *img = [UIImage imageWithData:_frameData]; 

     NSLog(@"SETUP IMAGE!"); 
     _imgView.image = img; 

     _currentFrameSize = 0; 
     [_frameData setLength:0]; 
    } 

    _tmpCounter++; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     _lblOperationsCounter.text = [NSString stringWithFormat:@"Received: %ld", (long)_tmpCounter]; 
    }); 
} 

正如你可以看到我想要收到几个步骤的画面,这里的原因。当我试图从流中读取数据时,无论我在maxLength:参数中输入了多少个数字,它总是读取最大1095个字节。但是,当我在第一段代码中发送图片时,它的发送完全没问题(29627字节,顺便说一句,图片的大小约为29 kb)

这就是问题出现的地方 - 为什么是这样? 29 kb通过NSOutputStream工作完全正常,当接收导致问题?有没有一种可靠的方法,使视频流通过NSInputStream和NSOutputStream工作?我只是没有找到关于这项技术的很多信息,我发现的只是一些简单的事情,我知道了。

+0

顺便说一下,流正在彼此工作。我忘了提到这一点。所以连接不好的问题可以排除在外。我用简单的字符串测试过流,它绝对正常工作 –

回答

0

我认为这个问题是在你的假设,即所有的数据将在NSInputStream,而你正在阅读它所有的时间。从NSURL对象进行NSInputStream具有异步特性,它应使用NSStreamDelegate进行相应访问。您可以在POSInputStreamLibrary的自述文件中查看示例。

+0

谢谢你的回复!我正在严格通过NSStreamDelegate方法处理我的NSInputStream,我根本没有做任何解决方法。所以当我阅读NSInputStream时,它100%有一些数据要给。主要问题是关于传递数据的长度。为什么我可以在一次调用中传递给29kb的NSOutputStream图片,但是当我读到它时,我不能和NSInputStream做同样的事情? –

+0

因为你不需要。 //// len是一个设置为非零值的全局变量; //// mdata是一个NSMutableData对象,当创建新输入 ////流时,该对象将被重置。 //// displayImage是一个块,它接受图像数据和一个参考 ////到图像将被渲染的层 uint8_t * buf [len]; len = [aStream read:(uint8_t *)buf maxLength:len]; (len> 0){mdata appendBytes:(const void *)buf length:len]; } else { displayImage(mdata,wLayer); } break; –

1

这里有一个程序,我写的,告诉您如何:

https://app.box.com/s/94dcm9qjk8giuar08305qspdbe0pc784

建立和Xcode 9项目,并在两个iOS的11设备上运行的应用程序。

要流式传输实时视频,请触摸两个设备之一上的摄像头图标。

如果您没有两个设备,则可以在模拟器中运行一个应用程序;但是,您只能在真实设备上使用相机(模拟器将显示播放的视频)。

只是让你知道:这不是在设备之间传输实时视频的理想方式(它应该是你最后的选择)。数据包(与数据流相比)更高效,速度更快。

无论如何,我真的很困惑你的NSInputStream相关的代码。这里的东西,使一些更有意义,我认为:

case NSStreamEventHasBytesAvailable: { 
    // len is a global variable set to a non-zero value; 
    // mdata is a NSMutableData object that is reset when a new input 
    // stream is created. 
    // displayImage is a block that accepts the image data and a reference 
    // to the layer on which the image will be rendered 
    uint8_t * buf[len]; 
    len = [aStream read:(uint8_t *)buf maxLength:len]; 
    if (len > 0) { 
     [mdata appendBytes:(const void *)buf length:len]; 
    } else { 
     displayImage(mdata, wLayer); 
    } 
    break; 
} 

输出流的代码应该是这个样子:

// data is an NSData object that contains the image data from the video 
// camera; 
// len is a global variable set to a non-zero value 
// byteIndex is a global variable set to zero each time a new output 
// stream is created 

if (data.length > 0 && len >= 0 && (byteIndex <= data.length)) { 
      len = (data.length - byteIndex) < DATA_LENGTH ? (data.length - byteIndex) : DATA_LENGTH; 
      uint8_t * bytes[len]; 
      [data getBytes:&bytes range:NSMakeRange(byteIndex, len)]; 
      byteIndex += [oStream write:(const uint8_t *)bytes maxLength:len]; 
     } 

还有很多更多的视频流比正确设置NSStream类-多很多。你会注意到,在我的应用程序中,我为输入和输出流创建了一个缓存。这解决了如果你不这样做,你可能会遇到的无数问题。

我从来没有见过任何人成功使用NSStreams进行视频流...永远。这是非常复杂的,有一个原因。

有许多不同的(和更好的)方式来流视频;我不会走这条路。因为没有其他人能够成功地做到这一点,我只是接受了它。

相关问题