Skip to content

Commit 3c7b644

Browse files
hhravnShahen Hovhannisyan
authored andcommitted
fix(FFMPEG): ensure FFMPEG cleanup on exception, reject properly on failure to create... (shahen94#168)
* ensure cleanup on exception, reject properly on failure to create preview from position * typo
1 parent 1d8c12f commit 3c7b644

File tree

1 file changed

+122
-108
lines changed

1 file changed

+122
-108
lines changed

android/src/main/java/com/shahenlibrary/Trimmer/Trimmer.java

Lines changed: 122 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -246,111 +246,115 @@ protected Void doInBackground(LoadFfmpegAsyncTaskParams... params) {
246246

247247
public static void getPreviewImages(String path, Promise promise, ReactApplicationContext ctx) {
248248
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
249-
if (VideoEdit.shouldUseURI(path)) {
250-
retriever.setDataSource(ctx, Uri.parse(path));
251-
} else {
252-
retriever.setDataSource(path);
253-
}
249+
try {
250+
if (VideoEdit.shouldUseURI(path)) {
251+
retriever.setDataSource(ctx, Uri.parse(path));
252+
} else {
253+
retriever.setDataSource(path);
254+
}
254255

255-
WritableArray images = Arguments.createArray();
256-
int duration = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
257-
int width = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
258-
int height = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
259-
int orientation = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION));
256+
WritableArray images = Arguments.createArray();
257+
int duration = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
258+
int width = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
259+
int height = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
260+
int orientation = Integer.parseInt(retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION));
260261

261-
float aspectRatio = width / height;
262+
float aspectRatio = width / height;
262263

263-
int resizeWidth = 200;
264-
int resizeHeight = Math.round(resizeWidth / aspectRatio);
264+
int resizeWidth = 200;
265+
int resizeHeight = Math.round(resizeWidth / aspectRatio);
265266

266-
float scaleWidth = ((float) resizeWidth) / width;
267-
float scaleHeight = ((float) resizeHeight) / height;
267+
float scaleWidth = ((float) resizeWidth) / width;
268+
float scaleHeight = ((float) resizeHeight) / height;
268269

269-
Log.d(TrimmerManager.REACT_PACKAGE, "getPreviewImages: \n\tduration: " + duration +
270-
"\n\twidth: " + width +
271-
"\n\theight: " + height +
272-
"\n\torientation: " + orientation +
273-
"\n\taspectRatio: " + aspectRatio +
274-
"\n\tresizeWidth: " + resizeWidth +
275-
"\n\tresizeHeight: " + resizeHeight
276-
);
270+
Log.d(TrimmerManager.REACT_PACKAGE, "getPreviewImages: \n\tduration: " + duration +
271+
"\n\twidth: " + width +
272+
"\n\theight: " + height +
273+
"\n\torientation: " + orientation +
274+
"\n\taspectRatio: " + aspectRatio +
275+
"\n\tresizeWidth: " + resizeWidth +
276+
"\n\tresizeHeight: " + resizeHeight
277+
);
277278

278-
Matrix mx = new Matrix();
279+
Matrix mx = new Matrix();
279280

280-
mx.postScale(scaleWidth, scaleHeight);
281-
mx.postRotate(orientation - 360);
281+
mx.postScale(scaleWidth, scaleHeight);
282+
mx.postRotate(orientation - 360);
282283

283-
for (int i = 0; i < duration; i += duration / 10) {
284-
Bitmap frame = retriever.getFrameAtTime(i * 1000);
284+
for (int i = 0; i < duration; i += duration / 10) {
285+
Bitmap frame = retriever.getFrameAtTime(i * 1000);
285286

286-
if(frame == null) {
287-
continue;
287+
if (frame == null) {
288+
continue;
289+
}
290+
Bitmap currBmp = Bitmap.createScaledBitmap(frame, resizeWidth, resizeHeight, false);
291+
292+
Bitmap normalizedBmp = Bitmap.createBitmap(currBmp, 0, 0, resizeWidth, resizeHeight, mx, true);
293+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
294+
normalizedBmp.compress(Bitmap.CompressFormat.PNG, 90, byteArrayOutputStream);
295+
byte[] byteArray = byteArrayOutputStream.toByteArray();
296+
String encoded = "data:image/png;base64," + Base64.encodeToString(byteArray, Base64.DEFAULT);
297+
images.pushString(encoded);
288298
}
289-
Bitmap currBmp = Bitmap.createScaledBitmap(frame, resizeWidth, resizeHeight, false);
290-
291-
Bitmap normalizedBmp = Bitmap.createBitmap(currBmp, 0, 0, resizeWidth, resizeHeight, mx, true);
292-
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
293-
normalizedBmp.compress(Bitmap.CompressFormat.PNG, 90, byteArrayOutputStream);
294-
byte[] byteArray = byteArrayOutputStream .toByteArray();
295-
String encoded = "data:image/png;base64," + Base64.encodeToString(byteArray, Base64.DEFAULT);
296-
images.pushString(encoded);
297-
}
298299

299-
WritableMap event = Arguments.createMap();
300+
WritableMap event = Arguments.createMap();
300301

301-
event.putArray("images", images);
302+
event.putArray("images", images);
302303

303-
promise.resolve(event);
304-
retriever.release();
304+
promise.resolve(event);
305+
} finally {
306+
retriever.release();
307+
}
305308
}
306309

