Video Compression using JavaCV - java

I'm using latest version of JavaCV to compress video and get mp4 file as per my requirement by using following piece of code.
File inputFile = new File(UTILS.getAppDirPath(),actual_input_file.getName());
File outputFile = new File(UTILS.getAppDirPath(),"comp_"+actual_file_name+".mp4");
FrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
grabber.start();
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile,
grabber.getImageWidth(), grabber.getImageHeight(),
grabber.getAudioChannels());
recorder.setFrameRate(grabber.getFrameRate());
recorder.setSampleRate(grabber.getSampleRate());
recorder.setFormat("mp4");
if(grabber.getVideoBitrate()>bitrate)
{
recorder.setVideoBitrate(bitrate);
}
else
{
recorder.setVideoBitrate(grabber.getVideoBitrate());
}
recorder.start();
int count = 0;
Frame frame;
while ((frame = grabber.grabFrame()) != null) {
recorder.record(frame);
count++;
}
recorder.stop();
grabber.stop();
And these are the libraries which I have placed in libs directory of application,
/libs
/libs/armeabi
/libs/armeabi/libavcodec.so
libs/armeabi/libavdevice.so
libs/armeabi/libavfilter.so
libs/armeabi/libavformat.so
libs/armeabi/libavutil.so
libs/armeabi/libjniavcodec.so
libs/armeabi/libjniavdevice.so
libs/armeabi/libjniavfilter.so
libs/armeabi/libjniavformat.so
libs/armeabi/libjniavutil.so
libs/armeabi/libjnicvkernels.so
libs/armeabi/libjniopencv_calib3d.so
libs/armeabi/libjniopencv_contrib.so
libs/armeabi/libjniopencv_core.so
libs/armeabi/libjniopencv_features2d.so
libs/armeabi/libjniopencv_flann.so
libs/armeabi/libjniopencv_highgui.so
libs/armeabi/libjniopencv_imgproc.so
libs/armeabi/libjniopencv_legacy.so
libs/armeabi/libjniopencv_ml.so
libs/armeabi/libjniopencv_nonfree.so
libs/armeabi/libjniopencv_objdetect.so
libs/armeabi/libjniopencv_photo.so
libs/armeabi/libjniopencv_stitching.so
libs/armeabi/libjniopencv_superres.so
libs/armeabi/libjniopencv_video.so
libs/armeabi/libjniopencv_videostab.so
libs/armeabi/libjnipostproc.so
libs/armeabi/libjniswresample.so
libs/armeabi/libjniswscale.so
libs/armeabi/libnative_camera_r2.2.0.so
libs/armeabi/libnative_camera_r2.3.3.so
libs/armeabi/libnative_camera_r3.0.1.so
libs/armeabi/libnative_camera_r4.0.0.so
libs/armeabi/libnative_camera_r4.0.3.so
libs/armeabi/libnative_camera_r4.1.1.so
libs/armeabi/libnative_camera_r4.2.0.so
libs/armeabi/libnative_camera_r4.3.0.so
libs/armeabi/libnative_camera_r4.4.0.so
libs/armeabi/libopencv_calib3d.so
libs/armeabi/libopencv_contrib.so
libs/armeabi/libopencv_core.so
libs/armeabi/libopencv_features2d.so
libs/armeabi/libopencv_flann.so
libs/armeabi/libopencv_gpu.so
libs/armeabi/libopencv_highgui.so
libs/armeabi/libopencv_imgproc.so
libs/armeabi/libopencv_legacy.so
libs/armeabi/libopencv_ml.so
libs/armeabi/libopencv_nonfree.so
libs/armeabi/libopencv_objdetect.so
libs/armeabi/libopencv_photo.so
libs/armeabi/libopencv_stitching.so
libs/armeabi/libopencv_superres.so
libs/armeabi/libopencv_video.so
libs/armeabi/libopencv_videostab.so
libs/armeabi/libpostproc.so
libs/armeabi/libswresample.so
libs/armeabi/libswscale.so
libs/armeabi/libtbb.so
libs/android-support-v4.jar
libs/commons-net-3.3.jar
libs/ffmpeg.jar
libs/gson-2.2.4.jar
libs/javacpp.jar
libs/javacv.jar
libs/opencv.jar
Issue:
Everything is working fine when I test on Samsung Galaxy S4, Google Nexus 7, Samsung Galaxy Core.
It is failed with errors when I test on Motorola Razr,
Errors which I am facing:
First error message:
02-11 09:54:57.579: E/dalvikvm(22745): dlopen("/data/app-lib/com.myapp.example.apk-1/libjniavdevice.so") failed: dlopen failed: cannot locate symbol "av_input_audio_device_next" referenced by "libjniavdevice.so"...
02-11 09:54:57.579: W/dalvikvm(22745): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lorg/bytedeco/javacpp/avdevice;
Second error message:
02-11 09:54:57.962: I/dalvikvm(22745): Could not find method java.awt.image.BufferedImage.getSampleModel, referenced from method org.bytedeco.javacpp.helper.opencv_core$AbstractIplImage.createFrom`
Third error message:
02-11 09:54:58.300: W/System.err(22745): org.bytedeco.javacv.FrameRecorder$Exception: avcodec_open2() error -22: Could not open audio codec.`
Note:
As of now, I have included library files for armeabi and I do have the library files for x86 as well.
Can the processor of some specific devices (Motorola Razr) be the reason for such crash? i.e.: Motorola Razr has Krait processor.

