Yesterday I used ExoPlayer to play a live stream, I also turned Closed caption ON.
My app is using ExoPlayer r2.2.0.
Device: Android Samsung Note 4 6.0.1
After a while, I got a crash. This is my crash log from Hockey App:
android.text.Layout.
java.lang.IllegalArgumentException: Layout: -317 < 0
Layout.java, line 199
1 android.text.Layout.Layout.java, line 199
2 android.text.StaticLayout.StaticLayout.java, line 479
3 android.text.StaticLayout.StaticLayout.java, line 465
4 android.text.StaticLayout.StaticLayout.java, line 443
5 android.text.StaticLayout.StaticLayout.java, line 423
6 com.google.android.exoplayer2.ui.SubtitlePainter.draw SubtitlePainter.java, line 277
7 com.google.android.exoplayer2.ui.SubtitleView.dispatchDraw SubtitleView.java, line 246
8 android.view.View.draw View.java, line 17472
9 android.view.View.updateDisplayListIfDirty View.java, line 16464
10 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
11 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
12 android.view.View.updateDisplayListIfDirty View.java, line 16424
13 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
14 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
15 android.view.View.updateDisplayListIfDirty View.java, line 16424
16 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
17 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
18 android.view.View.updateDisplayListIfDirty View.java, line 16424
19 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
20 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
21 android.view.View.updateDisplayListIfDirty View.java, line 16424
22 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
23 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
24 android.view.View.updateDisplayListIfDirty View.java, line 16424
25 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
26 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
27 android.view.View.updateDisplayListIfDirty View.java, line 16424
28 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
29 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
30 android.view.View.updateDisplayListIfDirty View.java, line 16424
31 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
32 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
33 android.view.View.updateDisplayListIfDirty View.java, line 16424
34 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
35 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
36 android.view.View.updateDisplayListIfDirty View.java, line 16424
37 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java, line 3905
38 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java, line 3885
39 android.view.View.updateDisplayListIfDirty View.java, line 16424
40 android.view.ThreadedRenderer.updateViewTreeDisplayList ThreadedRenderer.java, line 325
41 android.view.ThreadedRenderer.updateRootDisplayList ThreadedRenderer.java, line 331
42 android.view.ThreadedRenderer.draw ThreadedRenderer.java, line 366
43 android.view.ViewRootImpl.draw ViewRootImpl.java, line 3134
44 android.view.ViewRootImpl.performDraw ViewRootImpl.java, line 2933
45 android.view.ViewRootImpl.performTraversals ViewRootImpl.java, line 2522
46 android.view.ViewRootImpl.doTraversal ViewRootImpl.java, line 1437
47 android.view.ViewRootImpl$TraversalRunnable.run ViewRootImpl.java, line 7397
48 android.view.Choreographer$CallbackRecord.run Choreographer.java, line 920
49 android.view.Choreographer.doCallbacks Choreographer.java, line 695
50 android.view.Choreographer.doFrame Choreographer.java, line 631
51 android.view.Choreographer$FrameDisplayEventReceiver.run Choreographer.java, line 906
52 android.os.Handler.handleCallback Handler.java, line 739
53 android.os.Handler.dispatchMessage Handler.java, line 95
54 android.os.Looper.loop Looper.java, line 158
55 android.app.ActivityThread.main ActivityThread.java, line 7225
56 java.lang.reflect.Method.invoke Native Method
57 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run ZygoteInit.java, line 1230
58 com.android.internal.os.ZygoteInit.main ZygoteInit.java, line 1120
My question is:
Thank you.
Hm. We're attempting to render a caption with a negative width. It's unclear whether the subtitle itself contained invalid positioning data to cause this. Is it possible for you to provide the media that reproduces the crash so that we can determine the root cause, or is the media gone now, given it was a live stream?
Either way, we should just not render anything rather than crash if we do end up in this state. Hence marking as a bug.
@ojw28 : Cause that was a live stream so I don't know how to take the data back. Yes we should ignore any invalid data from subtitle than a crash.
Thanks for response my issue.
I do think the subtitle data must have been invalid, since the only case I can see this happening is where the subtitle specifies it should be positioned entirely to the right of the display area. As above, we'll provide a fix that discards the subtitle and logs a warning for this case, rather than crashing.
we saw the same issue on our DASH encrypted stream. Unfortunately it is encrypted and we can't share the url. I agree that the subtitle painter should discard any invlide cue rather than crash. What we did was to catch the exception in subtitleView.java:
for (int i = 0; i < cueCount; i++) {
try {
painters.get(i).draw(cues.get(i), applyEmbeddedStyles, style, textSizePx,
bottomPaddingFraction, canvas, left, top, right, bottom);
}catch (Exception e ) {
System.out.println(" WARNING: subtitle display failed. ");
}
}
@linhai326 : good catch! I'm simply using SubtitleView from library, but your idea is good for us at this time. Thank you!
Fixed in the dev-v2 branch.
Most helpful comment
Fixed in the dev-v2 branch.