2016-09-19, 08:06
The fix koying did is correct. As the write method changed from before v23 to now. I will add this.
Quote:int write (short[] audioData,
int offsetInShorts,
int sizeInShorts)
Writes the audio data to the audio sink for playback (streaming mode), or copies audio data for later playback (static buffer mode). The format specified in the AudioTrack constructor should be ENCODING_PCM_16BIT to correspond to the data in the array.
(2016-09-19, 08:15)fritsch Wrote: Mmmh - reading more exact, I need to take that back, see:
Quote:int write (short[] audioData,
int offsetInShorts,
int sizeInShorts)
Writes the audio data to the audio sink for playback (streaming mode), or copies audio data for later playback (static buffer mode). The format specified in the AudioTrack constructor should be ENCODING_PCM_16BIT to correspond to the data in the array.
As we explicitely don't open the device in ENCODING_PCM_16BIT mode, we now have undocumented behaviour. Please also backport the correct signed int writing method. Is that possible?
In other words:
If vendor A backports it correctly, it cannot correctly use it, cause vendor B missed this one method.
GetStaticValue(c, CJNIAudioFormat::ENCODING_IEC61937, "ENCODING_IEC61937");
Quote:Kodi 16.1 logs where IEC 61937 pass-through worked.^^ does not matter at all. We don't talk about "what works" but about how to do it properly to make it work once and for all in the way the API wants it.
https://drive.google.com/file/d/0B2JoqOT...JxRjA/view
Spreadsheet with Kodi Test Videos with Kodi 16.1 IEC pass-through based on RKMC.
https://drive.google.com/file/d/0B2JoqOT...FkUWM/view
static jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz,
jshortArray javaAudioData,
jint offsetInShorts, jint sizeInShorts,
jint javaAudioFormat,
jboolean isWriteBlocking) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for write()");
return 0;
}
jshort* cAudioData = NULL;
if (javaAudioData) {
cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
if (cAudioData == NULL) {
ALOGE("Error retrieving source of audio data to play, can't play");
return 0; // out of memory or no data to load
}
} else {
ALOGE("NULL java array of audio data to play, can't play");
return 0;
}
jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
offsetInShorts * sizeof(short), sizeInShorts * sizeof(short),
isWriteBlocking == JNI_TRUE /* blocking */);
env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);
if (written > 0) {
written /= sizeof(short);
}
return written;
}
(2016-09-19, 08:49)fritsch Wrote: https://developer.android.com/reference/...G_IEC61937 <- it is 13 (d), but we call
Code:GetStaticValue(c, CJNIAudioFormat::ENCODING_IEC61937, "ENCODING_IEC61937");
So that gets overwritten with the value you actually used yourself. But it's better to use 13 - as this is how it is defined in the API - for compatibility arround _all_ mediaplayers.
Quote:Kodi 16.1 logs where IEC 61937 pass-through worked.^^ does not matter at all. We don't talk about "what works" but about how to do it properly to make it work once and for all in the way the API wants it.
https://drive.google.com/file/d/0B2JoqOT...JxRjA/view
Spreadsheet with Kodi Test Videos with Kodi 16.1 IEC pass-through based on RKMC.
https://drive.google.com/file/d/0B2JoqOT...FkUWM/view
The patch is fine (besides the 13 (d in hex)). Please also backport the int16 API - which is very easy to do.
For your code, add:
Don't forget to add the method definition to the proper file.Code:static jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz,
jshortArray javaAudioData,
jint offsetInShorts, jint sizeInShorts,
jint javaAudioFormat,
jboolean isWriteBlocking) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for write()");
return 0;
}
jshort* cAudioData = NULL;
if (javaAudioData) {
cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
if (cAudioData == NULL) {
ALOGE("Error retrieving source of audio data to play, can't play");
return 0; // out of memory or no data to load
}
} else {
ALOGE("NULL java array of audio data to play, can't play");
return 0;
}
jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
offsetInShorts * sizeof(short), sizeInShorts * sizeof(short),
isWriteBlocking == JNI_TRUE /* blocking */);
env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);
if (written > 0) {
written /= sizeof(short);
}
return written;
}
int write (short[] audioData,
int offsetInShorts,
int sizeInShorts)
int write (short[] audioData,
int offsetInShorts,
int sizeInShorts,
int writeMode)
(2016-09-19, 11:26)fritsch Wrote: Take care:
Old, since API v3, you still need that:
New since API v23, you will need that for our PT:Code:int write (short[] audioData,
int offsetInShorts,
int sizeInShorts)
Code:int write (short[] audioData,
int offsetInShorts,
int sizeInShorts,
int writeMode)
It's a simple overwrite, needed so that the jni can map it correctly.
Edit: If you are really lazy (not recommended), just add the second method and call your first method ommiting the additional parameter. Not recommended, cause of the blocking mode that you cannot handle then. We assume blocking mode in the sink. As this is where the loop for adding packages stop.
Quote:Should these lines also be added to Lollipop as it is in Marshmallow or not needed and will cause other problems?
https://github.com/geekboxzone/mmallow_f...1846-L1849
(2016-09-20, 08:34)fritsch Wrote: Any news on your side?
public int write(short[] audioData, int offsetInShorts, int sizeInShorts
@WriteMode int writeMode) {
// lazy way to ignore the blocking argument
return write(audioData, offsetInShorts, sizeInShorts);
}
(2016-09-20, 09:11)fritsch Wrote: I know that the build works, cause it works on Nexus with Android N.
You just have to add the new method in there.
Easiest:
Code:public int write(short[] audioData, int offsetInShorts, int sizeInShorts
@WriteMode int writeMode) {
// lazy way to ignore the blocking argument
return write(audioData, offsetInShorts, sizeInShorts);
}
But as you support blocking for float anyways, it's just the code I gave you above already.