在Web视图中将视频流从iOS7摄像头发送到JavaScript Canvas

时间:2014-01-24 07:50:29

标签: javascript ios objective-c canvas uiwebview

首先要提醒一句:这个问题不适合胆小的人。这是我最近遇到的一个有趣的挑战。看看你是否可以解决它或以任何方式帮助接近答案,风险自负。

问题是:在里面创建一个标准UIWebView的iOS应用程序。从任一相机获取相机流。以可以呈现为HTML5画布的格式发送每个帧。有效地实现这一点,以便在iOS7设备中以720p 30fps或更高的速度显示视频流。

到目前为止,我还没有找到任何看起来有意义的解决方案。事实上,我从一个看起来最荒谬的解决方案开始,该解决方案在base64图像字符串中对每个帧进行编码,并通过stringByEvaluatingJavaScriptFromString将其传递给Web视图。这是执行JPEG编码的方法

- (NSString *)encodeToBase64StringJPEG:(UIImage *)image {
    return [UIImageJPEGRepresentation(image, 0.7) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}

viewDidLoad内,我创建并配置捕获会话

_output = [[AVCaptureVideoDataOutput alloc] init];

// create a queue to run the capture on
dispatch_queue_t captureQueue=dispatch_queue_create("captureQueue", NULL);

// setup output delegate
[_output setSampleBufferDelegate:self queue:captureQueue];

// configure the pixel format (could this be the problem? Is this suitable for JPEG?
_output.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey, nil];
[_session addOutput:_output];
[_session startRunning];

捕获帧并首先转换为UIImage

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection {
    _image = imageFromSampleBuffer(sampleBuffer);

    // here comes the ridiculus part. Attempt to encode the whole image and send it to JS land:
    _base64imgCmd = [NSString stringWithFormat:@"draw('data:image/png;base64,%@');", [self encodeToBase64StringJPEG:_image]];
        [self.webView stringByEvaluatingJavaScriptFromString:_base64imgCmd];
}

猜猜是什么,它没用。 XCode向我显示了这个错误:

DemoNativeToJS[3983:1803] bool _WebTryThreadLock(bool), 0x15e9d460: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
1   0x355435d3 WebThreadLock
2   0x3013e2f9 <redacted>
3   0x7c3a1 -[igViewController captureOutput:didOutputSampleBuffer:fromConnection:]
4   0x2c5bbe79 <redacted>

这个错误是因为WebView正在运行我们的内存qouta吗?我应该注意到崩溃前应用程序内存使用量出现大幅增长。它会在14MB到20MB之间崩溃,具体取决于JPEG编码的质量级别。

enter image description here

我不想用原生渲染相机流 - 这根本不是一个有趣的问题。我想将视频源传递到JavaScript域并在画布中绘制。

为了您的方便,我有一个minimal demo project (XCode) on github,您可以使用它来获取一个guick headstart:

git clone https://github.com/arasbm/DemoNativeToJS.git

如果您有其他更明智的想法来传递数据而不是使用stringByEvaluatingJavaScriptFromString,请告诉我。如果您有其他想法或建议,请随时通过评论告诉我,但我希望答案能够通过一些代码证明哪些路径可行。

1 个答案:

答案 0 :(得分:2)

您遇到的崩溃是由于UIWebKit尝试从后台线程调用UIKit。防止这种情况发生的最简单方法是强制stringByEvaluatingJavaScriptFromString,它调用UIKit在主线程中运行。您可以通过更改

来完成此操作
[self.webView stringByEvaluatingJavaScriptFromString:_base64imgCmd];

到此

[self.webView performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:_base64imgCmd waitUntilDone:NO];

现在将从主执行线程调用UIKit,这将是安全的。

相关问题