I've noticed that java/android/media has a method called createDecoderByType() that is supposed to return a MediaCodec object. However, when I look at the MediaCodec.java source code on GoogleGit, I can't really see how the actual decoder is generated. Here is the code for that method:
public static MediaCodec createDecoderByType(String type) {
return new MediaCodec(type, true /* nameIsType */, false /* encoder */);
}
Then when I look at the constructor to see what is returned, this is what I see:
private MediaCodec(
String name, boolean nameIsType, boolean encoder) {
native_setup(name, nameIsType, encoder);
}
Okay, great. Let's look at native_setup(). Here's the definition:
private native final void native_setup(
String name, boolean nameIsType, boolean encoder);
That function appears to have no body!
At first I assumed that this meant the method would be defined in a child class. But I am seeing this method called directly on MediaCodec itself in other functioning source code.
So my question is: Is there any way I can trace down and see how Android creates a decoder of a given type depending on the environment and parameters? I seem to have hit a dead end, and no amount of Googling is giving me any helpful results.
Just found the answer to this the minute after I posted it...of course. The issue is with the native keyword. From GeeksforGeeks:
The native keyword is applied to a method to indicates that the method is implemented in native code using JNI (Java Native Interface).
This means that it can be written in another language such as C or C++, or invoke hardware stuff. The MediaCodec JNI code that I was looking for is here.
Related
I have the following Java code generated using SWIG. Although SWIG was used to generate the code knowledge of SWIG should not be needed to understand this question
User facing Java code:
public class UuidUtil implements OCUuidUtilConstants {
public static Uuid generateUuid() {
long cPtr = UuidUtilJNI.generateUuid();
return (cPtr == 0) ? null : new Uuid(cPtr, true);
}
}
The UuidUtilJNI.generateUuid() is defined as follows
Java code calling JNI code
public class UuidUtilJNI {
public final static native long generateUuid();
}
The SWIG generated JNI C wrapper code uuid_wrap.c
uuid_t * jni_gen_uuid()
{
printf("Inside jni_gen_uuid\n");
uuid_t *value = (uuid_t *)malloc(sizeof(uuid_t));
printf("Calling gen_uuid\n");
gen_uuid(value);
return value;
}
SWIGEXPORT jlong JNICALL Java_UuidUtilJNI_generateUuid(JNIEnv *jenv, jclass jcls) {
jlong jresult = 0 ;
uuid_t *result = 0 ;
(void)jenv;
(void)jcls;
result = (uuid_t *)jni_gen_uuid();
*(uuid_t **)&jresult = result;
return jresult;
}
partial C code for gen_uuid(uuid_t *uuid) function uuid.c
void gen_uuid(uuid_t *uuid)
{
printf("Inside gen_uuid\n");
/* code to set the uuid to type 4 UUID according to RFC4122 */
}
I am testing it as follows:
#Test
public void generateAndConvert() {
Uuid testUuid = UuidUtil.generateUuid();
assertNotNull(testUuid);
// other test code left out for readability
}
When the test is run on Windows the code works as expected.
When I try and run the same code on Linux the test hangs.
It prints 2 of the 3 print staments found in the code.
Inside jni_gen_uuid
Calling gen_uuid
the line Inside gen_uuid is never called when the test is run on a Linux machine (Fedora 30).
My first thought was that there was some sort of mismatch in the output of the object files causing the wrapper code to fail when calling the uuid code. I have compared the build flags used to build uuid.c and uuid_wrap.c code and they are using the same flags with the exception that some of the build warning are shut off for the wrapper code because its generated by a tool and not intended to
be modified by me.
I don't really know where else to look.
I have checked the uuid.o file using nm and objdump as best I can tell it has the gen_uuid symbol.
I have not been able to properly attach gdb to the running sample so not sure if that would provide any useful information.
Any suggestions that may help find the issue?
Unfortunately this solution was very specific to my code.
When I wrote that the print statement
printf("Inside gen_uuid\n");
/* code to set the uuid to type 4 UUID according to RFC4122 */
was never called I was wrong. The text was just not flushed to the screen. Adding fflush(stdout); after the print statement would have shown that indeed the gen_uuid function was being called.
As noted in the question this code generates a type 4 UUID which is a random UUID.
The code that generates random numbers is OS specific. Before the random number can be read the random number generator must be initialized. On Linux this is done by grabbing a file descriptor to /dev/urandom on Windows it is done by seeding srand() function.
Linux would segfault when generating the random number if random_init was not called. Windows on the other hand would produce a number even if it were not seeded.
The solution was to call randomInit() before calling generateUuid() in the unit test.
If you are a developer exploring a similar failure and are using printf debugging to check if a line of code was reached then make sure the print statement is flushed to the screen before concluding that a line of code is not being reached.
I'm writing a program in Java for Spark 1.6.0 (so, please, don't supply Scala or Python code in your answers), and this is the code I'd like to implement:
double i = 0d;
JavaRDD<Vector> ideas = objects.map(
new Function<BSONObject, Vector>()
{
#Override public Vector call(final BSONObject t) throws Exception
{
double[] xy = new double[2];
xy[0] = i++;
xy[1] = ((Long)((Date)t.get("date")).toInstant().toEpochMilli()).doubleValue();
return Vectors.dense(xy);
}
}
);
but NetBeans shows an error: "Local variables referenced from an inner class must be final or effectively final".
I also tried to use Spark Accumulators, but if I call the value() method from the call() method I'm defining, a SparkException is raised during the job, telling me that "Task is not serializable", then the job fails.
So, how can I achieve my goal?
I apologize in advance if my English is not perfect (it's not my native language), and if my question could appear noob-ish, but I can't find any solution online.
Even if it compiled it wouldn't work as you expect. Each executor get its own copy of the variables referenced inside closure and any modifications are strictly local and are not propagated back to original source. Spark supports writable accumulators which can be used as follows:
Accumulator<Double> accum = sc.accumulator(0d);
objects.map(
...
accum.add(1d)
...
)
but these provide very weak guarantees (called at-least-once) when used inside transformations and, as you've already realized, are write-only from the worker perspective.
Regarding your code it looks like all you need is zipWithIndex:
objects.zipWithIndex().map(...)
Checking the source code for MediaPlayer (link), the start() method looks like this:
public void start() throws IllegalStateException {
stayAwake(true);
_start();
}
And _start() method looks like this:
private native void _start() throws IllegalStateException;
Checking the native _start() method (link) (called start() but should it not be called _start() because of the native call was named _start()?):
status_t MediaPlayer::start()
{
ALOGV("start");
Mutex::Autolock _l(mLock);
if (mCurrentState & MEDIA_PLAYER_STARTED)
return NO_ERROR;
if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
mPlayer->setLooping(mLoop);
mPlayer->setVolume(mLeftVolume, mRightVolume);
mPlayer->setAuxEffectSendLevel(mSendLevel);
mCurrentState = MEDIA_PLAYER_STARTED;
status_t ret = mPlayer->start();
if (ret != NO_ERROR) {
mCurrentState = MEDIA_PLAYER_STATE_ERROR;
} else {
if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
ALOGV("playback completed immediately following start()");
}
}
return ret;
}
ALOGE("start called in state %d", mCurrentState);
return INVALID_OPERATION;
}
Where is the data read? I wanted to check how Android work with RTSP but I could not find out where it loads the data. I wanted to know if it uses some library like FFMpeg or some other implementation.
EDIT:
Why was this code necessary to use JNI for?
All of the following paths reference src/frameworks/base/.
In media/jni/android_media_MediaPlayer.cpp you will find the JNI code that forwards the Java method call to the underlying native framework. You can see the name mapping in the gMethods[] array and the AndroidRuntime::registerNativeMethods call near the bottom of the file. You can read more about registering native methods with JNI here, but that's not really the interesting part.
At this stage we are in the native counterpart of the Java MediaPlayer. For the most part, it doesn't do anything interesting, either. It binds to the MediaPlayerService through IBinder transactions. The MediaPlayerService creates the actual native player based on the type of media, and maintains a client (MediaPlayerService::Client) to facilitate communication with the native MediaPlayer, which in turn bubbles things back up to Java. You can see all this happen in the following files (if you're interested):
media/libmedia/mediaplayer.cpp,
media/libmedia/IMediaPlayer.cpp,
media/libmedia/IMediaPlayerClient.cpp,
media/libmedia/IMediaPlayerService.cpp,
media/libmediaplayerservice/MediaPlayerService.cpp
Header files for libmedia are in include/media/libmedia/.
Now to the really interesting part, which are the component players. In MediaServicePlayer.cpp there are a couple of getPlayerType methods that decide what player to instantiate. There's Stagefright framework (AwesomePlayer and NuPlayer) and Sonivox player for MIDI. For RTSP, NuPlayer is what you'll get. You can find a glue layer in media/libmediaplayerservice/nuplayer/ and all the real source code in media/libstagefright/ and media/libstagefright/rtsp/.
You missed a step along the way. The private native void _start() in the Java code refers to this entry in the MediaPlayer JNI layer (which refers to this function).
As for the RTSP implementation, you'll probably find it among the Stagefright sources.
_start method is defined in jni in this mediaplayer file link
from here that libmedia start method is getting called.
I need to show on my panel the working dir.
I use String value = System.getProperty("user.dir"). Afterwards i put this string on label but I receive this message on console:
The method getProperty(String, String) in the type System is not applicable for the arguments (String).
I use eclipse.
Issue
I am guessing you have not gone through GWT 101 - You cannot blindly use JAVA CODE on client side.
Explanation
You can find the list of classes and methods supported for GWT from JAVA.
https://developers.google.com/web-toolkit/doc/latest/RefJreEmulation
For System only the following are supported.
err, out,
System(),
arraycopy(Object, int, Object, int, int),
currentTimeMillis(),
gc(),
identityHashCode(Object),
setErr(PrintStream),
setOut(PrintStream)
Solution
In your case Execute System.getProperty("user.dir") in your server side code and access it using RPC or any other server side gwt communication technique.
System.getProperty("key") is not supported,
but System.getProperty("key", "default") IS supported, though it will only return the default value as there is not system properties per se.
If you need the working directory during gwt compile, you need to use a custom linker or generator, grab the system property at build time, and emit it as a public resource file.
For linkers, you have to export an external file that gwt can download and get the compile-time data you want. For generators, you just inject the string you want into compiled source.
Here's a slideshow on linkers that is actually very interesting.
http://dl.google.com/googleio/2010/gwt-gwt-linkers.pdf
If you don't want to use a linker and an extra http request, you can use a generator as well, which is likely much easier (and faster):
interface BuildData {
String workingDirectory();
}
BuildData data = GWT.create(BuildData.class);
data.workingDirectory();
Then, you need to make a generator:
public class BuildDataGenerator extends IncrementalGenerator {
#Override
public RebindResult generateIncrementally(TreeLogger logger,
GeneratorContext context, String typeName){
//generator boilerplate
PrintWriter printWriter = context.tryCreate(logger, "com.foo", "BuildDataImpl");
if (printWriter == null){
logger.log(Type.TRACE, "Already generated");
return new RebindResult(RebindMode.USE_PARTIAL_CACHED,"com.foo.BuildDataImpl");
}
SourceFileComposerFactory composer =
new SourceFileComposerFactory("com.foo", "BuildDataImpl");
//must implement interface we are generating to avoid class cast exception
composer.addImplementedInterface("com.foo.BuildData");
SourceWriter sw = composer.createSourceWriter(printWriter);
//write the generated class; the class definition is done for you
sw.println("public String workingDirectory(){");
sw.println("return \""+System.getProperty("user.dir")+"\";");
sw.println("}");
return new RebindResult(RebindMode.USE_ALL_NEW_WITH_NO_CACHING
,"com.foo.BuildDataImpl");
}
}
Finally, you need to tell gwt to use your generator on your interface:
<generate-with class="dev.com.foo.BuildDataGenerator">
<when-type-assignable class="com.foo.BuildData" />
</generate-with>
Edit 2 After recieving a response from Mathworks support I've answered the question myself. In brief, there is an options class MWComponentOptions that is passed to the exported class when instantiated. This can, among other things, specify unique print streams for error output and regular output (i.e. from disp()-liked functions). Thanks for all the responses none the less :)
====================================================================
Just a quick question - is there any way to prevent MATLAB code from outputting to the Java console with disp (and similar) functions once compiled? What is useful debugging information in MATLAB quickly becomes annoying extra text in the Java logs.
The compilation tool I'm using is MATLAB Compiler (which I think is not the same as MATLAB Builder JA, but I might be wrong). I can't find any good documentation on the mcc command so am not sure if there are any options for this.
Of course if this is impossible and a direct consequence of the compiler converting all MATLAB code to its Java equivalent then that's completely understandable.
Thanks in advance
Edit This will also be useful to handle error reporting on the Java side alone - currently all MATLAB errors are sent to the console regardless of whether they are caught or not.
The isdeployed function returns true if run in a deployed application (with e.g. MATLAB Compiler or Builder JA) and false when running in live MATLAB.
You can surround your disp statements with an if isdeployed block.
I heard back from a request to Mathworks support, and they provided the following solution:
When creating whatever class has been exported, you can specify an MWComponentOptions object. This is poorly documented in R2012b, but for what I wanted the following example would work:
MWComponentOptions options = new MWComponentOptions();
PrintStream o = new PrintStream(new File("MATLAB log.log"));
options.setPrintStream(o); // send all standard dips() output to a log file
// the following ignores all error output (this will be caught by Java exception handling anyway)
options.setErrorStream((java.io.PrintStream)null);
// instantiate and use the exported class
myClass obj = new myClass(options);
obj.myMatlabFunction();
// etc...
Update
In case anyone does want to suppress all output, casing null to java.io.PrintStream ended up causing a NullPointerException in deployment. A better way to suppress all output is use to create a dummy print stream, something like:
PrintStream dummy = new PrintStream(new OutputStream() {
public void close() {}
public void flush() {}
public void write(byte[] b) {}
public void write(byte[] b, int off, int len) {}
public void write(int b) {}
} );
Then use
options.setErrorStream(dummy);
Hope this helps :)
Another possible hack if you have a stand-alone application and don't want to bother with classes at all:
Use evalc and deploy your func name during compile:
function my_wrap()
evalc('my_orig_func(''input_var'')');
end
And compile like
mcc -m my_wrap my_orig_func <...>
Well, it is obviously yet another hack.