你的打賞,是對我最大的支援:

測試位址:rtsp://218.204.223.237:554/live/1/0547424F573B085C/gsfp90ef4k0a6iap.sdp
本demo測試位址:rtsp://admin:[email protected]:554
測試方法:
在PC端下載下傳 VLC 播放器
下載下傳位址:
https://vlc-media-player.en.softonic.com/
demo運作結果
補充一句:不足的地方 就是第一次打開有點慢,30s
廢話不多說了,上代碼
主要代碼:
package demo.one;
//.....
/**
* _ooOoo_
* o8888888o
* 88" . "88
* (| -_- |)
* O\ = /O
* ____/`---'\____
* . ' \\| |// `.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' | |
* \ .-\__ `-` ___/-. /
* ___`. .' /--.--\ `. . __
* ."" '< `.___\_<|>_/___.' >'"".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `-. \_ __\ /__ _/ .-` / /
* ======`-.____`-.___\_____/___.-`____.-'======
* `=---='
* <p>
* .............................................
* 佛祖保佑 永無BUG
*
* @ProjectName: Demo_one
* @Package: demo.one
* @ClassName: VideoPalyerActivity
* @Description: java類作用描述,播放RSTSP視訊 播放位址:拼接方式
*
* rtsp://123:[email protected]:554
*
* 123 賬戶
* 123456 密碼
* 中間用冒号隔開:小寫
*
* 183.230.153.189:554 播放位址 + 端口
*
*用@符号
*
* @Author: HCJ
* @CreateDate: 2019/8/26 17:38
* @UpdateUser: 更新者
* @UpdateDate: 2019/8/26 17:38
* @UpdateRemark: 更新說明
* @Version: 1.0
*/
public class VideoPalyerActivity extends AppCompatActivity implements IVLCVout.OnNewVideoLayoutListener {
private static final String TAG = "VideoPalyerActivity";
private static final boolean ENABLE_SUBTITLES = true;
private static String SAMPLE_URL = "rtsp://admin:[email protected]:554";
// private static String SAMPLE_URL;
private static final int SURFACE_BEST_FIT = 0;
private static final int SURFACE_FIT_SCREEN = 1;
private static final int SURFACE_FILL = 2;
private static final int SURFACE_16_9 = 3;
private static final int SURFACE_4_3 = 4;
private static final int SURFACE_ORIGINAL = 5;
private static int CURRENT_SIZE = SURFACE_BEST_FIT;
private FrameLayout mVideoSurfaceFrame = null;
private SurfaceView mVideoSurface = null;
private SurfaceView mSubtitlesSurface = null;
private final Handler mHandler = new Handler();
private View.OnLayoutChangeListener mOnLayoutChangeListener = null;
private LibVLC mLibVLC = null;
private MediaPlayer mMediaPlayer = null;
private int mVideoHeight = 0;
private int mVideoWidth = 0;
private int mVideoVisibleHeight = 0;
private int mVideoVisibleWidth = 0;
private int mVideoSarNum = 0;
private int mVideoSarDen = 0;
// private void init() {
// Configuration mConfiguration = this.getResources().getConfiguration(); //擷取設定的配置資訊
// int ori = mConfiguration.orientation; //擷取螢幕方向
//
// if (ori == mConfiguration.ORIENTATION_PORTRAIT) {
// //豎屏
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//強制為橫屏
// }
//
//
// }
private void changeMediaPlayerLayout(int displayW, int displayH) {
/* Change the video placement using the MediaPlayer API */
switch (CURRENT_SIZE) {
case SURFACE_BEST_FIT:
mMediaPlayer.setAspectRatio("3:2");
mMediaPlayer.setScale(0);
break;
case SURFACE_FIT_SCREEN:
break;
case SURFACE_FILL: {
Media.VideoTrack vtrack = mMediaPlayer.getCurrentVideoTrack();
if (vtrack == null)
return;
final boolean videoSwapped = vtrack.orientation == Media.VideoTrack.Orientation.LeftBottom
|| vtrack.orientation == Media.VideoTrack.Orientation.RightTop;
if (CURRENT_SIZE == SURFACE_FIT_SCREEN) {
int videoW = vtrack.width;
int videoH = vtrack.height;
if (videoSwapped) {
int swap = videoW;
videoW = videoH;
videoH = swap;
}
if (vtrack.sarNum != vtrack.sarDen)
videoW = videoW * vtrack.sarNum / vtrack.sarDen;
float ar = videoW / (float) videoH;
float dar = displayW / (float) displayH;
float scale;
if (dar >= ar)
scale = displayW / (float) videoW; /* horizontal */
else
scale = displayH / (float) videoH; /* vertical */
mMediaPlayer.setScale(scale);
mMediaPlayer.setAspectRatio(null);
} else {
mMediaPlayer.setScale(0);
mMediaPlayer.setAspectRatio(!videoSwapped ? "" + displayW + ":" + displayH
: "" + displayH + ":" + displayW);
}
break;
}
case SURFACE_16_9:
mMediaPlayer.setAspectRatio("16:9");
mMediaPlayer.setScale(0);
break;
case SURFACE_4_3:
mMediaPlayer.setAspectRatio("4:3");
mMediaPlayer.setScale(0);
break;
case SURFACE_ORIGINAL:
mMediaPlayer.setAspectRatio(null);
mMediaPlayer.setScale(1);
break;
}
}
private void updateVideoSurfaces() {
int sw = getWindow().getDecorView().getWidth();
int sh = getWindow().getDecorView().getHeight();
// sanity check
if (sw * sh == 0) {
Log.e(TAG, "Invalid surface size");
return;
}
mMediaPlayer.getVLCVout().setWindowSize(sw, sh);
ViewGroup.LayoutParams lp = mVideoSurface.getLayoutParams();
if (mVideoWidth * mVideoHeight == 0) {
/* Case of OpenGL vouts: handles the placement of the video using MediaPlayer API */
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
mVideoSurface.setLayoutParams(lp);
lp = mVideoSurfaceFrame.getLayoutParams();
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
mVideoSurfaceFrame.setLayoutParams(lp);
changeMediaPlayerLayout(sw, sh);
return;
}
if (lp.width == lp.height && lp.width == ViewGroup.LayoutParams.MATCH_PARENT) {
/* We handle the placement of the video using Android View LayoutParams */
mMediaPlayer.setAspectRatio(null);
mMediaPlayer.setScale(0);
}
double dw = sw, dh = sh;
final boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (sw > sh && isPortrait || sw < sh && !isPortrait) {
dw = sh;
dh = sw;
}
// compute the aspect ratio
double ar, vw;
if (mVideoSarDen == mVideoSarNum) {
/* No indication about the density, assuming 1:1 */
vw = mVideoVisibleWidth;
ar = (double) mVideoVisibleWidth / (double) mVideoVisibleHeight;
} else {
/* Use the specified aspect ratio */
vw = mVideoVisibleWidth * (double) mVideoSarNum / mVideoSarDen;
ar = vw / mVideoVisibleHeight;
}
// compute the display aspect ratio
double dar = dw / dh;
switch (CURRENT_SIZE) {
case SURFACE_BEST_FIT:
if (dar < ar)
dh = dw / ar;
else
dw = dh * ar;
break;
case SURFACE_FIT_SCREEN:
if (dar >= ar)
dh = dw / ar; /* horizontal */
else
dw = dh * ar; /* vertical */
break;
case SURFACE_FILL:
break;
case SURFACE_16_9:
ar = 16.0 / 9.0;
if (dar < ar)
dh = dw / ar;
else
dw = dh * ar;
break;
case SURFACE_4_3:
ar = 4.0 / 3.0;
if (dar < ar)
dh = dw / ar;
else
dw = dh * ar;
break;
case SURFACE_ORIGINAL:
dh = mVideoVisibleHeight;
dw = vw;
break;
}
// set display size
lp.width = (int) Math.ceil(dw * mVideoWidth / mVideoVisibleWidth);
lp.height = (int) Math.ceil(dh * mVideoHeight / mVideoVisibleHeight);
mVideoSurface.setLayoutParams(lp);
if (mSubtitlesSurface != null)
mSubtitlesSurface.setLayoutParams(lp);
// set frame size (crop if necessary)
lp = mVideoSurfaceFrame.getLayoutParams();
lp.width = (int) Math.floor(dw);
lp.height = (int) Math.floor(dh);
mVideoSurfaceFrame.setLayoutParams(lp);
mVideoSurface.invalidate();
if (mSubtitlesSurface != null)
mSubtitlesSurface.invalidate();
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onNewVideoLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
mVideoWidth = width;
mVideoHeight = height;
mVideoVisibleWidth = visibleWidth;
mVideoVisibleHeight = visibleHeight;
mVideoSarNum = sarNum;
mVideoSarDen = sarDen;
updateVideoSurfaces();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videoplayer);
// SAMPLE_URL = getIntent().getStringExtra("extra_url");
// Log.d(TAG, "onCreate: " + SAMPLE_URL);
// init();
ArrayList<String> args = new ArrayList<>();
args.add("-vvv");
mLibVLC = new LibVLC(getApplicationContext(), args);
mMediaPlayer = new MediaPlayer(mLibVLC);
mMediaPlayer.setScale(0);
mVideoSurfaceFrame = (FrameLayout) findViewById(R.id.video_surface_frame);
mVideoSurface = (SurfaceView) findViewById(R.id.video_surface);
if (ENABLE_SUBTITLES) {
final ViewStub stub = (ViewStub) findViewById(R.id.subtitles_stub);
mSubtitlesSurface = (SurfaceView) stub.inflate();
mSubtitlesSurface.setZOrderMediaOverlay(true);
mSubtitlesSurface.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
}
@Override
protected void onStart() {
super.onStart();
final IVLCVout vlcVout = mMediaPlayer.getVLCVout();
vlcVout.setVideoView(mVideoSurface);
if (mSubtitlesSurface != null)
vlcVout.setSubtitlesView(mSubtitlesSurface);
vlcVout.attachViews(this);
Media media = new Media(mLibVLC, Uri.parse("rtsp://admin:[email protected]:554"));
mMediaPlayer.setMedia(media);
media.release();
mMediaPlayer.play();
if (mOnLayoutChangeListener == null) {
mOnLayoutChangeListener = new View.OnLayoutChangeListener() {
private final Runnable mRunnable = new Runnable() {
@Override
public void run() {
updateVideoSurfaces();
}
};
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
mHandler.removeCallbacks(mRunnable);
mHandler.post(mRunnable);
}
}
};
}
mVideoSurfaceFrame.addOnLayoutChangeListener(mOnLayoutChangeListener);
}
@Override
protected void onStop() {
super.onStop();
if (mOnLayoutChangeListener != null) {
mVideoSurfaceFrame.removeOnLayoutChangeListener(mOnLayoutChangeListener);
mOnLayoutChangeListener = null;
}
mMediaPlayer.stop();
mMediaPlayer.getVLCVout().detachViews();
}
@Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.release();
mLibVLC.release();
}
}
布局:
activity_videoplayer:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<FrameLayout
android:id="@+id/video_surface_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundGravity="clip_horizontal|clip_vertical"
android:gravity="center"
tools:ignore="true">
<SurfaceView
android:id="@+id/video_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" />
<ViewStub
android:id="@+id/subtitles_stub"
android:layout_width="1dp"
android:layout_height="1dp"
android:layout="@layout/subtitles_surface" />
</FrameLayout>
</LinearLayout>
subtitles_stub:
<?xml version="1.0" encoding="utf-8"?>
<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="1dp"
android:layout_height="1dp">
</SurfaceView>
引用包:
implementation files('libs/****.jar')
ndk {
//選擇要添加的對應cpu類型的.so庫。
abiFilters 'armeabi', 'armeabi-v7a'//, 'arm64-v8a', 'x86', 'x86_64'
// 還可以添加 'x86', 'x86_64', 'mips', 'mips64'
}
build
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "demo.one"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
//選擇要添加的對應cpu類型的.so庫。
abiFilters 'armeabi', 'armeabi-v7a'//, 'arm64-v8a', 'x86', 'x86_64'
// 還可以添加 'x86', 'x86_64', 'mips', 'mips64'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation files('libs/****.jar')
}
權限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="demo.one">
//......
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".VideoPalyerActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
AndroidManifest.xml 全部貼上來 給你們 看
在src/main 加上 jniLibs 庫
$99 for source code configuration:
