simplify execute methods

This commit is contained in:
Taner Sener 2022-01-02 17:04:21 +00:00
parent f4b0510148
commit 8a00606604
14 changed files with 253 additions and 157 deletions

View File

@ -1,8 +1,8 @@
## 4.5.1 ## 4.5.1
- Bugfix release - Feature release based on native v4.5.1
## 4.5.1-LTS ## 4.5.1-LTS
- Bugfix LTS release - Feature release based on native v4.5.1.LTS
## 4.5.0 ## 4.5.0
- Initial release - Initial release

View File

@ -43,6 +43,6 @@ repositories {
dependencies { dependencies {
implementation 'androidx.annotation:annotation:1.2.0' implementation 'androidx.annotation:annotation:1.2.0'
implementation 'com.arthenica:ffmpeg-kit-https:4.5.1' implementation 'com.arthenica:ffmpeg-kit-https:4.5.1-1'
} }

View File

@ -359,6 +359,13 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
resultHandler.errorAsync(result, "INVALID_ARGUMENTS", "Invalid arguments array."); resultHandler.errorAsync(result, "INVALID_ARGUMENTS", "Invalid arguments array.");
} }
break; break;
case "getMediaInformation":
if (sessionId != null) {
getMediaInformation(sessionId, result);
} else {
resultHandler.errorAsync(result, "INVALID_SESSION", "Invalid session id.");
}
break;
case "mediaInformationJsonParserFrom": case "mediaInformationJsonParserFrom":
if (ffprobeJsonOutput != null) { if (ffprobeJsonOutput != null) {
mediaInformationJsonParserFrom(ffprobeJsonOutput, result); mediaInformationJsonParserFrom(ffprobeJsonOutput, result);
@ -876,6 +883,21 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
resultHandler.successAsync(result, toMap(session)); resultHandler.successAsync(result, toMap(session));
} }
protected void getMediaInformation(@NonNull final Integer sessionId, @NonNull final Result result) {
final Session session = FFmpegKitConfig.getSession(sessionId.longValue());
if (session == null) {
resultHandler.errorAsync(result, "SESSION_NOT_FOUND", "Session not found.");
} else {
if (session.isMediaInformation()) {
final MediaInformationSession mediaInformationSession = (MediaInformationSession) session;
final MediaInformation mediaInformation = mediaInformationSession.getMediaInformation();
resultHandler.successAsync(result, toMap(mediaInformation));
} else {
resultHandler.errorAsync(result, "NOT_MEDIA_INFORMATION_SESSION", "A session is found but it does not have the correct type.");
}
}
}
// MediaInformationJsonParser // MediaInformationJsonParser
protected void mediaInformationJsonParserFrom(@NonNull final String ffprobeJsonOutput, @NonNull final Result result) { protected void mediaInformationJsonParserFrom(@NonNull final String ffprobeJsonOutput, @NonNull final Result result) {
@ -1332,19 +1354,17 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
sessionMap.put(KEY_SESSION_START_TIME, toLong(session.getStartTime())); sessionMap.put(KEY_SESSION_START_TIME, toLong(session.getStartTime()));
sessionMap.put(KEY_SESSION_COMMAND, session.getCommand()); sessionMap.put(KEY_SESSION_COMMAND, session.getCommand());
if (session.isFFprobe()) { if (session.isFFmpeg()) {
if (session.isMediaInformation()) { sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_FFMPEG);
} else if (session.isFFprobe()) {
sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_FFPROBE);
} else if (session.isMediaInformation()) {
final MediaInformationSession mediaInformationSession = (MediaInformationSession) session; final MediaInformationSession mediaInformationSession = (MediaInformationSession) session;
final MediaInformation mediaInformation = mediaInformationSession.getMediaInformation(); final MediaInformation mediaInformation = mediaInformationSession.getMediaInformation();
if (mediaInformation != null) { if (mediaInformation != null) {
sessionMap.put(KEY_SESSION_MEDIA_INFORMATION, toMap(mediaInformation)); sessionMap.put(KEY_SESSION_MEDIA_INFORMATION, toMap(mediaInformation));
} }
sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_MEDIA_INFORMATION); sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_MEDIA_INFORMATION);
} else {
sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_FFPROBE);
}
} else {
sessionMap.put(KEY_SESSION_TYPE, SESSION_TYPE_FFMPEG);
} }
return sessionMap; return sessionMap;
@ -1432,18 +1452,20 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
} }
protected static Map<String, Object> toMap(final MediaInformation mediaInformation) { protected static Map<String, Object> toMap(final MediaInformation mediaInformation) {
if (mediaInformation != null) {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
if (mediaInformation != null) {
if (mediaInformation.getAllProperties() != null) { if (mediaInformation.getAllProperties() != null) {
JSONObject allProperties = mediaInformation.getAllProperties(); JSONObject allProperties = mediaInformation.getAllProperties();
if (allProperties != null) { if (allProperties != null) {
map = toMap(allProperties); map = toMap(allProperties);
} }
} }
}
return map; return map;
} else {
return null;
}
} }
protected static Map<String, Object> toMap(final JSONObject jsonObject) { protected static Map<String, Object> toMap(final JSONObject jsonObject) {

View File

@ -232,6 +232,12 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
} else { } else {
result([FlutterError errorWithCode:@"INVALID_ARGUMENTS" message:@"Invalid arguments array." details:nil]); result([FlutterError errorWithCode:@"INVALID_ARGUMENTS" message:@"Invalid arguments array." details:nil]);
} }
} else if ([@"getMediaInformation" isEqualToString:call.method]) {
if (sessionId != nil) {
[self getMediaInformation:sessionId result:result];
} else {
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
}
} else if ([@"mediaInformationJsonParserFrom" isEqualToString:call.method]) { } else if ([@"mediaInformationJsonParserFrom" isEqualToString:call.method]) {
if (ffprobeJsonOutput != nil) { if (ffprobeJsonOutput != nil) {
[self mediaInformationJsonParserFrom:ffprobeJsonOutput result:result]; [self mediaInformationJsonParserFrom:ffprobeJsonOutput result:result];
@ -609,6 +615,20 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
result([FFmpegKitFlutterPlugin toSessionDictionary:session]); result([FFmpegKitFlutterPlugin toSessionDictionary:session]);
} }
- (void)getMediaInformation:(NSNumber*)sessionId result:(FlutterResult)result {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:[sessionId longValue]];
if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else {
if ([session isMediaInformation]) {
MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session;
result([FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]);
} else {
result([FlutterError errorWithCode:@"NOT_MEDIA_INFORMATION_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
}
}
}
// MediaInformationJsonParser // MediaInformationJsonParser
- (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { - (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result {
@ -1061,16 +1081,14 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithLong:[[session getStartTime] timeIntervalSince1970]*1000]; dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithLong:[[session getStartTime] timeIntervalSince1970]*1000];
dictionary[KEY_SESSION_COMMAND] = [session getCommand]; dictionary[KEY_SESSION_COMMAND] = [session getCommand];
if ([session isFFprobe]) { if ([session isFFmpeg]) {
if ([session isMediaInformation]) { dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG];
} else if ([session isFFprobe]) {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE];
} else if ([session isMediaInformation]) {
MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session;
dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]];
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION];
} else {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE];
}
} else {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG];
} }
return dictionary; return dictionary;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019-2021 Taner Sener * Copyright (c) 2019-2022 Taner Sener
* *
* This file is part of FFmpegKit. * This file is part of FFmpegKit.
* *
@ -34,21 +34,14 @@ class FFmpegKit {
/// Synchronously executes FFmpeg command provided. Space character is used /// Synchronously executes FFmpeg command provided. Space character is used
/// to split command into arguments. You can use single or double quote /// to split command into arguments. You can use single or double quote
/// characters to specify arguments inside your command. /// characters to specify arguments inside your command.
static Future<FFmpegSession> execute(String command, static Future<FFmpegSession> execute(String command) async =>
[FFmpegSessionCompleteCallback? completeCallback = null, FFmpegKit.executeWithArguments(FFmpegKitConfig.parseArguments(command));
LogCallback? logCallback = null,
StatisticsCallback? statisticsCallback = null]) async =>
FFmpegKit.executeWithArguments(FFmpegKitConfig.parseArguments(command),
completeCallback, logCallback, statisticsCallback);
/// Synchronously executes FFmpeg with arguments provided. /// Synchronously executes FFmpeg with arguments provided.
static Future<FFmpegSession> executeWithArguments( static Future<FFmpegSession> executeWithArguments(
List<String> commandArguments, List<String> commandArguments) async {
[FFmpegSessionCompleteCallback? completeCallback = null, final session =
LogCallback? logCallback = null, await FFmpegSession.create(commandArguments, null, null, null, null);
StatisticsCallback? statisticsCallback = null]) async {
final session = await FFmpegSession.create(commandArguments,
completeCallback, logCallback, statisticsCallback, null);
await FFmpegKitConfig.ffmpegExecute(session); await FFmpegKitConfig.ffmpegExecute(session);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019-2021 Taner Sener * Copyright (c) 2019-2022 Taner Sener
* *
* This file is part of FFmpegKit. * This file is part of FFmpegKit.
* *
@ -366,6 +366,55 @@ class FFmpegKitConfig {
} }
} }
/// Converts the given Structured Access Framework Uri ("content:…") into
/// an input url that can be used in FFmpeg and FFprobe commands.
///
/// Note that this method is Android only. It will fail if called on other
/// platforms. It also requires API Level &ge; 19. On older API levels it
/// returns an empty url.
static Future<String?> getSafParameterForRead(String uriString) async {
try {
await init();
return _platform.ffmpegKitConfigGetSafParameter(uriString, "r");
} on PlatformException catch (e, stack) {
print("Plugin getSafParameterForRead error: ${e.message}");
return Future.error("getSafParameterForRead failed.", stack);
}
}
/// Converts the given Structured Access Framework Uri ("content:…") into
/// an output url that can be used in FFmpeg and FFprobe commands.
///
/// Note that this method is Android only. It will fail if called on other
/// platforms. It also requires API Level &ge; 19. On older API levels it
/// returns an empty url.
static Future<String?> getSafParameterForWrite(String uriString) async {
try {
await init();
return _platform.ffmpegKitConfigGetSafParameter(uriString, "w");
} on PlatformException catch (e, stack) {
print("Plugin getSafParameterForWrite error: ${e.message}");
return Future.error("getSafParameterForWrite failed.", stack);
}
}
/// Converts the given Structured Access Framework Uri into an saf protocol
/// url opened with the given open mode.
///
/// Note that this method is Android only. It will fail if called on other
/// platforms. It also requires API Level &ge; 19. On older API levels it
/// returns an empty url.
static Future<String?> getSafParameter(
String uriString, String openMode) async {
try {
await init();
return _platform.ffmpegKitConfigGetSafParameter(uriString, openMode);
} on PlatformException catch (e, stack) {
print("Plugin getSafParameter error: ${e.message}");
return Future.error("getSafParameter failed.", stack);
}
}
/// Returns the session history size. /// Returns the session history size.
static Future<int?> getSessionHistorySize() async { static Future<int?> getSessionHistorySize() async {
try { try {
@ -763,53 +812,4 @@ class FFmpegKitConfig {
return Future.error("selectDocumentForWrite failed.", stack); return Future.error("selectDocumentForWrite failed.", stack);
} }
} }
/// Converts the given Structured Access Framework Uri ("content:…") into
/// an input url that can be used in FFmpeg and FFprobe commands.
///
/// Note that this method is Android only. It will fail if called on other
/// platforms. It also requires API Level &ge; 19. On older API levels it
/// returns an empty url.
static Future<String?> getSafParameterForRead(String uriString) async {
try {
await init();
return _platform.ffmpegKitConfigGetSafParameter(uriString, "r");
} on PlatformException catch (e, stack) {
print("Plugin getSafParameterForRead error: ${e.message}");
return Future.error("getSafParameterForRead failed.", stack);
}
}
/// Converts the given Structured Access Framework Uri ("content:…") into
/// an output url that can be used in FFmpeg and FFprobe commands.
///
/// Note that this method is Android only. It will fail if called on other
/// platforms. It also requires API Level &ge; 19. On older API levels it
/// returns an empty url.
static Future<String?> getSafParameterForWrite(String uriString) async {
try {
await init();
return _platform.ffmpegKitConfigGetSafParameter(uriString, "w");
} on PlatformException catch (e, stack) {
print("Plugin getSafParameterForWrite error: ${e.message}");
return Future.error("getSafParameterForWrite failed.", stack);
}
}
/// Converts the given Structured Access Framework Uri into an saf protocol
/// url opened with the given open mode.
///
/// Note that this method is Android only. It will fail if called on other
/// platforms. It also requires API Level &ge; 19. On older API levels it
/// returns an empty url.
static Future<String?> getSafParameter(
String uriString, String openMode) async {
try {
await init();
return _platform.ffmpegKitConfigGetSafParameter(uriString, openMode);
} on PlatformException catch (e, stack) {
print("Plugin getSafParameter error: ${e.message}");
return Future.error("getSafParameter failed.", stack);
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019-2021 Taner Sener * Copyright (c) 2019-2022 Taner Sener
* *
* This file is part of FFmpegKit. * This file is part of FFmpegKit.
* *
@ -35,19 +35,14 @@ class FFprobeKit {
/// Synchronously executes FFprobe command provided. Space character is used /// Synchronously executes FFprobe command provided. Space character is used
/// to split command into arguments. You can use single or double quote /// to split command into arguments. You can use single or double quote
/// characters to specify arguments inside your command. /// characters to specify arguments inside your command.
static Future<FFprobeSession> execute(String command, static Future<FFprobeSession> execute(String command) async =>
[FFprobeSessionCompleteCallback? completeCallback = null, FFprobeKit.executeWithArguments(FFmpegKitConfig.parseArguments(command));
LogCallback? logCallback = null]) async =>
FFprobeKit.executeWithArguments(FFmpegKitConfig.parseArguments(command),
completeCallback, logCallback);
/// Synchronously executes FFprobe with arguments provided. /// Synchronously executes FFprobe with arguments provided.
static Future<FFprobeSession> executeWithArguments( static Future<FFprobeSession> executeWithArguments(
List<String> commandArguments, List<String> commandArguments) async {
[FFprobeSessionCompleteCallback? completeCallback = null, final session =
LogCallback? logCallback = null]) async { await FFprobeSession.create(commandArguments, null, null, null);
final session = await FFprobeSession.create(
commandArguments, completeCallback, logCallback, null);
await FFmpegKitConfig.ffprobeExecute(session); await FFmpegKitConfig.ffprobeExecute(session);
@ -85,9 +80,7 @@ class FFprobeKit {
/// Extracts media information for the file specified with path. /// Extracts media information for the file specified with path.
static Future<MediaInformationSession> getMediaInformation(String path, static Future<MediaInformationSession> getMediaInformation(String path,
[MediaInformationSessionCompleteCallback? completeCallback = null, [int? waitTimeout = null]) async {
LogCallback? logCallback = null,
int? waitTimeout = null]) async {
final commandArguments = [ final commandArguments = [
"-v", "-v",
"error", "error",
@ -101,7 +94,7 @@ class FFprobeKit {
path path
]; ];
return FFprobeKit.getMediaInformationFromCommandArguments( return FFprobeKit.getMediaInformationFromCommandArguments(
commandArguments, completeCallback, logCallback, waitTimeout); commandArguments, waitTimeout);
} }
/// Extracts media information using the command provided. The command /// Extracts media information using the command provided. The command
@ -109,28 +102,28 @@ class FFprobeKit {
/// successfully extract media information from it. /// successfully extract media information from it.
static Future<MediaInformationSession> getMediaInformationFromCommand( static Future<MediaInformationSession> getMediaInformationFromCommand(
String command, String command,
[MediaInformationSessionCompleteCallback? completeCallback = null, [int? waitTimeout = null]) async =>
LogCallback? logCallback = null,
int? waitTimeout = null]) async =>
FFprobeKit.getMediaInformationFromCommandArguments( FFprobeKit.getMediaInformationFromCommandArguments(
FFmpegKitConfig.parseArguments(command), FFmpegKitConfig.parseArguments(command), waitTimeout);
completeCallback,
logCallback,
waitTimeout);
/// Extracts media information using the command arguments provided. The /// Extracts media information using the command arguments provided. The
/// command passed to this method must generate the output in JSON format in /// command passed to this method must generate the output in JSON format in
/// order to successfully extract media information from it. /// order to successfully extract media information from it.
static Future<MediaInformationSession> static Future<MediaInformationSession>
getMediaInformationFromCommandArguments(List<String> commandArguments, getMediaInformationFromCommandArguments(List<String> commandArguments,
[MediaInformationSessionCompleteCallback? completeCallback = null, [int? waitTimeout = null]) async {
LogCallback? logCallback = null, final session =
int? waitTimeout = null]) async { await MediaInformationSession.create(commandArguments, null, null);
final session = await MediaInformationSession.create(
commandArguments, completeCallback, logCallback);
await FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout); await FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout);
final mediaInformation = await _platform
.mediaInformationSessionGetMediaInformation(session.getSessionId())
.then(FFmpegKitFactory.mapToNullableMediaInformation);
if (mediaInformation != null) {
session.setMediaInformation(mediaInformation);
}
return session; return session;
} }
@ -193,6 +186,13 @@ class FFprobeKit {
await FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout); await FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout);
final mediaInformation = await _platform
.mediaInformationSessionGetMediaInformation(session.getSessionId())
.then(FFmpegKitFactory.mapToNullableMediaInformation);
if (mediaInformation != null) {
session.setMediaInformation(mediaInformation);
}
return session; return session;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019-2021 Taner Sener * Copyright (c) 2019-2022 Taner Sener
* *
* This file is part of FFmpegKit. * This file is part of FFmpegKit.
* *
@ -24,6 +24,7 @@ import '../ffprobe_session_complete_callback.dart';
import '../log.dart'; import '../log.dart';
import '../log_callback.dart'; import '../log_callback.dart';
import '../log_redirection_strategy.dart'; import '../log_redirection_strategy.dart';
import '../media_information.dart';
import '../media_information_session.dart'; import '../media_information_session.dart';
import '../media_information_session_complete_callback.dart'; import '../media_information_session_complete_callback.dart';
import '../session.dart'; import '../session.dart';
@ -90,7 +91,16 @@ class FFmpegKitFactory {
} }
} }
static String getVersion() => "4.5.0"; static MediaInformation? mapToNullableMediaInformation(
Map<dynamic, dynamic>? mediaInformationMap) {
if (mediaInformationMap != null) {
return new MediaInformation(mediaInformationMap);
} else {
return null;
}
}
static String getVersion() => "4.5.1";
static LogRedirectionStrategy? getLogRedirectionStrategy(int? sessionId) => static LogRedirectionStrategy? getLogRedirectionStrategy(int? sessionId) =>
logRedirectionStrategyMap[sessionId]; logRedirectionStrategyMap[sessionId];

View File

@ -57,7 +57,7 @@ static int const SESSION_TYPE_MEDIA_INFORMATION = 3;
// EVENTS // EVENTS
static NSString *const EVENT_LOG_CALLBACK_EVENT = @"FFmpegKitLogCallbackEvent"; static NSString *const EVENT_LOG_CALLBACK_EVENT = @"FFmpegKitLogCallbackEvent";
static NSString *const EVENT_STATISTICS_CALLBACK_EVENT = @"FFmpegKitStatisticsCallbackEvent"; static NSString *const EVENT_STATISTICS_CALLBACK_EVENT = @"FFmpegKitStatisticsCallbackEvent";
static NSString *const EVENT_EXECUTE_CALLBACK_EVENT = @"FFmpegKitCompleteCallbackEvent"; static NSString *const EVENT_COMPLETE_CALLBACK_EVENT = @"FFmpegKitCompleteCallbackEvent";
// ARGUMENT NAMES // ARGUMENT NAMES
static NSString *const ARGUMENT_SESSION_ID = @"sessionId"; static NSString *const ARGUMENT_SESSION_ID = @"sessionId";
@ -110,9 +110,19 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
} }
- (void)registerGlobalCallbacks { - (void)registerGlobalCallbacks {
[FFmpegKitConfig enableExecuteCallback:^(id<Session> session){ [FFmpegKitConfig enableFFmpegSessionCompleteCallback:^(FFmpegSession* session){
NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session]; NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session];
self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_EXECUTE_CALLBACK_EVENT withDictionary:dictionary]); self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]);
}];
[FFmpegKitConfig enableFFprobeSessionCompleteCallback:^(FFprobeSession* session){
NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session];
self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]);
}];
[FFmpegKitConfig enableMediaInformationSessionCompleteCallback:^(MediaInformationSession* session){
NSDictionary *dictionary = [FFmpegKitFlutterPlugin toSessionDictionary:session];
self->_eventSink([FFmpegKitFlutterPlugin toStringDictionary:EVENT_COMPLETE_CALLBACK_EVENT withDictionary:dictionary]);
}]; }];
[FFmpegKitConfig enableLogCallback: ^(Log* log){ [FFmpegKitConfig enableLogCallback: ^(Log* log){
@ -222,6 +232,12 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
} else { } else {
result([FlutterError errorWithCode:@"INVALID_ARGUMENTS" message:@"Invalid arguments array." details:nil]); result([FlutterError errorWithCode:@"INVALID_ARGUMENTS" message:@"Invalid arguments array." details:nil]);
} }
} else if ([@"getMediaInformation" isEqualToString:call.method]) {
if (sessionId != nil) {
[self getMediaInformation:sessionId result:result];
} else {
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
}
} else if ([@"mediaInformationJsonParserFrom" isEqualToString:call.method]) { } else if ([@"mediaInformationJsonParserFrom" isEqualToString:call.method]) {
if (ffprobeJsonOutput != nil) { if (ffprobeJsonOutput != nil) {
[self mediaInformationJsonParserFrom:ffprobeJsonOutput result:result]; [self mediaInformationJsonParserFrom:ffprobeJsonOutput result:result];
@ -419,6 +435,8 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
[self getFFmpegSessions:result]; [self getFFmpegSessions:result];
} else if ([@"getFFprobeSessions" isEqualToString:call.method]) { } else if ([@"getFFprobeSessions" isEqualToString:call.method]) {
[self getFFprobeSessions:result]; [self getFFprobeSessions:result];
} else if ([@"getMediaInformationSessions" isEqualToString:call.method]) {
[self getMediaInformationSessions:result];
} else if ([@"getPackageName" isEqualToString:call.method]) { } else if ([@"getPackageName" isEqualToString:call.method]) {
[self getPackageName:result]; [self getPackageName:result];
} else if ([@"getExternalLibraries" isEqualToString:call.method]) { } else if ([@"getExternalLibraries" isEqualToString:call.method]) {
@ -545,7 +563,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
// FFmpegSession // FFmpegSession
- (void)ffmpegSession:(NSArray*)arguments result:(FlutterResult)result { - (void)ffmpegSession:(NSArray*)arguments result:(FlutterResult)result {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withStatisticsCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
result([FFmpegKitFlutterPlugin toSessionDictionary:session]); result([FFmpegKitFlutterPlugin toSessionDictionary:session]);
} }
@ -554,7 +572,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[FFmpegSession class]]) { if ([session isFFmpeg]) {
int timeout; int timeout;
if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) { if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) {
timeout = [waitTimeout intValue]; timeout = [waitTimeout intValue];
@ -574,7 +592,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[FFmpegSession class]]) { if ([session isFFmpeg]) {
NSArray* statistics = [(FFmpegSession*)session getStatistics]; NSArray* statistics = [(FFmpegSession*)session getStatistics];
result([FFmpegKitFlutterPlugin toStatisticsArray:statistics]); result([FFmpegKitFlutterPlugin toStatisticsArray:statistics]);
} else { } else {
@ -586,17 +604,31 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
// FFprobeSession // FFprobeSession
- (void)ffprobeSession:(NSArray*)arguments result:(FlutterResult)result { - (void)ffprobeSession:(NSArray*)arguments result:(FlutterResult)result {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
result([FFmpegKitFlutterPlugin toSessionDictionary:session]); result([FFmpegKitFlutterPlugin toSessionDictionary:session]);
} }
// MediaInformationSession // MediaInformationSession
- (void)mediaInformationSession:(NSArray*)arguments result:(FlutterResult)result { - (void)mediaInformationSession:(NSArray*)arguments result:(FlutterResult)result {
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteCallback:nil withLogCallback:nil]; MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:nil withLogCallback:nil];
result([FFmpegKitFlutterPlugin toSessionDictionary:session]); result([FFmpegKitFlutterPlugin toSessionDictionary:session]);
} }
- (void)getMediaInformation:(NSNumber*)sessionId result:(FlutterResult)result {
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:[sessionId longValue]];
if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else {
if ([session isMediaInformation]) {
MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session;
result([FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]);
} else {
result([FlutterError errorWithCode:@"NOT_MEDIA_INFORMATION_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
}
}
}
// MediaInformationJsonParser // MediaInformationJsonParser
- (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result { - (void)mediaInformationJsonParserFrom:(NSString*)ffprobeJsonOutput result:(FlutterResult)result {
@ -733,7 +765,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[FFmpegSession class]]) { if ([session isFFmpeg]) {
dispatch_async(asyncDispatchQueue, ^{ dispatch_async(asyncDispatchQueue, ^{
[FFmpegKitConfig ffmpegExecute:(FFmpegSession*)session]; [FFmpegKitConfig ffmpegExecute:(FFmpegSession*)session];
result(nil); result(nil);
@ -749,7 +781,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[FFprobeSession class]]) { if ([session isFFprobe]) {
dispatch_async(asyncDispatchQueue, ^{ dispatch_async(asyncDispatchQueue, ^{
[FFmpegKitConfig ffprobeExecute:(FFprobeSession*)session]; [FFmpegKitConfig ffprobeExecute:(FFprobeSession*)session];
result(nil); result(nil);
@ -765,7 +797,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[MediaInformationSession class]]) { if ([session isMediaInformation]) {
int timeout; int timeout;
if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) { if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) {
timeout = [waitTimeout intValue]; timeout = [waitTimeout intValue];
@ -787,7 +819,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[FFmpegSession class]]) { if ([session isFFmpeg]) {
[FFmpegKitConfig asyncFFmpegExecute:(FFmpegSession*)session]; [FFmpegKitConfig asyncFFmpegExecute:(FFmpegSession*)session];
result(nil); result(nil);
} else { } else {
@ -801,7 +833,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[FFprobeSession class]]) { if ([session isFFprobe]) {
[FFmpegKitConfig asyncFFprobeExecute:(FFprobeSession*)session]; [FFmpegKitConfig asyncFFprobeExecute:(FFprobeSession*)session];
result(nil); result(nil);
} else { } else {
@ -815,7 +847,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
if (session == nil) { if (session == nil) {
result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]); result([FlutterError errorWithCode:@"SESSION_NOT_FOUND" message:@"Session not found." details:nil]);
} else { } else {
if ([session isMemberOfClass:[MediaInformationSession class]]) { if ([session isMediaInformation]) {
int timeout; int timeout;
if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) { if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) {
timeout = [waitTimeout intValue]; timeout = [waitTimeout intValue];
@ -1007,7 +1039,11 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
// FFprobeKit // FFprobeKit
- (void)getFFprobeSessions:(FlutterResult)result { - (void)getFFprobeSessions:(FlutterResult)result {
result([FFmpegKitFlutterPlugin toSessionArray:[FFprobeKit listSessions]]); result([FFmpegKitFlutterPlugin toSessionArray:[FFprobeKit listFFprobeSessions]]);
}
- (void)getMediaInformationSessions:(FlutterResult)result {
result([FFmpegKitFlutterPlugin toSessionArray:[FFprobeKit listMediaInformationSessions]]);
} }
// Packages // Packages
@ -1045,16 +1081,14 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithLong:[[session getStartTime] timeIntervalSince1970]*1000]; dictionary[KEY_SESSION_START_TIME] = [NSNumber numberWithLong:[[session getStartTime] timeIntervalSince1970]*1000];
dictionary[KEY_SESSION_COMMAND] = [session getCommand]; dictionary[KEY_SESSION_COMMAND] = [session getCommand];
if ([session isFFprobe]) { if ([session isFFmpeg]) {
if ([(AbstractSession*)session isMemberOfClass:[MediaInformationSession class]]) { dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG];
} else if ([session isFFprobe]) {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE];
} else if ([session isMediaInformation]) {
MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session; MediaInformationSession *mediaInformationSession = (MediaInformationSession*)session;
dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]]; dictionary[KEY_SESSION_MEDIA_INFORMATION] = [FFmpegKitFlutterPlugin toMediaInformationDictionary:[mediaInformationSession getMediaInformation]];
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION]; dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_MEDIA_INFORMATION];
} else {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFPROBE];
}
} else {
dictionary[KEY_SESSION_TYPE] = [NSNumber numberWithInt:SESSION_TYPE_FFMPEG];
} }
return dictionary; return dictionary;

View File

@ -21,7 +21,7 @@ flutter:
pluginClass: FFmpegKitFlutterPlugin pluginClass: FFmpegKitFlutterPlugin
dependencies: dependencies:
ffmpeg_kit_flutter_platform_interface: ^0.1.1 ffmpeg_kit_flutter_platform_interface: ^0.2.0
flutter: flutter:
sdk: flutter sdk: flutter

View File

@ -1,2 +1,8 @@
## 0.2.0
- Implements execute methods
- Merges existing getSafParameter methods into a single method with a new openMode parameter
- Adds list media information sessions methods to FFprobeKit
- Adds getMediaInformation method
## 0.1.0 ## 0.1.0
- Initial release - Initial release

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Taner Sener * Copyright (c) 2021-2022 Taner Sener
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -382,6 +382,12 @@ abstract class FFmpegKitPlatform extends PlatformInterface {
'mediaInformationJsonParserFromWithError() has not been implemented!'); 'mediaInformationJsonParserFromWithError() has not been implemented!');
} }
Future<Map<dynamic, dynamic>?> mediaInformationSessionGetMediaInformation(
int? sessionId) async {
throw UnimplementedError('mediaInformationSessionGetMediaInformation() '
'has not been implemented!');
}
Future<String?> getPackageName() async { Future<String?> getPackageName() async {
throw UnimplementedError('getPackageName() has not been implemented!'); throw UnimplementedError('getPackageName() has not been implemented!');
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Taner Sener * Copyright (c) 2021-2022 Taner Sener
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -99,13 +99,14 @@ class MethodChannelFFmpegKit extends FFmpegKitPlatform {
int? sessionId) async => int? sessionId) async =>
_channel.invokeMethod<bool>( _channel.invokeMethod<bool>(
'abstractSessionThereAreAsynchronousMessagesInTransmit', 'abstractSessionThereAreAsynchronousMessagesInTransmit',
{'sessionId': sessionId}).then((value) => value ?? false); {'sessionId': sessionId}).then((bool? value) => value ?? false);
// ArchDetect // ArchDetect
@override @override
Future<String> archDetectGetArch() async => Future<String> archDetectGetArch() async => _channel
_channel.invokeMethod<String>('getArch').then((value) => value ?? ""); .invokeMethod<String>('getArch')
.then((String? value) => value ?? "");
// FFmpegKit // FFmpegKit
@ -180,14 +181,12 @@ class MethodChannelFFmpegKit extends FFmpegKitPlatform {
_channel.invokeMethod<void>('ignoreSignal', {'signal': signal}); _channel.invokeMethod<void>('ignoreSignal', {'signal': signal});
@override @override
Future<void> ffmpegKitConfigFFmpegExecute(int? sessionId) async => Future<void> ffmpegKitConfigFFmpegExecute(int? sessionId) async => _channel
_channel.invokeMethod<void>( .invokeMethod<void>('ffmpegSessionExecute', {'sessionId': sessionId});
'ffmpegSessionExecute', {'sessionId': sessionId});
@override @override
Future<void> ffmpegKitConfigFFprobeExecute(int? sessionId) async => Future<void> ffmpegKitConfigFFprobeExecute(int? sessionId) async => _channel
_channel.invokeMethod<void>( .invokeMethod<void>('ffprobeSessionExecute', {'sessionId': sessionId});
'ffprobeSessionExecute', {'sessionId': sessionId});
@override @override
Future<void> ffmpegKitConfigGetMediaInformationExecute( Future<void> ffmpegKitConfigGetMediaInformationExecute(
@ -351,6 +350,14 @@ class MethodChannelFFmpegKit extends FFmpegKitPlatform {
'mediaInformationJsonParserFromWithError', 'mediaInformationJsonParserFromWithError',
{'ffprobeJsonOutput': ffprobeJsonOutput}); {'ffprobeJsonOutput': ffprobeJsonOutput});
// MediaInformationSession
@override
Future<Map<dynamic, dynamic>?> mediaInformationSessionGetMediaInformation(
int? sessionId) async =>
_channel.invokeMethod<Map<dynamic, dynamic>>(
'getMediaInformation(', {'sessionId': sessionId});
@override @override
Future<String?> getPackageName() async => Future<String?> getPackageName() async =>
_channel.invokeMethod<String>('getPackageName'); _channel.invokeMethod<String>('getPackageName');

View File

@ -5,7 +5,7 @@ issue_tracker: https://github.com/tanersener/ffmpeg-kit/issues
homepage: https://github.com/tanersener/ffmpeg-kit homepage: https://github.com/tanersener/ffmpeg-kit
# NOTE: We strongly prefer non-breaking changes, even at the expense of a # NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
version: 0.1.0 version: 0.2.0
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"