remove onLive module

dev
xufuji456 4 years ago
parent 442d35414e
commit ba919de3b4
  1. 1
      OnLive/.gitignore
  2. 52
      OnLive/build.gradle
  3. BIN
      OnLive/libs/arm64-v8a/libijkffmpeg.so
  4. BIN
      OnLive/libs/arm64-v8a/libijkplayer.so
  5. BIN
      OnLive/libs/arm64-v8a/libijksdl.so
  6. BIN
      OnLive/libs/armeabi-v7a/libijkffmpeg.so
  7. BIN
      OnLive/libs/armeabi-v7a/libijkplayer.so
  8. BIN
      OnLive/libs/armeabi-v7a/libijksdl.so
  9. 17
      OnLive/proguard-rules.pro
  10. 43
      OnLive/src/main/AndroidManifest.xml
  11. 469
      OnLive/src/main/java/com/frank/living/activity/MultiScreenActivity.java
  12. 154
      OnLive/src/main/java/com/frank/living/activity/RtspLiveActivity.java
  13. 108
      OnLive/src/main/java/com/frank/living/config/Settings.java
  14. 10
      OnLive/src/main/java/com/frank/living/constant/Constants.java
  15. 14
      OnLive/src/main/java/com/frank/living/listener/IjkPlayerListener.java
  16. 59
      OnLive/src/main/java/com/frank/living/listener/OnDoubleClickListener.java
  17. 52
      OnLive/src/main/java/com/frank/living/util/PhotoUtil.java
  18. 87
      OnLive/src/main/java/com/frank/living/widget/AndroidMediaController.java
  19. 57
      OnLive/src/main/java/com/frank/living/widget/FileMediaDataSource.java
  20. 42
      OnLive/src/main/java/com/frank/living/widget/IMediaController.java
  21. 87
      OnLive/src/main/java/com/frank/living/widget/IRenderView.java
  22. 1205
      OnLive/src/main/java/com/frank/living/widget/IjkVideoView.java
  23. 164
      OnLive/src/main/java/com/frank/living/widget/InfoHudViewHolder.java
  24. 248
      OnLive/src/main/java/com/frank/living/widget/MeasureHelper.java
  25. 76
      OnLive/src/main/java/com/frank/living/widget/MediaPlayerCompat.java
  26. 286
      OnLive/src/main/java/com/frank/living/widget/SurfaceRenderView.java
  27. 131
      OnLive/src/main/java/com/frank/living/widget/TableLayoutBinder.java
  28. 368
      OnLive/src/main/java/com/frank/living/widget/TextureRenderView.java
  29. 20
      OnLive/src/main/project.properties
  30. BIN
      OnLive/src/main/res/drawable-xhdpi/ic_pause.png
  31. BIN
      OnLive/src/main/res/drawable-xhdpi/ic_play.png
  32. BIN
      OnLive/src/main/res/drawable-xhdpi/ic_screen_shot.png
  33. BIN
      OnLive/src/main/res/drawable-xhdpi/ic_silence.png
  34. BIN
      OnLive/src/main/res/drawable-xhdpi/ic_sound.png
  35. 54
      OnLive/src/main/res/layout/activity_live.xml
  36. 48
      OnLive/src/main/res/layout/activity_multi_screen.xml
  37. 13
      OnLive/src/main/res/layout/table_media_info.xml
  38. 21
      OnLive/src/main/res/layout/table_media_info_row1.xml
  39. 24
      OnLive/src/main/res/layout/table_media_info_row2.xml
  40. 15
      OnLive/src/main/res/layout/table_media_info_section.xml
  41. BIN
      OnLive/src/main/res/mipmap-xhdpi/ic_launcher.png
  42. BIN
      OnLive/src/main/res/mipmap-xxhdpi/ic_launcher.png
  43. 19
      OnLive/src/main/res/values/colors.xml
  44. 8
      OnLive/src/main/res/values/dimens.xml
  45. 4
      OnLive/src/main/res/values/ids.xml
  46. 73
      OnLive/src/main/res/values/strings.xml
  47. 112
      OnLive/src/main/res/values/strings_pref.xml
  48. 19
      OnLive/src/main/res/values/styles.xml
  49. 8
      OnLive/src/main/res/values/themes.xml
  50. 74
      OnLive/src/main/res/xml/settings.xml
  51. 4
      settings.gradle

1
OnLive/.gitignore vendored

@ -1 +0,0 @@
/build

@ -1,52 +0,0 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
lintOptions {
abortOnError false
}
defaultConfig {
applicationId "com.frank.living"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
flavorDimensions "800400"
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
all32 { minSdkVersion rootProject.ext.minSdkVersion }
all64 { minSdkVersion rootProject.ext.minSdkVersion }
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:$rootProject.appcompatVersion"
implementation "androidx.preference:preference:$rootProject.preferenceVersion"
implementation "androidx.annotation:annotation:$rootProject.annotationVersion"
implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerviewVersion"
implementation "com.squareup:otto:$rootProject.ottoVersion"
implementation "tv.danmaku.ijk.media:ijkplayer-java:$rootProject.ijkVersion"
implementation "tv.danmaku.ijk.media:ijkplayer-exo:$rootProject.ijkVersion"
}

@ -1,17 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /opt/android/ADK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.frank.living">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="com.frank.living.activity.RtspLiveActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@style/FullscreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.frank.living.activity.MultiScreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:theme="@style/FullscreenTheme">
<!--<intent-filter>-->
<!--<action android:name="android.intent.action.MAIN" />-->
<!--<action android:name="android.intent.action.VIEW" />-->
<!--<category android:name="android.intent.category.LAUNCHER" />-->
<!--</intent-filter>-->
</activity>
</application>
</manifest>

