Skip to content

Commit 09b36ca

Browse files
committed
Use single lock per ASS_Library for all libass calls
1 parent f952bc6 commit 09b36ca

4 files changed

Lines changed: 83 additions & 53 deletions

File tree

lib_ass_kt/src/main/java/io/github/peerless2012/ass/Ass.kt

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.github.peerless2012.ass
22

3+
import java.util.concurrent.locks.ReentrantLock
4+
import kotlin.concurrent.withLock
5+
36
/**
47
* @Author peerless2012
58
* @Email peerless2012@126.com
@@ -29,38 +32,51 @@ class Ass {
2932

3033
}
3134

35+
/** Single lock for all libass calls on this library instance. */
36+
val lock = ReentrantLock()
37+
3238
private var nativeAss: Long = nativeAssInit()
3339

3440
@Volatile
3541
var released = false
3642
private set
3743

3844
public fun createTrack(): AssTrack {
39-
if (released || nativeAss == 0L) throw IllegalStateException("Ass already released")
40-
return AssTrack(nativeAss)
45+
return lock.withLock {
46+
if (released || nativeAss == 0L) throw IllegalStateException("Ass already released")
47+
AssTrack(nativeAss, lock)
48+
}
4149
}
4250

4351
public fun createRender(): AssRender {
44-
if (released || nativeAss == 0L) throw IllegalStateException("Ass already released")
45-
return AssRender(nativeAss)
52+
return lock.withLock {
53+
if (released || nativeAss == 0L) throw IllegalStateException("Ass already released")
54+
AssRender(nativeAss, lock)
55+
}
4656
}
4757

4858
public fun addFont(name: String, buffer: ByteArray) {
49-
if (released || nativeAss == 0L) return
50-
nativeAssAddFont(nativeAss, name, buffer)
59+
lock.withLock {
60+
if (released || nativeAss == 0L) return
61+
nativeAssAddFont(nativeAss, name, buffer)
62+
}
5163
}
5264

5365
public fun clearFont() {
54-
if (released || nativeAss == 0L) return
55-
nativeAssClearFont(nativeAss)
66+
lock.withLock {
67+
if (released || nativeAss == 0L) return
68+
nativeAssClearFont(nativeAss)
69+
}
5670
}
5771

