@@ -98,7 +98,18 @@ static String[] candidate() {
9898 return byNameTried ? null : BY_NAME [0 ];
9999 }
100100
101- synchronized boolean decode (Frame frame , Surface target , int w , int h ) throws Exception {
101+ /** Frames queued in a row without any output: the decoder is not working (Qodo on #135). */
102+ static final int MAX_SILENT_FRAMES = 15 ;
103+ private int silentFrames ;
104+
105+ /** Checked under the lock: false once the stream that called decode() has stopped. */
106+ interface Current {
107+ boolean holds ();
108+ }
109+
110+ synchronized boolean decode (Frame frame , Surface target , int w , int h , Current current )
111+ throws Exception {
112+ if (!current .holds ()) return false ;
102113 String [] dec = chosen != null ? chosen : find ();
103114 if (dec == null ) {
104115 if (byNameTried ) throw new IllegalStateException ("no JPEG decoder" );
@@ -120,6 +131,7 @@ synchronized boolean decode(Frame frame, Surface target, int w, int h) throws Ex
120131 }
121132 codec = c ;
122133 chosen = dec ;
134+ silentFrames = 0 ;
123135 surface = target ;
124136 width = w ;
125137 height = h ;
@@ -128,13 +140,15 @@ synchronized boolean decode(Frame frame, Surface target, int w, int h) throws Ex
128140 int in = codec .dequeueInputBuffer (40_000 );
129141 if (in >= 0 ) {
130142 ByteBuffer b = codec .getInputBuffer (in );
131- if (b != null && b .capacity () >= frame .length ()) {
132- b .clear ();
133- b .put (frame .data (), 0 , frame .length ());
134- codec .queueInputBuffer (in , 0 , frame .length (), System .nanoTime () / 1000 , 0 );
135- } else {
143+ if (b == null || b .capacity () < frame .length ()) {
144+ // A frame larger than the decoder's input buffers: let the software path have it
136145 codec .queueInputBuffer (in , 0 , 0 , 0 , 0 );
146+ throw new IllegalStateException ("JPEG frame of " + frame .length ()
147+ + " bytes does not fit the input buffer" );
137148 }
149+ b .clear ();
150+ b .put (frame .data (), 0 , frame .length ());
151+ codec .queueInputBuffer (in , 0 , frame .length (), System .nanoTime () / 1000 , 0 );
138152 }
139153 boolean rendered = false ;
140154 int out ;
@@ -146,6 +160,10 @@ synchronized boolean decode(Frame frame, Surface target, int w, int h) throws Ex
146160 }
147161 in = -1 ; // after the first output, only take what is ready
148162 }
163+ silentFrames = rendered ? 0 : silentFrames + 1 ;
164+ if (silentFrames > MAX_SILENT_FRAMES ) {
165+ throw new IllegalStateException (MAX_SILENT_FRAMES + " frames without output" );
166+ }
149167 return rendered ;
150168 }
151169
0 commit comments