@ -1,469 +0,0 @@
package com.frank.living.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;
import android.os.Process;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import com.frank.living.R;
import com.frank.living.constant.Constants;
import com.frank.living.listener.OnDoubleClickListener;
import com.frank.living.listener.IjkPlayerListener;
import com.frank.living.widget.IjkVideoView;
import java.util.HashMap;
import java.util.TreeMap;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
/**
* multi screen living
* Created by xufulong on 2019/01/04
*/
public class MultiScreenActivity extends AppCompatActivity {
private static final String TAG = MultiScreenActivity.class.getSimpleName();
private IjkVideoView mVideoView1;
private IjkVideoView mVideoView2;
private IjkVideoView mVideoView3;
private IjkVideoView mVideoView4;
private View divider1;
private View divider2;
private IMediaPlayer ijkPlayer;
private CustomReceiver customReceiver;
private String ipAddress;
//is multi-screen mode or full-screen mode
private boolean isMultiScreen;
//relationship of between client id and channel number
private HashMap<String, Integer> clientMap = new HashMap<>();
//record each channel state
private TreeMap<Integer, Boolean> channelMap = new TreeMap<>();
private String url = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_multi_screen);
parseIntent();
registerBroadcast();
initView();
initListener();
setupView();
wakeUp();
}
private void initView() {
mVideoView1 = findViewById(R.id.video_view1);
mVideoView2 = findViewById(R.id.video_view2);
mVideoView3 = findViewById(R.id.video_view3);
mVideoView4 = findViewById(R.id.video_view4);
divider1 = findViewById(R.id.divider1);
divider2 = findViewById(R.id.divider2);
}
private void initListener() {
mVideoView1.setOnTouchListener(new OnDoubleClickListener(new OnDoubleClickListener.OnDoubleClick() {
@Override
public void onDouble() {
changeScreenMode(1);
}
}));
mVideoView2.setOnTouchListener(new OnDoubleClickListener(new OnDoubleClickListener.OnDoubleClick() {
@Override
public void onDouble() {
changeScreenMode(2);
}
}));
mVideoView3.setOnTouchListener(new OnDoubleClickListener(new OnDoubleClickListener.OnDoubleClick() {
@Override
public void onDouble() {
changeScreenMode(3);
}
}));
mVideoView4.setOnTouchListener(new OnDoubleClickListener(new OnDoubleClickListener.OnDoubleClick() {
@Override
public void onDouble() {
changeScreenMode(4);
}
}));
}
private void setupView() {
//default full screen
enterFullScreen(1);
mVideoView1.setVideoPath(url);
mVideoView1.setIjkPlayerListener(new IjkPlayerListener() {
@Override
public void onIjkPlayer(IjkMediaPlayer ijkMediaPlayer) {
//setting ijkPlayer option
setOptions(ijkMediaPlayer);
}
});
mVideoView1.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(IMediaPlayer iMediaPlayer) {
ijkPlayer = iMediaPlayer;
}
});
mVideoView1.start();
}
/**
* parse params
*/
private void parseIntent() {
for (int i = 1; i <= 4; i++) {
channelMap.put(i, false);
}
clientMap.put(ipAddress, 1);
channelMap.put(1, true);
Intent intent = getIntent();
String url = intent.getStringExtra("url");
if (!TextUtils.isEmpty(url)) {
this.url = url;
}
String ip = intent.getStringExtra("ip");
if (!TextUtils.isEmpty(ip)) {
ipAddress = ip;
}
}
//wake up the screen
private void wakeUp() {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (powerManager == null)
return;
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
wakeLock.acquire(1000);
wakeLock.release();
}
/**
* config the options of ijkPlayer
*/
private void setOptions(IjkMediaPlayer ijkPlayer) {
if (ijkPlayer == null)
return;
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "fast", 1);//no extra optimize
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 200);//size of probe data
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);//enable cache or not
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 1);
//0:disable 1:enable
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);//enable hardware decode or not
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);//auto rotate
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 0);
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 0);//max buffer size
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", 2);//minimum frame size
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", 30);//maximum cached duration
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 1);
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "nobuffer");
//max analyzed duration
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzedmaxduration", 100);
//ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");//using tcp or udp
}
/**
* register broadcast
*/
private void registerBroadcast() {
customReceiver = new CustomReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Constants.ACTION_CLIENT_REMOVE);
intentFilter.addAction(Constants.ACTION_CLIENT_ADD);
registerReceiver(customReceiver, intentFilter);
}
/**
* unregister broadcast
*/
private void unregisterBroadcast() {
if (customReceiver != null) {
unregisterReceiver(customReceiver);
customReceiver = null;
}
}
/**
* custom broadcast receiver
*/
private class CustomReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == null)
return;
Log.e(TAG, "onReceive=" + action);
switch (action) {
case Constants.ACTION_CLIENT_REMOVE://remove client
int num = intent.getIntExtra("clientNum", 0);
if (num == 0) {
Process.killProcess(Process.myPid());
} else if (num > 0) {
String ipAddress = intent.getStringExtra("ipAddress");
int target = clientMap.get(ipAddress);
removeClient(target);
clientMap.remove(ipAddress);
channelMap.put(target, false);
if (num == 1) {
int castingChannel = getCastingChannel();
enterFullScreen(castingChannel);
}
}
break;
case Constants.ACTION_CLIENT_ADD://add client
int clientNum = intent.getIntExtra("clientNum", 0);
String otherUrl = intent.getStringExtra("url");
String ipAddress = intent.getStringExtra("ip");
//select the idle channel
int channel = selectIdleChannel(clientNum);
clientMap.put(ipAddress, channel);
channelMap.put(channel, true);
addClient(channel, otherUrl);
//switch multi-screen mode
if (clientNum == 2) {
exitFullScreen();
}
break;
default:
break;
}
}
}
/**
* select the first idle channel
*
* @param clientNum clientNum
* @return idleChannel
*/
private int selectIdleChannel(int clientNum) {
for (int channel = 1; channel < clientNum; channel++) {
if (!channelMap.get(channel)) {
return channel;
}
}
return clientNum;
}
/**
* get current casting channel
*
* @return idleChannel
*/
private int getCastingChannel() {
for (int channel = 1; channel <= 4; channel++) {
if (channelMap.get(channel)) {
return channel;
}
}
return 0;
}
/**
* add client to casting
*
* @param target target
* @param clientUrl clientUrl
*/
private void addClient(int target, String clientUrl) {
switch (target) {
case 1:
mVideoView1.setVisibility(View.VISIBLE);
mVideoView1.setVideoPath(clientUrl);
mVideoView1.start();
break;
case 2:
mVideoView2.setVisibility(View.VISIBLE);
mVideoView2.setVideoPath(clientUrl);
mVideoView2.start();
break;
case 3:
mVideoView3.setVisibility(View.VISIBLE);
mVideoView3.setVideoPath(clientUrl);
mVideoView3.start();
break;
case 4:
mVideoView4.setVisibility(View.VISIBLE);
mVideoView4.setVideoPath(clientUrl);
mVideoView4.start();
break;
default:
break;
}
}
/**
* remove client
*
* @param target target
*/
private void removeClient(int target) {
switch (target) {
case 1:
mVideoView1.stopPlayback();
mVideoView1.setVisibility(View.GONE);
break;
case 2:
mVideoView2.stopPlayback();
mVideoView2.setVisibility(View.GONE);
break;
case 3:
mVideoView3.stopPlayback();
mVideoView3.setVisibility(View.GONE);
break;
case 4:
mVideoView4.stopPlayback();
mVideoView4.setVisibility(View.GONE);
break;
default:
break;
}
}
/**
* hide divider in multi-screen mode
*/
private void hideDivider() {
divider1.setVisibility(View.GONE);
divider2.setVisibility(View.GONE);
}
/**
* show divider in multi-screen mode
*/
private void showDivider() {
divider1.setVisibility(View.VISIBLE);
divider2.setVisibility(View.VISIBLE);
}
/**
* enter full-screen mode
*
* @param channel channel
*/
private void enterFullScreen(int channel) {
hideDivider();
switch (channel) {
case 1:
mVideoView1.setRenderViewVisible();
mVideoView2.setRenderViewGone();
mVideoView3.setRenderViewGone();
mVideoView4.setRenderViewGone();
mVideoView1.setVisibility(View.VISIBLE);
mVideoView2.setVisibility(View.GONE);
mVideoView3.setVisibility(View.GONE);
mVideoView4.setVisibility(View.GONE);
break;
case 2:
mVideoView1.setRenderViewGone();
mVideoView2.setRenderViewVisible();
mVideoView3.setRenderViewGone();
mVideoView4.setRenderViewGone();
mVideoView1.setVisibility(View.GONE);
mVideoView2.setVisibility(View.VISIBLE);
mVideoView3.setVisibility(View.GONE);
mVideoView4.setVisibility(View.GONE);
break;
case 3:
mVideoView1.setRenderViewGone();
mVideoView2.setRenderViewGone();
mVideoView3.setRenderViewVisible();
mVideoView4.setRenderViewGone();
mVideoView1.setVisibility(View.GONE);
mVideoView2.setVisibility(View.GONE);
mVideoView3.setVisibility(View.VISIBLE);
mVideoView4.setVisibility(View.GONE);
break;
case 4:
mVideoView1.setRenderViewGone();
mVideoView2.setRenderViewGone();
mVideoView3.setRenderViewGone();
mVideoView4.setRenderViewVisible();
mVideoView1.setVisibility(View.GONE);
mVideoView2.setVisibility(View.GONE);
mVideoView3.setVisibility(View.GONE);
mVideoView4.setVisibility(View.VISIBLE);
break;
default:
break;
}
}
/**
* exit full-screen mode
*/
private void exitFullScreen() {
mVideoView1.setRenderViewVisible();
mVideoView2.setRenderViewVisible();
mVideoView3.setRenderViewVisible();
mVideoView4.setRenderViewVisible();
showDivider();
mVideoView1.setVisibility(View.VISIBLE);
mVideoView2.setVisibility(View.VISIBLE);
mVideoView3.setVisibility(View.VISIBLE);
mVideoView4.setVisibility(View.VISIBLE);
}
/**
* switch screen mode
*
* @param channel channel
*/
private void changeScreenMode(int channel) {
isMultiScreen = !isMultiScreen;
if (isMultiScreen) {
enterFullScreen(channel);
} else {
exitFullScreen();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterBroadcast();
mVideoView1.stopPlayback();
mVideoView1.release(true);
mVideoView2.stopPlayback();
mVideoView2.release(true);
mVideoView3.stopPlayback();
mVideoView3.release(true);
mVideoView4.stopPlayback();
mVideoView4.release(true);
IjkMediaPlayer.native_profileEnd();
}
}

