Skip to content

Commit 55711ca

Browse files
committed
Make encoder and decoder thread-safe
1 parent 7112fbf commit 55711ca

File tree

7 files changed

+98
-62
lines changed

7 files changed

+98
-62
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>de.maxhenkel.lame4j</groupId>
88
<artifactId>lame4j</artifactId>
9-
<version>2.0.2</version>
9+
<version>2.0.3</version>
1010

1111
<name>Lame Wrapper for Java</name>
1212
<url>https://maxhenkel.de</url>

rust/Cargo.lock

+22-22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "lame4j"
3-
version = "2.0.2"
3+
version = "2.0.3"
44
edition = "2021"
55

66
[dependencies]

rust/src/lame/decoder.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct DecoderWrapper {
1313
}
1414

1515
#[no_mangle]
16-
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_createDecoder(_env: JNIEnv, _class: JClass) -> jlong {
16+
pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_createDecoder0(_env: JNIEnv, _class: JClass) -> jlong {
1717
let stream_wrapper = JavaInputStream {
1818
env: None,
1919
input_stream: None,
@@ -32,7 +32,7 @@ pub extern "C" fn Java_de_maxhenkel_lame4j_Mp3Decoder_createDecoder(_env: JNIEnv
3232
}
3333

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

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

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

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

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

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

135135
if pointer == 0 {

rust/src/lame/encoder.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct LameEncoder {
1616
}
1717

1818
#[no_mangle]
19-
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 {
19+
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 {
2020
let lame = lame_init();
2121

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

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

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

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

148148
if pointer == 0 {

src/main/java/de/maxhenkel/lame4j/Mp3Decoder.java

+44-14
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ public class Mp3Decoder implements Audio, AutoCloseable {
1313
public Mp3Decoder(InputStream inputStream) throws IOException, UnknownPlatformException {
1414
Lame.load();
1515
this.inputStream = inputStream;
16-
decoder = createDecoder();
16+
decoder = createDecoder0();
1717
}
1818

19-
private static native long createDecoder();
19+
private static native long createDecoder0();
20+
21+
private native short[] decodeNextFrame0(InputStream stream) throws IOException;
2022

2123
/**
2224
* Decodes the next frame in the mp3 file and returns the decoded audio data as PCM samples.
@@ -27,31 +29,55 @@ public Mp3Decoder(InputStream inputStream) throws IOException, UnknownPlatformEx
2729
* @return the decoded audio data as PCM samples or <code>null</code> if the end of the mp3 file is reached
2830
* @throws IOException if an I/O error occurs
2931
*/
30-
private native short[] decodeNextFrame(InputStream stream) throws IOException;
31-
3232
public short[] decodeNextFrame() throws IOException {
33-
return decodeNextFrame(inputStream);
33+
synchronized (this) {
34+
return decodeNextFrame0(inputStream);
35+
}
3436
}
3537

38+
private native boolean headerParsed0();
39+
3640
/**
3741
* @return if the header of the mp3 file is parsed
3842
*/
39-
public native boolean headerParsed();
43+
public boolean headerParsed() {
44+
synchronized (this) {
45+
return headerParsed0();
46+
}
47+
}
48+
49+
private native int getChannelCount0();
4050

4151
/**
4252
* @return the number of channels of the decoded audio or -1 if the header of the mp3 file is not yet parsed
4353
*/
44-
public native int getChannelCount();
54+
public int getChannelCount() {
55+
synchronized (this) {
56+
return getChannelCount0();
57+
}
58+
}
59+
60+
private native int getBitRate0();
4561

4662
/**
4763
* @return the bitrate of the mp3 file or -1 if the header of the mp3 file is not yet parsed
4864
*/
49-
public native int getBitRate();
65+
public int getBitRate() {
66+
synchronized (this) {
67+
return getBitRate0();
68+
}
69+
}
70+
71+
private native int getSampleRate0();
5072

5173
/**
5274
* @return the sample rate of the decoded audio or -1 if the header of the mp3 file is not yet parsed
5375
*/
54-
public native int getSampleRate();
76+
public int getSampleRate() {
77+
synchronized (this) {
78+
return getSampleRate0();
79+
}
80+
}
5581

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

70-
private native void destroyDecoder();
96+
private native void destroyDecoder0();
7197

7298
@Override
7399
public void close() throws IOException {
74-
destroyDecoder();
75-
decoder = 0L;
76-
inputStream.close();
100+
synchronized (this) {
101+
destroyDecoder0();
102+
decoder = 0L;
103+
inputStream.close();
104+
}
77105
}
78106

79107
public boolean isClosed() {
80-
return decoder == 0L;
108+
synchronized (this) {
109+
return decoder == 0L;
110+
}
81111
}
82112

83113
/**

0 commit comments

Comments
 (0)