Skip to content

Commit fd957a3

Browse files
committed
Fix seekbar crashing on drag with faulty frameset
1 parent 035c394 commit fd957a3

1 file changed

Lines changed: 41 additions & 11 deletions

File tree

app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,8 @@ private void generateDataFrom(final Frameset frameset, final UUID updateRequestI
132132

133133
// Get the bounds where the frame is found
134134
final int[] bounds = frameset.getFrameBoundsAt(currentPosMs);
135-
generatedDataForUrl.put(currentPosMs, () -> {
136-
// It can happen, that the original bitmap could not be downloaded
137-
// In such a case - we don't want a NullPointer - simply return null
138-
if (srcBitMap == null) {
139-
return null;
140-
}
141-
142-
// Cut out the corresponding bitmap form the "srcBitMap"
143-
return Bitmap.createBitmap(srcBitMap, bounds[1], bounds[2],
144-
frameset.getFrameWidth(), frameset.getFrameHeight());
145-
});
135+
generatedDataForUrl.put(currentPosMs,
136+
createBitmapSupplier(srcBitMap, bounds, frameset));
146137

147138
currentPosMs += frameset.getDurationPerFrame();
148139
pos++;
@@ -165,6 +156,45 @@ private void generateDataFrom(final Frameset frameset, final UUID updateRequestI
165156
}
166157
}
167158

159+
private Supplier<Bitmap> createBitmapSupplier(final Bitmap srcBitMap,
160+
final int[] bounds,
161+
final Frameset frameset) {
162+
return () -> {
163+
// It can happen, that the original bitmap could not be downloaded
164+
// (or it was recycled though that should not happen)
165+
// In such a case - we don't want a NullPointer/
166+
// "cannot use a recycled source in createBitmap" Exception -> simply return null
167+
if (srcBitMap == null || srcBitMap.isRecycled()) {
168+
return null;
169+
}
170+
171+
// Under some rare circumstances the youtube api returns slightly too small storyboards,
172+
// (or not the matching frame width/height)
173+
// This would lead to createBitmap cutting out a bitmap that is out of bounds,
174+
// so we need to adjust the bounds accordingly
175+
if (srcBitMap.getWidth() < bounds[1] + frameset.getFrameWidth()) {
176+
bounds[1] = srcBitMap.getWidth() - frameset.getFrameWidth();
177+
}
178+
179+
if (srcBitMap.getHeight() < bounds[2] + frameset.getFrameHeight()) {
180+
bounds[2] = srcBitMap.getHeight() - frameset.getFrameHeight();
181+
}
182+
183+
// Cut out the corresponding bitmap form the "srcBitMap"
184+
final Bitmap cutOutBitmap = Bitmap.createBitmap(srcBitMap, bounds[1], bounds[2],
185+
frameset.getFrameWidth(), frameset.getFrameHeight());
186+
187+
// If the cut out bitmap is identical to its source,
188+
// we need to copy the bitmap to create a new instance.
189+
// createBitmap allows itself to return the original object that is was created with
190+
// this leads to recycled bitmaps being returned (if they are identical)
191+
// Reference: https://stackoverflow.com/a/23683075 + first comment
192+
// Fixes: https://github.com/TeamNewPipe/NewPipe/issues/11461
193+
return cutOutBitmap == srcBitMap
194+
? cutOutBitmap.copy(cutOutBitmap.getConfig(), true) : cutOutBitmap;
195+
};
196+
}
197+
168198
@Nullable
169199
private Bitmap getBitMapFrom(final String url) {
170200
if (url == null) {

0 commit comments

Comments
 (0)