Use AspectRatioVideoView instead of standard video view
This commit is contained in:
parent
85800d14ac
commit
b038f3c877
|
@ -2,12 +2,13 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical">
|
||||
|
||||
<VideoView
|
||||
<de.danoeh.antennapod.view.AspectRatioVideoView
|
||||
android:id="@+id/videoview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressIndicator"
|
||||
|
@ -15,7 +16,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="invisible"
|
||||
android:indeterminateOnly="true" />
|
||||
android:indeterminateOnly="true"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butPlay"
|
||||
|
@ -24,7 +25,7 @@
|
|||
android:layout_gravity="center"
|
||||
android:scaleType="fitXY"
|
||||
android:background="@drawable/overlay_button_circle_background"
|
||||
android:src="@drawable/ic_action_pause_over_video" />
|
||||
android:src="@drawable/ic_action_pause_over_video"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/overlay"
|
||||
|
@ -32,14 +33,14 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center"
|
||||
android:background="#80000000"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/timecontrol"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:paddingTop="8dp"
|
||||
android:layout_marginBottom="4dp" >
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPosition"
|
||||
|
@ -53,7 +54,7 @@
|
|||
android:layout_marginTop="4dp"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/position_default_label" />
|
||||
android:text="@string/position_default_label"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLength"
|
||||
|
@ -67,7 +68,7 @@
|
|||
android:layout_marginTop="4dp"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/position_default_label" />
|
||||
android:text="@string/position_default_label"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/sbPosition"
|
||||
|
@ -75,7 +76,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@+id/txtvLength"
|
||||
android:layout_toRightOf="@+id/txtvPosition"
|
||||
android:max="500" />
|
||||
android:max="500"/>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
@ -7,21 +7,21 @@ import android.os.AsyncTask;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.*;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.VideoView;
|
||||
import de.danoeh.antennapod.AppConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.feed.MediaType;
|
||||
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.service.playback.PlayerStatus;
|
||||
import de.danoeh.antennapod.util.playback.ExternalMedia;
|
||||
import de.danoeh.antennapod.util.playback.Playable;
|
||||
import de.danoeh.antennapod.view.AspectRatioVideoView;
|
||||
|
||||
/**
|
||||
* Activity for playing video files.
|
||||
|
@ -37,7 +37,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
|||
private VideoControlsHider videoControlsToggler;
|
||||
|
||||
private LinearLayout videoOverlay;
|
||||
private VideoView videoview;
|
||||
private AspectRatioVideoView videoview;
|
||||
private ProgressBar progressIndicator;
|
||||
|
||||
@Override
|
||||
|
@ -103,7 +103,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
|||
protected void setupGUI() {
|
||||
super.setupGUI();
|
||||
videoOverlay = (LinearLayout) findViewById(R.id.overlay);
|
||||
videoview = (VideoView) findViewById(R.id.videoview);
|
||||
videoview = (AspectRatioVideoView) findViewById(R.id.videoview);
|
||||
progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
|
||||
videoview.getHolder().addCallback(surfaceHolderCallback);
|
||||
videoview.setOnTouchListener(onVideoviewTouched);
|
||||
|
@ -119,6 +119,14 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
|||
if (AppConfig.DEBUG)
|
||||
Log.d(TAG,
|
||||
"Videosurface already created, setting videosurface now");
|
||||
|
||||
Pair<Integer, Integer> videoSize = controller.getVideoSize();
|
||||
if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
|
||||
if (AppConfig.DEBUG) Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
|
||||
videoview.setVideoSize(videoSize.first, videoSize.second);
|
||||
} else {
|
||||
Log.e(TAG, "Could not determine video size");
|
||||
}
|
||||
controller.setVideoSurface(videoview.getHolder());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.os.IBinder;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import de.danoeh.antennapod.AppConfig;
|
||||
|
@ -991,6 +992,10 @@ public class PlaybackService extends Service {
|
|||
return mediaPlayer.isStreaming();
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getVideoSize() {
|
||||
return mediaPlayer.getVideoSize();
|
||||
}
|
||||
|
||||
private void setCurrentlyPlayingMedia(long id) {
|
||||
SharedPreferences.Editor editor = PreferenceManager
|
||||
.getDefaultSharedPreferences(getApplicationContext()).edit();
|
||||
|
|
|
@ -3,11 +3,11 @@ package de.danoeh.antennapod.service.playback;
|
|||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.RemoteControlClient;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.SurfaceHolder;
|
||||
import de.danoeh.antennapod.AppConfig;
|
||||
import de.danoeh.antennapod.feed.Chapter;
|
||||
|
@ -47,6 +47,7 @@ public class PlaybackServiceMediaPlayer {
|
|||
private volatile MediaType mediaType;
|
||||
private volatile AtomicBoolean startWhenPrepared;
|
||||
private volatile boolean pausedBecauseOfTransientAudiofocusLoss;
|
||||
private volatile Pair<Integer, Integer> videoSize;
|
||||
|
||||
/**
|
||||
* Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads
|
||||
|
@ -76,15 +77,9 @@ public class PlaybackServiceMediaPlayer {
|
|||
pausedBecauseOfTransientAudiofocusLoss = false;
|
||||
mediaType = MediaType.UNKNOWN;
|
||||
playerStatus = PlayerStatus.STOPPED;
|
||||
videoSize = null;
|
||||
}
|
||||
|
||||
private Handler.Callback handlerCallback = new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts or prepares playback of the specified Playable object. If another Playable object is already being played, the currently playing
|
||||
* episode will be stopped and replaced with the new Playable object. If the Playable object is already being played, the method will
|
||||
|
@ -156,6 +151,7 @@ public class PlaybackServiceMediaPlayer {
|
|||
this.media = playable;
|
||||
this.stream = stream;
|
||||
this.mediaType = media.getMediaType();
|
||||
this.videoSize = null;
|
||||
PlaybackServiceMediaPlayer.this.startWhenPrepared.set(startWhenPrepared);
|
||||
setPlayerStatus(PlayerStatus.INITIALIZING, media);
|
||||
try {
|
||||
|
@ -324,6 +320,11 @@ public class PlaybackServiceMediaPlayer {
|
|||
if (AppConfig.DEBUG)
|
||||
Log.d(TAG, "Resource prepared");
|
||||
|
||||
if (mediaType == MediaType.VIDEO) {
|
||||
VideoPlayer vp = (VideoPlayer) mediaPlayer;
|
||||
videoSize = new Pair<Integer, Integer>(vp.getVideoWidth(), vp.getVideoHeight());
|
||||
}
|
||||
|
||||
mediaPlayer.seekTo(media.getPosition());
|
||||
if (media.getDuration() == 0) {
|
||||
if (AppConfig.DEBUG)
|
||||
|
@ -603,6 +604,30 @@ public class PlaybackServiceMediaPlayer {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return width and height of the currently playing video as a pair.
|
||||
*
|
||||
* @return Width and height as a Pair or null if the video size could not be determined. The method might still
|
||||
* return an invalid non-null value if the getVideoWidth() and getVideoHeight() methods of the media player return
|
||||
* invalid values.
|
||||
*/
|
||||
public Pair<Integer, Integer> getVideoSize() {
|
||||
if (!playerLock.tryLock()) {
|
||||
// use cached value if lock can't be aquired
|
||||
return videoSize;
|
||||
}
|
||||
Pair<Integer, Integer> res;
|
||||
if (mediaPlayer == null || playerStatus == PlayerStatus.ERROR || mediaType != MediaType.VIDEO) {
|
||||
res = null;
|
||||
} else {
|
||||
VideoPlayer vp = (VideoPlayer) mediaPlayer;
|
||||
videoSize = new Pair<Integer, Integer>(vp.getVideoWidth(), vp.getVideoHeight());
|
||||
res = videoSize;
|
||||
}
|
||||
playerLock.unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a PSMInfo object that contains information about the current state of the PSMP object.
|
||||
*
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.os.AsyncTask;
|
|||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
@ -698,6 +699,14 @@ public abstract class PlaybackController {
|
|||
return false;
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getVideoSize() {
|
||||
if (playbackService != null) {
|
||||
return playbackService.getVideoSize();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if PlaybackController can communicate with the playback
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package de.danoeh.antennapod.view;
|
||||
|
||||
/*
|
||||
* Copyright (C) Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.VideoView;
|
||||
|
||||
public class AspectRatioVideoView extends VideoView {
|
||||
|
||||
|
||||
private int mVideoWidth;
|
||||
private int mVideoHeight;
|
||||
|
||||
public AspectRatioVideoView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public AspectRatioVideoView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public AspectRatioVideoView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (mVideoWidth <= 0 || mVideoHeight <= 0) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
return;
|
||||
}
|
||||
|
||||
float heightRatio = (float) mVideoHeight / (float) getHeight();
|
||||
float widthRatio = (float) mVideoWidth / (float) getWidth();
|
||||
|
||||
int scaledHeight;
|
||||
int scaledWidth;
|
||||
|
||||
if (heightRatio > widthRatio) {
|
||||
scaledHeight = (int) Math.ceil((float) mVideoHeight
|
||||
/ heightRatio);
|
||||
scaledWidth = (int) Math.ceil((float) mVideoWidth
|
||||
/ heightRatio);
|
||||
} else {
|
||||
scaledHeight = (int) Math.ceil((float) mVideoHeight
|
||||
/ widthRatio);
|
||||
scaledWidth = (int) Math.ceil((float) mVideoWidth
|
||||
/ widthRatio);
|
||||
}
|
||||
|
||||
setMeasuredDimension(scaledWidth, scaledHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Source code originally from:
|
||||
* http://clseto.mysinablog.com/index.php?op=ViewArticle&articleId=2992625
|
||||
*
|
||||
* @param videoWidth
|
||||
* @param videoHeight
|
||||
*/
|
||||
public void setVideoSize(int videoWidth, int videoHeight) {
|
||||
// Set the new video size
|
||||
mVideoWidth = videoWidth;
|
||||
mVideoHeight = videoHeight;
|
||||
|
||||
/**
|
||||
* If this isn't set the video is stretched across the
|
||||
* SurfaceHolders display surface (i.e. the SurfaceHolder
|
||||
* as the same size and the video is drawn to fit this
|
||||
* display area). We want the size to be the video size
|
||||
* and allow the aspectratio to handle how the surface is shown
|
||||
*/
|
||||
getHolder().setFixedSize(videoWidth, videoHeight);
|
||||
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue