Merge pull request #14500 from mshabunin:backport-avfoundation

pull/14504/head
Alexander Alekhin 6 years ago
commit 455323ed58
  1. 188
      modules/videoio/src/cap_avfoundation_mac.mm
  2. 6
      modules/videoio/src/cap_mfx_writer.cpp
  3. 2
      modules/videoio/test/test_mfx.cpp
  4. 2
      modules/videoio/test/test_video_io.cpp

@ -43,6 +43,7 @@
#include "precomp.hpp"
#include "opencv2/imgproc.hpp"
#include <stdio.h>
#include <Availability.h>
#import <AVFoundation/AVFoundation.h>
/********************** Declaration of class headers ************************/
@ -177,12 +178,14 @@ private:
class CvVideoWriter_AVFoundation : public CvVideoWriter {
public:
CvVideoWriter_AVFoundation(const char* filename, int fourcc,
double fps, CvSize frame_size,
int is_color=1);
CvVideoWriter_AVFoundation(const std::string &filename, int fourcc, double fps, CvSize frame_size, int is_color);
~CvVideoWriter_AVFoundation();
bool writeFrame(const IplImage* image) CV_OVERRIDE;
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_AVFOUNDATION; }
bool isOpened() const
{
return is_good;
}
private:
IplImage* argbimage;
@ -197,6 +200,7 @@ class CvVideoWriter_AVFoundation : public CvVideoWriter {
CvSize movieSize;
int movieColor;
unsigned long mFrameNum;
bool is_good;
};
/****************** Implementation of interface functions ********************/
@ -221,7 +225,13 @@ CvCapture* cvCreateCameraCapture_AVFoundation(int index ) {
CvVideoWriter* cvCreateVideoWriter_AVFoundation(const char* filename, int fourcc,
double fps, CvSize frame_size,
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 ****************************/
@ -305,6 +315,28 @@ void CvCaptureCAM::stopCaptureDevice() {
int CvCaptureCAM::startCaptureDevice(int cameraNum) {
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
NSArray *devices = [[AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]
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,
double fps, CvSize frame_size,
int is_color) {
CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const std::string &filename, int fourcc, double fps, CvSize frame_size, int is_color)
: argbimage(nil), mMovieWriter(nil), mMovieWriterInput(nil), mMovieWriterAdaptor(nil), path(nil),
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];
mFrameNum = 0;
mMovieFPS = fps;
movieSize = frame_size;
movieColor = is_color;
argbimage = cvCreateImage(movieSize, IPL_DEPTH_8U, 4);
path = [[[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] 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.
*/
path = [[[NSString stringWithUTF8String:filename.c_str()] stringByExpandingTildeInPath] retain];
NSString *fileExt =[[[path pathExtension] lowercaseString] copy];
if ([fileExt isEqualToString:@"mov"] || [fileExt isEqualToString:@"qt"]){
@ -1136,12 +1150,8 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
fileType = [AVFileTypeMPEG4 copy];
}else if ([fileExt isEqualToString:@"m4v"]){
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{
fileType = [AVFileTypeMPEG4 copy]; //default mp4
is_good = false;
}
[fileExt release];
@ -1153,8 +1163,7 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
cc[4] = 0;
int cc2 = CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
if (cc2!=fourcc) {
fprintf(stderr, "OpenCV: Didn't properly encode FourCC. Expected 0x%08X but got 0x%08X.\n", fourcc, cc2);
//exception;
is_good = false;
}
// 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')){
codec = [AVVideoCodecH264 copy];
}else{
codec = [AVVideoCodecH264 copy]; // default canonical H264.
is_good = false;
}
//NSLog(@"Path: %@", path);
NSError *error = nil;
if (is_good)
{
NSError *error = nil;
// Make sure the file does not already exist. Necessary to overwirte??
/*
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:path]){
[fileManager removeItemAtPath:path error:&error];
}
*/
// Wire the writer:
// Supported file types:
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
// Make sure the file does not already exist. Necessary to overwirte??
/*
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:path]){
[fileManager removeItemAtPath:path error:&error];
}
*/
mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
fileType:fileType
error:&error];
//NSParameterAssert(mMovieWriter);
// Wire the writer:
// Supported file types:
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
codec, AVVideoCodecKey,
[NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
[NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
nil];
mMovieWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
fileType:fileType
error:&error];
//NSParameterAssert(mMovieWriter);
mMovieWriterInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
codec, AVVideoCodecKey,
[NSNumber numberWithInt:movieSize.width], AVVideoWidthKey,
[NSNumber numberWithInt:movieSize.height], AVVideoHeightKey,
nil];
//NSParameterAssert(mMovieWriterInput);
//NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
mMovieWriterInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
[mMovieWriter addInput:mMovieWriterInput];
//NSParameterAssert(mMovieWriterInput);
//NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
[mMovieWriter addInput:mMovieWriterInput];
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc] initWithAssetWriterInput:mMovieWriterInput sourcePixelBufferAttributes:nil];
//Start a session:
[mMovieWriter startWriting];
[mMovieWriter startSessionAtSourceTime:kCMTimeZero];
//Start a session:
[mMovieWriter startWriting];
[mMovieWriter startSessionAtSourceTime:kCMTimeZero];
if(mMovieWriter.status == AVAssetWriterStatusFailed){
NSLog(@"AVF: AVAssetWriter status: %@", [mMovieWriter.error localizedDescription]);
// TODO: error handling, cleanup. Throw execption?
// return;
if(mMovieWriter.status == AVAssetWriterStatusFailed){
NSLog(@"AVF: AVAssetWriter status: %@", [mMovieWriter.error localizedDescription]);
is_good = false;
}
}
[localpool drain];
@ -1227,15 +1236,22 @@ CvVideoWriter_AVFoundation::CvVideoWriter_AVFoundation(const char* filename, int
CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() {
NSAutoreleasePool* localpool = [[NSAutoreleasePool alloc] init];
[mMovieWriterInput markAsFinished];
[mMovieWriter finishWriting];
[mMovieWriter release];
[mMovieWriterInput release];
[mMovieWriterAdaptor release];
[path release];
[codec release];
[fileType release];
cvReleaseImage(&argbimage);
if (mMovieWriterInput && mMovieWriter && mMovieWriterAdaptor)
{
[mMovieWriterInput markAsFinished];
[mMovieWriter finishWriting];
[mMovieWriter release];
[mMovieWriterInput release];
[mMovieWriterAdaptor release];
}
if (path)
[path release];
if (codec)
[codec release];
if (fileType)
[fileType release];
if (argbimage)
cvReleaseImage(&argbimage);
[localpool drain];

@ -40,6 +40,12 @@ VideoWriter_IntelMFX::VideoWriter_IntelMFX(const String &filename, int _fourcc,
return;
}
if (fps <= 0)
{
MSG(cerr << "MFX: Invalid FPS passed to encoder" << endl);
return;
}
// Init device and session
deviceHandler = createDeviceHandler();
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));
EXPECT_FALSE(res);
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(writer.isOpened());

@ -419,8 +419,6 @@ static Ext_Fourcc_PSNR synthetic_params[] = {
makeParam("mp4", "MJPG", 30.f, CAP_AVFOUNDATION),
makeParam("m4v", "H264", 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
#ifdef HAVE_FFMPEG

Loading…
Cancel
Save