5872
fun release() {
59-
if (released) return
60-
released = true
61-
if (nativeAss != 0L) {
62-
nativeAssDeinit(nativeAss)
63-
nativeAss = 0
73+
lock.withLock {
74+
if (released) return
75+
released = true
76+
if (nativeAss != 0L) {
77+
nativeAssDeinit(nativeAss)
78+
nativeAss = 0
79+
}
6480
}
6581
}
6682

lib_ass_kt/src/main/java/io/github/peerless2012/ass/AssRender.kt

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import kotlin.concurrent.withLock
1010
* @Version V1.0
1111
* @Description
1212
*/
13-
class AssRender(nativeAss: Long) {
13+
class AssRender(nativeAss: Long, private val lock: ReentrantLock) {
1414

1515
companion object {
1616

@@ -36,8 +36,6 @@ class AssRender(nativeAss: Long) {
3636
external fun nativeAssRenderDeinit(render: Long)
3737
}
3838

39-
val lock = ReentrantLock()
40-
4139
private var nativeRender: Long = nativeAssRenderInit(nativeAss)
4240

4341
@Volatile
@@ -53,23 +51,31 @@ class AssRender(nativeAss: Long) {
5351
}
5452

5553
public fun setFontScale(scale: Float) {
56-
if (released || nativeRender == 0L) return
57-
nativeAssRenderSetFontScale(nativeRender, scale)
54+
lock.withLock {
55+
if (released || nativeRender == 0L) return
56+
nativeAssRenderSetFontScale(nativeRender, scale)
57+
}
5858
}
5959

6060
public fun setCacheLimit(glyphMax: Int, bitmapMaxSize: Int) {
61-
if (released || nativeRender == 0L) return
62-
nativeAssRenderSetCacheLimit(nativeRender, glyphMax, bitmapMaxSize)
61+
lock.withLock {
62+
if (released || nativeRender == 0L) return
63+
nativeAssRenderSetCacheLimit(nativeRender, glyphMax, bitmapMaxSize)
64+
}
6365
}
6466

6567
public fun setStorageSize(width: Int, height: Int) {
66-
if (released || nativeRender == 0L) return
67-
nativeAssRenderSetStorageSize(nativeRender, width, height)
68+
lock.withLock {
69+
if (released || nativeRender == 0L) return
70+
nativeAssRenderSetStorageSize(nativeRender, width, height)
71+
}
6872
}
6973

7074
public fun setFrameSize(width: Int, height: Int) {
71-
if (released || nativeRender == 0L) return
72-
nativeAssRenderSetFrameSize(nativeRender, width, height)
75+
lock.withLock {
76+
if (released || nativeRender == 0L) return
77+
nativeAssRenderSetFrameSize(nativeRender, width, height)
78+
}
7379
}
7480

7581
public fun renderFrame(time: Long, type: AssTexType): AssFrame? {

lib_ass_kt/src/main/java/io/github/peerless2012/ass/AssTrack.kt

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package io.github.peerless2012.ass
22

3+
import java.util.concurrent.locks.ReentrantLock
4+
import kotlin.concurrent.withLock
5+
36
/**
47
* @Author peerless2012
58
* @Email peerless2012@126.com
69
* @DateTime 2025/Jan/05 14:18
710
* @Version V1.0
811
* @Description
912
*/
10-
class AssTrack(private val ass: Long) {
13+
class AssTrack(private val ass: Long, private val lock: ReentrantLock) {
1114

1215
companion object {
1316

@@ -44,41 +47,55 @@ class AssTrack(private val ass: Long) {
4447
private set
4548

4649
public fun getWidth(): Int {
47-
if (released || nativeAssTrack == 0L) return 0
48-
return nativeAssTrackGetWidth(nativeAssTrack)
50+
lock.withLock {
51+
if (released || nativeAssTrack == 0L) return 0
52+
return nativeAssTrackGetWidth(nativeAssTrack)
53+
}
4954
}
5055

5156
public fun getHeight(): Int {
52-
if (released || nativeAssTrack == 0L) return 0
53-
return nativeAssTrackGetHeight(nativeAssTrack)
57+
lock.withLock {
58+
if (released || nativeAssTrack == 0L) return 0
59+
return nativeAssTrackGetHeight(nativeAssTrack)
60+
}
5461
}
5562

5663
public fun getEvents(): Array<AssEvent>? {
57-
if (released || nativeAssTrack == 0L) return null
58-
return nativeAssTrackGetEvents(nativeAssTrack)
64+
lock.withLock {
65+
if (released || nativeAssTrack == 0L) return null
66+
return nativeAssTrackGetEvents(nativeAssTrack)
67+
}
5968
}
6069

6170
public fun clearEvent() {
62-
if (released || nativeAssTrack == 0L) return
63-
nativeAssTrackClearEvents(nativeAssTrack)
71+
lock.withLock {
72+
if (released || nativeAssTrack == 0L) return
73+
nativeAssTrackClearEvents(nativeAssTrack)
74+
}
6475
}
6576

6677
public fun readBuffer(array: ByteArray, offset: Int = 0, length : Int = array.size) {
67-
if (released || nativeAssTrack == 0L) return
68-
nativeAssTrackReadBuffer(nativeAssTrack, array, offset, length)
78+
lock.withLock {
79+
if (released || nativeAssTrack == 0L) return
80+
nativeAssTrackReadBuffer(nativeAssTrack, array, offset, length)
81+
}
6982
}
7083

7184
public fun readChunk(start: Long, duration: Long, array: ByteArray, offset: Int = 0, length: Int = array.size) {
72-
if (released || nativeAssTrack == 0L) return
73-
nativeAssTrackReadChunk(nativeAssTrack, start, duration, array, offset, length)
85+
lock.withLock {
86+
if (released || nativeAssTrack == 0L) return
87+
nativeAssTrackReadChunk(nativeAssTrack, start, duration, array, offset, length)
88+
}
7489
}
7590

7691
fun release() {
77-
if (released) return
78-
released = true
79-
if (nativeAssTrack != 0L) {
80-
nativeAssTrackDeinit(nativeAssTrack)
81-
nativeAssTrack = 0
92+
lock.withLock {
93+
if (released) return
94+
released = true
95+
if (nativeAssTrack != 0L) {
96+
nativeAssTrackDeinit(nativeAssTrack)
97+
nativeAssTrack = 0
98+
}
8299
}
83100
}
84101

lib_ass_media/src/main/java/io/github/peerless2012/ass/media/AssHandler.kt

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import io.github.peerless2012.ass.Ass
1919
import io.github.peerless2012.ass.media.parser.AssHeaderParser
2020
import io.github.peerless2012.ass.media.render.AssOverlayManager
2121
import io.github.peerless2012.ass.media.type.AssRenderType
22-
import kotlin.concurrent.withLock
2322

2423
/**
2524
* Handles ASS subtitle rendering and integration with ExoPlayer.
@@ -298,8 +297,7 @@ class AssHandler(
298297

299298
/**
300299
* Reads a dialogue into the track of the given [trackId].
301-
* Synchronized with renderFrame via the render lock to prevent concurrent
302-
* ass_process_chunk / ass_render_frame on the same track.
300+
* Thread-safe: AssTrack.readChunk internally acquires the shared libass lock.
303301
*/
304302
fun readTrackDialogue(
305303
trackId: String?,
@@ -310,14 +308,7 @@ class AssHandler(
310308
length: Int = data.size
311309
) {
312310
val t = availableTracks[trackId] ?: return
313-
val r = render
314-
if (r != null) {
315-
r.lock.withLock {
316-
t.readChunk(start, duration, data, offset, length)
317-
}
318-
} else {
319-
t.readChunk(start, duration, data, offset, length)
320-
}
311+
t.readChunk(start, duration, data, offset, length)
321312
}
322313

323314
/**

0 commit comments

Comments
 (0)