Related

MidiUnavailableException in Java on Android

I am writing a program in Java for android. When calling the getSequencer method, I get a MidiUnavailableException exception.
When executing this code :
MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
if (devices.length == 0) {
System.out.println("No MIDI devices found");
} else {
for (MidiDevice.Info dev : devices) {
System.out.println(dev);
}
}
I got the "No MIDI devices found". I realized that you can solve this problem by installing soundbank at this link:https://www.oracle.com/java/technologies/sound-banks.html
But it describes the installation method for Windows. And how to install soundbank for android?

Why is MediaExtractor returning 0 for getTrackCount() on Android O?

I am trying to create a custom video player in Android Oreo. After migrating from L, the extractor is returning 0 when getting trackCount. When the file is inserted in assets, it is working. There is no error on the opening extractor, only the log is showing no tracks found.
I added all permissions for writing and reading storage both from code and in the xml.
MediaExtractor extractor = new MediaExtractor();
try {
extractor.setDataSource(
"/sdcard/bbb_sunflower_1080p_30fps_normal.mp4" );
} catch (IOException e) {
e.printStackTrace();
}
int numTracks = extractor.getTrackCount();
I have fixed it by using com.android.tools.build:gradle:4.0.2 in build.gradle and gradle-6.9-all.zip in gradle-wrapper.properties. Please refer to below link: Why MediaExtractor getTrackCount returns 0 in android 4.4.2

Using Sphinx4: java.lang.IncompatibleClassChangeError

