From 500fd453a13dcc4a570523ecba914357f46d4c74 Mon Sep 17 00:00:00 2001 From: Rostislav Vasilikhin Date: Wed, 13 Dec 2023 13:54:31 +0100 Subject: [PATCH] Merge pull request #24592 from savuor:recorder_android Android sample for VideoWriter #24592 This PR: * adds an Android sample for video recording with MediaNDK and built-in MJPEG. * adds a flag `--no_media_ndk` for `build_sdk.py` script to disable MediaNDK linkage. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- platforms/android/build_sdk.py | 8 +- samples/android/CMakeLists.txt | 1 + samples/android/video-recorder/CMakeLists.txt | 12 + .../android/video-recorder/build.gradle.in | 36 ++ .../video-recorder/gradle/AndroidManifest.xml | 38 ++ .../video-recorder/res/drawable/icon.png | Bin 0 -> 1997 bytes .../res/layout/recorder_surface_view.xml | 38 ++ .../video-recorder/res/values/strings.xml | 4 + .../samples/recorder/RecorderActivity.java | 340 ++++++++++++++++++ 9 files changed, 475 insertions(+), 2 deletions(-) create mode 100644 samples/android/video-recorder/CMakeLists.txt create mode 100644 samples/android/video-recorder/build.gradle.in create mode 100644 samples/android/video-recorder/gradle/AndroidManifest.xml create mode 100644 samples/android/video-recorder/res/drawable/icon.png create mode 100644 samples/android/video-recorder/res/layout/recorder_surface_view.xml create mode 100644 samples/android/video-recorder/res/values/strings.xml create mode 100644 samples/android/video-recorder/src/org/opencv/samples/recorder/RecorderActivity.java diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py index f4d39074c7..f27a392f7e 100755 --- a/platforms/android/build_sdk.py +++ b/platforms/android/build_sdk.py @@ -215,7 +215,7 @@ class Builder: for d in ["CMakeCache.txt", "CMakeFiles/", "bin/", "libs/", "lib/", "package/", "install/samples/"]: rm_one(d) - def build_library(self, abi, do_install): + def build_library(self, abi, do_install, no_media_ndk): cmd = [self.cmake_path, "-GNinja"] cmake_vars = dict( CMAKE_TOOLCHAIN_FILE=self.get_toolchain_file(), @@ -260,6 +260,9 @@ class Builder: if do_install: cmd.extend(["-DBUILD_TESTS=ON", "-DINSTALL_TESTS=ON"]) + if no_media_ndk: + cmake_vars['WITH_ANDROID_MEDIANDK'] = "OFF" + cmake_vars.update(abi.cmake_vars) cmd += [ "-D%s='%s'" % (k, v) for (k, v) in cmake_vars.items() if v is not None] cmd.append(self.opencvdir) @@ -370,6 +373,7 @@ if __name__ == "__main__": parser.add_argument('--opencl', action="store_true", help="Enable OpenCL support") parser.add_argument('--no_kotlin', action="store_true", help="Disable Kotlin extensions") parser.add_argument('--shared', action="store_true", help="Build shared libraries") + parser.add_argument('--no_media_ndk', action="store_true", help="Do not link Media NDK (required for video I/O support)") args = parser.parse_args() log.basicConfig(format='%(message)s', level=log.DEBUG) @@ -447,7 +451,7 @@ if __name__ == "__main__": os.chdir(builder.libdest) builder.clean_library_build_dir() - builder.build_library(abi, do_install) + builder.build_library(abi, do_install, args.no_media_ndk) builder.gather_results() diff --git a/samples/android/CMakeLists.txt b/samples/android/CMakeLists.txt index f4fe882447..fe6318f48e 100644 --- a/samples/android/CMakeLists.txt +++ b/samples/android/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(image-manipulations) add_subdirectory(camera-calibration) add_subdirectory(color-blob-detection) add_subdirectory(mobilenet-objdetect) +add_subdirectory(video-recorder) add_subdirectory(tutorial-1-camerapreview) add_subdirectory(tutorial-2-mixedprocessing) add_subdirectory(tutorial-3-cameracontrol) diff --git a/samples/android/video-recorder/CMakeLists.txt b/samples/android/video-recorder/CMakeLists.txt new file mode 100644 index 0000000000..e833d8fd6f --- /dev/null +++ b/samples/android/video-recorder/CMakeLists.txt @@ -0,0 +1,12 @@ +set(sample example-video-recorder) + +if(BUILD_FAT_JAVA_LIB) + set(native_deps opencv_java) +else() + set(native_deps videoio) +endif() + +add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS "${OPENCV_ANDROID_LIB_DIR}" SDK_TARGET 11 "${ANDROID_SDK_TARGET}" NATIVE_DEPS ${native_deps}) +if(TARGET ${sample}) + add_dependencies(opencv_android_examples ${sample}) +endif() diff --git a/samples/android/video-recorder/build.gradle.in b/samples/android/video-recorder/build.gradle.in new file mode 100644 index 0000000000..b279623803 --- /dev/null +++ b/samples/android/video-recorder/build.gradle.in @@ -0,0 +1,36 @@ +apply plugin: 'com.android.application' + +android { + namespace 'org.opencv.samples.recorder' + compileSdkVersion @ANDROID_COMPILE_SDK_VERSION@ + defaultConfig { + applicationId "org.opencv.samples.recorder" + minSdkVersion @ANDROID_MIN_SDK_VERSION@ + targetSdkVersion @ANDROID_TARGET_SDK_VERSION@ + versionCode 301 + versionName "3.01" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + sourceSets { + main { + java.srcDirs = @ANDROID_SAMPLE_JAVA_PATH@ + aidl.srcDirs = @ANDROID_SAMPLE_JAVA_PATH@ + res.srcDirs = @ANDROID_SAMPLE_RES_PATH@ + manifest.srcFile '@ANDROID_SAMPLE_MANIFEST_PATH@' + } + } +} + +dependencies { + //implementation fileTree(dir: 'libs', include: ['*.jar']) + if (gradle.opencv_source == "sdk_path") { + implementation project(':opencv') + } else if (gradle.opencv_source == "maven_local" || gradle.opencv_source == "maven_cenral") { + implementation 'org.opencv:opencv:@OPENCV_VERSION_PLAIN@' + } +} diff --git a/samples/android/video-recorder/gradle/AndroidManifest.xml b/samples/android/video-recorder/gradle/AndroidManifest.xml new file mode 100644 index 0000000000..fc4129c0f2 --- /dev/null +++ b/samples/android/video-recorder/gradle/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/android/video-recorder/res/drawable/icon.png b/samples/android/video-recorder/res/drawable/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..630454927b592eb585c21527c430fc739c7970a6 GIT binary patch literal 1997 zcmV;;2Qv7HP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007bV*G`2iyk& z2s4Z(uWcvB1k+?B|HcZ5+p(*;Q^&-8AtzSnVCK7?)^Xiwf0*7z0ZN;t#z9i`sgtpqdV3hDNF*c2bKc!qcQaX zUny)Tz}^_l!dPca%!U9i64N>!i~1_h=?F58~*Mqs?aUag-wNp3eJ zaArHlobMV1PMO^yg*noOAUz|E0i{}8`nIiHOW|~F4mjoR_GH_vZVKN?bHNdXe;To> zxdyn_TnD>62p5lGlR~e9qrf7C+ui6sX@;J1@Mx>Yo=qMBRs~*)bDAoXUZYSHTab?f z_PACCXF@bcF}lW`X>mi~9D%@SGZ2{F%CTpbhLf>?v)%*vE3D~)z{*wz=t^t3pfEGA zffL(4AU5DX%yUkKoB_Jb(8oFW!NI-`j{z#&Z&^_sT-34vIXFYp`=GEPgYAu)4n9D4 z%K`*+8v7m2z|O!Kz|Xto?PB|!;VL`0G=ur`jDlQ$D=+i6dSt)j#Si?i#3rh3ZDkkx z+9TWVDcFEP;8fsZmts4LZyQ^=NS&&oMq^DBPd9*r!p~~YrdwMdQuxcK)CgcvlC7iQ z6m}XDL=_ke!d;S<2IvOy5aI>4B-sk!6i-qAqn6i#qR%}BH;aqaE~#zv6|u2ViZHn? z1hW8E8rkz`nyn$2WU0dhK4^p<)W{{jH|2^S^#FZ&jV&V)7;HC58VOgls*{S?bCuB! zgJG~P)&TrE+Oa9jPq^~G`MQI^ISDar1?}7f7D?&qi-Zc{Oivqep0%xlm22B7?$lt? zRDoZ$&ZSsjO2nE0ft%CR$aVrKp5WRX7^zue>Cw3+QGx=M@MFBYs{CEWmLZ zN*9hpz)s*B96QRjjj`Qi_;Vb>Z73h0DK9}$-axr}l%1BFSp9)x9Ky;`(^n%*$`F!V zkY*oPaAK+6&unXUeSit`5c;F3iU&9)kOVILi%-C3#za9jc>jUr;Wvs~#jZ#FaZ!2fi34Sb1N@BsFCj&@J zs;eb(o@Ffe=D?d6qPKGdXKQjn9~5j94Pu>ge`)`61V~3frX{l7>dTEi%6<8;N9K*(u}%^bWomltk*Vp@k|^lo)yA?qH}(jBlCHBo51XA|gNf(* zoeh<>k{r9Y4)pw$!k7FX&+PyB(?mq~(*^;K7{UQF&X#s!ILS zHX&7zhmyZ|_z=x$C7sRWW=r7+&daHU&gPWWQt)uC*X>tEFZ6J;H6WaAcCCQRo2VjP z>v8^kmJJ*U_eqdHY-p9+xixW&Umgf^mpLS>_nMj zvaJlD2pv8o7#@|SuT=D$XZ)5=GJyZFvEPhNoO#NE^Nc>q2{?8F#Z+({^MQk9zw9zH z=)VjA4HzfT(Fq(eDSwVGl!7_^3!$70OgHG7MYIxpx7Q{~Cgnag|7WoceAizs@IKwlGBBq*Ioi0qby4ylKkgqvR5BcLR&Vy39?8 + +