繁体   English   中英

通过控制台应用程序在iOS7上捕获静止图像

[英]Capture a still image on iOS7 through a console app

我试图通过控制台在越狱的iPhone上捕获静止图像。

免责声明:我是一个Objective-C新手-大部分代码来自: AVCaptureStillImageOutput从不调用完成处理程序

我只想知道它是否可以在终端上工作。

我已经尝试过各种关于SO的示例,但似乎都没有用。 我的问题是-可能吗? 还是Apple由于某些原因将其锁定(可能不允许通过终端访问相机等)。

这是我当前的相机。

#import <Foundation/Foundation.h>
#import <CoreVideo/CoreVideo.h>
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVFoundation.h>
#import <ImageIO/CGImageProperties.h>
#import <stdio.h>
#import <UIKit/UIKit.h>

@interface Camera : NSObject {
}

@property (readwrite, retain) AVCaptureStillImageOutput *stillImageOutput;
- (AVCaptureDevice *)frontFacingCameraIfAvailable;
- (void)setupCaptureSession;
- (void)captureNow;
@end

@implementation Camera
@synthesize stillImageOutput;

-(AVCaptureDevice *) frontFacingCameraIfAvailable{

    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    AVCaptureDevice *captureDevice = nil;

   for (AVCaptureDevice *device in videoDevices){

        if (device.position == AVCaptureDevicePositionFront){

            captureDevice = device;
            break;
        }
    }

    //  couldn't find one on the front, so just get the default video device.
    if (!captureDevice){

        captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    }

    return captureDevice;
}

-(void) setupCaptureSession {
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    session.sessionPreset = AVCaptureSessionPresetMedium;

    AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer    alloc] initWithSession:session];
    //[self.view.layer addSublayer:captureVideoPreviewLayer];

    NSError *error = nil;
    AVCaptureDevice *device = [self frontFacingCameraIfAvailable];
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (!input) {
        // Handle the error appropriately.
        NSLog(@"ERROR: trying to open camera: %@", error);
    }
    [session addInput:input];

    self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
    [self.stillImageOutput setOutputSettings:outputSettings];

    [session addOutput:self.stillImageOutput];

    [session startRunning];
}

-(void) captureNow {
    AVCaptureConnection *videoConnection = nil;
    for (AVCaptureConnection *connection in self.stillImageOutput.connections) {
        for (AVCaptureInputPort *port in [connection inputPorts]) {
            if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
                videoConnection = connection;
                break;
            }
        }
        if (videoConnection) { break; }
    }

    NSLog(@"about to request a capture from: %@", self.stillImageOutput);
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
        UIImage *image = [[UIImage alloc] initWithData:imageData];
        NSLog(@"image captured: %@", [imageData bytes]);
     }];
}
@end

int main(int argc, const char *argv[]) {
    Camera *camera = [[Camera alloc] init];
    [camera setupCaptureSession];
    [camera captureNow];
}

这是我的Makefile:

XCODE_BASE=/Applications/Xcode.app/Contents
IPHONEOS=$(XCODE_BASE)/Developer/Platforms/iPhoneOS.platform
SDK=$(IPHONEOS)/Developer/SDKs/iPhoneOS7.1.sdk
FRAMEWORKS=$(SDK)/System/Library/Frameworks/
INCLUDES=$(SDK)/usr/include

camera:
    clang   -mios-version-min=7.0 \
            -isysroot $(SDK) \
            -arch armv7 \
            camera.m \
            -lobjc \
            -framework Foundation -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework CoreGraphics -framework CoreImage -framework UIKit -framework ImageIO \
            -o camera

将相机二进制文件复制到iPhone:

scp camera root@10.1.1.32:/var/root/camera
root@10.1.1.32's password:
camera                                    100%   51KB  51.0KB/s   00:00

iPhone运行该应用程序的结果:

iPhone:~ root# ./camera
2014-03-21 15:17:55.550 camera[9483:507] about to request a capture from: <AVCaptureStillImageOutput: 0x14e2b940>

如您所见,正确设置了AVCaptureSession,找到并设置了前置摄像头,正确设置了AVCaptureConnection。 但是captureStillImageAsynchronouslyFromConnection:completionHandler:永远不会被调用。

这有可能吗? 难道我做错了什么?

编辑:我已经修改了captureNow使其在线程上休眠,直到completedHandler完成并且应用程序在启动后一直等待。

-(void) captureNow {
    AVCaptureConnection *videoConnection = nil;
    for (AVCaptureConnection *connection in self.stillImageOutput.connections) {
        for (AVCaptureInputPort *port in [connection inputPorts]) {
            if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
                videoConnection = connection;
                break;
            }
        }
        if (videoConnection) { break; }
    }

    __block BOOL done = NO;

    NSLog(@"about to request a capture from: %@", self.stillImageOutput);
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
        UIImage *image = [[UIImage alloc] initWithData:imageData];
        NSLog(@"image captured");

        done = YES;
     }];

    while (!done) {
        [NSThread sleepForTimeInterval:1.0];
    }
}

您的应用在捕获照片之前退出。 需要将completionBlock arg添加到-captureNow,并且在主要实现中应如下所示:

__block BOOL done = NO;

[camera captureWithCompletionBlock:^(UIImage* image)
{
    done = YES;
}];

while (!done)
{
    [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}

我的意思是这样的-

- (void)captureWithCompletionBlock:(void(^)(UIImage* image))block {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in self.stillImageOutput.connections) {
    for (AVCaptureInputPort *port in [connection inputPorts]) {
        if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
            videoConnection = connection;
            break;
        }
    }
    if (videoConnection) { break; }
}

NSLog(@"about to request a capture from: %@", self.stillImageOutput);
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
    NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
    UIImage *image = [[UIImage alloc] initWithData:imageData];
    NSLog(@"image captured: %@", [imageData bytes]);
    block(image);
}];

}

另外,您需要保留AVCaptureSession,只需将其添加为属性即可。

@property (nonatomic,strong) AVCaptureSession* session;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM