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

256 lines
6.3 KiB

/*
* Copyright (c) 2021-2022 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 "FFmpegKit.h"
#import "FFmpegKitConfig.h"
#import "LogCallback.h"
#import "ReturnCode.h"
int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit = 5000;
static AtomicLong *sessionIdGenerator = nil;
extern void addSessionToSessionHistory(id<Session> session);
@implementation AbstractSession {
long _sessionId;
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
withLogCallback:(LogCallback)logCallback
withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init];
if (self) {
_sessionId = [sessionIdGenerator getAndIncrement];
_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;
addSessionToSessionHistory(self);
}
return self;
}
- (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 [FFmpegKitConfig 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:@"%@\n%@", [exception userInfo],
[exception callStackSymbols]];
_state = SessionStateFailed;
_endTime = [NSDate date];
}
- (BOOL)isFFmpeg {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (BOOL)isFFprobe {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (BOOL)isMediaInformation {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (void)cancel {
if (_state == SessionStateRunning) {
[FFmpegKit cancel:_sessionId];
}
}
@end