Skip to content

Commit

Permalink
Make encoder and decoder thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
henkelmax committed Aug 10, 2023
1 parent 7112fbf commit 55711ca
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 62 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>de.maxhenkel.lame4j</groupId>
<artifactId>lame4j</artifactId>
<version>2.0.2</version>
<version>2.0.3</version>

<name>Lame Wrapper for Java</name>
<url>https://maxhenkel.de</url>
Expand Down
44 changes: 22 additions & 22 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "lame4j"
version = "2.0.2"
version = "2.0.3"
edition = "2021"

[dependencies]
Expand Down
14 changes: 7 additions & 7 deletions rust/src/lame/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct DecoderWrapper {
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_createDecoder(_env: JNIEnv, _class: JClass) -> jlong {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_createDecoder0(_env: JNIEnv, _class: JClass) -> jlong {
let stream_wrapper = JavaInputStream {
env: None,
input_stream: None,
Expand All @@ -32,7 +32,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_createDecoder(_env: JNIEnv
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_decodeNextFrame<'a>(mut env: JNIEnv<'static>, obj: JObject<'a>, stream: JObject<'static>) -> JShortArray<'a> {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_decodeNextFrame0<'a>(mut env: JNIEnv<'static>, obj: JObject<'a>, stream: JObject<'static>) -> JShortArray<'a> {
let decoder_wrapper = match get_decoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand Down Expand Up @@ -85,7 +85,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_decodeNextFrame<'a>(mut en
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_headerParsed(mut env: JNIEnv, obj: JObject) -> jboolean {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_headerParsed0(mut env: JNIEnv, obj: JObject) -> jboolean {
let decoder_wrapper = match get_decoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand All @@ -96,7 +96,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_headerParsed(mut env: JNIE
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getChannelCount(mut env: JNIEnv, obj: JObject) -> jint {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getChannelCount0(mut env: JNIEnv, obj: JObject) -> jint {
let decoder_wrapper = match get_decoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand All @@ -107,7 +107,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getChannelCount(mut env: J
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getBitRate(mut env: JNIEnv, obj: JObject) -> jint {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getBitRate0(mut env: JNIEnv, obj: JObject) -> jint {
let decoder_wrapper = match get_decoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand All @@ -118,7 +118,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getBitRate(mut env: JNIEnv
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getSampleRate(mut env: JNIEnv, obj: JObject) -> jint {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getSampleRate0(mut env: JNIEnv, obj: JObject) -> jint {
let decoder_wrapper = match get_decoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand All @@ -129,7 +129,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_getSampleRate(mut env: JNI
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_destroyDecoder(mut env: JNIEnv, obj: JObject) {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_destroyDecoder0(mut env: JNIEnv, obj: JObject) {
let pointer = get_pointer(&mut env, &obj);

if pointer == 0 {
Expand Down
8 changes: 4 additions & 4 deletions rust/src/lame/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct LameEncoder {
}

#[no_mangle]
pub unsafe extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_createEncoder(mut env: JNIEnv, _class: JClass, channels: jint, sample_rate: jint, bit_rate: jint, quality: jint) -> jlong {
pub unsafe extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_createEncoder0(mut env: JNIEnv, _class: JClass, channels: jint, sample_rate: jint, bit_rate: jint, quality: jint) -> jlong {
let lame = lame_init();

lame_set_num_channels(lame, channels as i32);
Expand All @@ -42,7 +42,7 @@ pub unsafe extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_createEncoder(mut e
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_writeInternal<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>, input: JShortArray<'a>) -> JByteArray<'a> {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_writeInternal0<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>, input: JShortArray<'a>) -> JByteArray<'a> {
let lame = match get_lame(&mut env, &obj) {
Some(lame) => lame,
None => {
Expand Down Expand Up @@ -110,7 +110,7 @@ fn estimate_mp3_buffer_size(num_samples: i32) -> usize {
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_flush<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>) -> JByteArray<'a> {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_flush0<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>) -> JByteArray<'a> {
let lame = match get_lame(&mut env, &obj) {
Some(lame) => lame,
None => {
Expand Down Expand Up @@ -142,7 +142,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_flush<'a>(mut env: JNIEnv<
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_destroyEncoder(mut env: JNIEnv, obj: JObject) {
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Encoder_destroyEncoder0(mut env: JNIEnv, obj: JObject) {
let pointer = get_pointer(&mut env, &obj);

if pointer == 0 {
Expand Down
58 changes: 44 additions & 14 deletions src/main/java/de/maxhenkel/lame4j/Mp3Decoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ public class Mp3Decoder implements Audio, AutoCloseable {
public Mp3Decoder(InputStream inputStream) throws IOException, UnknownPlatformException {
Lame.load();
this.inputStream = inputStream;
decoder = createDecoder();
decoder = createDecoder0();
}

private static native long createDecoder();
private static native long createDecoder0();

private native short[] decodeNextFrame0(InputStream stream) throws IOException;

/**
* Decodes the next frame in the mp3 file and returns the decoded audio data as PCM samples.
Expand All @@ -27,31 +29,55 @@ public Mp3Decoder(InputStream inputStream) throws IOException, UnknownPlatformEx
* @return the decoded audio data as PCM samples or <code>null</code> if the end of the mp3 file is reached
* @throws IOException if an I/O error occurs
*/
private native short[] decodeNextFrame(InputStream stream) throws IOException;

public short[] decodeNextFrame() throws IOException {
return decodeNextFrame(inputStream);
synchronized (this) {
return decodeNextFrame0(inputStream);
}
}

private native boolean headerParsed0();

/**
* @return if the header of the mp3 file is parsed
*/
public native boolean headerParsed();
public boolean headerParsed() {
synchronized (this) {
return headerParsed0();
}
}

private native int getChannelCount0();

/**
* @return the number of channels of the decoded audio or -1 if the header of the mp3 file is not yet parsed
*/
public native int getChannelCount();
public int getChannelCount() {
synchronized (this) {
return getChannelCount0();
}
}

private native int getBitRate0();

/**
* @return the bitrate of the mp3 file or -1 if the header of the mp3 file is not yet parsed
*/
public native int getBitRate();
public int getBitRate() {
synchronized (this) {
return getBitRate0();
}
}

private native int getSampleRate0();

/**
* @return the sample rate of the decoded audio or -1 if the header of the mp3 file is not yet parsed
*/
public native int getSampleRate();
public int getSampleRate() {
synchronized (this) {
return getSampleRate0();
}
}

/**
* Creates an AudioFormat object for the decoded audio.
Expand All @@ -67,17 +93,21 @@ public AudioFormat createAudioFormat() {
return Audio.super.createAudioFormat();
}

private native void destroyDecoder();
private native void destroyDecoder0();

@Override
public void close() throws IOException {
destroyDecoder();
decoder = 0L;
inputStream.close();
synchronized (this) {
destroyDecoder0();
decoder = 0L;
inputStream.close();
}
}

public boolean isClosed() {
return decoder == 0L;
synchronized (this) {
return decoder == 0L;
}
}

/**
Expand Down
Loading

0 comments on commit 55711ca

Please sign in to comment.