@ -1,154 +0,0 @@
package com.frank.living.activity;
import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TableLayout;
import com.frank.living.R;
import com.frank.living.listener.IjkPlayerListener;
import androidx.core.app.ActivityCompat;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import com.frank.living.util.PhotoUtil;
import com.frank.living.widget.IjkVideoView;
import java.io.File;
public class RtspLiveActivity extends AppCompatActivity implements IjkPlayerListener, View.OnClickListener {
private final static String TAG = RtspLiveActivity.class.getSimpleName();
private IjkMediaPlayer ijkMediaPlayer;
private IjkVideoView mVideoView;
private ImageButton btnPlay;
private ImageButton btnSound;
private boolean isPause;
private boolean isSilence;
private String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
private final static String url = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live);
requestPermission();
init();
}
private void init() {
IjkMediaPlayer.loadLibrariesOnce(null);
IjkMediaPlayer.native_profileBegin("libijkplayer.so");
TableLayout mHudView = findViewById(R.id.hud_view);
mVideoView = findViewById(R.id.video_view);
mVideoView.setHudView(mHudView);
mVideoView.setIjkPlayerListener(this);
mVideoView.setVideoPath(url);
mVideoView.start();
btnPlay = findViewById(R.id.btn_play);
btnPlay.setOnClickListener(this);
btnSound = findViewById(R.id.btn_sound);
btnSound.setOnClickListener(this);
ImageButton btnScreenShot = findViewById(R.id.btn_screenshot);
btnScreenShot.setOnClickListener(this);
}
private void requestPermission() {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, permissions, 1234);
}
}
private void initOptions() {
if (ijkMediaPlayer == null)
return;
Log.e(TAG, "initOptions");
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "fast", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 200);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 1);
//0:disable 1:enable
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", 2);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", 30);
//input buffer:don't limit the input buffer size (useful with realtime streams)
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "nobuffer");
//ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzedmaxduration", 100);
}
@Override
public void onIjkPlayer(IjkMediaPlayer ijkMediaPlayer) {
this.ijkMediaPlayer = ijkMediaPlayer;
initOptions();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_play:
isPause = !isPause;
if (isPause) {//pause
mVideoView.pause();
btnPlay.setBackgroundResource(R.drawable.ic_play);
} else {//resume
mVideoView.start();
btnPlay.setBackgroundResource(R.drawable.ic_pause);
}
break;
case R.id.btn_sound:
isSilence = !isSilence;
if (ijkMediaPlayer == null)
return;
if (isSilence) {
ijkMediaPlayer.setVolume(0, 0);
btnSound.setBackgroundResource(R.drawable.ic_sound);
} else {
ijkMediaPlayer.setVolume(50, 50);
btnSound.setBackgroundResource(R.drawable.ic_silence);
}
break;
case R.id.btn_screenshot:
if (mVideoView != null) {
Bitmap currentFrame = mVideoView.getCurrentFrame();
if (currentFrame != null) {
String photoName = "img_" + System.currentTimeMillis() + ".jpg";
String photoPath = Environment.getExternalStorageDirectory().getPath() + File.separator + photoName;
PhotoUtil.savePhoto(currentFrame, photoPath, this);
}
}
break;
default:
break;
}
}
@Override
protected void onStop() {
super.onStop();
mVideoView.stopPlayback();
mVideoView.release(true);
IjkMediaPlayer.native_profileEnd();
}
}

@ -1,108 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.config;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.frank.living.R;
public class Settings {
private Context mAppContext;
private SharedPreferences mSharedPreferences;
public static final int PV_PLAYER__Auto = 0;
public static final int PV_PLAYER__AndroidMediaPlayer = 1;
public static final int PV_PLAYER__IjkMediaPlayer = 2;
public static final int PV_PLAYER__IjkExoMediaPlayer = 3;
public Settings(Context context) {
mAppContext = context.getApplicationContext();
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mAppContext);
}
public int getPlayer() {
String key = mAppContext.getString(R.string.pref_key_player);
String value = mSharedPreferences.getString(key, "");
try {
return Integer.valueOf(value).intValue();
} catch (NumberFormatException e) {
return 0;
}
}
public boolean getUsingMediaCodec() {
String key = mAppContext.getString(R.string.pref_key_using_media_codec);
return mSharedPreferences.getBoolean(key, false);
}
public boolean getUsingMediaCodecAutoRotate() {
String key = mAppContext.getString(R.string.pref_key_using_media_codec_auto_rotate);
return mSharedPreferences.getBoolean(key, false);
}
public boolean getMediaCodecHandleResolutionChange() {
String key = mAppContext.getString(R.string.pref_key_media_codec_handle_resolution_change);
return mSharedPreferences.getBoolean(key, false);
}
public boolean getUsingOpenSLES() {
String key = mAppContext.getString(R.string.pref_key_using_opensl_es);
return mSharedPreferences.getBoolean(key, false);
}
public String getPixelFormat() {
String key = mAppContext.getString(R.string.pref_key_pixel_format);
return mSharedPreferences.getString(key, "");
}
public boolean getEnableNoView() {
String key = mAppContext.getString(R.string.pref_key_enable_no_view);
return mSharedPreferences.getBoolean(key, false);
}
public boolean getEnableSurfaceView() {
String key = mAppContext.getString(R.string.pref_key_enable_surface_view);
return mSharedPreferences.getBoolean(key, false);
}
public boolean getEnableTextureView() {
String key = mAppContext.getString(R.string.pref_key_enable_texture_view);
return mSharedPreferences.getBoolean(key, true);
}
public boolean getEnableDetachedSurfaceTextureView() {
String key = mAppContext.getString(R.string.pref_key_enable_detached_surface_texture);
return mSharedPreferences.getBoolean(key, false);
}
public boolean getUsingMediaDataSource() {
String key = mAppContext.getString(R.string.pref_key_using_mediadatasource);
return mSharedPreferences.getBoolean(key, false);
}
public String getLastDirectory() {
String key = mAppContext.getString(R.string.pref_key_last_directory);
return mSharedPreferences.getString(key, "/");
}
public void setLastDirectory(String path) {
String key = mAppContext.getString(R.string.pref_key_last_directory);
mSharedPreferences.edit().putString(key, path).apply();
}
}

@ -1,10 +0,0 @@
package com.frank.living.constant;
public class Constants {
//broadcast of add client
public final static String ACTION_CLIENT_ADD = "action.client.ADD";
//broadcast of remove client
public final static String ACTION_CLIENT_REMOVE = "action.client.REMOVE";
}

@ -1,14 +0,0 @@
package com.frank.living.listener;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
/**
*
* Created by frank on 2019/1/4.
*/
public interface IjkPlayerListener {
void onIjkPlayer(IjkMediaPlayer ijkMediaPlayer);
}

@ -1,59 +0,0 @@
package com.frank.living.listener;
import android.view.MotionEvent;
import android.view.View;
/**
* double click listener
* Created by xufulong on 2019/2/27.
*/
public class OnDoubleClickListener implements View.OnTouchListener {
private final static long DOUBLE_TIME = 500;
private long firstClick;
private long secondClick;
private int clickCount;
private OnDoubleClick onDoubleClick;
public OnDoubleClickListener(OnDoubleClick onDoubleClick) {
this.onDoubleClick = onDoubleClick;
}
public interface OnDoubleClick {
void onDouble();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
return v.performClick();
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
clickCount++;
if (clickCount == 1) {
firstClick = System.currentTimeMillis();
} else if (clickCount == 2) {
secondClick = System.currentTimeMillis();
if (secondClick - firstClick <= DOUBLE_TIME) {
firstClick = 0;
clickCount = 1;
if (onDoubleClick != null) {
onDoubleClick.onDouble();
}
} else {
firstClick = secondClick;
clickCount = 1;
}
secondClick = 0;
} else {
clickCount = 0;
firstClick = 0;
secondClick = 0;
}
}
return false;
}
}

@ -1,52 +0,0 @@
package com.frank.living.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* the tool of photo
* Created by frank on 2019/12/31
*/
public class PhotoUtil {
public static void savePhoto(Bitmap bitmap, String path, Context context) {
savePhoto(bitmap, path, context, 100);
}
public static void savePhoto(Bitmap bitmap, String path, Context context, int quality) {
if (bitmap == null || TextUtils.isEmpty(path) || context == null) {
return;
}
if (quality <= 0 || quality > 100) {
quality = 100;
}
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, fileOutputStream);
fileOutputStream.flush();
if (Looper.myLooper() == Looper.getMainLooper()) {
Toast.makeText(context.getApplicationContext(), "save success:" + path, Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

@ -1,87 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import android.util.AttributeSet;
import android.view.View;
import android.widget.MediaController;
import java.util.ArrayList;
public class AndroidMediaController extends MediaController implements IMediaController {
private ActionBar mActionBar;
public AndroidMediaController(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public AndroidMediaController(Context context, boolean useFastForward) {
super(context, useFastForward);
initView(context);
}
public AndroidMediaController(Context context) {
super(context);
initView(context);
}
private void initView(Context context) {
}
public void setSupportActionBar(@Nullable ActionBar actionBar) {
mActionBar = actionBar;
if (isShowing()) {
actionBar.show();
} else {
actionBar.hide();
}
}
@Override
public void show() {
super.show();
if (mActionBar != null)
mActionBar.show();
}
@Override
public void hide() {
super.hide();
if (mActionBar != null)
mActionBar.hide();
for (View view : mShowOnceArray)
view.setVisibility(View.GONE);
mShowOnceArray.clear();
}
//----------
// Extends
//----------
private ArrayList<View> mShowOnceArray = new ArrayList<View>();
public void showOnce(@NonNull View view) {
mShowOnceArray.add(view);
view.setVisibility(View.VISIBLE);
show();
}
}

@ -1,57 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
public class FileMediaDataSource implements IMediaDataSource {
private RandomAccessFile mFile;
private long mFileSize;
public FileMediaDataSource(File file) throws IOException {
mFile = new RandomAccessFile(file, "r");
mFileSize = mFile.length();
}
@Override
public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
if (mFile.getFilePointer() != position)
mFile.seek(position);
if (size == 0)
return 0;
return mFile.read(buffer, 0, size);
}
@Override
public long getSize() throws IOException {
return mFileSize;
}
@Override
public void close() throws IOException {
mFileSize = 0;
mFile.close();
mFile = null;
}
}

@ -1,42 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import android.view.View;
import android.widget.MediaController;
public interface IMediaController {
void hide();
boolean isShowing();
void setAnchorView(View view);
void setEnabled(boolean enabled);
void setMediaPlayer(MediaController.MediaPlayerControl player);
void show(int timeout);
void show();
//----------
// Extends
//----------
void showOnce(View view);
}

@ -1,87 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import android.graphics.SurfaceTexture;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import tv.danmaku.ijk.media.player.IMediaPlayer;
public interface IRenderView {
int AR_ASPECT_FIT_PARENT = 0; // without clip
int AR_ASPECT_FILL_PARENT = 1; // may clip
int AR_ASPECT_WRAP_CONTENT = 2;
int AR_MATCH_PARENT = 3;
int AR_16_9_FIT_PARENT = 4;
int AR_4_3_FIT_PARENT = 5;
View getView();
boolean shouldWaitForResize();
void setVideoSize(int videoWidth, int videoHeight);
void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen);
void setVideoRotation(int degree);
void setAspectRatio(int aspectRatio);
void addRenderCallback(@NonNull IRenderCallback callback);
void removeRenderCallback(@NonNull IRenderCallback callback);
interface ISurfaceHolder {
void bindToMediaPlayer(IMediaPlayer mp);
@NonNull
IRenderView getRenderView();
@Nullable
SurfaceHolder getSurfaceHolder();
@Nullable
Surface openSurface();
@Nullable
SurfaceTexture getSurfaceTexture();
}
interface IRenderCallback {
/**
* @param holder
* @param width could be 0
* @param height could be 0
*/
void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height);
/**
* @param holder
* @param format could be 0
* @param width
* @param height
*/
void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height);
void onSurfaceDestroyed(@NonNull ISurfaceHolder holder);
}
}

