mirror of
https://github.com/opencv/opencv.git
synced 2025-01-23 18:33:16 +08:00
Merge pull request #14500 from mshabunin:backport-avfoundation
This commit is contained in:
commit
455323ed58
@ -43,6 +43,7 @@
|
|||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
#include "opencv2/imgproc.hpp"
|
#include "opencv2/imgproc.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <Availability.h>
|
||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
/********************** Declaration of class headers ************************/
|
/********************** Declaration of class headers ************************/
|
||||||
@ -177,12 +178,14 @@ private:
|
|||||||
|
|
||||||
class CvVideoWriter_AVFoundation : public CvVideoWriter {
|
class CvVideoWriter_AVFoundation : public CvVideoWriter {
|
||||||
public:
|
public:
|
||||||
CvVideoWriter_AVFoundation(const char* filename, int fourcc,
|
CvVideoWriter_AVFoundation(const std::string &filename, int fourcc, double fps, CvSize frame_size, int is_color);
|
||||||
double fps, CvSize frame_size,
|
|
||||||
int is_color=1);
|
|
||||||
~CvVideoWriter_AVFoundation();
|
~CvVideoWriter_AVFoundation();
|
||||||
bool writeFrame(const IplImage* image) CV_OVERRIDE;
|
bool writeFrame(const IplImage* image) CV_OVERRIDE;
|
||||||
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_AVFOUNDATION; }
|
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_AVFOUNDATION; }
|
||||||
|
bool isOpened() const
|
||||||
|
{
|
||||||
|
return is_good;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
IplImage* argbimage;
|
IplImage* argbimage;
|
||||||
|
|
||||||
@ -197,6 +200,7 @@ class CvVideoWriter_AVFoundation : public CvVideoWriter {
|
|||||||
CvSize movieSize;
|
CvSize movieSize;
|
||||||
int movieColor;
|
int movieColor;
|
||||||
unsigned long mFrameNum;
|
unsigned long mFrameNum;
|
||||||
|
bool is_good;
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************** Implementation of interface functions ********************/
|
/****************** Implementation of interface functions ********************/
|
||||||
@ -221,7 +225,13 @@ CvCapture* cvCreateCameraCapture_AVFoundation(int index ) {
|
|||||||
CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc,
|
CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc,
|
||||||
double fps, CvSize frame_size,
|
double fps, CvSize frame_size,
|
||||||
int is_color) {
|
int is_color) {
|
||||||
return new CvVideoWriter_AVFoundation(filename, fourcc, fps, frame_size,is_color);
|
CvVideoWriter_AVFoundation* wrt = new CvVideoWriter_AVFoundation(filename, fourcc, fps, frame_size, is_color);
|
||||||
|
if (wrt->isOpened())
|
||||||
|
{
|
||||||
|
return wrt;
|
||||||
|
}
|
||||||
|
delete wrt;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************** Implementation of Classes ****************************/
|
/********************** Implementation of Classes ****************************/
|
||||||
@ -305,6 +315,28 @@ void CvCaptureCAM::stopCaptureDevice() {
|
|||||||
int CvCaptureCAM::startCaptureDevice(int cameraNum) {
|
int CvCaptureCAM::startCaptureDevice(int cameraNum) {
|
||||||
NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
|
||||||
|
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||||
|
if (status == AVAuthorizationStatusDenied)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "OpenCV: camera access has been denied. Either run 'tccutil reset Camera' "
|
||||||
|
"command in same terminal to reset application authorization status, "
|
||||||
|
"either modify 'System Preferences -> Security & Privacy -> Camera' "
|
||||||
|
"settings for your application.\n");
|
||||||
|
[localpool drain];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (status != AVAuthorizationStatusAuthorized)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "OpenCV: not authorized to capture video (status %ld), requesting...\n", status);
|
||||||
|
// TODO: doesn't work via ssh
|
||||||
|
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL) { /* we don't care */}];
|
||||||
|
// we do not wait for completion
|
||||||
|
[localpool drain];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// get capture device
|
// get capture device
|
||||||
NSArray *devices = [[AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]
|
NSArray *devices = [[AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]
|
||||||
arrayByAddingObjectsFromArray:[AVCaptureDevice devicesWithMediaType:AVMediaTypeMuxed]];
|
arrayByAddingObjectsFromArray:[AVCaptureDevice devicesWithMediaType:AVMediaTypeMuxed]];
|
||||||
@ -1096,38 +1128,20 @@ bool CvCaptureFile::setProperty(int property_id, double value) {
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int fourcc,
|
CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const std::string &filename, int fourcc, double fps, CvSize frame_size, int is_color)
|
||||||
double fps, CvSize frame_size,
|
: argbimage(nil), mMovieWriter(nil), mMovieWriterInput(nil), mMovieWriterAdaptor(nil), path(nil),
|
||||||
int is_color) {
|
codec(nil), fileType(nil), mMovieFPS(fps), movieSize(frame_size), movieColor(is_color), mFrameNum(0),
|
||||||
|
is_good(true)
|
||||||
|
{
|
||||||
|
if (mMovieFPS <= 0 || movieSize.width <= 0 || movieSize.height <= 0)
|
||||||
|
{
|
||||||
|
is_good = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
|
||||||
mFrameNum = 0;
|
|
||||||
mMovieFPS = fps;
|
|
||||||
movieSize = frame_size;
|
|
||||||
movieColor = is_color;
|
|
||||||
argbimage = cvCreateImage(movieSize, IPL_DEPTH_8U, 4);
|
argbimage = cvCreateImage(movieSize, IPL_DEPTH_8U, 4);
|
||||||
path = [[[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] stringByExpandingTildeInPath] retain];
|
path = [[[NSString stringWithUTF8String:filename.c_str()] stringByExpandingTildeInPath] retain];
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
AVFileTypeQuickTimeMovie
|
|
||||||
UTI for the QuickTime movie file format.
|
|
||||||
The value of this UTI is com.apple.quicktime-movie. Files are identified with the .mov and .qt extensions.
|
|
||||||
|
|
||||||
AVFileTypeMPEG4
|
|
||||||
UTI for the MPEG-4 file format.
|
|
||||||
The value of this UTI is public.mpeg-4. Files are identified with the .mp4 extension.
|
|
||||||
|
|
||||||
AVFileTypeAppleM4V
|
|
||||||
UTI for the iTunes video file format.
|
|
||||||
The value of this UTI is com.apple.mpeg-4-video. Files are identified with the .m4v extension.
|
|
||||||
|
|
||||||
AVFileType3GPP
|
|
||||||
UTI for the 3GPP file format.
|
|
||||||
The value of this UTI is public.3gpp. Files are identified with the .3gp, .3gpp, and .sdv extensions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
NSString *fileExt =[[[path pathExtension] lowercaseString] copy];
|
NSString *fileExt =[[[path pathExtension] lowercaseString] copy];
|
||||||
if ([fileExt isEqualToString:@"mov"] || [fileExt isEqualToString:@"qt"]){
|
if ([fileExt isEqualToString:@"mov"] || [fileExt isEqualToString:@"qt"]){
|
||||||
@ -1136,12 +1150,8 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
|
|||||||
fileType = [AVFileTypeMPEG4 copy];
|
fileType = [AVFileTypeMPEG4 copy];
|
||||||
}else if ([fileExt isEqualToString:@"m4v"]){
|
}else if ([fileExt isEqualToString:@"m4v"]){
|
||||||
fileType = [AVFileTypeAppleM4V copy];
|
fileType = [AVFileTypeAppleM4V copy];
|
||||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
|
||||||
}else if ([fileExt isEqualToString:@"3gp"] || [fileExt isEqualToString:@"3gpp"] || [fileExt isEqualToString:@"sdv"] ){
|
|
||||||
fileType = [AVFileType3GPP copy];
|
|
||||||
#endif
|
|
||||||
} else{
|
} else{
|
||||||
fileType = [AVFileTypeMPEG4 copy]; //default mp4
|
is_good = false;
|
||||||
}
|
}
|
||||||
[fileExt release];
|
[fileExt release];
|
||||||
|
|
||||||
@ -1153,8 +1163,7 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
|
|||||||
cc[4] = 0;
|
cc[4] = 0;
|
||||||
int cc2 = CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
|
int cc2 = CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
|
||||||
if (cc2!=fourcc) {
|
if (cc2!=fourcc) {
|
||||||
fprintf(stderr, "OpenCV: Didn't properly encode FourCC. Expected 0x%08X but got 0x%08X.\n", fourcc, cc2);
|
is_good = false;
|
||||||
//exception;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two codec supported AVVideoCodecH264 AVVideoCodecJPEG
|
// Two codec supported AVVideoCodecH264 AVVideoCodecJPEG
|
||||||
@ -1165,59 +1174,59 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
|
|||||||
}else if(fourcc == CV_FOURCC('H','2','6','4') || fourcc == CV_FOURCC('a','v','c','1')){
|
}else if(fourcc == CV_FOURCC('H','2','6','4') || fourcc == CV_FOURCC('a','v','c','1')){
|
||||||
codec = [AVVideoCodecH264 copy];
|
codec = [AVVideoCodecH264 copy];
|
||||||
}else{
|
}else{
|
||||||
codec = [AVVideoCodecH264 copy]; // default canonical H264.
|
is_good = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//NSLog(@"Path: %@", path);
|
//NSLog(@"Path: %@", path);
|
||||||
|
|
||||||
NSError *error = nil;
|
if (is_good)
|
||||||
|
{
|
||||||
|
NSError *error = nil;
|
||||||
|
|
||||||
|
|
||||||
// Make sure the file does not already exist. Necessary to overwirte??
|
// Make sure the file does not already exist. Necessary to overwirte??
|
||||||
/*
|
/*
|
||||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||||
if ([fileManager fileExistsAtPath:path]){
|
if ([fileManager fileExistsAtPath:path]){
|
||||||
[fileManager removeItemAtPath:path error:&error];
|
[fileManager removeItemAtPath:path error:&error];
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Wire the writer:
|
// Wire the writer:
|
||||||
// Supported file types:
|
// Supported file types:
|
||||||
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
|
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
|
||||||
|
|
||||||
mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
|
mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
|
||||||
fileType:fileType
|
fileType:fileType
|
||||||
error:&error];
|
error:&error];
|
||||||
//NSParameterAssert(mMovieWriter);
|
//NSParameterAssert(mMovieWriter);
|
||||||
|
|
||||||
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
|
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
codec, AVVideoCodecKey,
|
codec, AVVideoCodecKey,
|
||||||
[NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
|
[NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
|
||||||
[NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
|
[NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
|
||||||
nil];
|
nil];
|
||||||
|
|
||||||
mMovieWriterInput = [[AVAssetWriterInput
|
mMovieWriterInput = [[AVAssetWriterInput
|
||||||
assetWriterInputWithMediaType:AVMediaTypeVideo
|
assetWriterInputWithMediaType:AVMediaTypeVideo
|
||||||
outputSettings:videoSettings] retain];
|
outputSettings:videoSettings] retain];
|
||||||
|
|
||||||
//NSParameterAssert(mMovieWriterInput);
|
//NSParameterAssert(mMovieWriterInput);
|
||||||
//NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
|
//NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
|
||||||
|
|
||||||
[mMovieWriter addInput:mMovieWriterInput];
|
[mMovieWriter addInput:mMovieWriterInput];
|
||||||
|
|
||||||
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
|
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
|
||||||
|
|
||||||
|
|
||||||
//Start a session:
|
//Start a session:
|
||||||
[mMovieWriter startWriting];
|
[mMovieWriter startWriting];
|
||||||
[mMovieWriter startSessionAtSourceTime:kCMTimeZero];
|
[mMovieWriter startSessionAtSourceTime:kCMTimeZero];
|
||||||
|
|
||||||
|
if(mMovieWriter.status == AVAssetWriterStatusFailed){
|
||||||
if(mMovieWriter.status == AVAssetWriterStatusFailed){
|
NSLog(@"AVF: AVAssetWriter status: %@", [mMovieWriter.error localizedDescription]);
|
||||||
NSLog(@"AVF: AVAssetWriter status: %@", [mMovieWriter.error localizedDescription]);
|
is_good = false;
|
||||||
// TODO: error handling, cleanup. Throw execption?
|
}
|
||||||
// return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[localpool drain];
|
[localpool drain];
|
||||||
@ -1227,15 +1236,22 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
|
|||||||
CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() {
|
CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() {
|
||||||
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
[mMovieWriterInput markAsFinished];
|
if (mMovieWriterInput && mMovieWriter && mMovieWriterAdaptor)
|
||||||
[mMovieWriter finishWriting];
|
{
|
||||||
[mMovieWriter release];
|
[mMovieWriterInput markAsFinished];
|
||||||
[mMovieWriterInput release];
|
[mMovieWriter finishWriting];
|
||||||
[mMovieWriterAdaptor release];
|
[mMovieWriter release];
|
||||||
[path release];
|
[mMovieWriterInput release];
|
||||||
[codec release];
|
[mMovieWriterAdaptor release];
|
||||||
[fileType release];
|
}
|
||||||
cvReleaseImage(&argbimage);
|
if (path)
|
||||||
|
[path release];
|
||||||
|
if (codec)
|
||||||
|
[codec release];
|
||||||
|
if (fileType)
|
||||||
|
[fileType release];
|
||||||
|
if (argbimage)
|
||||||
|
cvReleaseImage(&argbimage);
|
||||||
|
|
||||||
[localpool drain];
|
[localpool drain];
|
||||||
|
|
||||||
|
@ -40,6 +40,12 @@ VideoWriter_IntelMFX::VideoWriter_IntelMFX(const String &filename, int _fourcc,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fps <= 0)
|
||||||
|
{
|
||||||
|
MSG(cerr << "MFX: Invalid FPS passed to encoder" << endl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Init device and session
|
// Init device and session
|
||||||
deviceHandler = createDeviceHandler();
|
deviceHandler = createDeviceHandler();
|
||||||
session = new MFXVideoSession();
|
session = new MFXVideoSession();
|
||||||
|
@ -35,7 +35,7 @@ TEST(Videoio_MFX, write_invalid)
|
|||||||
ASSERT_NO_THROW(res = writer.open(String(), CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(640, 480), true));
|
ASSERT_NO_THROW(res = writer.open(String(), CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(640, 480), true));
|
||||||
EXPECT_FALSE(res);
|
EXPECT_FALSE(res);
|
||||||
EXPECT_FALSE(writer.isOpened());
|
EXPECT_FALSE(writer.isOpened());
|
||||||
ASSERT_ANY_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 0, Size(640, 480), true));
|
ASSERT_NO_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 0, Size(640, 480), true));
|
||||||
EXPECT_FALSE(res);
|
EXPECT_FALSE(res);
|
||||||
EXPECT_FALSE(writer.isOpened());
|
EXPECT_FALSE(writer.isOpened());
|
||||||
|
|
||||||
|
@ -419,8 +419,6 @@ static Ext_Fourcc_PSNR synthetic_params[] = {
|
|||||||
makeParam("mp4", "MJPG", 30.f, CAP_AVFOUNDATION),
|
makeParam("mp4", "MJPG", 30.f, CAP_AVFOUNDATION),
|
||||||
makeParam("m4v", "H264", 30.f, CAP_AVFOUNDATION),
|
makeParam("m4v", "H264", 30.f, CAP_AVFOUNDATION),
|
||||||
makeParam("m4v", "MJPG", 30.f, CAP_AVFOUNDATION),
|
makeParam("m4v", "MJPG", 30.f, CAP_AVFOUNDATION),
|
||||||
makeParam("3gp", "H264", 30.f, CAP_AVFOUNDATION),
|
|
||||||
makeParam("3gp", "MJPG", 30.f, CAP_AVFOUNDATION),
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_FFMPEG
|
#ifdef HAVE_FFMPEG
|
||||||
|
Loading…
Reference in New Issue
Block a user