我这样做的方式是实现一个 AVCaptureSession,它有一个委托和一个在每一帧上运行的回调。该回调通过网络将每个帧发送到服务器,服务器有一个自定义设置来接收它。
流程如下:
http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/03_MediaCapture.html#//apple_ref/doc/uid/TP40010188-CH5-SW2
这里有一些代码:
// make input device
NSError *deviceError;
AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *inputDevice = [AVCaptureDeviceInput deviceInputWithDevice:cameraDevice error:&deviceError];
// make output device
AVCaptureVideoDataOutput *outputDevice = [[AVCaptureVideoDataOutput alloc] init];
[outputDevice setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
// initialize capture session
AVCaptureSession *captureSession = [[[AVCaptureSession alloc] init] autorelease];
[captureSession addInput:inputDevice];
[captureSession addOutput:outputDevice];
// make preview layer and add so that camera's view is displayed on screen
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
previewLayer.frame = view.bounds;
[view.layer addSublayer:previewLayer];
// go!
[captureSession startRunning];
那么输出设备的委托(这里是self)必须实现回调:
-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
{
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 );
}
发送原始帧或单个图像对您来说永远不够好(因为数据量和帧数)。您也不能通过电话合理地提供任何服务(WWAN 网络有各种防火墙)。您需要对视频进行编码,并将其流式传输到服务器,最有可能通过标准流格式(RTSP、RTMP)。 iPhone >= 3GS 上有一个 H.264 编码器芯片。问题是它不是面向流的。也就是说,它输出最后解析视频所需的元数据。这给您留下了一些选择。
1) 获取原始数据并在手机上使用 FFmpeg 进行编码(将消耗大量 CPU 和电池)。
2) 为 H.264/AAC 输出编写自己的解析器(非常难)。
3) 以块的形式记录和处理(将增加等于块长度的延迟,并在您开始和停止会话时在每个块之间减少大约 1/4 秒的视频)。