I am trying to build a program that will use basic voice recognition. I am encounter a issue while attempting to look up the "recognizer" component in the voice.config.xml file. I am relatively new to using Sphinx4 so it could be a very simple mistake. I have spent hours trying to find it so a well explained and detailed response would be greatly appreciated.
This is the methods that I will use to translate the input.
public static void translate() {
URL url = S2T.class.getResource("voice.config.xml");
ConfigurationManager cm = new ConfigurationManager(url);
PropertySheet ps = cm.getPropertySheet("voice.config.xml");
Microphone microphone = (Microphone) cm.lookup("microphone");
Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
recognizer.allocate();
if(microphone.startRecording()) {
while(true) {
Result result = recognizer.recognize();
String resultText = result.getBestResultNoFiller();
System.out.println("You said: " + resultText);
}
}
}
This is the error that I am getting when I call the method from another class:
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found class edu.cmu.sphinx.util.props.PropertySheet, but interface was expected
at edu.cmu.sphinx.model.acoustic.WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.Model.newProperties(Model.java:158)
at edu.cmu.sphinx.util.props.PropertySheet.getOwner(PropertySheet.java:505)
at edu.cmu.sphinx.util.props.PropertySheet.getComponent(PropertySheet.java:287)
at edu.cmu.sphinx.linguist.flat.FlatLinguist.setupAcousticModel(FlatLinguist.java:278)
at edu.cmu.sphinx.linguist.flat.FlatLinguist.newProperties(FlatLinguist.java:244)
at edu.cmu.sphinx.util.props.PropertySheet.getOwner(PropertySheet.java:505)
at edu.cmu.sphinx.util.props.PropertySheet.getComponent(PropertySheet.java:287)
at edu.cmu.sphinx.decoder.search.SimpleBreadthFirstSearchManager.newProperties(SimpleBreadthFirstSearchManager.java:182)
at edu.cmu.sphinx.util.props.PropertySheet.getOwner(PropertySheet.java:505)
at edu.cmu.sphinx.util.props.PropertySheet.getComponent(PropertySheet.java:287)
at edu.cmu.sphinx.decoder.AbstractDecoder.newProperties(AbstractDecoder.java:65)
at edu.cmu.sphinx.decoder.Decoder.newProperties(Decoder.java:37)
at edu.cmu.sphinx.util.props.PropertySheet.getOwner(PropertySheet.java:505)
at edu.cmu.sphinx.util.props.PropertySheet.getComponent(PropertySheet.java:287)
at edu.cmu.sphinx.recognizer.Recognizer.newProperties(Recognizer.java:90)
at edu.cmu.sphinx.util.props.PropertySheet.getOwner(PropertySheet.java:505)
at edu.cmu.sphinx.util.props.ConfigurationManager.lookup(ConfigurationManager.java:161)
at LukeTrujillo.CAB.Voice.S2T.translate(S2T.java:25)
at LukeTrujllo.CAB.Main.Main.main(Main.java:14)
This is the my current build path for the package that this class is in:
LukeTrujillo/CAB/Voice/
- Main.java
- S2T.gram
- voice.config.xml
- voice.Manifest
Sphinx JARs in Classpath:
js.jar
jsapi-1.0-base.jar
sphinx4.jar
tags.jar
jl1.01.jar
resty-0.3.2.jar
WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar
TIDIGITS_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar
You are using outdated sphinx4 with incompatible versions. You can find a tutorial
and the latest downloads on CMUSphinx website:
http://cmusphinx.sourceforge.net/wiki/tutorialsphinx4

MediaRecorder - setOrientationHint() exception/fail

