通过流获取帧并在屏幕上显示

Posted

技术标签:

【中文标题】通过流获取帧并在屏幕上显示【英文标题】:Getting frames though a stream and display on screen 【发布时间】:2015-05-27 11:47:41 【问题描述】:

我需要从服务器流式传输并在屏幕上显示流式传输的内容...使用 NSStream、NSInputStream 和 NSOutputStream 流式传输工作正常。如何在屏幕上显示它?

使用的流看起来像@"http://191.168.143.41:1212/;

            if(stream == inputStream) 

            uint8_t buf[1024];
            unsigned int len = 0;

            len = [inputStream read:buf maxLength:1024];

            if(len > 0) 
                NSMutableData* datas=[[NSMutableData alloc] initWithLength:0];

                [datas appendBytes: (const void *)buf length:len];

                NSString *s = [[NSString alloc] initWithData:datas encoding:NSASCIIStringEncoding];

                [self readIn:s];
                NSLog(@"ss%@",s);
                 [self loadMovie:s]; //method for movie player 
            

我试图在下面的电影播放器​​中显示它..

-(void_loadMovie:(NSString*)moviePrefix
   
    NSString *path = [NSString stringWithFormat:@"%@.mjpg", moviePrefix];

    NSURL *url = [NSURL fileURLWithPath:path];
    if (url) 
        _moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];

       _moviePlayer.view.frame = CGRectMake(0, 70, 600, 450);
       _moviePlayer.controlStyle = MPMovieControlStyleNone;
        _moviePlayer.scalingMode = MPMovieScalingModeNone;
        [dic setObject:__moviePlayer forKey:path];
    


[_moviePlayer prepareToPlay];
[self.view addSubview: _moviePlayer.view];
[self.view bringSubviewToFront:_moviePlayer.view];
[self.view addSubview: _moviePlayer.view];
[_moviePlayer play];  

是 NSString *path = [NSString stringWithFormat:@"%@.mjpg", moviePrefix];正确的方法??

这显示黑屏。什么问题? 如果这种方式不正确,还有其他方法可以显示这些帧吗? 谁能帮我解决这个问题...

【问题讨论】:

NSString *path = [NSString stringWithFormat:stringWithFormat:@".mjpeg", moviePrefix, @"movie"]; 你为什么要使用stringWithFormat: 两次 @OmerWaqasKhan 抱歉,这是一个拼写错误。 【参考方案1】:

MJPEG 只是一个接一个地发送的 JPEG。 几年前我在这方面工作。 在 ios 版本(iOS5?)上,使用UIWebView 很容易阅读,但 iOS 的更新打破了这一切。这打破了我目前的所有工作。 也许UIWebView 今天可以再次成功(修复)。

无论如何,由于它只是一堆 JPEG,您可以只读取 JPG(检测 JPG 文件的开始/结束),创建 JPG 图像并将其显示在 UIImageView 中。

一种解决方法(未经测试),但您应该了解整个想法:

//属性

@property (nonatomic, strong) NSMutableData *data;
@property (nonatomic, weak)   IBOutlet UIImageView *streamImageView;

//在某处初始化

_data = [[NSMutableData alloc] init];

//在流委托方法中:

//Start JPG: FFD8 — End JPG: FFD9
UInt8 startJPEGBytes[2];
startJPEGBytes[0] = 0xFF;
startJPEGBytes[1] = 0xD8;
NSData *startData = [NSData dataWithBytes:&startJPEGBytes length:2];

UInt8 endJPEGBytes[2];
endJPEGBytes[0] = 0xFF;
endJPEGBytes[0] = 0xD9;
NSData *endData = [NSData dataWithBytes:&endJPEGBytes length:2];

[_data appendBytes: (const void *)buf length:len]; 
NSRange startRange = [_data rangeOfData:startData options:0 range:NSMakeRange(0, [_data length])];
if (startRange.location != NSNotFound) //We found the start of a JPEG

    NSRange endRange = [_data rangeOfData:endData options:0 range:NSMakeRange(startRange.location, [_data length]-startRange.location)];
    if (endRange.location != NSNotFound) //We found the end of a JPEG
    
        NSRange imageRange = NSMakeRange(startRange.location, endRange.location+endRange.length-startRange.location);
        NSData *imageData = [_data subDataWithRange: imageRange];
        streamImage = [UIImage imageWithData:imageData];
        [_streamImageView setImage:streamImage];
        [_data replaceBytesInRange:NSMakeRange(0, imageRange.location+imageRange.length withBytes:NULL length:0]; //We remove the start till the end of JPEG frame. Start at 0, since there could be garbage at the start.
    


【讨论】:

【参考方案2】:

您没有在字符串中添加moviePrefix

NSString *path = [NSString stringWithFormat:@".mjpg", moviePrefix, @"movie"];

改成

NSString *path = [NSString stringWithFormat:@"%@.mjpg", moviePrefix, @"movie"];

【讨论】:

您没有收到任何与此相关的警告吗? 最后的@"movie" 仍然没有被使用。也许@"%@%@.mjpg" 这个@"movie"是什么?它来这里的目的是什么?对不起,我无法理解。 @OmerWaqasKhan 纠正错误,@"movie" 不需要,我在一个例子中看到过。但是播放器仍然显示黑屏 您尝试过在任何浏览器上流式传输 URL 吗?【参考方案3】:

https://github.com/horsson/mjpeg-iphone/tree/55251a85e2c2489014036ddf5a491783f9b1962d

用它来获取流和显示。它的工作原理

【讨论】:

以上是关于通过流获取帧并在屏幕上显示的主要内容,如果未能解决你的问题,请参考以下文章

如何通过鼠标移动事件获取相机位置并在three.js中转换为屏幕坐标? [关闭]

通过 SurfaceTexture 在 GLSurfaceView 上显示相机流

如何通过辅助功能 API 获取当前选定文本的全局屏幕坐标。

如何在 Swift iOS 中仅在最后一个屏幕上获取导航栏?

spark中将每个组作为新数据帧并在循环中传递另一个函数的最佳方法是啥?

android camera2 处理每一帧并显示其预览