FFmpegKit iOS / macOS / tvOS API  4.4
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 
32 @implementation AbstractSession {
33  long _sessionId;
36  NSDate* _createTime;
37  NSDate* _startTime;
38  NSDate* _endTime;
39  NSArray* _arguments;
40  NSMutableArray* _logs;
41  NSRecursiveLock* _logsLock;
42  SessionState _state;
44  NSString* _failStackTrace;
45  LogRedirectionStrategy _logRedirectionStrategy;
46 }
47 
48 + (void)initialize {
49  sessionIdGenerator = [[AtomicLong alloc] initWithValue:1];
50 }
51 
52 - (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
53  self = [super init];
54  if (self) {
55  _sessionId = [sessionIdGenerator getAndIncrement];
58  _createTime = [NSDate date];
59  _startTime = nil;
60  _endTime = nil;
61  _arguments = arguments;
62  _logs = [[NSMutableArray alloc] init];
63  _logsLock = [[NSRecursiveLock alloc] init];
64  _state = SessionStateCreated;
65  _returnCode = nil;
66  _failStackTrace = nil;
67  _logRedirectionStrategy = logRedirectionStrategy;
68  }
69 
70  return self;
71 }
72 
73 - (ExecuteCallback)getExecuteCallback {
74  return _executeCallback;
75 }
76 
77 - (LogCallback)getLogCallback {
78  return _logCallback;
79 }
80 
81 - (long)getSessionId {
82  return _sessionId;
83 }
84 
85 - (NSDate*)getCreateTime {
86  return _createTime;
87 }
88 
89 - (NSDate*)getStartTime {
90  return _startTime;
91 }
92 
93 - (NSDate*)getEndTime {
94  return _endTime;
95 }
96 
97 - (long)getDuration {
98  NSDate* startTime = _startTime;
99  NSDate* endTime = _endTime;
100  if (startTime != nil && endTime != nil) {
101  return [[NSNumber numberWithDouble:([endTime timeIntervalSinceDate:startTime]*1000)] longValue];
102  }
103 
104  return 0;
105 }
106 
107 - (NSArray*)getArguments {
108  return _arguments;
109 }
110 
111 - (NSString*)getCommand {
112  return [FFmpegKit argumentsToString:_arguments];
113 }
114 
115 - (void)waitForAsynchronousMessagesInTransmit:(int)timeout {
116  NSDate* expireDate = [[NSDate date] dateByAddingTimeInterval:((double)timeout)/1000];
117  dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
118 
119  while ([self thereAreAsynchronousMessagesInTransmit] && ([[NSDate date] timeIntervalSinceDate:expireDate] < 0)) {
120  dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC));
121  }
122 }
123 
124 - (NSArray*)getAllLogsWithTimeout:(int)waitTimeout {
125  [self waitForAsynchronousMessagesInTransmit:waitTimeout];
126 
127  if ([self thereAreAsynchronousMessagesInTransmit]) {
128  NSLog(@"getAllLogsWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
129  }
130 
131  return [self getLogs];
132 }
133 
134 - (NSArray*)getAllLogs {
135  return [self getAllLogsWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
136 }
137 
138 - (NSArray*)getLogs {
139  [_logsLock lock];
140  NSArray* logsCopy = [_logs copy];
141  [_logsLock unlock];
142 
143  return logsCopy;
144 }
145 
146 - (NSString*)getAllLogsAsStringWithTimeout:(int)waitTimeout {
147  [self waitForAsynchronousMessagesInTransmit:waitTimeout];
148 
149  if ([self thereAreAsynchronousMessagesInTransmit]) {
150  NSLog(@"getAllLogsAsStringWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
151  }
152 
153  return [self getLogsAsString];
154 }
155 
156 - (NSString*)getAllLogsAsString {
157  return [self getAllLogsAsStringWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
158 }
159 
160 - (NSString*)getLogsAsString {
161  NSMutableString* concatenatedString = [[NSMutableString alloc] init];
162 
163  [_logsLock lock];
164  for (int i=0; i < [_logs count]; i++) {
165  [concatenatedString appendString:[[_logs objectAtIndex:i] getMessage]];
166  }
167  [_logsLock unlock];
168 
169  return concatenatedString;
170 }
171 
172 - (NSString*)getOutput {
173  return [self getAllLogsAsString];
174 }
175 
176 - (SessionState)getState {
177  return _state;
178 }
179 
180 - (ReturnCode*)getReturnCode {
181  return _returnCode;
182 }
183 
184 - (NSString*)getFailStackTrace {
185  return _failStackTrace;
186 }
187 
188 - (LogRedirectionStrategy)getLogRedirectionStrategy {
190 }
191 
192 - (BOOL)thereAreAsynchronousMessagesInTransmit {
193  return ([FFmpegKitConfig messagesInTransmit:_sessionId] != 0);
194 }
195 
196 - (void)addLog:(Log*)log {
197  [_logsLock lock];
198  [_logs addObject:log];
199  [_logsLock unlock];
200 }
201 
202 - (void)startRunning {
203  _state = SessionStateRunning;
204  _startTime = [NSDate date];
205 }
206 
207 - (void)complete:(ReturnCode*)returnCode {
208  _returnCode = returnCode;
209  _state = SessionStateCompleted;
210  _endTime = [NSDate date];
211 }
212 
213 - (void)fail:(NSException*)exception {
214  _failStackTrace = [NSString stringWithFormat:@"%@", [exception callStackSymbols]];
215  _state = SessionStateFailed;
216  _endTime = [NSDate date];
217 }
218 
219 - (BOOL)isFFmpeg {
220  // IMPLEMENTED IN SUBCLASSES
221  return false;
222 }
223 
224 - (BOOL)isFFprobe {
225  // IMPLEMENTED IN SUBCLASSES
226  return false;
227 }
228 
229 - (void)cancel {
230  if (_state == SessionStateRunning) {
231  [FFmpegKit cancel:_sessionId];
232  }
233 }
234 
235 @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(^ ExecuteCallback)(id< Session > session)
static LogCallback logCallback
__thread volatile long _sessionId
static ExecuteCallback executeCallback
static dispatch_semaphore_t semaphore
void(^ LogCallback)(Log *log)
Definition: LogCallback.h:31
long getAndIncrement()
Definition: AtomicLong.m:40
void cancel:(long sessionId)
Definition: FFmpegKit.m:106
NSString * argumentsToString:(NSArray *arguments)
Definition: FFmpegKit.m:165
Definition: Log.h:29