@ -1,164 +0,0 @@
package com.frank.living.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.SparseArray;
import android.view.View;
import android.widget.TableLayout;
import com.frank.living.R;
import java.util.Locale;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.MediaPlayerProxy;
public class InfoHudViewHolder {
private TableLayoutBinder mTableLayoutBinder;
private SparseArray<View> mRowMap = new SparseArray<View>();
private IMediaPlayer mMediaPlayer;
private long mLoadCost = 0;
private long mSeekCost = 0;
public InfoHudViewHolder(Context context, TableLayout tableLayout) {
mTableLayoutBinder = new TableLayoutBinder(context, tableLayout);
}
private void appendSection(int nameId) {
mTableLayoutBinder.appendSection(nameId);
}
private void appendRow(int nameId) {
View rowView = mTableLayoutBinder.appendRow2(nameId, null);
mRowMap.put(nameId, rowView);
}
private void setRowValue(int id, String value) {
View rowView = mRowMap.get(id);
if (rowView == null) {
rowView = mTableLayoutBinder.appendRow2(id, value);
mRowMap.put(id, rowView);
} else {
mTableLayoutBinder.setValueText(rowView, value);
}
}
public void setMediaPlayer(IMediaPlayer mp) {
mMediaPlayer = mp;
if (mMediaPlayer != null) {
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500);
} else {
mHandler.removeMessages(MSG_UPDATE_HUD);
}
}
private static String formatedDurationMilli(long duration) {
if (duration >= 1000) {
return String.format(Locale.US, "%.2f sec", ((float)duration) / 1000);
} else {
return String.format(Locale.US, "%d msec", duration);
}
}
private static String formatedSpeed(long bytes,long elapsed_milli) {
if (elapsed_milli <= 0) {
return "0 B/s";
}
if (bytes <= 0) {
return "0 B/s";
}
float bytes_per_sec = ((float)bytes) * 1000.f / elapsed_milli;
if (bytes_per_sec >= 1000 * 1000) {
return String.format(Locale.US, "%.2f MB/s", ((float)bytes_per_sec) / 1000 / 1000);
} else if (bytes_per_sec >= 1000) {
return String.format(Locale.US, "%.1f KB/s", ((float)bytes_per_sec) / 1000);
} else {
return String.format(Locale.US, "%d B/s", (long)bytes_per_sec);
}
}
public void updateLoadCost(long time) {
mLoadCost = time;
}
public void updateSeekCost(long time) {
mSeekCost = time;
}
private static String formatedSize(long bytes) {
if (bytes >= 100 * 1000) {
return String.format(Locale.US, "%.2f MB", ((float)bytes) / 1000 / 1000);
} else if (bytes >= 100) {
return String.format(Locale.US, "%.1f KB", ((float)bytes) / 1000);
} else {
return String.format(Locale.US, "%d B", bytes);
}
}
private static final int MSG_UPDATE_HUD = 1;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_HUD: {
InfoHudViewHolder holder = InfoHudViewHolder.this;
IjkMediaPlayer mp = null;
if (mMediaPlayer == null)
break;
if (mMediaPlayer instanceof IjkMediaPlayer) {
mp = (IjkMediaPlayer) mMediaPlayer;
} else if (mMediaPlayer instanceof MediaPlayerProxy) {
MediaPlayerProxy proxy = (MediaPlayerProxy) mMediaPlayer;
IMediaPlayer internal = proxy.getInternalMediaPlayer();
if (internal != null && internal instanceof IjkMediaPlayer)
mp = (IjkMediaPlayer) internal;
}
if (mp == null)
break;
int vdec = mp.getVideoDecoder();
switch (vdec) {
case IjkMediaPlayer.FFP_PROPV_DECODER_AVCODEC:
setRowValue(R.string.vdec, "avcodec");
break;
case IjkMediaPlayer.FFP_PROPV_DECODER_MEDIACODEC:
setRowValue(R.string.vdec, "MediaCodec");
break;
default:
setRowValue(R.string.vdec, "");
break;
}
float fpsOutput = mp.getVideoOutputFramesPerSecond();
float fpsDecode = mp.getVideoDecodeFramesPerSecond();
setRowValue(R.string.fps, String.format(Locale.US, "%.2f / %.2f", fpsDecode, fpsOutput));
long videoCachedDuration = mp.getVideoCachedDuration();
long audioCachedDuration = mp.getAudioCachedDuration();
long videoCachedBytes = mp.getVideoCachedBytes();
long audioCachedBytes = mp.getAudioCachedBytes();
long tcpSpeed = mp.getTcpSpeed();
long bitRate = mp.getBitRate();
long seekLoadDuration = mp.getSeekLoadDuration();
setRowValue(R.string.v_cache, String.format(Locale.US, "%s, %s", formatedDurationMilli(videoCachedDuration), formatedSize(videoCachedBytes)));
setRowValue(R.string.a_cache, String.format(Locale.US, "%s, %s", formatedDurationMilli(audioCachedDuration), formatedSize(audioCachedBytes)));
setRowValue(R.string.load_cost, String.format(Locale.US, "%d ms", mLoadCost));
setRowValue(R.string.seek_cost, String.format(Locale.US, "%d ms", mSeekCost));
setRowValue(R.string.seek_load_cost, String.format(Locale.US, "%d ms", seekLoadDuration));
setRowValue(R.string.tcp_speed, String.format(Locale.US, "%s", formatedSpeed(tcpSpeed, 1000)));
setRowValue(R.string.bit_rate, String.format(Locale.US, "%.2f kbs", bitRate/1000f));
mHandler.removeMessages(MSG_UPDATE_HUD);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500);
}
}
}
};
}

