FFmpegKit iOS / macOS / tvOS API 4.5
AbstractSession.m
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Taner Sener
3 *
4 * This file is part of FFmpegKit.
5 *
6 * FFmpegKit is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * FFmpegKit is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General License
17 * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#import "AbstractSession.h"
21#import "AtomicLong.h"
22#import "ExecuteCallback.h"
23#import "FFmpegKit.h"
24#import "FFmpegKitConfig.h"
25#import "LogCallback.h"
26#import "ReturnCode.h"
27
29
31
32extern void addSessionToSessionHistory(id<Session> session);
33
34@implementation AbstractSession {
35 long _sessionId;
38 NSDate* _createTime;
39 NSDate* _startTime;
40 NSDate* _endTime;
41 NSArray* _arguments;
42 NSMutableArray* _logs;
43 NSRecursiveLock* _logsLock;
44 SessionState _state;
46 NSString* _failStackTrace;
47 LogRedirectionStrategy _logRedirectionStrategy;
48}
49
50+ (void)initialize {
51 sessionIdGenerator = [[AtomicLong alloc] initWithValue:1];
52}
53
54- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
55 self = [super init];
56 if (self) {
57 _sessionId = [sessionIdGenerator getAndIncrement];
60 _createTime = [NSDate date];
61 _startTime = nil;
62 _endTime = nil;
63 _arguments = arguments;
64 _logs = [[NSMutableArray alloc] init];
65 _logsLock = [[NSRecursiveLock alloc] init];
66 _state = SessionStateCreated;
67 _returnCode = nil;
68 _failStackTrace = nil;
69 _logRedirectionStrategy = logRedirectionStrategy;
70
72 }
73
74 return self;
75}
76
77- (ExecuteCallback)getExecuteCallback {
78 return _executeCallback;
79}
80
81- (LogCallback)getLogCallback {
82 return _logCallback;
83}
84
85- (long)getSessionId {
86 return _sessionId;
87}
88
89- (NSDate*)getCreateTime {
90 return _createTime;
91}
92
93- (NSDate*)getStartTime {
94 return _startTime;
95}
96
97- (NSDate*)getEndTime {
98 return _endTime;
99}
100
101- (long)getDuration {
102 NSDate* startTime = _startTime;
103 NSDate* endTime = _endTime;
104 if (startTime != nil && endTime != nil) {
105 return [[NSNumber numberWithDouble:([endTime timeIntervalSinceDate:startTime]*1000)] longValue];
106 }
107
108 return 0;
109}
110
111- (NSArray*)getArguments {
112 return _arguments;
113}
114
115- (NSString*)getCommand {
116 return [FFmpegKitConfig argumentsToString:_arguments];
117}
118
119- (void)waitForAsynchronousMessagesInTransmit:(int)timeout {
120 NSDate* expireDate = [[NSDate date] dateByAddingTimeInterval:((double)timeout)/1000];
121 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
122
123 while ([self thereAreAsynchronousMessagesInTransmit] && ([[NSDate date] timeIntervalSinceDate:expireDate] < 0)) {
124 dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC));
125 }
126}
127
128- (NSArray*)getAllLogsWithTimeout:(int)waitTimeout {
129 [self waitForAsynchronousMessagesInTransmit:waitTimeout];
130
131 if ([self thereAreAsynchronousMessagesInTransmit]) {
132 NSLog(@"getAllLogsWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
133 }
134
135 return [self getLogs];
136}
137
138- (NSArray*)getAllLogs {
139 return [self getAllLogsWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
140}
141
142- (NSArray*)getLogs {
143 [_logsLock lock];
144 NSArray* logsCopy = [_logs copy];
145 [_logsLock unlock];
146
147 return logsCopy;
148}
149
150- (NSString*)getAllLogsAsStringWithTimeout:(int)waitTimeout {
151 [self waitForAsynchronousMessagesInTransmit:waitTimeout];
152
153 if ([self thereAreAsynchronousMessagesInTransmit]) {
154 NSLog(@"getAllLogsAsStringWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
155 }
156
157 return [self getLogsAsString];
158}
159
160- (NSString*)getAllLogsAsString {
161 return [self getAllLogsAsStringWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
162}
163
164- (NSString*)getLogsAsString {
165 NSMutableString* concatenatedString = [[NSMutableString alloc] init];
166
167 [_logsLock lock];
168 for (int i=0; i < [_logs count]; i++) {
169 [concatenatedString appendString:[[_logs objectAtIndex:i] getMessage]];
170 }
171 [_logsLock unlock];
172
173 return concatenatedString;
174}
175
176- (NSString*)getOutput {
177 return [self getAllLogsAsString];
178}
179
180- (SessionState)getState {
181 return _state;
182}
183
184- (ReturnCode*)getReturnCode {
185 return _returnCode;
186}
187
188- (NSString*)getFailStackTrace {
189 return _failStackTrace;
190}
191
192- (LogRedirectionStrategy)getLogRedirectionStrategy {
194}
195
196- (BOOL)thereAreAsynchronousMessagesInTransmit {
197 return ([FFmpegKitConfig messagesInTransmit:_sessionId] != 0);
198}
199
200- (void)addLog:(Log*)log {
201 [_logsLock lock];
202 [_logs addObject:log];
203 [_logsLock unlock];
204}
205
206- (void)startRunning {
207 _state = SessionStateRunning;
208 _startTime = [NSDate date];
209}
210
211- (void)complete:(ReturnCode*)returnCode {
212 _returnCode = returnCode;
213 _state = SessionStateCompleted;
214 _endTime = [NSDate date];
215}
216
217- (void)fail:(NSException*)exception {
218 _failStackTrace = [NSString stringWithFormat:@"%@", [exception callStackSymbols]];
219 _state = SessionStateFailed;
220 _endTime = [NSDate date];
221}
222
223- (BOOL)isFFmpeg {
224 // IMPLEMENTED IN SUBCLASSES
225 return false;
226}
227
228- (BOOL)isFFprobe {
229 // IMPLEMENTED IN SUBCLASSES
230 return false;
231}
232
233- (void)cancel {
234 if (_state == SessionStateRunning) {
235 [FFmpegKit cancel:_sessionId];
236 }
237}
238
239@end
ExecuteCallback _executeCallback
NSString * _failStackTrace
NSRecursiveLock * _logsLock
NSDate * _endTime
NSArray * _arguments
SessionState _state
LogRedirectionStrategy _logRedirectionStrategy
NSDate * _startTime
int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit
NSDate * _createTime
static AtomicLong * sessionIdGenerator
ReturnCode * _returnCode
LogCallback _logCallback
NSMutableArray * _logs
void addSessionToSessionHistory(id< Session > session)
void(^ ExecuteCallback)(id< Session > session)
static LogCallback logCallback
long _sessionId
static ExecuteCallback executeCallback
static dispatch_semaphore_t semaphore
void(^ LogCallback)(Log *log)
Definition: LogCallback.h:31
long getAndIncrement()
Definition: AtomicLong.m:40
NSString * argumentsToString:(NSArray *arguments)
void cancel:(long sessionId)
Definition: FFmpegKit.m:106
Definition: Log.h:29