diff --git a/README.md b/README.md index 844940e..be36346 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ Test applications are tagged with `ffmpeg-kit` release they depend on. | Platform | FFmpegKit Version | Tag | | :----: |:-----------------:|:----------------------------------------------------------------------------------:| +| Flutter | 4.5.1 | [4.5.1](https://github.com/tanersener/ffmpeg-kit-test/tree/flutter.v4.5.1) | +| Flutter | 4.5.1-LTS | [4.5.1-LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/flutter.v4.5.1.lts) | | React Native | 4.5.1 | [4.5.1](https://github.com/tanersener/ffmpeg-kit-test/tree/react.native.v4.5.1) | | Android | 4.5.1 | [4.5.1](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5.1) | | Android | 4.5.1.LTS | [4.5.1.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5.1.lts) | diff --git a/flutter/test-app-local-dependency/ios/Podfile.lock b/flutter/test-app-local-dependency/ios/Podfile.lock index dcea1e6..b9d1cc6 100644 --- a/flutter/test-app-local-dependency/ios/Podfile.lock +++ b/flutter/test-app-local-dependency/ios/Podfile.lock @@ -1,10 +1,10 @@ PODS: - - ffmpeg-kit-ios-https (4.5) - - ffmpeg_kit_flutter (4.5.0): - - ffmpeg_kit_flutter/https (= 4.5.0) + - ffmpeg-kit-ios-https (4.5.1) + - ffmpeg_kit_flutter (4.5.1): + - ffmpeg_kit_flutter/https (= 4.5.1) - Flutter - - ffmpeg_kit_flutter/https (4.5.0): - - ffmpeg-kit-ios-https (= 4.5) + - ffmpeg_kit_flutter/https (4.5.1): + - ffmpeg-kit-ios-https (= 4.5.1) - Flutter - Flutter (1.0.0) - fluttertoast (0.0.2): @@ -41,8 +41,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/video_player/ios" SPEC CHECKSUMS: - ffmpeg-kit-ios-https: f7f34d0e0000a01dbc678f615588330ef1e23cc6 - ffmpeg_kit_flutter: a2f609d248cd61728aac6213af8a69449d482cf8 + ffmpeg-kit-ios-https: cec24d405b511e4f274980d8a9c751d384f89558 + ffmpeg_kit_flutter: e2f0bd6b75e361faeee3b34c70650d3ec6ec35d0 Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a fluttertoast: 6122fa75143e992b1d3470f61000f591a798cc58 path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de diff --git a/flutter/test-app-local-dependency/ios/Runner.xcodeproj/project.pbxproj b/flutter/test-app-local-dependency/ios/Runner.xcodeproj/project.pbxproj index 1e701bd..fb26ada 100644 --- a/flutter/test-app-local-dependency/ios/Runner.xcodeproj/project.pbxproj +++ b/flutter/test-app-local-dependency/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ @@ -150,6 +150,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 47E9AAF8724B27176BE2FBDD /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -166,7 +167,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -243,6 +244,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 47E9AAF8724B27176BE2FBDD /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -350,7 +368,10 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.flutter.FFmpegKitFlutter; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; @@ -470,7 +491,10 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.flutter.FFmpegKitFlutter; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; @@ -485,7 +509,10 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.flutter.FFmpegKitFlutter; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; diff --git a/flutter/test-app-local-dependency/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter/test-app-local-dependency/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..3db53b6 100644 --- a/flutter/test-app-local-dependency/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/flutter/test-app-local-dependency/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ streams = information.getStreams(); - for (var i = 0; i < streams.length; ++i) { - StreamInformation stream = streams[i]; - if (stream.getIndex() != null) { - this.appendOutput("Stream index: ${stream.getIndex()}\n"); - } - if (stream.getType() != null) { - this.appendOutput("Stream type: ${stream.getType()}\n"); - } - if (stream.getCodec() != null) { - this.appendOutput("Stream codec: ${stream.getCodec()}\n"); - } - if (stream.getFullCodec() != null) { - this.appendOutput("Stream full codec: ${stream.getFullCodec()}\n"); - } - if (stream.getFormat() != null) { - this.appendOutput("Stream format: ${stream.getFormat()}\n"); - } - if (stream.getWidth() != null) { - this.appendOutput("Stream width: ${stream.getWidth()}\n"); - } - if (stream.getHeight() != null) { - this.appendOutput("Stream height: ${stream.getHeight()}\n"); - } - if (stream.getBitrate() != null) { - this.appendOutput("Stream bitrate: ${stream.getBitrate()}\n"); - } - if (stream.getSampleRate() != null) { - this.appendOutput("Stream sample rate: ${stream.getSampleRate()}\n"); - } - if (stream.getSampleFormat() != null) { - this.appendOutput( - "Stream sample format: ${stream.getSampleFormat()}\n"); - } - if (stream.getChannelLayout() != null) { - this.appendOutput( - "Stream channel layout: ${stream.getChannelLayout()}\n"); - } - if (stream.getSampleAspectRatio() != null) { - this.appendOutput( - "Stream sample aspect ratio: ${stream.getSampleAspectRatio()}\n"); - } - if (stream.getDisplayAspectRatio() != null) { - this.appendOutput( - "Stream display ascpect ratio: ${stream.getDisplayAspectRatio()}\n"); - } - if (stream.getAverageFrameRate() != null) { - this.appendOutput( - "Stream average frame rate: ${stream.getAverageFrameRate()}\n"); + this.appendOutput("Get media information failed\n"); + this.appendOutput("State: ${state}\n"); + this.appendOutput("Duration: ${duration}\n"); + this.appendOutput("Return Code: ${returnCode}\n"); + this.appendOutput( + "Fail stack trace: ${notNull(failStackTrace, "\\n")}\n"); + this.appendOutput("Output: ${output}\n"); + } else { + this.appendOutput( + "Media information for ${information.getFilename()}\n"); + + if (information.getFormat() != null) { + this.appendOutput("Format: ${information.getFormat()}\n"); } - if (stream.getRealFrameRate() != null) { - this.appendOutput( - "Stream real frame rate: ${stream.getRealFrameRate()}\n"); + if (information.getBitrate() != null) { + this.appendOutput("Bitrate: ${information.getBitrate()}\n"); } - if (stream.getTimeBase() != null) { - this.appendOutput("Stream time base: ${stream.getTimeBase()}\n"); + if (information.getDuration() != null) { + this.appendOutput("Duration: ${information.getDuration()}\n"); } - if (stream.getCodecTimeBase() != null) { - this.appendOutput( - "Stream codec time base: ${stream.getCodecTimeBase()}\n"); + if (information.getStartTime() != null) { + this.appendOutput("Start time: ${information.getStartTime()}\n"); } - if (stream.getTags() != null) { - final tags = stream.getTags(); + if (information.getTags() != null) { + final tags = information.getTags(); if (tags != null) { tags.forEach((key, value) { - this.appendOutput("Stream tag: ${key}:${tags[key]}\n"); + this.appendOutput("Tag: ${key}:${tags[key]}\n"); }); } } + + List streams = information.getStreams(); + for (var i = 0; i < streams.length; ++i) { + StreamInformation stream = streams[i]; + if (stream.getIndex() != null) { + this.appendOutput("Stream index: ${stream.getIndex()}\n"); + } + if (stream.getType() != null) { + this.appendOutput("Stream type: ${stream.getType()}\n"); + } + if (stream.getCodec() != null) { + this.appendOutput("Stream codec: ${stream.getCodec()}\n"); + } + if (stream.getFullCodec() != null) { + this.appendOutput("Stream full codec: ${stream.getFullCodec()}\n"); + } + if (stream.getFormat() != null) { + this.appendOutput("Stream format: ${stream.getFormat()}\n"); + } + if (stream.getWidth() != null) { + this.appendOutput("Stream width: ${stream.getWidth()}\n"); + } + if (stream.getHeight() != null) { + this.appendOutput("Stream height: ${stream.getHeight()}\n"); + } + if (stream.getBitrate() != null) { + this.appendOutput("Stream bitrate: ${stream.getBitrate()}\n"); + } + if (stream.getSampleRate() != null) { + this.appendOutput( + "Stream sample rate: ${stream.getSampleRate()}\n"); + } + if (stream.getSampleFormat() != null) { + this.appendOutput( + "Stream sample format: ${stream.getSampleFormat()}\n"); + } + if (stream.getChannelLayout() != null) { + this.appendOutput( + "Stream channel layout: ${stream.getChannelLayout()}\n"); + } + if (stream.getSampleAspectRatio() != null) { + this.appendOutput( + "Stream sample aspect ratio: ${stream.getSampleAspectRatio()}\n"); + } + if (stream.getDisplayAspectRatio() != null) { + this.appendOutput( + "Stream display ascpect ratio: ${stream.getDisplayAspectRatio()}\n"); + } + if (stream.getAverageFrameRate() != null) { + this.appendOutput( + "Stream average frame rate: ${stream.getAverageFrameRate()}\n"); + } + if (stream.getRealFrameRate() != null) { + this.appendOutput( + "Stream real frame rate: ${stream.getRealFrameRate()}\n"); + } + if (stream.getTimeBase() != null) { + this.appendOutput("Stream time base: ${stream.getTimeBase()}\n"); + } + if (stream.getCodecTimeBase() != null) { + this.appendOutput( + "Stream codec time base: ${stream.getCodecTimeBase()}\n"); + } + if (stream.getTags() != null) { + final tags = stream.getTags(); + if (tags != null) { + tags.forEach((key, value) { + this.appendOutput("Stream tag: ${key}:${tags[key]}\n"); + }); + } + } + } + + List chapters = information.getChapters(); + for (var i = 0; i < chapters.length; ++i) { + Chapter chapter = chapters[i]; + if (chapter.getId() != null) { + appendOutput("Chapter id: ${chapter.getId()}\n"); + } + if (chapter.getTimeBase() != null) { + appendOutput("Chapter time base: ${chapter.getTimeBase()}\n"); + } + if (chapter.getStart() != null) { + appendOutput("Chapter start: ${chapter.getStart()}\n"); + } + if (chapter.getStartTime() != null) { + appendOutput("Chapter start time: ${chapter.getStartTime()}\n"); + } + if (chapter.getEnd() != null) { + appendOutput("Chapter end: ${chapter.getEnd()}\n"); + } + if (chapter.getEndTime() != null) { + appendOutput("Chapter end time: ${chapter.getEndTime()}\n"); + } + if (chapter.getTags() != null) { + final tags = chapter.getTags(); + if (tags != null) { + tags.forEach((key, value) { + this.appendOutput("Chapter tag: ${key}:${tags[key]}\n"); + }); + } + } + } } - } + }); } String getOutputText() => _outputText; diff --git a/flutter/test-app-local-dependency/lib/main.dart b/flutter/test-app-local-dependency/lib/main.dart index 8ec084c..633c97e 100644 --- a/flutter/test-app-local-dependency/lib/main.dart +++ b/flutter/test-app-local-dependency/lib/main.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-local-dependency/lib/other_tab.dart b/flutter/test-app-local-dependency/lib/other_tab.dart index 167684b..383720e 100644 --- a/flutter/test-app-local-dependency/lib/other_tab.dart +++ b/flutter/test-app-local-dependency/lib/other_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -89,6 +89,9 @@ class OtherTab { case "webp": this.testWebp(); break; + case "zscale": + this.testZscale(); + break; } } @@ -198,6 +201,38 @@ class OtherTab { }); } + testZscale() { + getVideoFile().then((videoFile) { + getZscaledVideoFile().then((zscaledVideoFile) { + this.getWebpOutputFile().then((outputPath) { + ffprint( + "Testing 'zscale' filter with video file created on the Video tab"); + + final ffmpegCommand = VideoUtil.generateZscaleVideoScript( + videoFile.path, zscaledVideoFile.path); + + ffprint("FFmpeg process started with arguments '${ffmpegCommand}'."); + + FFmpegKit.executeAsync(ffmpegCommand, (session) async { + final state = + FFmpegKitConfig.sessionStateToString(await session.getState()); + final returnCode = await session.getReturnCode(); + final failStackTrace = await session.getFailStackTrace(); + + ffprint( + "FFmpeg process exited with state ${state} and rc ${returnCode}.${notNull(failStackTrace, "\\n")}"); + + if (ReturnCode.isSuccess(returnCode)) { + showPopup("zscale completed successfully."); + } else { + showPopup("zscale failed. Please check logs for the details."); + } + }, (log) => this.appendOutput(log.getMessage())); + }); + }); + }); + } + Future getChromaprintSampleFile() async { Directory documentsDirectory = await VideoUtil.documentsDirectory; return new File("${documentsDirectory.path}/audio-sample.wav"); @@ -218,6 +253,16 @@ class OtherTab { return new File("${documentsDirectory.path}/video.webp"); } + Future getVideoFile() async { + Directory documentsDirectory = await VideoUtil.documentsDirectory; + return new File("${documentsDirectory.path}/video.mp4"); + } + + Future getZscaledVideoFile() async { + Directory documentsDirectory = await VideoUtil.documentsDirectory; + return new File("${documentsDirectory.path}/video.zscaled.mp4"); + } + List> getTestList() { List> list = List.empty(growable: true); @@ -231,6 +276,9 @@ class OtherTab { list.add(new DropdownMenuItem( value: "webp", child: SizedBox(width: 100, child: Center(child: new Text("webp"))))); + list.add(new DropdownMenuItem( + value: "zscale", + child: SizedBox(width: 100, child: Center(child: new Text("zscale"))))); return list; } diff --git a/flutter/test-app-local-dependency/lib/pipe_tab.dart b/flutter/test-app-local-dependency/lib/pipe_tab.dart index 7801621..7aa622a 100644 --- a/flutter/test-app-local-dependency/lib/pipe_tab.dart +++ b/flutter/test-app-local-dependency/lib/pipe_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -85,7 +85,7 @@ class PipeTab implements PlayerTab { ffprint( "FFmpeg process started with arguments:\n\'${ffmpegCommand}\'."); - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (FFmpegSession session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-local-dependency/lib/player.dart b/flutter/test-app-local-dependency/lib/player.dart index 6141650..c3bbfa2 100644 --- a/flutter/test-app-local-dependency/lib/player.dart +++ b/flutter/test-app-local-dependency/lib/player.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-local-dependency/lib/popup.dart b/flutter/test-app-local-dependency/lib/popup.dart index 77af273..27dd44d 100644 --- a/flutter/test-app-local-dependency/lib/popup.dart +++ b/flutter/test-app-local-dependency/lib/popup.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-local-dependency/lib/progress_modal.dart b/flutter/test-app-local-dependency/lib/progress_modal.dart index 4ff340f..d5f1582 100644 --- a/flutter/test-app-local-dependency/lib/progress_modal.dart +++ b/flutter/test-app-local-dependency/lib/progress_modal.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-local-dependency/lib/saf_tab.dart b/flutter/test-app-local-dependency/lib/saf_tab.dart index cf04f93..241498c 100644 --- a/flutter/test-app-local-dependency/lib/saf_tab.dart +++ b/flutter/test-app-local-dependency/lib/saf_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,6 @@ import 'package:ffmpeg_kit_flutter/ffmpeg_kit_config.dart'; import 'package:ffmpeg_kit_flutter/ffprobe_kit.dart'; import 'package:ffmpeg_kit_flutter/log.dart'; import 'package:ffmpeg_kit_flutter/return_code.dart'; -import 'package:ffmpeg_kit_flutter/session.dart'; import 'package:ffmpeg_kit_flutter/statistics.dart'; import 'abstract.dart'; @@ -84,7 +83,7 @@ class SafTab { ffprint("FFprobe process started with arguments:\n'$ffprobeCommand'"); - FFprobeKit.executeAsync(ffprobeCommand, (session) async { + FFprobeKit.execute(ffprobeCommand).then((session) async { final state = FFmpegKitConfig.sessionStateToString(await session.getState()); final returnCode = await session.getReturnCode(); @@ -128,7 +127,7 @@ class SafTab { ffprint( "FFmpeg process started with arguments:\n'${ffmpegCommand}'."); - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-local-dependency/lib/subtitle_tab.dart b/flutter/test-app-local-dependency/lib/subtitle_tab.dart index 54bbf08..6def254 100644 --- a/flutter/test-app-local-dependency/lib/subtitle_tab.dart +++ b/flutter/test-app-local-dependency/lib/subtitle_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -97,7 +97,7 @@ class SubtitleTab implements PlayerTab { _state = _State.CREATING; - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-local-dependency/lib/test_api.dart b/flutter/test-app-local-dependency/lib/test_api.dart index 9afa745..c7b948d 100644 --- a/flutter/test-app-local-dependency/lib/test_api.dart +++ b/flutter/test-app-local-dependency/lib/test_api.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-local-dependency/lib/tooltip.dart b/flutter/test-app-local-dependency/lib/tooltip.dart index ce3473f..a54fb3b 100644 --- a/flutter/test-app-local-dependency/lib/tooltip.dart +++ b/flutter/test-app-local-dependency/lib/tooltip.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-local-dependency/lib/util.dart b/flutter/test-app-local-dependency/lib/util.dart index 4c39d52..eb4dc8f 100644 --- a/flutter/test-app-local-dependency/lib/util.dart +++ b/flutter/test-app-local-dependency/lib/util.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -65,7 +65,7 @@ void deleteFile(File file) { } void listFFprobeSessions() { - FFprobeKit.listSessions().then((sessionList) { + FFprobeKit.listFFprobeSessions().then((sessionList) { ffprint("Listing ${sessionList.length} FFprobe sessions asynchronously."); int count = 0; diff --git a/flutter/test-app-local-dependency/lib/vid_stab_tab.dart b/flutter/test-app-local-dependency/lib/vid_stab_tab.dart index 4677788..0d424b5 100644 --- a/flutter/test-app-local-dependency/lib/vid_stab_tab.dart +++ b/flutter/test-app-local-dependency/lib/vid_stab_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -93,7 +93,7 @@ class VidStabTab { ffprint( "FFmpeg process started with arguments:\n\'${ffmpegCommand}\'."); - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-local-dependency/lib/video_tab.dart b/flutter/test-app-local-dependency/lib/video_tab.dart index fba1da1..f377b00 100644 --- a/flutter/test-app-local-dependency/lib/video_tab.dart +++ b/flutter/test-app-local-dependency/lib/video_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,6 @@ import 'dart:io'; import 'package:ffmpeg_kit_flutter/ffmpeg_kit.dart'; import 'package:ffmpeg_kit_flutter/ffmpeg_kit_config.dart'; import 'package:ffmpeg_kit_flutter/return_code.dart'; -import 'package:ffmpeg_kit_flutter/session.dart'; import 'package:ffmpeg_kit_flutter/statistics.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; @@ -80,20 +79,22 @@ class VideoTab implements PlayerTab { this.hideProgressDialog(); this.showProgressDialog(); - final ffmpegCommand = VideoUtil.generateEncodeVideoScript( - image1Path, - image2Path, - image3Path, - videoFile.path, - videoCodec, - this.getCustomOptions()); + final ffmpegCommand = + VideoUtil.generateEncodeVideoScriptWithCustomPixelFormat( + image1Path, + image2Path, + image3Path, + videoFile.path, + videoCodec, + this.getPixelFormat(), + this.getCustomOptions()); ffprint( "FFmpeg process started with arguments:\n\'${ffmpegCommand}\'."); FFmpegKit.executeAsync( ffmpegCommand, - (Session session) async { + (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); @@ -145,6 +146,19 @@ class VideoTab implements PlayerTab { } } + getPixelFormat() { + String videoCodec = _selectedCodec; + + String pixelFormat; + if (videoCodec == "x265") { + pixelFormat = "yuv420p10le"; + } else { + pixelFormat = "yuv420p"; + } + + return pixelFormat; + } + String getSelectedVideoCodec() { String videoCodec = _selectedCodec; diff --git a/flutter/test-app-local-dependency/lib/video_util.dart b/flutter/test-app-local-dependency/lib/video_util.dart index c096066..d857d72 100644 --- a/flutter/test-app-local-dependency/lib/video_util.dart +++ b/flutter/test-app-local-dependency/lib/video_util.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -98,6 +98,24 @@ class VideoUtil { String videoFilePath, String videoCodec, String customOptions) { + return generateEncodeVideoScriptWithCustomPixelFormat( + image1Path, + image2Path, + image3Path, + videoFilePath, + videoCodec, + "yuv420p", + customOptions); + } + + static generateEncodeVideoScriptWithCustomPixelFormat( + String image1Path, + String image2Path, + String image3Path, + String videoFilePath, + String videoCodec, + String pixelFormat, + String customOptions) { return "-hide_banner -y -loop 1 -i '" + image1Path + "' " + @@ -119,7 +137,9 @@ class VideoUtil { "[stream3out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30)[stream3starting];" + "[stream2starting][stream1ending]blend=all_expr='if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)':shortest=1[stream2blended];" + "[stream3starting][stream2ending]blend=all_expr='if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)':shortest=1[stream3blended];" + - "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\"" + + "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=" + + pixelFormat + + "[video]\"" + " -map [video] -vsync 2 -async 1 " + customOptions + "-c:v " + @@ -188,4 +208,11 @@ class VideoUtil { " -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 " + videoFilePath; } + + static generateZscaleVideoScript(inputVideoFilePath, outputVideoFilePath) { + return "-y -i " + + inputVideoFilePath + + " -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p " + + outputVideoFilePath; + } } diff --git a/flutter/test-app-local-dependency/macos/Podfile.lock b/flutter/test-app-local-dependency/macos/Podfile.lock index 0f27f00..4ce3585 100644 --- a/flutter/test-app-local-dependency/macos/Podfile.lock +++ b/flutter/test-app-local-dependency/macos/Podfile.lock @@ -1,10 +1,10 @@ PODS: - - ffmpeg-kit-macos-https (4.5) - - ffmpeg_kit_flutter (4.5.0): - - ffmpeg_kit_flutter/https (= 4.5.0) + - ffmpeg-kit-macos-https (4.5.1) + - ffmpeg_kit_flutter (4.5.1): + - ffmpeg_kit_flutter/https (= 4.5.1) - FlutterMacOS - - ffmpeg_kit_flutter/https (4.5.0): - - ffmpeg-kit-macos-https (= 4.5) + - ffmpeg_kit_flutter/https (4.5.1): + - ffmpeg-kit-macos-https (= 4.5.1) - FlutterMacOS - FlutterMacOS (1.0.0) - path_provider_macos (0.0.1): @@ -28,8 +28,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos SPEC CHECKSUMS: - ffmpeg-kit-macos-https: 8f6c3f22d95caf18e1e00821791738dfa81f57f7 - ffmpeg_kit_flutter: ee76eb10344fa024d454cd7fddc8508b185e9e6c + ffmpeg-kit-macos-https: 664f1b3518c477dfa8f197f07e44576215c82db4 + ffmpeg_kit_flutter: 064253e46fed1adf3b6301c58568f06dfe7e9eb9 FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f diff --git a/flutter/test-app-local-dependency/pubspec.lock b/flutter/test-app-local-dependency/pubspec.lock index 5fedcd9..ce469b9 100644 --- a/flutter/test-app-local-dependency/pubspec.lock +++ b/flutter/test-app-local-dependency/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,7 +21,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: @@ -77,14 +77,14 @@ packages: path: "../../../ffmpeg-kit/flutter/flutter" relative: true source: path - version: "4.5.0" + version: "4.5.1" ffmpeg_kit_flutter_platform_interface: dependency: transitive description: name: ffmpeg_kit_flutter_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.1.0" + version: "0.2.1" file: dependency: transitive description: @@ -134,7 +134,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: @@ -251,7 +251,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.3" typed_data: dependency: transitive description: @@ -265,7 +265,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" video_player: dependency: "direct main" description: diff --git a/flutter/test-app-local-dependency/pubspec.yaml b/flutter/test-app-local-dependency/pubspec.yaml index 1e9f00f..fa4d6d3 100644 --- a/flutter/test-app-local-dependency/pubspec.yaml +++ b/flutter/test-app-local-dependency/pubspec.yaml @@ -1,6 +1,6 @@ name: ffmpeg_kit_flutter_test description: Demonstrates how to use the ffmpeg_kit_flutter plugin. -version: 4.5.0 +version: 4.5.1 publish_to: 'none' environment: diff --git a/flutter/test-app-pub/ios/Podfile.lock b/flutter/test-app-pub/ios/Podfile.lock index 9b74653..25aad56 100644 --- a/flutter/test-app-pub/ios/Podfile.lock +++ b/flutter/test-app-pub/ios/Podfile.lock @@ -1,10 +1,10 @@ PODS: - - ffmpeg-kit-ios-video (4.5.LTS) - - ffmpeg_kit_flutter_video (4.5.0.LTS): - - ffmpeg_kit_flutter_video/video-lts (= 4.5.0.LTS) + - ffmpeg-kit-ios-video (4.5.1.LTS) + - ffmpeg_kit_flutter_video (4.5.1.LTS): + - ffmpeg_kit_flutter_video/video-lts (= 4.5.1.LTS) - Flutter - - ffmpeg_kit_flutter_video/video-lts (4.5.0.LTS): - - ffmpeg-kit-ios-video (= 4.5.LTS) + - ffmpeg_kit_flutter_video/video-lts (4.5.1.LTS): + - ffmpeg-kit-ios-video (= 4.5.1.LTS) - Flutter - Flutter (1.0.0) - fluttertoast (0.0.2): @@ -41,8 +41,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/video_player/ios" SPEC CHECKSUMS: - ffmpeg-kit-ios-video: 1056a5bc26f78c2b618688ead42f65ffde85d690 - ffmpeg_kit_flutter_video: 1792e03e78d1e86a7e1ca0647eb1c2a2c918fef4 + ffmpeg-kit-ios-video: 6fb3322566c8e6c74e2d66dffc12e4b58605e5a4 + ffmpeg_kit_flutter_video: b0969c42b4a7e55d54e9fab7f05e0b8ba632f32c Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a fluttertoast: 6122fa75143e992b1d3470f61000f591a798cc58 path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de diff --git a/flutter/test-app-pub/ios/Runner.xcodeproj/project.pbxproj b/flutter/test-app-pub/ios/Runner.xcodeproj/project.pbxproj index 1e701bd..29dcee0 100644 --- a/flutter/test-app-pub/ios/Runner.xcodeproj/project.pbxproj +++ b/flutter/test-app-pub/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ @@ -150,6 +150,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 6D3839A1881BE2681E74FF01 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -166,7 +167,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -243,6 +244,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 6D3839A1881BE2681E74FF01 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/flutter/test-app-pub/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter/test-app-pub/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..3db53b6 100644 --- a/flutter/test-app-pub/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/flutter/test-app-pub/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ streams = information.getStreams(); - for (var i = 0; i < streams.length; ++i) { - StreamInformation stream = streams[i]; - if (stream.getIndex() != null) { - this.appendOutput("Stream index: ${stream.getIndex()}\n"); - } - if (stream.getType() != null) { - this.appendOutput("Stream type: ${stream.getType()}\n"); - } - if (stream.getCodec() != null) { - this.appendOutput("Stream codec: ${stream.getCodec()}\n"); - } - if (stream.getFullCodec() != null) { - this.appendOutput("Stream full codec: ${stream.getFullCodec()}\n"); - } - if (stream.getFormat() != null) { - this.appendOutput("Stream format: ${stream.getFormat()}\n"); - } - if (stream.getWidth() != null) { - this.appendOutput("Stream width: ${stream.getWidth()}\n"); - } - if (stream.getHeight() != null) { - this.appendOutput("Stream height: ${stream.getHeight()}\n"); - } - if (stream.getBitrate() != null) { - this.appendOutput("Stream bitrate: ${stream.getBitrate()}\n"); - } - if (stream.getSampleRate() != null) { - this.appendOutput("Stream sample rate: ${stream.getSampleRate()}\n"); - } - if (stream.getSampleFormat() != null) { - this.appendOutput( - "Stream sample format: ${stream.getSampleFormat()}\n"); - } - if (stream.getChannelLayout() != null) { - this.appendOutput( - "Stream channel layout: ${stream.getChannelLayout()}\n"); - } - if (stream.getSampleAspectRatio() != null) { - this.appendOutput( - "Stream sample aspect ratio: ${stream.getSampleAspectRatio()}\n"); - } - if (stream.getDisplayAspectRatio() != null) { - this.appendOutput( - "Stream display ascpect ratio: ${stream.getDisplayAspectRatio()}\n"); - } - if (stream.getAverageFrameRate() != null) { - this.appendOutput( - "Stream average frame rate: ${stream.getAverageFrameRate()}\n"); + this.appendOutput("Get media information failed\n"); + this.appendOutput("State: ${state}\n"); + this.appendOutput("Duration: ${duration}\n"); + this.appendOutput("Return Code: ${returnCode}\n"); + this.appendOutput( + "Fail stack trace: ${notNull(failStackTrace, "\\n")}\n"); + this.appendOutput("Output: ${output}\n"); + } else { + this.appendOutput( + "Media information for ${information.getFilename()}\n"); + + if (information.getFormat() != null) { + this.appendOutput("Format: ${information.getFormat()}\n"); } - if (stream.getRealFrameRate() != null) { - this.appendOutput( - "Stream real frame rate: ${stream.getRealFrameRate()}\n"); + if (information.getBitrate() != null) { + this.appendOutput("Bitrate: ${information.getBitrate()}\n"); } - if (stream.getTimeBase() != null) { - this.appendOutput("Stream time base: ${stream.getTimeBase()}\n"); + if (information.getDuration() != null) { + this.appendOutput("Duration: ${information.getDuration()}\n"); } - if (stream.getCodecTimeBase() != null) { - this.appendOutput( - "Stream codec time base: ${stream.getCodecTimeBase()}\n"); + if (information.getStartTime() != null) { + this.appendOutput("Start time: ${information.getStartTime()}\n"); } - if (stream.getTags() != null) { - final tags = stream.getTags(); + if (information.getTags() != null) { + final tags = information.getTags(); if (tags != null) { tags.forEach((key, value) { - this.appendOutput("Stream tag: ${key}:${tags[key]}\n"); + this.appendOutput("Tag: ${key}:${tags[key]}\n"); }); } } + + List streams = information.getStreams(); + for (var i = 0; i < streams.length; ++i) { + StreamInformation stream = streams[i]; + if (stream.getIndex() != null) { + this.appendOutput("Stream index: ${stream.getIndex()}\n"); + } + if (stream.getType() != null) { + this.appendOutput("Stream type: ${stream.getType()}\n"); + } + if (stream.getCodec() != null) { + this.appendOutput("Stream codec: ${stream.getCodec()}\n"); + } + if (stream.getFullCodec() != null) { + this.appendOutput("Stream full codec: ${stream.getFullCodec()}\n"); + } + if (stream.getFormat() != null) { + this.appendOutput("Stream format: ${stream.getFormat()}\n"); + } + if (stream.getWidth() != null) { + this.appendOutput("Stream width: ${stream.getWidth()}\n"); + } + if (stream.getHeight() != null) { + this.appendOutput("Stream height: ${stream.getHeight()}\n"); + } + if (stream.getBitrate() != null) { + this.appendOutput("Stream bitrate: ${stream.getBitrate()}\n"); + } + if (stream.getSampleRate() != null) { + this.appendOutput( + "Stream sample rate: ${stream.getSampleRate()}\n"); + } + if (stream.getSampleFormat() != null) { + this.appendOutput( + "Stream sample format: ${stream.getSampleFormat()}\n"); + } + if (stream.getChannelLayout() != null) { + this.appendOutput( + "Stream channel layout: ${stream.getChannelLayout()}\n"); + } + if (stream.getSampleAspectRatio() != null) { + this.appendOutput( + "Stream sample aspect ratio: ${stream.getSampleAspectRatio()}\n"); + } + if (stream.getDisplayAspectRatio() != null) { + this.appendOutput( + "Stream display ascpect ratio: ${stream.getDisplayAspectRatio()}\n"); + } + if (stream.getAverageFrameRate() != null) { + this.appendOutput( + "Stream average frame rate: ${stream.getAverageFrameRate()}\n"); + } + if (stream.getRealFrameRate() != null) { + this.appendOutput( + "Stream real frame rate: ${stream.getRealFrameRate()}\n"); + } + if (stream.getTimeBase() != null) { + this.appendOutput("Stream time base: ${stream.getTimeBase()}\n"); + } + if (stream.getCodecTimeBase() != null) { + this.appendOutput( + "Stream codec time base: ${stream.getCodecTimeBase()}\n"); + } + if (stream.getTags() != null) { + final tags = stream.getTags(); + if (tags != null) { + tags.forEach((key, value) { + this.appendOutput("Stream tag: ${key}:${tags[key]}\n"); + }); + } + } + } + + List chapters = information.getChapters(); + for (var i = 0; i < chapters.length; ++i) { + Chapter chapter = chapters[i]; + if (chapter.getId() != null) { + appendOutput("Chapter id: ${chapter.getId()}\n"); + } + if (chapter.getTimeBase() != null) { + appendOutput("Chapter time base: ${chapter.getTimeBase()}\n"); + } + if (chapter.getStart() != null) { + appendOutput("Chapter start: ${chapter.getStart()}\n"); + } + if (chapter.getStartTime() != null) { + appendOutput("Chapter start time: ${chapter.getStartTime()}\n"); + } + if (chapter.getEnd() != null) { + appendOutput("Chapter end: ${chapter.getEnd()}\n"); + } + if (chapter.getEndTime() != null) { + appendOutput("Chapter end time: ${chapter.getEndTime()}\n"); + } + if (chapter.getTags() != null) { + final tags = chapter.getTags(); + if (tags != null) { + tags.forEach((key, value) { + this.appendOutput("Chapter tag: ${key}:${tags[key]}\n"); + }); + } + } + } } - } + }); } String getOutputText() => _outputText; diff --git a/flutter/test-app-pub/lib/main.dart b/flutter/test-app-pub/lib/main.dart index 9488b2e..8433a8b 100644 --- a/flutter/test-app-pub/lib/main.dart +++ b/flutter/test-app-pub/lib/main.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-pub/lib/other_tab.dart b/flutter/test-app-pub/lib/other_tab.dart index 166f41a..27aed2c 100644 --- a/flutter/test-app-pub/lib/other_tab.dart +++ b/flutter/test-app-pub/lib/other_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -89,6 +89,9 @@ class OtherTab { case "webp": this.testWebp(); break; + case "zscale": + this.testZscale(); + break; } } @@ -198,6 +201,38 @@ class OtherTab { }); } + testZscale() { + getVideoFile().then((videoFile) { + getZscaledVideoFile().then((zscaledVideoFile) { + this.getWebpOutputFile().then((outputPath) { + ffprint( + "Testing 'zscale' filter with video file created on the Video tab"); + + final ffmpegCommand = VideoUtil.generateZscaleVideoScript( + videoFile.path, zscaledVideoFile.path); + + ffprint("FFmpeg process started with arguments '${ffmpegCommand}'."); + + FFmpegKit.executeAsync(ffmpegCommand, (session) async { + final state = + FFmpegKitConfig.sessionStateToString(await session.getState()); + final returnCode = await session.getReturnCode(); + final failStackTrace = await session.getFailStackTrace(); + + ffprint( + "FFmpeg process exited with state ${state} and rc ${returnCode}.${notNull(failStackTrace, "\\n")}"); + + if (ReturnCode.isSuccess(returnCode)) { + showPopup("zscale completed successfully."); + } else { + showPopup("zscale failed. Please check logs for the details."); + } + }, (log) => this.appendOutput(log.getMessage())); + }); + }); + }); + } + Future getChromaprintSampleFile() async { Directory documentsDirectory = await VideoUtil.documentsDirectory; return new File("${documentsDirectory.path}/audio-sample.wav"); @@ -218,6 +253,16 @@ class OtherTab { return new File("${documentsDirectory.path}/video.webp"); } + Future getVideoFile() async { + Directory documentsDirectory = await VideoUtil.documentsDirectory; + return new File("${documentsDirectory.path}/video.mp4"); + } + + Future getZscaledVideoFile() async { + Directory documentsDirectory = await VideoUtil.documentsDirectory; + return new File("${documentsDirectory.path}/video.zscaled.mp4"); + } + List> getTestList() { List> list = List.empty(growable: true); @@ -231,6 +276,9 @@ class OtherTab { list.add(new DropdownMenuItem( value: "webp", child: SizedBox(width: 100, child: Center(child: new Text("webp"))))); + list.add(new DropdownMenuItem( + value: "zscale", + child: SizedBox(width: 100, child: Center(child: new Text("zscale"))))); return list; } diff --git a/flutter/test-app-pub/lib/pipe_tab.dart b/flutter/test-app-pub/lib/pipe_tab.dart index 6d1b479..b17cba2 100644 --- a/flutter/test-app-pub/lib/pipe_tab.dart +++ b/flutter/test-app-pub/lib/pipe_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -85,7 +85,7 @@ class PipeTab implements PlayerTab { ffprint( "FFmpeg process started with arguments:\n\'${ffmpegCommand}\'."); - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (FFmpegSession session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-pub/lib/player.dart b/flutter/test-app-pub/lib/player.dart index 6141650..c3bbfa2 100644 --- a/flutter/test-app-pub/lib/player.dart +++ b/flutter/test-app-pub/lib/player.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-pub/lib/popup.dart b/flutter/test-app-pub/lib/popup.dart index 77af273..27dd44d 100644 --- a/flutter/test-app-pub/lib/popup.dart +++ b/flutter/test-app-pub/lib/popup.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-pub/lib/progress_modal.dart b/flutter/test-app-pub/lib/progress_modal.dart index 4ff340f..d5f1582 100644 --- a/flutter/test-app-pub/lib/progress_modal.dart +++ b/flutter/test-app-pub/lib/progress_modal.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-pub/lib/saf_tab.dart b/flutter/test-app-pub/lib/saf_tab.dart index dec40e5..1c2442d 100644 --- a/flutter/test-app-pub/lib/saf_tab.dart +++ b/flutter/test-app-pub/lib/saf_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,6 @@ import 'package:ffmpeg_kit_flutter_video/ffmpeg_kit_config.dart'; import 'package:ffmpeg_kit_flutter_video/ffprobe_kit.dart'; import 'package:ffmpeg_kit_flutter_video/log.dart'; import 'package:ffmpeg_kit_flutter_video/return_code.dart'; -import 'package:ffmpeg_kit_flutter_video/session.dart'; import 'package:ffmpeg_kit_flutter_video/statistics.dart'; import 'abstract.dart'; @@ -84,7 +83,7 @@ class SafTab { ffprint("FFprobe process started with arguments:\n'$ffprobeCommand'"); - FFprobeKit.executeAsync(ffprobeCommand, (session) async { + FFprobeKit.execute(ffprobeCommand).then((session) async { final state = FFmpegKitConfig.sessionStateToString(await session.getState()); final returnCode = await session.getReturnCode(); @@ -128,7 +127,7 @@ class SafTab { ffprint( "FFmpeg process started with arguments:\n'${ffmpegCommand}'."); - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-pub/lib/subtitle_tab.dart b/flutter/test-app-pub/lib/subtitle_tab.dart index b7939b8..71e0269 100644 --- a/flutter/test-app-pub/lib/subtitle_tab.dart +++ b/flutter/test-app-pub/lib/subtitle_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -97,7 +97,7 @@ class SubtitleTab implements PlayerTab { _state = _State.CREATING; - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-pub/lib/test_api.dart b/flutter/test-app-pub/lib/test_api.dart index ada811d..774c5a2 100644 --- a/flutter/test-app-pub/lib/test_api.dart +++ b/flutter/test-app-pub/lib/test_api.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-pub/lib/tooltip.dart b/flutter/test-app-pub/lib/tooltip.dart index ce3473f..a54fb3b 100644 --- a/flutter/test-app-pub/lib/tooltip.dart +++ b/flutter/test-app-pub/lib/tooltip.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/flutter/test-app-pub/lib/util.dart b/flutter/test-app-pub/lib/util.dart index 1c025a7..dca9003 100644 --- a/flutter/test-app-pub/lib/util.dart +++ b/flutter/test-app-pub/lib/util.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -65,7 +65,7 @@ void deleteFile(File file) { } void listFFprobeSessions() { - FFprobeKit.listSessions().then((sessionList) { + FFprobeKit.listFFprobeSessions().then((sessionList) { ffprint("Listing ${sessionList.length} FFprobe sessions asynchronously."); int count = 0; diff --git a/flutter/test-app-pub/lib/vid_stab_tab.dart b/flutter/test-app-pub/lib/vid_stab_tab.dart index 4f02cc6..86ce5d2 100644 --- a/flutter/test-app-pub/lib/vid_stab_tab.dart +++ b/flutter/test-app-pub/lib/vid_stab_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -93,7 +93,7 @@ class VidStabTab { ffprint( "FFmpeg process started with arguments:\n\'${ffmpegCommand}\'."); - FFmpegKit.executeAsync(ffmpegCommand, (Session session) async { + FFmpegKit.executeAsync(ffmpegCommand, (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); diff --git a/flutter/test-app-pub/lib/video_tab.dart b/flutter/test-app-pub/lib/video_tab.dart index ced8582..630c9a4 100644 --- a/flutter/test-app-pub/lib/video_tab.dart +++ b/flutter/test-app-pub/lib/video_tab.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,6 @@ import 'dart:io'; import 'package:ffmpeg_kit_flutter_video/ffmpeg_kit.dart'; import 'package:ffmpeg_kit_flutter_video/ffmpeg_kit_config.dart'; import 'package:ffmpeg_kit_flutter_video/return_code.dart'; -import 'package:ffmpeg_kit_flutter_video/session.dart'; import 'package:ffmpeg_kit_flutter_video/statistics.dart'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; @@ -80,20 +79,22 @@ class VideoTab implements PlayerTab { this.hideProgressDialog(); this.showProgressDialog(); - final ffmpegCommand = VideoUtil.generateEncodeVideoScript( - image1Path, - image2Path, - image3Path, - videoFile.path, - videoCodec, - this.getCustomOptions()); + final ffmpegCommand = + VideoUtil.generateEncodeVideoScriptWithCustomPixelFormat( + image1Path, + image2Path, + image3Path, + videoFile.path, + videoCodec, + this.getPixelFormat(), + this.getCustomOptions()); ffprint( "FFmpeg process started with arguments:\n\'${ffmpegCommand}\'."); FFmpegKit.executeAsync( ffmpegCommand, - (Session session) async { + (session) async { final state = FFmpegKitConfig.sessionStateToString( await session.getState()); final returnCode = await session.getReturnCode(); @@ -145,6 +146,19 @@ class VideoTab implements PlayerTab { } } + getPixelFormat() { + String videoCodec = _selectedCodec; + + String pixelFormat; + if (videoCodec == "x265") { + pixelFormat = "yuv420p10le"; + } else { + pixelFormat = "yuv420p"; + } + + return pixelFormat; + } + String getSelectedVideoCodec() { String videoCodec = _selectedCodec; diff --git a/flutter/test-app-pub/lib/video_util.dart b/flutter/test-app-pub/lib/video_util.dart index 788a6c0..713c055 100644 --- a/flutter/test-app-pub/lib/video_util.dart +++ b/flutter/test-app-pub/lib/video_util.dart @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021 Taner Sener + * Copyright (c) 2018-2022 Taner Sener * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -98,6 +98,24 @@ class VideoUtil { String videoFilePath, String videoCodec, String customOptions) { + return generateEncodeVideoScriptWithCustomPixelFormat( + image1Path, + image2Path, + image3Path, + videoFilePath, + videoCodec, + "yuv420p", + customOptions); + } + + static generateEncodeVideoScriptWithCustomPixelFormat( + String image1Path, + String image2Path, + String image3Path, + String videoFilePath, + String videoCodec, + String pixelFormat, + String customOptions) { return "-hide_banner -y -loop 1 -i '" + image1Path + "' " + @@ -119,7 +137,9 @@ class VideoUtil { "[stream3out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30)[stream3starting];" + "[stream2starting][stream1ending]blend=all_expr='if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)':shortest=1[stream2blended];" + "[stream3starting][stream2ending]blend=all_expr='if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)':shortest=1[stream3blended];" + - "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\"" + + "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=" + + pixelFormat + + "[video]\"" + " -map [video] -vsync 2 -async 1 " + customOptions + "-c:v " + @@ -188,4 +208,11 @@ class VideoUtil { " -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 " + videoFilePath; } + + static generateZscaleVideoScript(inputVideoFilePath, outputVideoFilePath) { + return "-y -i " + + inputVideoFilePath + + " -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p " + + outputVideoFilePath; + } } diff --git a/flutter/test-app-pub/macos/Podfile.lock b/flutter/test-app-pub/macos/Podfile.lock index 0f27f00..66a047e 100644 --- a/flutter/test-app-pub/macos/Podfile.lock +++ b/flutter/test-app-pub/macos/Podfile.lock @@ -1,35 +1,35 @@ PODS: - - ffmpeg-kit-macos-https (4.5) - - ffmpeg_kit_flutter (4.5.0): - - ffmpeg_kit_flutter/https (= 4.5.0) + - ffmpeg-kit-macos-video (4.5.1.LTS) + - ffmpeg_kit_flutter_video (4.5.1.LTS): + - ffmpeg_kit_flutter_video/video-lts (= 4.5.1.LTS) - FlutterMacOS - - ffmpeg_kit_flutter/https (4.5.0): - - ffmpeg-kit-macos-https (= 4.5) + - ffmpeg_kit_flutter_video/video-lts (4.5.1.LTS): + - ffmpeg-kit-macos-video (= 4.5.1.LTS) - FlutterMacOS - FlutterMacOS (1.0.0) - path_provider_macos (0.0.1): - FlutterMacOS DEPENDENCIES: - - ffmpeg_kit_flutter (from `Flutter/ephemeral/.symlinks/plugins/ffmpeg_kit_flutter/macos`) + - ffmpeg_kit_flutter_video (from `Flutter/ephemeral/.symlinks/plugins/ffmpeg_kit_flutter_video/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) SPEC REPOS: trunk: - - ffmpeg-kit-macos-https + - ffmpeg-kit-macos-video EXTERNAL SOURCES: - ffmpeg_kit_flutter: - :path: Flutter/ephemeral/.symlinks/plugins/ffmpeg_kit_flutter/macos + ffmpeg_kit_flutter_video: + :path: Flutter/ephemeral/.symlinks/plugins/ffmpeg_kit_flutter_video/macos FlutterMacOS: :path: Flutter/ephemeral path_provider_macos: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos SPEC CHECKSUMS: - ffmpeg-kit-macos-https: 8f6c3f22d95caf18e1e00821791738dfa81f57f7 - ffmpeg_kit_flutter: ee76eb10344fa024d454cd7fddc8508b185e9e6c + ffmpeg-kit-macos-video: be3b8ff085d8940d655b696bf773fc6b7dc0caf2 + ffmpeg_kit_flutter_video: 2a2dc691d97423724666d340ff06d5eec4a9112e FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f diff --git a/flutter/test-app-pub/pubspec.lock b/flutter/test-app-pub/pubspec.lock index 18f00be..497782d 100644 --- a/flutter/test-app-pub/pubspec.lock +++ b/flutter/test-app-pub/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,7 +21,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: @@ -77,14 +77,14 @@ packages: name: ffmpeg_kit_flutter_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.1.0" + version: "0.2.1" ffmpeg_kit_flutter_video: dependency: "direct main" description: name: ffmpeg_kit_flutter_video url: "https://pub.dartlang.org" source: hosted - version: "4.5.0-LTS" + version: "4.5.1-LTS" file: dependency: transitive description: @@ -134,7 +134,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: @@ -251,7 +251,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.3" typed_data: dependency: transitive description: @@ -265,7 +265,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" video_player: dependency: "direct main" description: diff --git a/flutter/test-app-pub/pubspec.yaml b/flutter/test-app-pub/pubspec.yaml index 1956dbf..1b5643a 100644 --- a/flutter/test-app-pub/pubspec.yaml +++ b/flutter/test-app-pub/pubspec.yaml @@ -1,6 +1,6 @@ name: ffmpeg_kit_flutter_test description: Demonstrates how to use the ffmpeg_kit_flutter plugin. -version: 4.5.0 +version: 4.5.1 publish_to: 'none' environment: @@ -9,7 +9,7 @@ environment: dependencies: flutter: sdk: flutter - ffmpeg_kit_flutter_video: 4.5.0-LTS + ffmpeg_kit_flutter_video: 4.5.1-LTS cupertino_icons: ^1.0.3 path_provider: ^2.0.5 path: ^1.8.0