@ -1,248 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import android.content.Context;
import androidx.annotation.NonNull;
import android.view.View;
import com.frank.living.R;
import java.lang.ref.WeakReference;
public final class MeasureHelper {
private WeakReference<View> mWeakView;
private int mVideoWidth;
private int mVideoHeight;
private int mVideoSarNum;
private int mVideoSarDen;
private int mVideoRotationDegree;
private int mMeasuredWidth;
private int mMeasuredHeight;
private int mCurrentAspectRatio = IRenderView.AR_ASPECT_FIT_PARENT;
public MeasureHelper(View view) {
mWeakView = new WeakReference<View>(view);
}
public View getView() {
if (mWeakView == null)
return null;
return mWeakView.get();
}
public void setVideoSize(int videoWidth, int videoHeight) {
mVideoWidth = videoWidth;
mVideoHeight = videoHeight;
}
public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
mVideoSarNum = videoSarNum;
mVideoSarDen = videoSarDen;
}
public void setVideoRotation(int videoRotationDegree) {
mVideoRotationDegree = videoRotationDegree;
}
/**
* Must be called by View.onMeasure(int, int)
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
public void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
// + MeasureSpec.toString(heightMeasureSpec) + ")");
if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
int tempSpec = widthMeasureSpec;
widthMeasureSpec = heightMeasureSpec;
heightMeasureSpec = tempSpec;
}
int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mCurrentAspectRatio == IRenderView.AR_MATCH_PARENT) {
width = widthMeasureSpec;
height = heightMeasureSpec;
} else if (mVideoWidth > 0 && mVideoHeight > 0) {
int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == View.MeasureSpec.AT_MOST && heightSpecMode == View.MeasureSpec.AT_MOST) {
float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize;
float displayAspectRatio;
switch (mCurrentAspectRatio) {
case IRenderView.AR_16_9_FIT_PARENT:
displayAspectRatio = 16.0f / 9.0f;
if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
displayAspectRatio = 1.0f / displayAspectRatio;
break;
case IRenderView.AR_4_3_FIT_PARENT:
displayAspectRatio = 4.0f / 3.0f;
if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
displayAspectRatio = 1.0f / displayAspectRatio;
break;
case IRenderView.AR_ASPECT_FIT_PARENT:
case IRenderView.AR_ASPECT_FILL_PARENT:
case IRenderView.AR_ASPECT_WRAP_CONTENT:
default:
displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;
if (mVideoSarNum > 0 && mVideoSarDen > 0)
displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen;
break;
}
boolean shouldBeWider = displayAspectRatio > specAspectRatio;
switch (mCurrentAspectRatio) {
case IRenderView.AR_ASPECT_FIT_PARENT:
case IRenderView.AR_16_9_FIT_PARENT:
case IRenderView.AR_4_3_FIT_PARENT:
if (shouldBeWider) {
// too wide, fix width
width = widthSpecSize;
height = (int) (width / displayAspectRatio);
} else {
// too high, fix height
height = heightSpecSize;
width = (int) (height * displayAspectRatio);
}
break;
case IRenderView.AR_ASPECT_FILL_PARENT:
if (shouldBeWider) {
// not high enough, fix height
height = heightSpecSize;
width = (int) (height * displayAspectRatio);
} else {
// not wide enough, fix width
width = widthSpecSize;
height = (int) (width / displayAspectRatio);
}
break;
case IRenderView.AR_ASPECT_WRAP_CONTENT:
default:
if (shouldBeWider) {
// too wide, fix width
width = Math.min(mVideoWidth, widthSpecSize);
height = (int) (width / displayAspectRatio);
} else {
// too high, fix height
height = Math.min(mVideoHeight, heightSpecSize);
width = (int) (height * displayAspectRatio);
}
break;
}
} else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) {
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if (mVideoWidth * height < width * mVideoHeight) {
//Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else if (mVideoWidth * height > width * mVideoHeight) {
//Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
}
} else if (widthSpecMode == View.MeasureSpec.EXACTLY) {
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
} else if (heightSpecMode == View.MeasureSpec.EXACTLY) {
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
} else {
// neither the width nor the height are fixed, try to use actual video size
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
}
} else {
// no size yet, just adopt the given spec sizes
}
mMeasuredWidth = width;
mMeasuredHeight = height;
}
public int getMeasuredWidth() {
return mMeasuredWidth;
}
public int getMeasuredHeight() {
return mMeasuredHeight;
}
public void setAspectRatio(int aspectRatio) {
mCurrentAspectRatio = aspectRatio;
}
@NonNull
public static String getAspectRatioText(Context context, int aspectRatio) {
String text;
switch (aspectRatio) {
case IRenderView.AR_ASPECT_FIT_PARENT:
text = context.getString(R.string.VideoView_ar_aspect_fit_parent);
break;
case IRenderView.AR_ASPECT_FILL_PARENT:
text = context.getString(R.string.VideoView_ar_aspect_fill_parent);
break;
case IRenderView.AR_ASPECT_WRAP_CONTENT:
text = context.getString(R.string.VideoView_ar_aspect_wrap_content);
break;
case IRenderView.AR_MATCH_PARENT:
text = context.getString(R.string.VideoView_ar_match_parent);
break;
case IRenderView.AR_16_9_FIT_PARENT:
text = context.getString(R.string.VideoView_ar_16_9_fit_parent);
break;
case IRenderView.AR_4_3_FIT_PARENT:
text = context.getString(R.string.VideoView_ar_4_3_fit_parent);
break;
default:
text = context.getString(R.string.N_A);
break;
}
return text;
}
}

@ -1,76 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.MediaPlayerProxy;
import tv.danmaku.ijk.media.player.TextureMediaPlayer;
public class MediaPlayerCompat {
public static String getName(IMediaPlayer mp) {
if (mp == null) {
return "null";
} else if (mp instanceof TextureMediaPlayer) {
StringBuilder sb = new StringBuilder("TextureMediaPlayer <");
IMediaPlayer internalMediaPlayer = ((TextureMediaPlayer) mp).getInternalMediaPlayer();
if (internalMediaPlayer == null) {
sb.append("null>");
} else {
sb.append(internalMediaPlayer.getClass().getSimpleName());
sb.append(">");
}
return sb.toString();
} else {
return mp.getClass().getSimpleName();
}
}
public static IjkMediaPlayer getIjkMediaPlayer(IMediaPlayer mp) {
IjkMediaPlayer ijkMediaPlayer = null;
if (mp == null) {
return null;
} if (mp instanceof IjkMediaPlayer) {
ijkMediaPlayer = (IjkMediaPlayer) mp;
} else if (mp instanceof MediaPlayerProxy && ((MediaPlayerProxy) mp).getInternalMediaPlayer() instanceof IjkMediaPlayer) {
ijkMediaPlayer = (IjkMediaPlayer) ((MediaPlayerProxy) mp).getInternalMediaPlayer();
}
return ijkMediaPlayer;
}
public static void selectTrack(IMediaPlayer mp, int stream) {
IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
if (ijkMediaPlayer == null)
return;
ijkMediaPlayer.selectTrack(stream);
}
public static void deselectTrack(IMediaPlayer mp, int stream) {
IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
if (ijkMediaPlayer == null)
return;
ijkMediaPlayer.deselectTrack(stream);
}
public static int getSelectedTrack(IMediaPlayer mp, int trackType) {
IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
if (ijkMediaPlayer == null)
return -1;
return ijkMediaPlayer.getSelectedTrack(trackType);
}
}

@ -1,286 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
public class SurfaceRenderView extends SurfaceView implements IRenderView {
private MeasureHelper mMeasureHelper;
public SurfaceRenderView(Context context) {
super(context);
initView(context);
}
public SurfaceRenderView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView(context);
}
private void initView(Context context) {
mMeasureHelper = new MeasureHelper(this);
mSurfaceCallback = new SurfaceCallback(this);
getHolder().addCallback(mSurfaceCallback);
//noinspection deprecation
getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
}
@Override
public View getView() {
return this;
}
@Override
public boolean shouldWaitForResize() {
return true;
}
//--------------------
// Layout & Measure
//--------------------
@Override
public void setVideoSize(int videoWidth, int videoHeight) {
if (videoWidth > 0 && videoHeight > 0) {
mMeasureHelper.setVideoSize(videoWidth, videoHeight);
getHolder().setFixedSize(videoWidth, videoHeight);
requestLayout();
}
}
@Override
public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
if (videoSarNum > 0 && videoSarDen > 0) {
mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
requestLayout();
}
}
@Override
public void setVideoRotation(int degree) {
Log.e("", "SurfaceView doesn't support rotation (" + degree + ")!\n");
}
@Override
public void setAspectRatio(int aspectRatio) {
mMeasureHelper.setAspectRatio(aspectRatio);
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
}
//--------------------
// SurfaceViewHolder
//--------------------
private static final class InternalSurfaceHolder implements IRenderView.ISurfaceHolder {
private SurfaceRenderView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
public InternalSurfaceHolder(@NonNull SurfaceRenderView surfaceView,
@Nullable SurfaceHolder surfaceHolder) {
mSurfaceView = surfaceView;
mSurfaceHolder = surfaceHolder;
}
public void bindToMediaPlayer(IMediaPlayer mp) {
if (mp != null) {
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
(mp instanceof ISurfaceTextureHolder)) {
ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
textureHolder.setSurfaceTexture(null);
}
mp.setDisplay(mSurfaceHolder);
}
}
@NonNull
@Override
public IRenderView getRenderView() {
return mSurfaceView;
}
@Nullable
@Override
public SurfaceHolder getSurfaceHolder() {
return mSurfaceHolder;
}
@Nullable
@Override
public SurfaceTexture getSurfaceTexture() {
return null;
}
@Nullable
@Override
public Surface openSurface() {
if (mSurfaceHolder == null)
return null;
return mSurfaceHolder.getSurface();
}
}
//-------------------------
// SurfaceHolder.Callback
//-------------------------
@Override
public void addRenderCallback(IRenderCallback callback) {
mSurfaceCallback.addRenderCallback(callback);
}
@Override
public void removeRenderCallback(IRenderCallback callback) {
mSurfaceCallback.removeRenderCallback(callback);
}
private SurfaceCallback mSurfaceCallback;
private static final class SurfaceCallback implements SurfaceHolder.Callback {
private SurfaceHolder mSurfaceHolder;
private boolean mIsFormatChanged;
private int mFormat;
private int mWidth;
private int mHeight;
private WeakReference<SurfaceRenderView> mWeakSurfaceView;
private Map<IRenderCallback, Object> mRenderCallbackMap = new ConcurrentHashMap<IRenderCallback, Object>();
public SurfaceCallback(@NonNull SurfaceRenderView surfaceView) {
mWeakSurfaceView = new WeakReference<SurfaceRenderView>(surfaceView);
}
public void addRenderCallback(@NonNull IRenderCallback callback) {
mRenderCallbackMap.put(callback, callback);
ISurfaceHolder surfaceHolder = null;
if (mSurfaceHolder != null) {
if (surfaceHolder == null)
surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
}
if (mIsFormatChanged) {
if (surfaceHolder == null)
surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
callback.onSurfaceChanged(surfaceHolder, mFormat, mWidth, mHeight);
}
}
public void removeRenderCallback(@NonNull IRenderCallback callback) {
mRenderCallbackMap.remove(callback);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mSurfaceHolder = holder;
mIsFormatChanged = false;
mFormat = 0;
mWidth = 0;
mHeight = 0;
ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mSurfaceHolder = null;
mIsFormatChanged = false;
mFormat = 0;
mWidth = 0;
mHeight = 0;
ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
renderCallback.onSurfaceDestroyed(surfaceHolder);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
mSurfaceHolder = holder;
mIsFormatChanged = true;
mFormat = format;
mWidth = width;
mHeight = height;
// mMeasureHelper.setVideoSize(width, height);
ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
renderCallback.onSurfaceChanged(surfaceHolder, format, width, height);
}
}
}
//--------------------
// Accessibility
//--------------------
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(SurfaceRenderView.class.getName());
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
info.setClassName(SurfaceRenderView.class.getName());
}
}
}

@ -1,131 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import android.content.Context;
import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TableLayout;
import android.widget.TextView;
import com.frank.living.R;
public class TableLayoutBinder {
private Context mContext;
public ViewGroup mTableView;
public TableLayout mTableLayout;
public TableLayoutBinder(Context context) {
this(context, R.layout.table_media_info);
}
public TableLayoutBinder(Context context, int layoutResourceId) {
mContext = context;
mTableView = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutResourceId, null);
mTableLayout = (TableLayout) mTableView.findViewById(R.id.table);
}
public TableLayoutBinder(Context context, TableLayout tableLayout) {
mContext = context;
mTableView = tableLayout;
mTableLayout = tableLayout;
}
public View appendRow1(String name, String value) {
return appendRow(R.layout.table_media_info_row1, name, value);
}
public View appendRow1(int nameId, String value) {
return appendRow1(mContext.getString(nameId), value);
}
public View appendRow2(String name, String value) {
return appendRow(R.layout.table_media_info_row2, name, value);
}
public View appendRow2(int nameId, String value) {
return appendRow2(mContext.getString(nameId), value);
}
public View appendSection(String name) {
return appendRow(R.layout.table_media_info_section, name, null);
}
public View appendSection(int nameId) {
return appendSection(mContext.getString(nameId));
}
public View appendRow(int layoutId, String name, String value) {
ViewGroup rowView = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutId, mTableLayout, false);
setNameValueText(rowView, name, value);
mTableLayout.addView(rowView);
return rowView;
}
public ViewHolder obtainViewHolder(View rowView) {
ViewHolder viewHolder = (ViewHolder) rowView.getTag();
if (viewHolder == null) {
viewHolder = new ViewHolder();
viewHolder.mNameTextView = (TextView) rowView.findViewById(R.id.name);
viewHolder.mValueTextView = (TextView) rowView.findViewById(R.id.value);
rowView.setTag(viewHolder);
}
return viewHolder;
}
public void setNameValueText(View rowView, String name, String value) {
ViewHolder viewHolder = obtainViewHolder(rowView);
viewHolder.setName(name);
viewHolder.setValue(value);
}
public void setValueText(View rowView, String value) {
ViewHolder viewHolder = obtainViewHolder(rowView);
viewHolder.setValue(value);
}
public ViewGroup buildLayout() {
return mTableView;
}
public AlertDialog.Builder buildAlertDialogBuilder() {
AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(mContext);
dlgBuilder.setView(buildLayout());
return dlgBuilder;
}
private static class ViewHolder {
public TextView mNameTextView;
public TextView mValueTextView;
public void setName(String name) {
if (mNameTextView != null) {
mNameTextView.setText(name);
}
}
public void setValue(String value) {
if (mValueTextView != null) {
mValueTextView.setText(value);
}
}
}
}

@ -1,368 +0,0 @@
/*
* Copyright (C) 2015 Bilibili
* Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
*
* 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.
*/
package com.frank.living.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.TextureView;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
import tv.danmaku.ijk.media.player.ISurfaceTextureHost;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class TextureRenderView extends TextureView implements IRenderView {
private static final String TAG = "TextureRenderView";
private MeasureHelper mMeasureHelper;
public TextureRenderView(Context context) {
super(context);
initView(context);
}
public TextureRenderView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView(context);
}
private void initView(Context context) {
mMeasureHelper = new MeasureHelper(this);
mSurfaceCallback = new SurfaceCallback(this);
setSurfaceTextureListener(mSurfaceCallback);
}
@Override
public View getView() {
return this;
}
@Override
public boolean shouldWaitForResize() {
return false;
}
@Override
protected void onDetachedFromWindow() {
mSurfaceCallback.willDetachFromWindow();
super.onDetachedFromWindow();
mSurfaceCallback.didDetachFromWindow();
}
//--------------------
// Layout & Measure
//--------------------
@Override
public void setVideoSize(int videoWidth, int videoHeight) {
if (videoWidth > 0 && videoHeight > 0) {
mMeasureHelper.setVideoSize(videoWidth, videoHeight);
requestLayout();
}
}
@Override
public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
if (videoSarNum > 0 && videoSarDen > 0) {
mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
requestLayout();
}
}
@Override
public void setVideoRotation(int degree) {
mMeasureHelper.setVideoRotation(degree);
setRotation(degree);
}
@Override
public void setAspectRatio(int aspectRatio) {
mMeasureHelper.setAspectRatio(aspectRatio);
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
}
//--------------------
// TextureViewHolder
//--------------------
public IRenderView.ISurfaceHolder getSurfaceHolder() {
return new InternalSurfaceHolder(this, mSurfaceCallback.mSurfaceTexture, mSurfaceCallback);
}
private static final class InternalSurfaceHolder implements IRenderView.ISurfaceHolder {
private TextureRenderView mTextureView;
private SurfaceTexture mSurfaceTexture;
private ISurfaceTextureHost mSurfaceTextureHost;
public InternalSurfaceHolder(@NonNull TextureRenderView textureView,
@Nullable SurfaceTexture surfaceTexture,
@NonNull ISurfaceTextureHost surfaceTextureHost) {
mTextureView = textureView;
mSurfaceTexture = surfaceTexture;
mSurfaceTextureHost = surfaceTextureHost;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void bindToMediaPlayer(IMediaPlayer mp) {
if (mp == null)
return;
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
(mp instanceof ISurfaceTextureHolder)) {
ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
mTextureView.mSurfaceCallback.setOwnSurfaceTexture(false);
SurfaceTexture surfaceTexture = textureHolder.getSurfaceTexture();
if (surfaceTexture != null) {
mTextureView.setSurfaceTexture(surfaceTexture);
} else {
textureHolder.setSurfaceTexture(mSurfaceTexture);
textureHolder.setSurfaceTextureHost(mTextureView.mSurfaceCallback);
}
} else {
mp.setSurface(openSurface());
}
}
@NonNull
@Override
public IRenderView getRenderView() {
return mTextureView;
}
@Nullable
@Override
public SurfaceHolder getSurfaceHolder() {
return null;
}
@Nullable
@Override
public SurfaceTexture getSurfaceTexture() {
return mSurfaceTexture;
}
@Nullable
@Override
public Surface openSurface() {
if (mSurfaceTexture == null)
return null;
return new Surface(mSurfaceTexture);
}
}
//-------------------------
// SurfaceHolder.Callback
//-------------------------
@Override
public void addRenderCallback(IRenderCallback callback) {
mSurfaceCallback.addRenderCallback(callback);
}
@Override
public void removeRenderCallback(IRenderCallback callback) {
mSurfaceCallback.removeRenderCallback(callback);
}
private SurfaceCallback mSurfaceCallback;
private static final class SurfaceCallback implements TextureView.SurfaceTextureListener, ISurfaceTextureHost {
private SurfaceTexture mSurfaceTexture;
private boolean mIsFormatChanged;
private int mWidth;
private int mHeight;
private boolean mOwnSurfaceTexture = true;
private boolean mWillDetachFromWindow = false;
private boolean mDidDetachFromWindow = false;
private WeakReference<TextureRenderView> mWeakRenderView;
private Map<IRenderCallback, Object> mRenderCallbackMap = new ConcurrentHashMap<IRenderCallback, Object>();
public SurfaceCallback(@NonNull TextureRenderView renderView) {
mWeakRenderView = new WeakReference<TextureRenderView>(renderView);
}
public void setOwnSurfaceTexture(boolean ownSurfaceTexture) {
mOwnSurfaceTexture = ownSurfaceTexture;
}
public void addRenderCallback(@NonNull IRenderCallback callback) {
mRenderCallbackMap.put(callback, callback);
ISurfaceHolder surfaceHolder = null;
if (mSurfaceTexture != null) {
if (surfaceHolder == null)
surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
}
if (mIsFormatChanged) {
if (surfaceHolder == null)
surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
callback.onSurfaceChanged(surfaceHolder, 0, mWidth, mHeight);
}
}
public void removeRenderCallback(@NonNull IRenderCallback callback) {
mRenderCallbackMap.remove(callback);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurfaceTexture = surface;
mIsFormatChanged = false;
mWidth = 0;
mHeight = 0;
ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
mSurfaceTexture = surface;
mIsFormatChanged = true;
mWidth = width;
mHeight = height;
ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
renderCallback.onSurfaceChanged(surfaceHolder, 0, width, height);
}
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mSurfaceTexture = surface;
mIsFormatChanged = false;
mWidth = 0;
mHeight = 0;
ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
renderCallback.onSurfaceDestroyed(surfaceHolder);
}
Log.d(TAG, "onSurfaceTextureDestroyed: destroy: " + mOwnSurfaceTexture);
return mOwnSurfaceTexture;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
//-------------------------
// ISurfaceTextureHost
//-------------------------
@Override
public void releaseSurfaceTexture(SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
Log.d(TAG, "releaseSurfaceTexture: null");
} else if (mDidDetachFromWindow) {
if (surfaceTexture != mSurfaceTexture) {
Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release different SurfaceTexture");
surfaceTexture.release();
} else if (!mOwnSurfaceTexture) {
Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release detached SurfaceTexture");
surfaceTexture.release();
} else {
Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): already released by TextureView");
}
} else if (mWillDetachFromWindow) {
if (surfaceTexture != mSurfaceTexture) {
Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): release different SurfaceTexture");
surfaceTexture.release();
} else if (!mOwnSurfaceTexture) {
Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): re-attach SurfaceTexture to TextureView");
setOwnSurfaceTexture(true);
} else {
Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): will released by TextureView");
}
} else {
if (surfaceTexture != mSurfaceTexture) {
Log.d(TAG, "releaseSurfaceTexture: alive: release different SurfaceTexture");
surfaceTexture.release();
} else if (!mOwnSurfaceTexture) {
Log.d(TAG, "releaseSurfaceTexture: alive: re-attach SurfaceTexture to TextureView");
setOwnSurfaceTexture(true);
} else {
Log.d(TAG, "releaseSurfaceTexture: alive: will released by TextureView");
}
}
}
public void willDetachFromWindow() {
Log.d(TAG, "willDetachFromWindow()");
mWillDetachFromWindow = true;
}
public void didDetachFromWindow() {
Log.d(TAG, "didDetachFromWindow()");
mDidDetachFromWindow = true;
}
}
//--------------------
// Accessibility
//--------------------
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(TextureRenderView.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(TextureRenderView.class.getName());
}
}

