From 83c976f2d7cf35d27e040281eab4a2fd40c6d08b Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 31 Jan 2020 14:28:27 +0100 Subject: use ExoPlayer for video playback --- build.gradle | 3 +- .../engine/MediaTranscoderEngine.java | 14 ---- .../format/AndroidStandardFormatStrategy.java | 3 +- .../services/AttachFileToConversationRunnable.java | 4 - .../pixart/messenger/ui/MediaViewerActivity.java | 85 ++++++++++++++++------ .../java/de/pixart/messenger/utils/MimeUtils.java | 1 + src/main/res/layout/activity_media_viewer.xml | 2 +- src/main/res/values/about.xml | 2 +- 8 files changed, 71 insertions(+), 43 deletions(-) diff --git a/build.gradle b/build.gradle index 83729b11f..a54f7a517 100644 --- a/build.gradle +++ b/build.gradle @@ -71,7 +71,8 @@ dependencies { implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0' - implementation project(':libs:fullscreenvideoview') + implementation 'com.google.android.exoplayer:exoplayer-core:2.11.1' + implementation 'com.google.android.exoplayer:exoplayer-ui:2.11.1' implementation 'pub.devrel:easypermissions:3.0.0' // version >= 3.0.0 needs android X libraries implementation 'com.wefika:flowlayout:0.4.1' implementation 'com.googlecode.ez-vcard:ez-vcard:0.10.5' diff --git a/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/MediaTranscoderEngine.java b/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/MediaTranscoderEngine.java index 274d91cac..86637fd0e 100644 --- a/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/MediaTranscoderEngine.java +++ b/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/engine/MediaTranscoderEngine.java @@ -19,11 +19,9 @@ import android.media.MediaExtractor; import android.media.MediaFormat; import android.media.MediaMetadataRetriever; import android.media.MediaMuxer; -import android.os.Build; import android.util.Log; import net.ypresto.androidtranscoder.format.MediaFormatStrategy; -import net.ypresto.androidtranscoder.utils.ISO6709LocationParser; import net.ypresto.androidtranscoder.utils.MediaExtractorUtils; import java.io.FileDescriptor; @@ -139,18 +137,6 @@ public class MediaTranscoderEngine { // skip } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - String locationString = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION); - if (locationString != null) { - float[] location = new ISO6709LocationParser().parse(locationString); - if (location != null) { - mMuxer.setLocation(location[0], location[1]); - } else { - Log.d(TAG, "Failed to parse the location metadata: " + locationString); - } - } - } - try { mDurationUs = Long.parseLong(mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)) * 1000; } catch (NumberFormatException e) { diff --git a/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/format/AndroidStandardFormatStrategy.java b/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/format/AndroidStandardFormatStrategy.java index 822c45fbd..6b1990e69 100644 --- a/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/format/AndroidStandardFormatStrategy.java +++ b/libs/android-transcoder/src/main/java/net/ypresto/androidtranscoder/format/AndroidStandardFormatStrategy.java @@ -18,9 +18,10 @@ package net.ypresto.androidtranscoder.format; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.os.Build; -import androidx.annotation.RequiresApi; import android.util.Log; +import androidx.annotation.RequiresApi; + class AndroidStandardFormatStrategy implements MediaFormatStrategy { public static final int AUDIO_BITRATE_AS_IS = -1; public static final int AUDIO_CHANNELS_AS_IS = -1; diff --git a/src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java b/src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java index bb907a5cd..e8d6524d2 100644 --- a/src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java +++ b/src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java @@ -182,10 +182,6 @@ public class AttachFileToConversationRunnable implements Runnable, MediaTranscod } } - private String getVideoCompression() { - return getVideoCompression(mXmppConnectionService); - } - public static String getVideoCompression(final Context context) { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); return preferences.getString("video_compression", context.getResources().getString(R.string.video_compression)); diff --git a/src/main/java/de/pixart/messenger/ui/MediaViewerActivity.java b/src/main/java/de/pixart/messenger/ui/MediaViewerActivity.java index 04d44e142..b9dff18c7 100644 --- a/src/main/java/de/pixart/messenger/ui/MediaViewerActivity.java +++ b/src/main/java/de/pixart/messenger/ui/MediaViewerActivity.java @@ -22,7 +22,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.webkit.MimeTypeMap; -import android.widget.ImageView; import android.widget.Toast; import androidx.appcompat.app.ActionBar; @@ -30,10 +29,17 @@ import androidx.appcompat.app.AlertDialog; import androidx.databinding.DataBindingUtil; import com.davemorrissey.labs.subscaleview.ImageSource; +import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.util.Util; import java.io.File; import java.io.FileNotFoundException; -import java.io.IOException; import java.io.InputStream; import java.util.List; @@ -49,7 +55,7 @@ import static de.pixart.messenger.persistance.FileBackend.close; public class MediaViewerActivity extends XmppActivity implements AudioManager.OnAudioFocusChangeListener { Integer oldOrientation; - ImageView mFullscreenbutton; + SimpleExoPlayer player; Uri mFileUri; File mFile; int height = 0; @@ -86,8 +92,6 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On showFab(); return super.onDown(e); } - - }); ActionBar actionBar = getSupportActionBar(); @@ -104,7 +108,6 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On getWindow().setAttributes(layout); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - mFullscreenbutton = findViewById(R.id.vcv_img_fullscreen); binding.speedDial.inflate(R.menu.media_viewer); binding.speedDial.setOnActionSelectedListener(actionItem -> { switch (actionItem.getId()) { @@ -226,9 +229,8 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On } } - private void DisplayImage(final File file, final Uri FileUri) { - boolean gif = false; - gif = "image/gif".equalsIgnoreCase(getMimeType(file.toString())); + private void DisplayImage(final File file, final Uri uri) { + final boolean gif = "image/gif".equalsIgnoreCase(getMimeType(file.toString())); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(new File(file.getPath()).getAbsolutePath(), options); @@ -242,12 +244,11 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On try { if (gif) { binding.messageGifView.setVisibility(View.VISIBLE); - binding.messageGifView.setImageURI(FileUri); + binding.messageGifView.setImageURI(uri); binding.messageGifView.setOnTouchListener((view, motionEvent) -> gestureDetector.onTouchEvent(motionEvent)); } else { binding.messageImageView.setVisibility(View.VISIBLE); - binding.messageImageView.setOrientation(rotation); - binding.messageImageView.setImage(ImageSource.uri(FileUri)); + binding.messageImageView.setImage(ImageSource.uri(uri)); binding.messageImageView.setOnTouchListener((view, motionEvent) -> gestureDetector.onTouchEvent(motionEvent)); } } catch (Exception e) { @@ -262,7 +263,7 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On retriever.setDataSource(uri.getPath()); Bitmap bitmap = null; try { - bitmap = retriever.getFrameAtTime(); + bitmap = retriever.getFrameAtTime(0); height = bitmap.getHeight(); width = bitmap.getWidth(); } catch (Exception e) { @@ -273,21 +274,35 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On bitmap.recycle(); } } - rotation = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)); + try { + rotation = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)); + } catch (Exception e) { + rotation = 0; + } Log.d(Config.LOGTAG, "Video height: " + height + ", width: " + width + ", rotation: " + rotation); if (useAutoRotateScreen()) { rotateScreen(width, height, rotation); } binding.messageVideoView.setVisibility(View.VISIBLE); - binding.messageVideoView.setVideoURI(uri); - mFullscreenbutton.setVisibility(View.INVISIBLE); - binding.messageVideoView.setShouldAutoplay(true); + player = new SimpleExoPlayer.Builder(this).build(); + player.setPlayWhenReady(true); + player.addListener(new SimpleExoPlayer.EventListener() { + @Override + public void onPlayerError(ExoPlaybackException error) { + open(); + } + }); + player.setRepeatMode(Player.REPEAT_MODE_OFF); + binding.messageVideoView.setPlayer(player); + DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "de.pixart.messenger")); + MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri); + player.prepare(videoSource); requestAudioFocus(); setVolumeControlStream(AudioManager.STREAM_MUSIC); binding.messageVideoView.setOnTouchListener((view, motionEvent) -> gestureDetector.onTouchEvent(motionEvent)); } catch (Exception e) { - open(); e.printStackTrace(); + open(); } } @@ -331,6 +346,34 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On } } + private void pausePlayer() { + if (isVideo && isPlaying()) { + player.setPlayWhenReady(false); + player.getPlaybackState(); + } + } + + private void startPlayer() { + if (isVideo && !isPlaying()) { + player.setPlayWhenReady(true); + player.getPlaybackState(); + } + } + + private void stopPlayer() { + if (isVideo && isPlaying()) { + player.stop(true); + player.release(); + } + } + + private boolean isPlaying() { + return player != null + && player.getPlaybackState() != Player.STATE_ENDED + && player.getPlaybackState() != Player.STATE_IDLE + && player.getPlayWhenReady(); + } + @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -344,13 +387,13 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On } getWindow().setAttributes(layout); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - binding.messageVideoView.setShouldAutoplay(true); + startPlayer(); super.onResume(); } @Override public void onPause() { - binding.messageVideoView.reset(); + pausePlayer(); WindowManager.LayoutParams layout = getWindow().getAttributes(); if (useMaxBrightness()) { layout.screenBrightness = -1; @@ -363,7 +406,7 @@ public class MediaViewerActivity extends XmppActivity implements AudioManager.On @Override public void onStop() { - binding.messageVideoView.reset(); + stopPlayer(); releaseAudiFocus(); WindowManager.LayoutParams layout = getWindow().getAttributes(); if (useMaxBrightness()) { diff --git a/src/main/java/de/pixart/messenger/utils/MimeUtils.java b/src/main/java/de/pixart/messenger/utils/MimeUtils.java index 4ca8eb01a..8603a8a89 100644 --- a/src/main/java/de/pixart/messenger/utils/MimeUtils.java +++ b/src/main/java/de/pixart/messenger/utils/MimeUtils.java @@ -376,6 +376,7 @@ public final class MimeUtils { add("video/mpeg", "mpg"); add("video/mpeg", "mpe"); add("video/mp4", "mp4"); + add("video/mp4", "gifv"); add("video/mpeg", "VOB"); add("video/quicktime", "qt"); add("video/quicktime", "mov"); diff --git a/src/main/res/layout/activity_media_viewer.xml b/src/main/res/layout/activity_media_viewer.xml index cca277e51..2b64fb81a 100644 --- a/src/main/res/layout/activity_media_viewer.xml +++ b/src/main/res/layout/activity_media_viewer.xml @@ -22,7 +22,7 @@ android:adjustViewBounds="true" android:visibility="gone" /> -