307310
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
308311
public static void getVideoInfo(String path, Promise promise, ReactApplicationContext ctx) {
309312
FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
313+
try {
314+
if (VideoEdit.shouldUseURI(path)) {
315+
mmr.setDataSource(ctx, Uri.parse(path));
316+
} else {
317+
mmr.setDataSource(path);
318+
}
310319

311-
if (VideoEdit.shouldUseURI(path)) {
312-
mmr.setDataSource(ctx, Uri.parse(path));
313-
} else {
314-
mmr.setDataSource(path);
315-
}
320+
int duration = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
321+
int width = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
322+
int height = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
323+
int orientation = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION));
324+
// METADATA_KEY_FRAMERATE returns a float or int or might not exist
325+
Integer frameRate = VideoEdit.getIntFromString(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_FRAMERATE));
326+
// METADATA_KEY_VARIANT_BITRATE returns a int or might not exist
327+
Integer bitrate = VideoEdit.getIntFromString(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VARIANT_BITRATE));
328+
if (orientation == 90 || orientation == 270) {
329+
width = width + height;
330+
height = width - height;
331+
width = width - height;
332+
}
316333

317-
int duration = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
318-
int width = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
319-
int height = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
320-
int orientation = Integer.parseInt(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION));
321-
// METADATA_KEY_FRAMERATE returns a float or int or might not exist
322-
Integer frameRate = VideoEdit.getIntFromString(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_FRAMERATE));
323-
// METADATA_KEY_VARIANT_BITRATE returns a int or might not exist
324-
Integer bitrate = VideoEdit.getIntFromString(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VARIANT_BITRATE));
325-
if (orientation == 90 || orientation == 270) {
326-
width = width + height;
327-
height = width - height;
328-
width = width - height;
329-
}
334+
WritableMap event = Arguments.createMap();
335+
WritableMap size = Arguments.createMap();
330336

331-
WritableMap event = Arguments.createMap();
332-
WritableMap size = Arguments.createMap();
337+
size.putInt(Events.WIDTH, width);
338+
size.putInt(Events.HEIGHT, height);
333339

334-
size.putInt(Events.WIDTH, width);
335-
size.putInt(Events.HEIGHT, height);
340+
event.putMap(Events.SIZE, size);
341+
event.putInt(Events.DURATION, duration / 1000);
342+
event.putInt(Events.ORIENTATION, orientation);
343+
if (frameRate != null) {
344+
event.putInt(Events.FRAMERATE, frameRate);
345+
} else {
346+
event.putNull(Events.FRAMERATE);
347+
}
348+
if (bitrate != null) {
349+
event.putInt(Events.BITRATE, bitrate);
350+
} else {
351+
event.putNull(Events.BITRATE);
352+
}
336353

337-
event.putMap(Events.SIZE, size);
338-
event.putInt(Events.DURATION, duration / 1000);
339-
event.putInt(Events.ORIENTATION, orientation);
340-
if (frameRate != null) {
341-
event.putInt(Events.FRAMERATE, frameRate);
342-
} else {
343-
event.putNull(Events.FRAMERATE);
344-
}
345-
if (bitrate != null) {
346-
event.putInt(Events.BITRATE, bitrate);
347-
} else {
348-
event.putNull(Events.BITRATE);
354+
promise.resolve(event);
355+
} finally {
356+
mmr.release();
349357
}
350-
351-
promise.resolve(event);
352-
353-
mmr.release();
354358
}
355359