@ -1,20 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-22
android.library.reference.1=../../../player-arm64/src/main
android.library.reference.2=../../../player-armv5/src/main
android.library.reference.3=../../../player-armv7a/src/main
android.library.reference.4=../../../player-x86/src/main
android.library.reference.5=../../../player-java/src/main
android.library.reference.6=../../../../contrib/appcompat

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

@ -1,54 +0,0 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.frank.living.activity.RtspLiveActivity"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.frank.living.widget.IjkVideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
</com.frank.living.widget.IjkVideoView>
<ImageButton
android:id="@+id/btn_play"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/ic_pause"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"/>
<ImageButton
android:id="@+id/btn_sound"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/ic_silence"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="20dp"
android:layout_marginBottom="10dp"/>
<ImageButton
android:id="@+id/btn_screenshot"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/ic_screen_shot"
android:layout_alignParentBottom="true"
android:layout_toStartOf="@+id/btn_sound"
android:layout_marginEnd="30dp"
android:layout_marginBottom="10dp"/>
<TableLayout
android:id="@+id/hud_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:background="@color/ijk_transparent_dark"
android:padding="8dp"
android:visibility="gone"/>
</RelativeLayout>

@ -1,48 +0,0 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/divider1"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/ijk_color_blue_800"
android:layout_centerVertical="true"/>
<View
android:id="@+id/divider2"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/ijk_color_blue_800"
android:layout_centerHorizontal="true"/>
<com.frank.living.widget.IjkVideoView
android:id="@+id/video_view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/divider1"
android:layout_toStartOf="@id/divider2"/>
<com.frank.living.widget.IjkVideoView
android:id="@+id/video_view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/divider1"
android:layout_toEndOf="@id/divider2"/>
<com.frank.living.widget.IjkVideoView
android:id="@+id/video_view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/divider1"
android:layout_toStartOf="@id/divider2"/>
<com.frank.living.widget.IjkVideoView
android:id="@+id/video_view4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/divider1"
android:layout_toEndOf="@id/divider2"/>
</RelativeLayout>

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent" >
<TableLayout
android:id="@+id/table"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1" >
</TableLayout>
</ScrollView>

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_marginLeft="10dip"
android:paddingBottom="2dip"
android:paddingTop="2dip" >
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp" />
<TextView
android:id="@+id/value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:textSize="15sp" />
</TableRow>

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingBottom="0dip"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:paddingTop="0dip"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp" />
<TextView
android:id="@+id/value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:textSize="12sp" />
</TableRow>

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingBottom="2dip"
android:paddingLeft="8dip"
android:paddingRight="8dip"
android:paddingTop="4dip" >
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold" />
</TableRow>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

