implement execute methods for flutter
This commit is contained in:
parent
0b45c3e101
commit
9b34c7215f
|
@ -127,11 +127,11 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
|
|||
public static final String ARGUMENT_FFPROBE_JSON_OUTPUT = "ffprobeJsonOutput";
|
||||
public static final String ARGUMENT_WRITABLE = "writable";
|
||||
|
||||
private static final int asyncWriteToPipeConcurrencyLimit = 10;
|
||||
private static final int asyncConcurrencyLimit = 10;
|
||||
|
||||
private final AtomicBoolean logsEnabled;
|
||||
private final AtomicBoolean statisticsEnabled;
|
||||
private final ExecutorService asyncWriteToPipeExecutorService;
|
||||
private final ExecutorService asyncExecutorService;
|
||||
|
||||
private MethodChannel methodChannel;
|
||||
private EventChannel eventChannel;
|
||||
|
@ -147,7 +147,7 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
|
|||
public FFmpegKitFlutterPlugin() {
|
||||
this.logsEnabled = new AtomicBoolean(false);
|
||||
this.statisticsEnabled = new AtomicBoolean(false);
|
||||
this.asyncWriteToPipeExecutorService = Executors.newFixedThreadPool(asyncWriteToPipeConcurrencyLimit);
|
||||
this.asyncExecutorService = Executors.newFixedThreadPool(asyncConcurrencyLimit);
|
||||
this.resultHandler = new FFmpegKitFlutterMethodResultHandler();
|
||||
|
||||
Log.d(LIBRARY_NAME, String.format("FFmpegKitFlutterPlugin created %s.", this));
|
||||
|
@ -457,6 +457,27 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
|
|||
resultHandler.errorAsync(result, "INVALID_SIGNAL", "Invalid signal value.");
|
||||
}
|
||||
break;
|
||||
case "ffmpegSessionExecute":
|
||||
if (sessionId != null) {
|
||||
ffmpegSessionExecute(sessionId, result);
|
||||
} else {
|
||||
resultHandler.errorAsync(result, "INVALID_SESSION", "Invalid session id.");
|
||||
}
|
||||
break;
|
||||
case "ffprobeSessionExecute":
|
||||
if (sessionId != null) {
|
||||
ffprobeSessionExecute(sessionId, result);
|
||||
} else {
|
||||
resultHandler.errorAsync(result, "INVALID_SESSION", "Invalid session id.");
|
||||
}
|
||||
break;
|
||||
case "mediaInformationSessionExecute":
|
||||
if (sessionId != null) {
|
||||
mediaInformationSessionExecute(sessionId, waitTimeout, result);
|
||||
} else {
|
||||
resultHandler.errorAsync(result, "INVALID_SESSION", "Invalid session id.");
|
||||
}
|
||||
break;
|
||||
case "asyncFFmpegSessionExecute":
|
||||
if (sessionId != null) {
|
||||
asyncFFmpegSessionExecute(sessionId, result);
|
||||
|
@ -994,6 +1015,54 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
|
|||
}
|
||||
}
|
||||
|
||||
protected void ffmpegSessionExecute(@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 instanceof FFmpegSession) {
|
||||
final FFmpegSessionExecuteTask ffmpegSessionExecuteTask = new FFmpegSessionExecuteTask((FFmpegSession) session, resultHandler, result);
|
||||
asyncExecutorService.submit(ffmpegSessionExecuteTask);
|
||||
} else {
|
||||
resultHandler.errorAsync(result, "NOT_FFMPEG_SESSION", "A session is found but it does not have the correct type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ffprobeSessionExecute(@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 instanceof FFprobeSession) {
|
||||
final FFprobeSessionExecuteTask ffprobeSessionExecuteTask = new FFprobeSessionExecuteTask((FFprobeSession) session, resultHandler, result);
|
||||
asyncExecutorService.submit(ffprobeSessionExecuteTask);
|
||||
} else {
|
||||
resultHandler.errorAsync(result, "NOT_FFPROBE_SESSION", "A session is found but it does not have the correct type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void mediaInformationSessionExecute(@NonNull final Integer sessionId, @Nullable final Integer waitTimeout, @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 instanceof MediaInformationSession) {
|
||||
final int timeout;
|
||||
if (isValidPositiveNumber(waitTimeout)) {
|
||||
timeout = waitTimeout;
|
||||
} else {
|
||||
timeout = AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT;
|
||||
}
|
||||
final MediaInformationSessionExecuteTask mediaInformationSessionExecuteTask = new MediaInformationSessionExecuteTask((MediaInformationSession) session, timeout, resultHandler, result);
|
||||
asyncExecutorService.submit(mediaInformationSessionExecuteTask);
|
||||
} else {
|
||||
resultHandler.errorAsync(result, "NOT_MEDIA_INFORMATION_SESSION", "A session is found but it does not have the correct type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void asyncFFmpegSessionExecute(@NonNull final Integer sessionId, @NonNull final Result result) {
|
||||
final Session session = FFmpegKitConfig.getSession(sessionId.longValue());
|
||||
if (session == null) {
|
||||
|
@ -1110,8 +1179,8 @@ public class FFmpegKitFlutterPlugin implements FlutterPlugin, ActivityAware, Met
|
|||
}
|
||||
|
||||
protected void writeToPipe(@NonNull final String inputPath, @NonNull final String namedPipePath, @NonNull final Result result) {
|
||||
final AsyncWriteToPipeTask asyncTask = new AsyncWriteToPipeTask(inputPath, namedPipePath, resultHandler, result);
|
||||
asyncWriteToPipeExecutorService.submit(asyncTask);
|
||||
final WriteToPipeTask asyncTask = new WriteToPipeTask(inputPath, namedPipePath, resultHandler, result);
|
||||
asyncExecutorService.submit(asyncTask);
|
||||
}
|
||||
|
||||
protected void selectDocument(@NonNull final Boolean writable, @Nullable final String title, @Nullable final String type, @Nullable final String[] extraTypes, @NonNull final Result result) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 Public 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 Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.ffmpegkit.flutter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.arthenica.ffmpegkit.FFmpegKitConfig;
|
||||
import com.arthenica.ffmpegkit.FFmpegSession;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class FFmpegSessionExecuteTask implements Runnable {
|
||||
private final FFmpegSession ffmpegSession;
|
||||
private final FFmpegKitFlutterMethodResultHandler resultHandler;
|
||||
private final MethodChannel.Result result;
|
||||
|
||||
public FFmpegSessionExecuteTask(@NonNull final FFmpegSession ffmpegSession, @NonNull final FFmpegKitFlutterMethodResultHandler resultHandler, @NonNull final MethodChannel.Result result) {
|
||||
this.ffmpegSession = ffmpegSession;
|
||||
this.resultHandler = resultHandler;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FFmpegKitConfig.ffmpegExecute(ffmpegSession);
|
||||
resultHandler.successAsync(result, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 Public 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 Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.ffmpegkit.flutter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.arthenica.ffmpegkit.FFmpegKitConfig;
|
||||
import com.arthenica.ffmpegkit.FFprobeSession;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class FFprobeSessionExecuteTask implements Runnable {
|
||||
private final FFprobeSession ffprobeSession;
|
||||
private final FFmpegKitFlutterMethodResultHandler resultHandler;
|
||||
private final MethodChannel.Result result;
|
||||
|
||||
public FFprobeSessionExecuteTask(@NonNull final FFprobeSession ffprobeSession, @NonNull final FFmpegKitFlutterMethodResultHandler resultHandler, @NonNull final MethodChannel.Result result) {
|
||||
this.ffprobeSession = ffprobeSession;
|
||||
this.resultHandler = resultHandler;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FFmpegKitConfig.ffprobeExecute(ffprobeSession);
|
||||
resultHandler.successAsync(result, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 Public 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 Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.ffmpegkit.flutter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.arthenica.ffmpegkit.FFmpegKitConfig;
|
||||
import com.arthenica.ffmpegkit.MediaInformationSession;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class MediaInformationSessionExecuteTask implements Runnable {
|
||||
private final MediaInformationSession mediaInformationSession;
|
||||
private final int timeout;
|
||||
private final FFmpegKitFlutterMethodResultHandler resultHandler;
|
||||
private final MethodChannel.Result result;
|
||||
|
||||
public MediaInformationSessionExecuteTask(@NonNull final MediaInformationSession mediaInformationSession, final int timeout, @NonNull final FFmpegKitFlutterMethodResultHandler resultHandler, @NonNull final MethodChannel.Result result) {
|
||||
this.mediaInformationSession = mediaInformationSession;
|
||||
this.timeout = timeout;
|
||||
this.resultHandler = resultHandler;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, timeout);
|
||||
resultHandler.successAsync(result, null);
|
||||
}
|
||||
}
|
|
@ -29,13 +29,13 @@ import java.io.IOException;
|
|||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class AsyncWriteToPipeTask implements Runnable {
|
||||
public class WriteToPipeTask implements Runnable {
|
||||
private final String inputPath;
|
||||
private final String namedPipePath;
|
||||
private final FFmpegKitFlutterMethodResultHandler resultHandler;
|
||||
private final MethodChannel.Result result;
|
||||
|
||||
public AsyncWriteToPipeTask(@NonNull final String inputPath, @NonNull final String namedPipePath, @NonNull final FFmpegKitFlutterMethodResultHandler resultHandler, @NonNull final MethodChannel.Result result) {
|
||||
public WriteToPipeTask(@NonNull final String inputPath, @NonNull final String namedPipePath, @NonNull final FFmpegKitFlutterMethodResultHandler resultHandler, @NonNull final MethodChannel.Result result) {
|
||||
this.inputPath = inputPath;
|
||||
this.namedPipePath = namedPipePath;
|
||||
this.resultHandler = resultHandler;
|
|
@ -71,7 +71,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
FlutterEventSink _eventSink;
|
||||
BOOL logsEnabled;
|
||||
BOOL statisticsEnabled;
|
||||
dispatch_queue_t asyncWriteToPipeDispatchQueue;
|
||||
dispatch_queue_t asyncDispatchQueue;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
|
@ -79,7 +79,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
if (self) {
|
||||
logsEnabled = false;
|
||||
statisticsEnabled = false;
|
||||
asyncWriteToPipeDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
asyncDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
|
||||
NSLog(@"FFmpegKitFlutterPlugin %p created.\n", self);
|
||||
}
|
||||
|
@ -301,6 +301,24 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SIGNAL" message:@"Invalid signal value." details:nil]);
|
||||
}
|
||||
} else if ([@"ffmpegSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self ffmpegSessionExecute:sessionId result:result];
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
|
||||
}
|
||||
} else if ([@"ffprobeSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self ffprobeSessionExecute:sessionId result:result];
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
|
||||
}
|
||||
} else if ([@"mediaInformationSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self mediaInformationSessionExecute:sessionId timeout:waitTimeout result:result];
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
|
||||
}
|
||||
} else if ([@"asyncFFmpegSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self asyncFFmpegSessionExecute:sessionId result:result];
|
||||
|
@ -710,6 +728,60 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)ffmpegSessionExecute:(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 isMemberOfClass:[FFmpegSession class]]) {
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
[FFmpegKitConfig ffmpegExecute:(FFmpegSession*)session];
|
||||
result(nil);
|
||||
});
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"NOT_FFMPEG_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)ffprobeSessionExecute:(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 isMemberOfClass:[FFprobeSession class]]) {
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
[FFmpegKitConfig ffprobeExecute:(FFprobeSession*)session];
|
||||
result(nil);
|
||||
});
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"NOT_FFPROBE_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mediaInformationSessionExecute:(NSNumber*)sessionId timeout:(NSNumber*)waitTimeout 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 isMemberOfClass:[MediaInformationSession class]]) {
|
||||
int timeout;
|
||||
if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) {
|
||||
timeout = [waitTimeout intValue];
|
||||
} else {
|
||||
timeout = AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
||||
}
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
[FFmpegKitConfig getMediaInformationExecute:(MediaInformationSession*)session withTimeout:timeout];
|
||||
result(nil);
|
||||
});
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"NOT_MEDIA_INFORMATION_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)asyncFFmpegSessionExecute:(NSNumber*)sessionId result:(FlutterResult)result {
|
||||
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:[sessionId longValue]];
|
||||
if (session == nil) {
|
||||
|
@ -854,7 +926,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
}
|
||||
|
||||
- (void)writeToPipe:(NSString*)inputPath pipe:(NSString*)namedPipePath result:(FlutterResult)result {
|
||||
dispatch_async(asyncWriteToPipeDispatchQueue, ^{
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
|
||||
NSLog(@"Starting copy %@ to pipe %@ operation.\n", inputPath, namedPipePath);
|
||||
|
||||
|
|
|
@ -31,6 +31,33 @@ import 'statistics_callback.dart';
|
|||
class FFmpegKit {
|
||||
static FFmpegKitPlatform _platform = FFmpegKitPlatform.instance;
|
||||
|
||||
/// Synchronously executes FFmpeg command provided. Space character is used
|
||||
/// to split command into arguments. You can use single or double quote
|
||||
/// characters to specify arguments inside your command.
|
||||
static Future<FFmpegSession> execute(String command,
|
||||
[ExecuteCallback? executeCallback = null,
|
||||
LogCallback? logCallback = null,
|
||||
StatisticsCallback? statisticsCallback = null]) async =>
|
||||
FFmpegKit.executeWithArguments(
|
||||
FFmpegKitConfig.parseArguments(command),
|
||||
executeCallback,
|
||||
logCallback,
|
||||
statisticsCallback);
|
||||
|
||||
/// Synchronously executes FFmpeg with arguments provided.
|
||||
static Future<FFmpegSession> executeWithArguments(
|
||||
List<String> commandArguments,
|
||||
[ExecuteCallback? executeCallback = null,
|
||||
LogCallback? logCallback = null,
|
||||
StatisticsCallback? statisticsCallback = null]) async {
|
||||
final session = await FFmpegSession.create(commandArguments,
|
||||
executeCallback, logCallback, statisticsCallback, null);
|
||||
|
||||
await FFmpegKitConfig.ffmpegExecute(session);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/// Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
|
||||
/// into arguments. You can use single or double quote characters to specify arguments inside your command.
|
||||
///
|
||||
|
|
|
@ -215,6 +215,44 @@ class FFmpegKitConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// Synchronously executes the FFmpeg session provided.
|
||||
static Future<void> ffmpegExecute(FFmpegSession ffmpegSession) async {
|
||||
try {
|
||||
await init();
|
||||
return _platform
|
||||
.ffmpegKitConfigFFmpegExecute(ffmpegSession.getSessionId());
|
||||
} on PlatformException catch (e, stack) {
|
||||
print("Plugin ffmpegExecute error: ${e.message}");
|
||||
return Future.error("ffmpegExecute failed.", stack);
|
||||
}
|
||||
}
|
||||
|
||||
/// Synchronously executes the FFprobe session provided.
|
||||
static Future<void> ffprobeExecute(FFprobeSession ffprobeSession) async {
|
||||
try {
|
||||
await init();
|
||||
return _platform
|
||||
.ffmpegKitConfigFFprobeExecute(ffprobeSession.getSessionId());
|
||||
} on PlatformException catch (e, stack) {
|
||||
print("Plugin ffprobeExecute error: ${e.message}");
|
||||
return Future.error("ffprobeExecute failed.", stack);
|
||||
}
|
||||
}
|
||||
|
||||
/// Synchronously executes the media information session provided.
|
||||
static Future<void> getMediaInformationExecute(
|
||||
MediaInformationSession mediaInformationSession,
|
||||
[int? waitTimeout = null]) async {
|
||||
try {
|
||||
await init();
|
||||
return _platform.ffmpegKitConfigGetMediaInformationExecute(
|
||||
mediaInformationSession.getSessionId(), waitTimeout);
|
||||
} on PlatformException catch (e, stack) {
|
||||
print("Plugin getMediaInformationExecute error: ${e.message}");
|
||||
return Future.error("getMediaInformationExecute failed.", stack);
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts an asynchronous FFmpeg execution for the given session.
|
||||
///
|
||||
/// Note that this method returns immediately and does not wait the execution to complete. You must use an
|
||||
|
|
|
@ -31,6 +31,30 @@ import 'src/ffmpeg_kit_factory.dart';
|
|||
class FFprobeKit {
|
||||
static FFmpegKitPlatform _platform = FFmpegKitPlatform.instance;
|
||||
|
||||
/// Synchronously executes FFprobe command provided. Space character is used
|
||||
/// to split command into arguments. You can use single or double quote
|
||||
/// characters to specify arguments inside your command.
|
||||
static Future<FFprobeSession> execute(String command,
|
||||
[ExecuteCallback? executeCallback = null,
|
||||
LogCallback? logCallback = null]) async =>
|
||||
FFprobeKit.executeWithArguments(
|
||||
FFmpegKitConfig.parseArguments(command),
|
||||
executeCallback,
|
||||
logCallback);
|
||||
|
||||
/// Synchronously executes FFprobe with arguments provided.
|
||||
static Future<FFprobeSession> executeWithArguments(
|
||||
List<String> commandArguments,
|
||||
[ExecuteCallback? executeCallback = null,
|
||||
LogCallback? logCallback = null]) async {
|
||||
final session = await FFprobeSession.create(
|
||||
commandArguments, executeCallback, logCallback, null);
|
||||
|
||||
await FFmpegKitConfig.ffprobeExecute(session);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/// Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
|
||||
/// into arguments. You can use single or double quote characters to specify arguments inside your command.
|
||||
///
|
||||
|
@ -60,6 +84,58 @@ class FFprobeKit {
|
|||
return session;
|
||||
}
|
||||
|
||||
/// Extracts media information for the file specified with path.
|
||||
static Future<MediaInformationSession> getMediaInformation(String path,
|
||||
[ExecuteCallback? executeCallback = null,
|
||||
LogCallback? logCallback = null,
|
||||
int? waitTimeout = null]) async {
|
||||
final commandArguments = [
|
||||
"-v",
|
||||
"error",
|
||||
"-hide_banner",
|
||||
"-print_format",
|
||||
"json",
|
||||
"-show_format",
|
||||
"-show_streams",
|
||||
"-show_chapters",
|
||||
"-i",
|
||||
path
|
||||
];
|
||||
return FFprobeKit.getMediaInformationFromCommandArguments(
|
||||
commandArguments, executeCallback, logCallback, waitTimeout);
|
||||
}
|
||||
|
||||
/// Extracts media information using the command provided. The command
|
||||
/// passed to this method must generate the output in JSON format in order to
|
||||
/// successfully extract media information from it.
|
||||
static Future<MediaInformationSession> getMediaInformationFromCommand(
|
||||
String command,
|
||||
[ExecuteCallback? executeCallback = null,
|
||||
LogCallback? logCallback = null,
|
||||
int? waitTimeout = null]) async =>
|
||||
FFprobeKit.getMediaInformationFromCommandArguments(
|
||||
FFmpegKitConfig.parseArguments(command),
|
||||
executeCallback,
|
||||
logCallback,
|
||||
waitTimeout);
|
||||
|
||||
/// Extracts media information using the command arguments provided. The
|
||||
/// command passed to this method must generate the output in JSON format in
|
||||
/// order to successfully extract media information from it.
|
||||
static Future<MediaInformationSession>
|
||||
getMediaInformationFromCommandArguments(
|
||||
List<String> commandArguments,
|
||||
[ExecuteCallback? executeCallback = null,
|
||||
LogCallback? logCallback = null,
|
||||
int? waitTimeout = null]) async {
|
||||
final session = await MediaInformationSession.create(
|
||||
commandArguments, executeCallback, logCallback);
|
||||
|
||||
await FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/// Starts an asynchronous FFprobe execution to extract the media information for the specified file.
|
||||
///
|
||||
/// Note that this method returns immediately and does not wait the execution to complete. You must use an
|
||||
|
@ -100,12 +176,14 @@ class FFprobeKit {
|
|||
logCallback,
|
||||
waitTimeout);
|
||||
|
||||
/// Starts an asynchronous FFprobe execution to extract media information using command arguments. The command
|
||||
/// passed to this method must generate the output in JSON format in order to successfully extract media information
|
||||
/// from it.
|
||||
/// Starts an asynchronous FFprobe execution to extract media information
|
||||
/// using command arguments. The command passed to this method must generate
|
||||
/// the output in JSON format in order to successfully extract media
|
||||
/// information from it.
|
||||
///
|
||||
/// Note that this method returns immediately and does not wait the execution to complete. You must use an
|
||||
/// [ExecuteCallback] if you want to be notified about the result.
|
||||
/// Note that this method returns immediately and does not wait the execution
|
||||
/// to complete. You must use an [ExecuteCallback] if you want to be
|
||||
/// notified about the result.
|
||||
static Future<MediaInformationSession>
|
||||
getMediaInformationFromCommandArgumentsAsync(
|
||||
List<String> commandArguments,
|
||||
|
|
|
@ -71,7 +71,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
FlutterEventSink _eventSink;
|
||||
BOOL logsEnabled;
|
||||
BOOL statisticsEnabled;
|
||||
dispatch_queue_t asyncWriteToPipeDispatchQueue;
|
||||
dispatch_queue_t asyncDispatchQueue;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
|
@ -79,7 +79,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
if (self) {
|
||||
logsEnabled = false;
|
||||
statisticsEnabled = false;
|
||||
asyncWriteToPipeDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
asyncDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
|
||||
NSLog(@"FFmpegKitFlutterPlugin %p created.\n", self);
|
||||
}
|
||||
|
@ -301,6 +301,24 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SIGNAL" message:@"Invalid signal value." details:nil]);
|
||||
}
|
||||
} else if ([@"ffmpegSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self ffmpegSessionExecute:sessionId result:result];
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
|
||||
}
|
||||
} else if ([@"ffprobeSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self ffprobeSessionExecute:sessionId result:result];
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
|
||||
}
|
||||
} else if ([@"mediaInformationSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self mediaInformationSessionExecute:sessionId timeout:waitTimeout result:result];
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"INVALID_SESSION" message:@"Invalid session id." details:nil]);
|
||||
}
|
||||
} else if ([@"asyncFFmpegSessionExecute" isEqualToString:call.method]) {
|
||||
if (sessionId != nil) {
|
||||
[self asyncFFmpegSessionExecute:sessionId result:result];
|
||||
|
@ -710,6 +728,60 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)ffmpegSessionExecute:(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 isMemberOfClass:[FFmpegSession class]]) {
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
[FFmpegKitConfig ffmpegExecute:(FFmpegSession*)session];
|
||||
result(nil);
|
||||
});
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"NOT_FFMPEG_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)ffprobeSessionExecute:(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 isMemberOfClass:[FFprobeSession class]]) {
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
[FFmpegKitConfig ffprobeExecute:(FFprobeSession*)session];
|
||||
result(nil);
|
||||
});
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"NOT_FFPROBE_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mediaInformationSessionExecute:(NSNumber*)sessionId timeout:(NSNumber*)waitTimeout 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 isMemberOfClass:[MediaInformationSession class]]) {
|
||||
int timeout;
|
||||
if ([FFmpegKitFlutterPlugin isValidPositiveNumber:waitTimeout]) {
|
||||
timeout = [waitTimeout intValue];
|
||||
} else {
|
||||
timeout = AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
||||
}
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
[FFmpegKitConfig getMediaInformationExecute:(MediaInformationSession*)session withTimeout:timeout];
|
||||
result(nil);
|
||||
});
|
||||
} else {
|
||||
result([FlutterError errorWithCode:@"NOT_MEDIA_INFORMATION_SESSION" message:@"A session is found but it does not have the correct type." details:nil]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)asyncFFmpegSessionExecute:(NSNumber*)sessionId result:(FlutterResult)result {
|
||||
AbstractSession* session = (AbstractSession*)[FFmpegKitConfig getSession:[sessionId longValue]];
|
||||
if (session == nil) {
|
||||
|
@ -854,7 +926,7 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
|
|||
}
|
||||
|
||||
- (void)writeToPipe:(NSString*)inputPath pipe:(NSString*)namedPipePath result:(FlutterResult)result {
|
||||
dispatch_async(asyncWriteToPipeDispatchQueue, ^{
|
||||
dispatch_async(asyncDispatchQueue, ^{
|
||||
|
||||
NSLog(@"Starting copy %@ to pipe %@ operation.\n", inputPath, namedPipePath);
|
||||
|
||||
|
|
|
@ -218,6 +218,22 @@ abstract class FFmpegKitPlatform extends PlatformInterface {
|
|||
' has not been implemented!');
|
||||
}
|
||||
|
||||
Future<void> ffmpegKitConfigFFmpegExecute(int? sessionId) async {
|
||||
throw UnimplementedError(
|
||||
'ffmpegKitConfigFFmpegExecute() has not been implemented!');
|
||||
}
|
||||
|
||||
Future<void> ffmpegKitConfigFFprobeExecute(int? sessionId) async {
|
||||
throw UnimplementedError(
|
||||
'ffmpegKitConfigFFprobeExecute() has not been implemented!');
|
||||
}
|
||||
|
||||
Future<void> ffmpegKitConfigGetMediaInformationExecute(
|
||||
int? sessionId, int? waitTimeout) async {
|
||||
throw UnimplementedError('ffmpegKitConfigGetMediaInformationExecute()'
|
||||
' has not been implemented!');
|
||||
}
|
||||
|
||||
Future<void> ffmpegKitConfigSetLogLevel(int logLevel) async {
|
||||
throw UnimplementedError(
|
||||
'ffmpegKitConfigSetLogLevel() has not been implemented!');
|
||||
|
|
|
@ -179,6 +179,22 @@ class MethodChannelFFmpegKit extends FFmpegKitPlatform {
|
|||
Future<void> ffmpegKitConfigIgnoreSignal(int signal) async =>
|
||||
_channel.invokeMethod<void>('ignoreSignal', {'signal': signal});
|
||||
|
||||
@override
|
||||
Future<void> ffmpegKitConfigFFmpegExecute(int? sessionId) async =>
|
||||
_channel.invokeMethod<void>(
|
||||
'ffmpegSessionExecute', {'sessionId': sessionId});
|
||||
|
||||
@override
|
||||
Future<void> ffmpegKitConfigFFprobeExecute(int? sessionId) async =>
|
||||
_channel.invokeMethod<void>(
|
||||
'ffprobeSessionExecute', {'sessionId': sessionId});
|
||||
|
||||
@override
|
||||
Future<void> ffmpegKitConfigGetMediaInformationExecute(
|
||||
int? sessionId, int? waitTimeout) async =>
|
||||
_channel.invokeMethod<void>('mediaInformationSessionExecute',
|
||||
{'sessionId': sessionId, 'waitTimeout': waitTimeout});
|
||||
|
||||
@override
|
||||
Future<void> ffmpegKitConfigAsyncFFmpegExecute(int? sessionId) async =>
|
||||
_channel.invokeMethod<void>(
|
||||
|
|
Loading…
Reference in New Issue
Block a user