356360
static void trim(ReadableMap options, final Promise promise, ReactApplicationContext ctx) {
@@ -417,29 +421,30 @@ private static ReadableMap formatWidthAndHeightForFfmpeg(int width, int height,
417421

418422
private static ReadableMap getVideoRequiredMetadata(String source, Context ctx) {
419423
Log.d(LOG_TAG, "getVideoRequiredMetadata: " + source);
420-
421-
// FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
422424
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
423-
if (VideoEdit.shouldUseURI(source)) {
424-
retriever.setDataSource(ctx, Uri.parse(source));
425-
} else {
426-
retriever.setDataSource(source);
427-
}
428-
429-
int width = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
430-
int height = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
431-
int bitrate = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE));
432-
retriever.release();
433-
434-
Log.d(LOG_TAG, "getVideoRequiredMetadata: " + Integer.toString(width));
435-
Log.d(LOG_TAG, "getVideoRequiredMetadata: " + Integer.toString(height));
436-
Log.d(LOG_TAG, "getVideoRequiredMetadata: " + Integer.toString(bitrate));
425+
try {
426+
if (VideoEdit.shouldUseURI(source)) {
427+
retriever.setDataSource(ctx, Uri.parse(source));
428+
} else {
429+
retriever.setDataSource(source);
430+
}
437431

438-
WritableMap videoMetadata = Arguments.createMap();
439-
videoMetadata.putInt("width", width);
440-
videoMetadata.putInt("height", height);
441-
videoMetadata.putInt("bitrate", bitrate);
442-
return videoMetadata;
432+
int width = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
433+
int height = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
434+
int bitrate = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE));
435+
436+
Log.d(LOG_TAG, "getVideoRequiredMetadata: " + Integer.toString(width));
437+
Log.d(LOG_TAG, "getVideoRequiredMetadata: " + Integer.toString(height));
438+
Log.d(LOG_TAG, "getVideoRequiredMetadata: " + Integer.toString(bitrate));
439+
440+
WritableMap videoMetadata = Arguments.createMap();
441+
videoMetadata.putInt("width", width);
442+
videoMetadata.putInt("height", height);
443+
videoMetadata.putInt("bitrate", bitrate);
444+
return videoMetadata;
445+
} finally {
446+
retriever.release();
447+
}
443448
}
444449

445450
public static void compress(String source, ReadableMap options, final Promise promise, final OnCompressVideoListener cb, ThemedReactContext tctx, ReactApplicationContext rctx) {
@@ -534,15 +539,24 @@ static File createTempFile(String extension, final Promise promise, Context ctx)
534539
}
535540

536541
static void getPreviewImageAtPosition(String source, double sec, String format, final Promise promise, ReactApplicationContext ctx) {
542+
Bitmap bmp = null;
543+
int orientation = 0;
537544
FFmpegMediaMetadataRetriever metadataRetriever = new FFmpegMediaMetadataRetriever();
538-
FFmpegMediaMetadataRetriever.IN_PREFERRED_CONFIG = Bitmap.Config.ARGB_8888;
539-
metadataRetriever.setDataSource(source);
545+
try {
546+
FFmpegMediaMetadataRetriever.IN_PREFERRED_CONFIG = Bitmap.Config.ARGB_8888;
547+
metadataRetriever.setDataSource(source);
540548

541-
Bitmap bmp = metadataRetriever.getFrameAtTime((long) (sec * 1000000));
549+
bmp = metadataRetriever.getFrameAtTime((long) (sec * 1000000));
550+
if(bmp == null){
551+
promise.reject("Failed to get preview at requested position.");
552+
return;
553+
}
542554

543-
// NOTE: FIX ROTATED BITMAP
544-
int orientation = Integer.parseInt( metadataRetriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION) );
545-
metadataRetriever.release();
555+
// NOTE: FIX ROTATED BITMAP
556+
orientation = Integer.parseInt(metadataRetriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION));
557+
} finally {
558+
metadataRetriever.release();
559+
}
546560

547561
if ( orientation != 0 ) {
548562
Matrix matrix = new Matrix();

0 commit comments

Comments
 (0)