@ -1,19 +0,0 @@
<resources>
<color name="black_overlay">#66000000</color>
<color name="ijk_color_blue_main">@color/ijk_color_blue_500</color>
<color name="ijk_color_blue_50">#E3F2FD</color>
<color name="ijk_color_blue_100">#BBDEFB</color>
<color name="ijk_color_blue_200">#90CAF9</color>
<color name="ijk_color_blue_300">#64B5F6</color>
<color name="ijk_color_blue_400">#42A5F5</color>
<color name="ijk_color_blue_500">#2196F3</color>
<color name="ijk_color_blue_600">#1E88E5</color>
<color name="ijk_color_blue_700">#1976D2</color>
<color name="ijk_color_blue_800">#1565C0</color>
<color name="ijk_color_blue_900">#0D47A1</color>
<color name="ijk_transparent_dark">#77000000</color>
</resources>

@ -1,8 +0,0 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="ijk_horizontal_margin">@dimen/activity_horizontal_margin</dimen>
<dimen name="ijk_vertical_margin">@dimen/activity_vertical_margin</dimen>
</resources>

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="render_view" type="id"/>
</resources>

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">OnLive</string>
<string name="N_A">N/A</string>
<string name="close">Close</string>
<string name="exit">Exit</string>
<string name="sample">Sample</string>
<string name="recent">Recent</string>
<string name="settings">Settings</string>
<string name="tracks">Tracks</string>
<string name="toggle_player">Player</string>
<string name="toggle_render">Render</string>
<string name="toggle_ratio">Scale</string>
<string name="show_info">Info</string>
<string name="vdec">vdec</string>
<string name="fps">fps</string>
<string name="v_cache">v-cache</string>
<string name="a_cache">a-cache</string>
<string name="load_cost">load-cost</string>
<string name="seek_cost">seek_cost</string>
<string name="seek_load_cost">seek_load_cost</string>
<string name="tcp_speed">tcp_speed</string>
<string name="bit_rate">bit_rate</string>
<string name="media_information">Media Information</string>
<string name="mi_player">Player</string>
<string name="mi_media">Media</string>
<string name="mi_profile_level">Profile level</string>
<string name="mi_pixel_format">Pixel format</string>
<string name="mi_resolution">Resolution</string>
<string name="mi_length">Length</string>
<string name="mi_stream_fmt1">Stream #%d</string>
<string name="mi_type">Type</string>
<string name="mi_language">Language</string>
<string name="mi_codec">Codec</string>
<string name="mi_frame_rate">Frame rate</string>
<string name="mi_bit_rate">Bit rate</string>
<string name="mi_sample_rate">Sample rate</string>
<string name="mi_channels">Channels</string>
<string name="mi__selected_video_track">*</string>
<string name="mi__selected_audio_track">*</string>
<string name="mi__selected_subtitle_track">*</string>
<string name="TrackType_video">Video</string>
<string name="TrackType_audio">Audio</string>
<string name="TrackType_subtitle">Subtitle</string>
<string name="TrackType_timedtext">Timed text</string>
<string name="TrackType_metadata">Meta data</string>
<string name="TrackType_unknown">Unknown</string>
<string name="VideoView_error_text_invalid_progressive_playback">Invalid progressive playback</string>
<string name="VideoView_error_text_unknown">Unknown</string>
<string name="VideoView_error_button">OK</string>
<string name="VideoView_ar_aspect_fit_parent">Aspect / Fit parent</string>
<string name="VideoView_ar_aspect_fill_parent">Aspect / Fill parent</string>
<string name="VideoView_ar_aspect_wrap_content">Aspect / Wrap content</string>
<string name="VideoView_ar_match_parent">Free / Fill parent</string>
<string name="VideoView_ar_16_9_fit_parent">16:9 / Fit parent</string>
<string name="VideoView_ar_4_3_fit_parent">4:3 / Fit parent</string>
<string name="VideoView_render_none">Render: None</string>
<string name="VideoView_render_surface_view">Render: SurfaceView</string>
<string name="VideoView_render_texture_view">Render: TextureView</string>
<string name="VideoView_player_none">Player: None</string>
<string name="VideoView_player_AndroidMediaPlayer">Player: AndroidMediaPlayer</string>
<string name="VideoView_player_IjkMediaPlayer">Player: IjkMediaPlayer</string>
<string name="VideoView_player_IjkExoMediaPlayer">Player: IjkExoMediaPlayer</string>
</resources>

