From be4aa2afc96b86c89c2fc37735a4b0cf328d7415 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 11 Jul 2016 21:24:33 +0200 Subject: show a preview for video files --- art/play_video.svg | 59 +++++++++ art/render.rb | 1 + .../conversations/persistance/FileBackend.java | 140 +++++++++++++++++---- src/main/res/drawable-hdpi/play_video.png | Bin 0 -> 3813 bytes src/main/res/drawable-mdpi/play_video.png | Bin 0 -> 2432 bytes src/main/res/drawable-xhdpi/play_video.png | Bin 0 -> 5087 bytes src/main/res/drawable-xxhdpi/play_video.png | Bin 0 -> 7824 bytes src/main/res/drawable-xxxhdpi/play_video.png | Bin 0 -> 10668 bytes 8 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 art/play_video.svg create mode 100644 src/main/res/drawable-hdpi/play_video.png create mode 100644 src/main/res/drawable-mdpi/play_video.png create mode 100644 src/main/res/drawable-xhdpi/play_video.png create mode 100644 src/main/res/drawable-xxhdpi/play_video.png create mode 100644 src/main/res/drawable-xxxhdpi/play_video.png diff --git a/art/play_video.svg b/art/play_video.svg new file mode 100644 index 00000000..083e7cfa --- /dev/null +++ b/art/play_video.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/art/render.rb b/art/render.rb index 2b2caacf..fe39e66b 100755 --- a/art/render.rb +++ b/art/render.rb @@ -13,6 +13,7 @@ resolutions = { images = { 'ic_launcher.svg' => ['ic_launcher', 48], 'main_logo.svg' => ['main_logo', 200], + 'play_video.svg' => ['play_video', 96], 'conversations_mono.svg' => ['ic_notification', 24], 'ic_received_indicator.svg' => ['ic_received_indicator', 12], 'ic_send_text_offline.svg' => ['ic_send_text_offline', 36], diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index 85b1ac90..d1935a18 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -10,6 +10,7 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.RectF; +import android.media.MediaMetadataRetriever; import android.net.Uri; import android.os.Build; import android.os.Environment; @@ -380,21 +381,43 @@ public class FileBackend { if (thumbnail != null) { return thumbnail; } - File file = getFile(message); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = calcSampleSize(file, size); - Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(), options); - if (fullsize == null) { - throw new FileNotFoundException(); + DownloadableFile file = getFile(message); + if (file.getMimeType().startsWith("video/")) { + thumbnail = getVideoPreview(file, size); + } else { + Bitmap fullsize = getFullsizeImagePreview(file, size); + if (fullsize == null) { + throw new FileNotFoundException(); + } + thumbnail = resize(fullsize, size); + thumbnail = rotate(thumbnail, getRotation(file)); } - thumbnail = resize(fullsize, size); - thumbnail = rotate(thumbnail, getRotation(file)); this.mXmppConnectionService.getBitmapCache().put(uuid, thumbnail); } } return thumbnail; } + private Bitmap getFullsizeImagePreview(File file, int size) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = calcSampleSize(file, size); + return BitmapFactory.decodeFile(file.getAbsolutePath(), options); + } + + private Bitmap getVideoPreview(File file, int size) { + MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever(); + metadataRetriever.setDataSource(file.getAbsolutePath()); + Bitmap frame = metadataRetriever.getFrameAtTime(0); + metadataRetriever.release(); + frame = resize(frame, size); + Canvas canvas = new Canvas(frame); + Bitmap play = BitmapFactory.decodeResource(mXmppConnectionService.getResources(), R.drawable.play_video); + float x = (frame.getWidth() - play.getWidth()) / 2.0f; + float y = (frame.getHeight() - play.getHeight()) / 2.0f; + canvas.drawBitmap(play,x,y,null); + return frame; + } + public Uri getTakePhotoUri() { StringBuilder pathBuilder = new StringBuilder(); pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)); @@ -656,26 +679,95 @@ public class FileBackend { public void updateFileParams(Message message, URL url) { DownloadableFile file = getFile(message); - if (message.getType() == Message.TYPE_IMAGE || file.getMimeType().startsWith("image/")) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(file.getAbsolutePath(), options); - int rotation = getRotation(file); - boolean rotated = rotation == 90 || rotation == 270; - int imageHeight = rotated ? options.outWidth : options.outHeight; - int imageWidth = rotated ? options.outHeight : options.outWidth; - if (url == null) { - message.setBody(Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight); - } else { - message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight); + boolean image = message.getType() == Message.TYPE_IMAGE || file.getMimeType().startsWith("image/"); + boolean video = message.getMimeType().startsWith("video/"); + if (image || video) { + try { + Dimensions dimensions = image ? getImageDimensions(file) : getVideoDimensions(file); + if (url == null) { + message.setBody(Long.toString(file.getSize()) + '|' + dimensions.width + '|' + dimensions.height); + } else { + message.setBody(url.toString() + "|" + Long.toString(file.getSize()) + '|' + dimensions.width + '|' + dimensions.height); + } + return; + } catch (NotAVideoFile notAVideoFile) { + Log.d(Config.LOGTAG,"file with mime type "+file.getMimeType()+" was not a video file"); + //fall threw } + } + if (url != null) { + message.setBody(url.toString()+"|"+Long.toString(file.getSize())); } else { - if (url != null) { - message.setBody(url.toString()+"|"+Long.toString(file.getSize())); - } else { - message.setBody(Long.toString(file.getSize())); + message.setBody(Long.toString(file.getSize())); + } + + } + + private Dimensions getImageDimensions(File file) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + int rotation = getRotation(file); + boolean rotated = rotation == 90 || rotation == 270; + int imageHeight = rotated ? options.outWidth : options.outHeight; + int imageWidth = rotated ? options.outHeight : options.outWidth; + return new Dimensions(imageHeight, imageWidth); + } + + private Dimensions getVideoDimensions(File file) throws NotAVideoFile { + MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever(); + metadataRetriever.setDataSource(file.getAbsolutePath()); + String hasVideo = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO); + if (hasVideo == null) { + throw new NotAVideoFile(); + } + int rotation = extractRotationFromMediaRetriever(metadataRetriever); + boolean rotated = rotation == 90 || rotation == 270; + int height; + try { + String h = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); + height = Integer.parseInt(h); + } catch (Exception e) { + height = -1; + } + int width; + try { + String w = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); + width = Integer.parseInt(w); + } catch (Exception e) { + width = -1; + } + metadataRetriever.release(); + Log.d(Config.LOGTAG,"extracted video dims "+width+"x"+height); + return rotated ? new Dimensions(width, height) : new Dimensions(height, width); + } + + private int extractRotationFromMediaRetriever(MediaMetadataRetriever metadataRetriever) { + int rotation; + if (Build.VERSION.SDK_INT >= 17) { + String r = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); + try { + rotation = Integer.parseInt(r); + } catch (Exception e) { + rotation = 0; } + } else { + rotation = 0; } + return rotation; + } + + private class Dimensions { + public final int width; + public final int height; + + public Dimensions(int height, int width) { + this.width = width; + this.height = height; + } + } + + private class NotAVideoFile extends Exception { } diff --git a/src/main/res/drawable-hdpi/play_video.png b/src/main/res/drawable-hdpi/play_video.png new file mode 100644 index 00000000..70831fe4 Binary files /dev/null and b/src/main/res/drawable-hdpi/play_video.png differ diff --git a/src/main/res/drawable-mdpi/play_video.png b/src/main/res/drawable-mdpi/play_video.png new file mode 100644 index 00000000..96ab3988 Binary files /dev/null and b/src/main/res/drawable-mdpi/play_video.png differ diff --git a/src/main/res/drawable-xhdpi/play_video.png b/src/main/res/drawable-xhdpi/play_video.png new file mode 100644 index 00000000..d4e6d614 Binary files /dev/null and b/src/main/res/drawable-xhdpi/play_video.png differ diff --git a/src/main/res/drawable-xxhdpi/play_video.png b/src/main/res/drawable-xxhdpi/play_video.png new file mode 100644 index 00000000..562a1b62 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/play_video.png differ diff --git a/src/main/res/drawable-xxxhdpi/play_video.png b/src/main/res/drawable-xxxhdpi/play_video.png new file mode 100644 index 00000000..16f4d2a1 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/play_video.png differ -- cgit v1.2.3