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 9, 2023
1 parent 8f8cf58 commit 4fbbf8f
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 37 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.opus4j</groupId>
<artifactId>opus4j</artifactId>
<version>2.0.1</version>
<version>2.0.2</version>

<name>Opus Wrapper for Java</name>
<url>https://maxhenkel.de</url>
Expand Down
4 changes: 2 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A Java wrapper for the [Opus Codec](https://opus-codec.org/) written in Rust usi
<dependency>
<groupId>de.maxhenkel.opus4j</groupId>
<artifactId>opus4j</artifactId>
<version>2.0.0</version>
<version>2.0.2</version>
</dependency>

<repositories>
Expand All @@ -25,7 +25,7 @@ A Java wrapper for the [Opus Codec](https://opus-codec.org/) written in Rust usi

``` groovy
dependencies {
implementation 'de.maxhenkel.opus4j:opus4j:2.0.0'
implementation 'de.maxhenkel.opus4j:opus4j:2.0.2'
}
repositories {
Expand Down
12 changes: 6 additions & 6 deletions rust/src/opus/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_opus4j_OpusDecoder_createDecoder(mut env: JNIEnv, _class: JClass, sample_rate: jint, channels: jint) -> jlong {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_createDecoder0(mut env: JNIEnv, _class: JClass, sample_rate: jint, channels: jint) -> jlong {
let channels = match channels {
1 => Channels::Mono,
2 => Channels::Stereo,
Expand All @@ -37,7 +37,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_createDecoder(mut env: JN
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_setFrameSize(mut env: JNIEnv, obj: JObject, frame_size: jint) {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_setFrameSize0(mut env: JNIEnv, obj: JObject, frame_size: jint) {
if frame_size <= 0 {
throw_illegal_argument_exception(&mut env, format!("Invalid frame size: {}", frame_size));
return;
Expand All @@ -54,7 +54,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_setFrameSize(mut env: JNI
}

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

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_decode<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>, input: JByteArray<'a>, fec: jboolean) -> JShortArray<'a> {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_decode0<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>, input: JByteArray<'a>, fec: jboolean) -> JShortArray<'a> {
let decoder = match get_decoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand Down Expand Up @@ -129,7 +129,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_decode<'a>(mut env: JNIEn
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_resetState(mut env: JNIEnv, obj: JObject) {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_resetState0(mut env: JNIEnv, obj: JObject) {
let decoder = match get_decoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand All @@ -145,7 +145,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusDecoder_resetState(mut env: JNIEn
}

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

if pointer == 0 {
Expand Down
12 changes: 6 additions & 6 deletions rust/src/opus/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct EncoderWrapper {
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_createEncoder(mut env: JNIEnv, _class: JClass, sample_rate: jint, channels: jint, application: JObject) -> jlong {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_createEncoder0(mut env: JNIEnv, _class: JClass, sample_rate: jint, channels: jint, application: JObject) -> jlong {
let channels = match channels {
1 => Channels::Mono,
2 => Channels::Stereo,
Expand Down Expand Up @@ -58,7 +58,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_createEncoder(mut env: JN
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_setMaxPayloadSize(mut env: JNIEnv, obj: JObject, max_payload_size: jint) {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_setMaxPayloadSize0(mut env: JNIEnv, obj: JObject, max_payload_size: jint) {
if max_payload_size <= 0 {
throw_illegal_argument_exception(&mut env, format!("Invalid maximum payload size: {}", max_payload_size));
return;
Expand All @@ -75,7 +75,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_setMaxPayloadSize(mut env
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_getMaxPayloadSize(mut env: JNIEnv, obj: JObject) -> jint {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_getMaxPayloadSize0(mut env: JNIEnv, obj: JObject) -> jint {
let encoder = match get_encoder(&mut env, &obj) {
Some(encoder) => encoder,
None => {
Expand All @@ -88,7 +88,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_getMaxPayloadSize(mut env
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_encode<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>, input: JShortArray<'a>) -> JByteArray<'a> {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_encode0<'a>(mut env: JNIEnv<'a>, obj: JObject<'a>, input: JShortArray<'a>) -> JByteArray<'a> {
let encoder = match get_encoder(&mut env, &obj) {
Some(encoder) => encoder,
None => {
Expand Down Expand Up @@ -148,7 +148,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_encode<'a>(mut env: JNIEn
}

#[no_mangle]
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_resetState(mut env: JNIEnv, obj: JObject) {
pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_resetState0(mut env: JNIEnv, obj: JObject) {
let encoder = match get_encoder(&mut env, &obj) {
Some(decoder) => decoder,
None => {
Expand All @@ -164,7 +164,7 @@ pub extern "C" fn Java_de_maxhenkel_opus4j_OpusEncoder_resetState(mut env: JNIEn
}

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

if pointer == 0 {
Expand Down
52 changes: 41 additions & 11 deletions src/main/java/de/maxhenkel/opus4j/OpusDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,34 @@ public class OpusDecoder implements AutoCloseable {
*/
public OpusDecoder(int sampleRate, int channels) throws IOException, UnknownPlatformException {
Opus.load();
decoder = createDecoder(sampleRate, channels);
decoder = createDecoder0(sampleRate, channels);
}

private static native long createDecoder(int sampleRate, int channels) throws IOException;
private static native long createDecoder0(int sampleRate, int channels) throws IOException;

public native void setFrameSize(int frameSize);
private native void setFrameSize0(int frameSize);

public native int getFrameSize();
public void setFrameSize(int frameSize) {
synchronized (this) {
setFrameSize0(frameSize);
}
}

private native int getFrameSize0();

public int getFrameSize() {
synchronized (this) {
return getFrameSize0();
}
}

public native short[] decode(@Nullable byte[] input, boolean fec);
private native short[] decode0(@Nullable byte[] input, boolean fec);

public short[] decode(@Nullable byte[] input, boolean fec) {
synchronized (this) {
return decode0(input, fec);
}
}

public short[] decode(@Nullable byte[] input) {
return decode(input, false);
Expand All @@ -36,22 +54,34 @@ public short[] decodeFec() {
return decode(null, true);
}

public native void resetState();
private native void resetState0();

public void resetState() {
synchronized (this) {
resetState0();
}
}

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

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

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

@Override
public String toString() {
return String.format("OpusDecoder[%d]", decoder);
synchronized (this) {
return String.format("OpusDecoder[%d]", decoder);
}
}
}
52 changes: 41 additions & 11 deletions src/main/java/de/maxhenkel/opus4j/OpusEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,64 @@ public class OpusEncoder implements AutoCloseable {
*/
public OpusEncoder(int sampleRate, int channels, Application application) throws IOException, UnknownPlatformException {
Opus.load();
encoder = createEncoder(sampleRate, channels, application);
encoder = createEncoder0(sampleRate, channels, application);
}

private static native long createEncoder(int sampleRate, int channels, Application application) throws IOException;
private static native long createEncoder0(int sampleRate, int channels, Application application) throws IOException;

public native void setMaxPayloadSize(int maxPayloadSize);
private native void setMaxPayloadSize0(int maxPayloadSize);

public native int getMaxPayloadSize();
public void setMaxPayloadSize(int maxPayloadSize) {
synchronized (this) {
setMaxPayloadSize0(maxPayloadSize);
}
}

private native int getMaxPayloadSize0();

public int getMaxPayloadSize() {
synchronized (this) {
return getMaxPayloadSize0();
}
}

public native byte[] encode(short[] input);
private native byte[] encode0(short[] input);

public native void resetState();
public byte[] encode(short[] input) {
synchronized (this) {
return encode0(input);
}
}

private native void destroyEncoder();
private native void resetState0();

public void resetState() {
synchronized (this) {
resetState0();
}
}

private native void destroyEncoder0();

@Override
public void close() {
destroyEncoder();
encoder = 0L;
synchronized (this) {
destroyEncoder0();
encoder = 0L;
}
}

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

@Override
public String toString() {
return String.format("OpusEncoder[%d]", encoder);
synchronized (this) {
return String.format("OpusEncoder[%d]", encoder);
}
}

public static enum Application {
Expand Down

0 comments on commit 4fbbf8f

Please sign in to comment.