@ -1,112 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- -->
<string name="pref_title_general">General</string>
<string name="pref_key_enable_background_play">pref.enable_background_play</string>
<string name="pref_title_enable_background_play">Enable background play</string>
<string name="pref_summary_enable_background_play">need Android 4.0+</string>
<string name="pref_key_using_android_player">pref.using_android_player</string>
<string name="pref_title_using_android_player">Using system player</string>
<string name="pref_summary_using_android_player"></string>
<string name="pref_key_player">pref.player</string>
<string name="pref_title_player">Choose Player</string>
<string-array name="pref_entries_player">
<item>Auto Select</item>
<item>AndroidMediaPlayer</item>
<item>IjkMediaPlayer</item>
<item>IjkExoMediaPlayer</item>
</string-array>
<string-array name="pref_entry_values_player">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
<string-array name="pref_entry_summaries_player">
<item>Auto Select</item>
<item>AndroidMediaPlayer</item>
<item>IjkMediaPlayer</item>
<item>IjkExoMediaPlayer</item>
</string-array>
<!-- -->
<string name="pref_title_ijkplayer_video">Video: ijkplayer</string>
<string name="pref_key_using_media_codec">pref.using_media_codec</string>
<string name="pref_title_using_media_codec">Using MediaCodec</string>
<string name="pref_summary_using_media_codec"></string>
<string name="pref_key_using_media_codec_auto_rotate">pref.using_media_codec_auto_rotate</string>
<string name="pref_title_using_media_codec_auto_rotate">Using MediaCodec auto rotate</string>
<string name="pref_summary_using_media_codec_auto_rotate"></string>
<string name="pref_key_media_codec_handle_resolution_change">pref.media_codec_handle_resolution_change</string>
<string name="pref_title_media_codec_handle_resolution_change">MediaCodec handle resolution change</string>
<string name="pref_summary_media_codec_handle_resolution_change"></string>
<string name="pref_key_pixel_format">pref.pixel_format</string>
<string name="pref_title_pixel_format">Pixel Format</string>
<string-array name="pref_entries_pixel_format">
<item>Auto Select</item>
<item>RGB 565</item>
<item>RGB 888</item>
<item>RGBX 8888</item>
<item>YV12</item>
<item>OpenGL ES2</item>
</string-array>
<string-array name="pref_entry_values_pixel_format">
<item></item>
<item>fcc-rv16</item>
<item>fcc-rv24</item>
<item>fcc-rv32</item>
<item>fcc-yv12</item>
<item>fcc-_es2</item>
</string-array>
<string-array name="pref_entry_summaries_pixel_format">
<item>Auto Select</item>
<item>RGB 565</item>
<item>RGB 888</item>
<item>RGBX 8888</item>
<item>YV12</item>
<item>OpenGL ES2</item>
</string-array>
<!-- -->
<string name="pref_title_ijkplayer_audio">Audio: ijkplayer</string>
<string name="pref_key_using_opensl_es">pref.using_opensl_es</string>
<string name="pref_title_using_opensl_es">Using OpenSL ES</string>
<string name="pref_summary_using_opensl_es"></string>
<!-- -->
<string name="pref_title_render_view">RenderView</string>
<string name="pref_key_enable_no_view">pref.enable_no_view</string>
<string name="pref_title_enable_no_view">Enable NoView</string>
<string name="pref_summary_enable_no_view"></string>
<string name="pref_key_enable_surface_view">pref.enable_surface_view</string>
<string name="pref_title_enable_surface_view">Enable SurfaceView</string>
<string name="pref_summary_enable_surface_view"></string>
<string name="pref_key_enable_texture_view">pref.enable_texture_view</string>
<string name="pref_title_enable_texture_view">Enable TextureView</string>
<string name="pref_summary_enable_texture_view"></string>
<string name="pref_key_enable_detached_surface_texture">pref.enable_detached_surface_texture</string>
<string name="pref_title_enable_detached_surface_texture">Enable detached SurfaceTexture</string>
<string name="pref_summary_enable_detached_surface_texture"></string>
<!-- -->
<string name="pref_title_misc">Misc</string>
<string name="pref_key_using_mediadatasource">pref.using_mediadatasource</string>
<string name="pref_title_using_mediadatasource">Using MediaDataSource</string>
<string name="pref_summary_using_mediadatasource"></string>
<!-- -->
<string name="pref_key_last_directory"></string>
</resources>

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Widget.App.ActionButton" parent="@style/Widget.AppCompat.ActionButton">
<item name="textAllCaps">false</item>
</style>
<style name="Theme.App.Light.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
<item name="actionButtonStyle">@style/Widget.App.ActionButton</item>
</style>
<style name="Theme.App.NoActionBar" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@null</item>
<item name="actionButtonStyle">@style/Widget.App.ActionButton</item>
</style>
</resources>

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.App.Light.NoActionBar">
</style>
<style name="FullscreenTheme" parent="Theme.App.NoActionBar">
</style>
</resources>

@ -1,74 +0,0 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory android:title="@string/pref_title_general">
<CheckBoxPreference
android:defaultValue="false"
android:disableDependentsState="true"
android:key="@string/pref_key_enable_background_play"
android:persistent="true"
android:summary="@string/pref_summary_enable_background_play"
android:title="@string/pref_title_enable_background_play" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_ijkplayer_video">
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_using_media_codec"
android:persistent="true"
android:summary="@string/pref_summary_using_media_codec"
android:title="@string/pref_title_using_media_codec" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_using_media_codec_auto_rotate"
android:persistent="true"
android:summary="@string/pref_summary_using_media_codec_auto_rotate"
android:title="@string/pref_title_using_media_codec_auto_rotate" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_media_codec_handle_resolution_change"
android:persistent="true"
android:summary="@string/pref_summary_media_codec_handle_resolution_change"
android:title="@string/pref_title_media_codec_handle_resolution_change" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_ijkplayer_audio">
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_using_opensl_es"
android:persistent="true"
android:summary="@string/pref_summary_using_opensl_es"
android:title="@string/pref_title_using_opensl_es" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_render_view">
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_enable_no_view"
android:persistent="true"
android:summary="@string/pref_summary_enable_no_view"
android:title="@string/pref_title_enable_no_view" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_enable_surface_view"
android:persistent="true"
android:summary="@string/pref_summary_enable_surface_view"
android:title="@string/pref_title_enable_surface_view" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_enable_texture_view"
android:persistent="true"
android:summary="@string/pref_summary_enable_texture_view"
android:title="@string/pref_title_enable_texture_view" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_enable_detached_surface_texture"
android:persistent="true"
android:summary="@string/pref_summary_enable_detached_surface_texture"
android:title="@string/pref_title_enable_detached_surface_texture" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_misc">
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/pref_key_using_mediadatasource"
android:persistent="true"
android:summary="@string/pref_summary_using_mediadatasource"
android:title="@string/pref_title_using_mediadatasource" />
</PreferenceCategory>
</PreferenceScreen>

@ -1 +1,3 @@
include ':app', ':Live', ':OnLive', ':libmp3' include ':app'
include ':Live'
include ':libmp3'

Loading…
Cancel
Save