I've been trying to fix this problem with MediaRecorder video Rotation on and off for weeks. I cannot get the line setOrientationHint(90) to work on a physical Samsung Galaxy S1 running Android 2.3.3 (SDK 10). This should run fine on anything above SDK 9.
When I call setOrientationHint(90) I get an exception : setParameters(video-param-rotation-angle-degrees=90) failed. Detailed error details below.
As a result I'm forced to check SDK and only call setOrientationHint() if SDK>10. ie, this code works fine on all other SDK versions above 10 which I have tested. I have tested on Samsung Galaxy Nexus running 4.2.2 and works fine.
Here is my code:
(cut down to show order of calls to MediaRecorder)
mCamera = getCameraInstance();
mCamera.setPreviewDisplay(holder);
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setOrientationHint(90);
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: recording setup
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoSize(720,480);
mMediaRecorder.setVideoFrameRate(15);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
// Step 4: Set output file
currentOutputFileName = DIRECTORY_PATH + "zzzz"+ iCount +".mp4";
mFile = new File(currentOutputFileName);
mMediaRecorder.setOutputFile(mFile.getAbsolutePath());
// Step 4.1: Set recording length
mMediaRecorder.setMaxDuration(10000);
// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(cameraView.getHolder().getSurface());
// Step 6: Prepare configured MediaRecorder
mMediaRecorder.prepare();
Has anyone had this problem? I can't find anyone else is experiencing this and I can't believe thats the case. Is it possible its just a Australian Samsung Galaxy S1 running 2.3.3 issue?
I've seen references to people having problems where that line runs but with the actual video does not rotate but I actually receive an Exception - the line doesn't run at all. I've checked and rechecked the command order and it seems fine. I think what is most important is that the setOrientationHint() command occurs before mediaRecorder.prepare()
Here is the Error:
AuthorDriver::setParameter() unrecognized key "video-param-rotation-angle-degrees"
setParameter(video-param-rotation-angle-degrees = 90) failed with result -5
Ln 1047 handleSetParameters("video-param-rotation-angle-degrees=90") error
Command (12) failed
setParameters(video-param-rotation-angle-degrees=90) failed: -2147483648
Shutting down VM
threadid=1: thread exiting with uncaught exception (group=0x40015578)
FATAL EXCEPTION: main
java.lang.RuntimeException: setParameter failed.
at android.media.MediaRecorder.setParameter(Native Method)
at android.media.MediaRecorder.setOrientationHint(MediaRecorder.java:341)
at com.on3x.emergency.Recorder.prepareVideoRecorder(Recorder.java:196)
at com.on3x.emergency.Recorder.startRecording(Recorder.java:90)
at com.on3x.emergency.GUI.RecordActivity$1.onClick(RecordActivity.java:86)
at android.view.View.performClick(View.java:2538)
at android.view.View$PerformClick.run(View.java:9152)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Force finishing activity com.on3x.emergency/.GUI.RecordActivity
Dumpstate > /data/log/dumpstate_app_error
If anyone can give ANY help it would be much appreciated. For now I've had to tell our client that its not something I can fix at this moment and Video will have to be sideways.
Is there another way of rotating videos? Basically my app records videos and uploads them to the server. At the moment this 2.3.3 phone cannot rotate the video so its uploaded sideways
Cheers
Edit:
This is the code I now have in place. As suggested by Ashish Gupta, AuthorDriver does not contain the appropriate param on Samsung Galaxy S1 (australian model) running 2.3.3
if (android.os.Build.VERSION.SDK_INT>=9) {
// attempt to rotate the video 90 degrees.
try {
mMediaRecorder.setOrientationHint(90);
Utils.logLine("orientation rotated 90", this, Utils.LOG_TYPE_DEBUG);
} catch (Exception e) {
Utils.logLine("error trying setOrientationHint"+ e.getMessage(), this, Utils.LOG_TYPE_ERROR, e);
e.printStackTrace();
}
} else {
Utils.logLine("orientation set skipped ", this, Utils.LOG_TYPE_DEBUG);
}
Note: Utils.logLine is simply a Utilility function I have for printing debug and error statements to log. Hopefully that might help someone else...
Looking at the logs you have attached, it seems that Samsung Galaxy S1 running Android 2.3.3 does not support setOrientationHint.
This is the code from AuthorDriver.cpp
PVMFStatus AuthorDriver::setParameter(
const String8& key, const String8& value) {
if (key == "max-duration") {
int64_t max_duration_ms;
if (safe_strtoi64(value.string(), &max_duration_ms)) {
return setMaxDurationOrFileSize(
max_duration_ms, true /* limit_is_duration */);
}
} else if (key == "max-filesize") {
int64_t max_filesize_bytes;
if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
return setMaxDurationOrFileSize(
max_filesize_bytes, false /* limit is filesize */);
}
} else if (key == "audio-param-sampling-rate") {
int64_t sampling_rate;
if (safe_strtoi64(value.string(), &sampling_rate)) {
return setParamAudioSamplingRate(sampling_rate);
}
} else if (key == "audio-param-number-of-channels") {
int64_t number_of_channels;
if (safe_strtoi64(value.string(), &number_of_channels)) {
return setParamAudioNumberOfChannels(number_of_channels);
}
} else if (key == "audio-param-encoding-bitrate") {
int64_t audio_bitrate;
if (safe_strtoi64(value.string(), &audio_bitrate)) {
return setParamAudioEncodingBitrate(audio_bitrate);
}
} else if (key == "video-param-encoding-bitrate") {
int64_t video_bitrate;
if (safe_strtoi64(value.string(), &video_bitrate)) {
return setParamVideoEncodingBitrate(video_bitrate);
}
}
// Return error if the key wasnt found
LOGE("AuthorDriver::setParameter() unrecognized key \"%s\"", key.string());
return PVMFErrArgument;
}
The key video-param-rotation-angle-degrees is not supported on Samsung Galaxy S1 aith Android 2.3.3
You can compare the logs between Nexus 4.2.2 and S1 2.3.3 and see if you see any noticeable difference.

How to implement a Java compiler and DEX converter into an Android app?

