You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
ffmpeg-kit/apple/src/AbstractSession.m

235 lines
6.1 KiB

/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "AbstractSession.h"
#import "AtomicLong.h"
#import "ExecuteCallback.h"
#import "FFmpegKit.h"
#import "FFmpegKitConfig.h"
#import "LogCallback.h"
#import "ReturnCode.h"
int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit = 5000;
static AtomicLong *sessionIdGenerator = nil;
@implementation AbstractSession {
long _sessionId;
ExecuteCallback _executeCallback;
LogCallback _logCallback;
NSDate* _createTime;
NSDate* _startTime;
NSDate* _endTime;
NSArray* _arguments;
NSMutableArray* _logs;
NSRecursiveLock* _logsLock;
SessionState _state;
ReturnCode* _returnCode;
NSString* _failStackTrace;
LogRedirectionStrategy _logRedirectionStrategy;
}
+ (void)initialize {
sessionIdGenerator = [[AtomicLong alloc] initWithValue:1];
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init];
if (self) {
_sessionId = [sessionIdGenerator getAndIncrement];
_executeCallback = executeCallback;
_logCallback = logCallback;
_createTime = [NSDate date];
_startTime = nil;
_endTime = nil;
_arguments = arguments;
_logs = [[NSMutableArray alloc] init];
_logsLock = [[NSRecursiveLock alloc] init];
_state = SessionStateCreated;
_returnCode = nil;
_failStackTrace = nil;
_logRedirectionStrategy = logRedirectionStrategy;
}
return self;
}
- (ExecuteCallback)getExecuteCallback {
return _executeCallback;
}
- (LogCallback)getLogCallback {
return _logCallback;
}
- (long)getSessionId {
return _sessionId;
}
- (NSDate*)getCreateTime {
return _createTime;
}
- (NSDate*)getStartTime {
return _startTime;
}
- (NSDate*)getEndTime {
return _endTime;
}
- (long)getDuration {
NSDate* startTime = _startTime;
NSDate* endTime = _endTime;
if (startTime != nil && endTime != nil) {
return [[NSNumber numberWithDouble:([endTime timeIntervalSinceDate:startTime]*1000)] longValue];
}
return 0;
}
- (NSArray*)getArguments {
return _arguments;
}
- (NSString*)getCommand {
return [FFmpegKit argumentsToString:_arguments];
}
- (void)waitForAsynchronousMessagesInTransmit:(int)timeout {
NSDate* expireDate = [[NSDate date] dateByAddingTimeInterval:((double)timeout)/1000];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
while ([self thereAreAsynchronousMessagesInTransmit] && ([[NSDate date] timeIntervalSinceDate:expireDate] < 0)) {
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC));
}
}
- (NSArray*)getAllLogsWithTimeout:(int)waitTimeout {
[self waitForAsynchronousMessagesInTransmit:waitTimeout];
if ([self thereAreAsynchronousMessagesInTransmit]) {
NSLog(@"getAllLogsWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
}
return [self getLogs];
}
- (NSArray*)getAllLogs {
return [self getAllLogsWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
}
- (NSArray*)getLogs {
[_logsLock lock];
NSArray* logsCopy = [_logs copy];
[_logsLock unlock];
return logsCopy;
}
- (NSString*)getAllLogsAsStringWithTimeout:(int)waitTimeout {
[self waitForAsynchronousMessagesInTransmit:waitTimeout];
if ([self thereAreAsynchronousMessagesInTransmit]) {
NSLog(@"getAllLogsAsStringWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
}
return [self getLogsAsString];
}
- (NSString*)getAllLogsAsString {
return [self getAllLogsAsStringWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
}
- (NSString*)getLogsAsString {
NSMutableString* concatenatedString = [[NSMutableString alloc] init];
[_logsLock lock];
for (int i=0; i < [_logs count]; i++) {
[concatenatedString appendString:[[_logs objectAtIndex:i] getMessage]];
}
[_logsLock unlock];
return concatenatedString;
}
- (NSString*)getOutput {
return [self getAllLogsAsString];
}
- (SessionState)getState {
return _state;
}
- (ReturnCode*)getReturnCode {
return _returnCode;
}
- (NSString*)getFailStackTrace {
return _failStackTrace;
}
- (LogRedirectionStrategy)getLogRedirectionStrategy {
return _logRedirectionStrategy;
}
- (BOOL)thereAreAsynchronousMessagesInTransmit {
return ([FFmpegKitConfig messagesInTransmit:_sessionId] != 0);
}
- (void)addLog:(Log*)log {
[_logsLock lock];
[_logs addObject:log];
[_logsLock unlock];
}
- (void)startRunning {
_state = SessionStateRunning;
_startTime = [NSDate date];
}
- (void)complete:(ReturnCode*)returnCode {
_returnCode = returnCode;
_state = SessionStateCompleted;
_endTime = [NSDate date];
}
- (void)fail:(NSException*)exception {
_failStackTrace = [NSString stringWithFormat:@"%@", [exception callStackSymbols]];
_state = SessionStateFailed;
_endTime = [NSDate date];
}
- (BOOL)isFFmpeg {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (BOOL)isFFprobe {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (void)cancel {
if (_state == SessionStateRunning) {
[FFmpegKit cancel:_sessionId];
}
}
@end