While trying to find an answer to Android Jasper Reporting I found out that there are two other questions to be answered therefor, which I been asked to ask as a question, not as an answer ;):
My questions are now: "Is there any compiler to use directly on the device" AND "how to execute such without rooting the device.
If anybody could give me a hint I would really appreciate it...
I looked a little time forward on this approach, and found apps which makes it possible to create APKs directly on an Android device which is NOT rooted:
TerminalIDE - https://play.google.com/store/apps/details?id=com.spartacusrex.spartacuside&hl=de
JavaIDEdroid - http://code.google.com/p/java-ide-droid/
AIDE - https://play.google.com/store/apps/details?id=com.aide.ui&hl=en
Looks like they're using the compiler from eclipse and a ported dex converter. Now I'm trying to figure out how to do the same.
Sure: get the source code and look into it. But while I'm having curious problems to get a connection to the servers and trying to solve it, I follow the plea to ask this question here. Hoping both to help others with it and also getting an answer for myself ;)
I took the org.eclipse.jdt.core_3.7.3.v20120119-1537.jar from the plugin directory of my indigo and tried following code:
org.eclipse.jdt.internal.compiler.batch.Main ecjMain = new org.eclipse.jdt.internal.compiler.batch.Main(new PrintWriter(System.out), new PrintWriter(System.err), false/*noSystemExit*/, null, progress);
System.err.println("compiling...");
ecjMain.compile(new String[] {"-classpath", "/system/framework", storage.getAbsolutePath()+"/Test.java"});
ecjMain.compile(new String[] {storage.getAbsolutePath()+"/Test.java"});
System.err.println("compile succeeded!!!");
Sometimes the Exception was thrown that java.lang.Object could not be found and othertimes it stuck doing nothing while heating up my processor with 100% usage ... ...
At this time i could not figure out what is happening and why. And in cause that i have other work to do this part has to wait a little.
I succeeded after taking inspiration from source of JavaIDEdroid and realizing that I'm dumb (for a time I tried to uses the compiler with the dexified framework classes on the device - which naturtally could not work).
After i succeeded compiling my Test.java with a copy of ADTs android-jar on sdcard I just had to load the classes with the DexClassLoader.
While informing myselft about how to do that I found this nice article Custom Class Loading in Dalvik which inspired me at least to write this piece of code:
File storage = getDir("all41", Context.MODE_PRIVATE);
System.err.println("copying the android.jar from asssets to the internal storage to make it available to the compiler");
BufferedInputStream bis = null;
OutputStream dexWriter = null;
int BUF_SIZE = 8 * 1024;
try {
bis = new BufferedInputStream(getAssets().open("android.jar"));
dexWriter = new BufferedOutputStream(
new FileOutputStream(storage.getAbsolutePath() + "/android.jar"));
byte[] buf = new byte[BUF_SIZE];
int len;
while((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
dexWriter.write(buf, 0, len);
}
dexWriter.close();
bis.close();
} catch (Exception e) {
System.err.println("Error while copying from assets: " + e.getMessage());
e.printStackTrace();
}
System.err.println("instantiating the compiler and compiling the java file");
org.eclipse.jdt.internal.compiler.batch.Main ecjMain = new org.eclipse.jdt.internal.compiler.batch.Main(new PrintWriter(System.out), new PrintWriter(System.err), false/*noSystemExit*/, null);
ecjMain.compile(new String[] {"-classpath", storage.getAbsolutePath()+"/android.jar", Environment.getExternalStorageDirectory().getAbsolutePath() + "/Test.java"});
System.err.println("calling DEX and dexifying the test class");
com.android.dx.command.Main.main(new String[] {"--dex", "--output=" + storage.getAbsolutePath() + "/Test.zip", Environment.getExternalStorageDirectory().getAbsolutePath() + "/./Test.class"});
System.err.println("instantiating DexClassLoader, loading class and invoking toString()");
DexClassLoader cl = new DexClassLoader(storage.getAbsolutePath() + "/Test.zip", storage.getAbsolutePath(), null, getClassLoader());
try {
Class libProviderClazz = cl.loadClass("Test");
Object instance = libProviderClazz.newInstance();
System.err.println(instance.toString());
} catch (Exception e) {
System.err.println("Error while instanciating object: " + e.getMessage());
e.printStackTrace();
}
The Test.java only contains one method:
public String toString() {
return "Hallo Welt!";
}
To get it running you need the jars jdt-compiler-x.x.x.jar (found in plugins directory of eclipse) and dx.jar (found in directory platform-tools/lib of Android SDK)
Not really hard ;) And now I will find out what to change in source of JasperReports to get it work on our beloved Android devices :D

Categories

Resources