├── .gitignore
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── afap
│ │ └── lib_player
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── afap
│ │ │ └── lib_player
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── afap
│ └── lib_player
│ └── ExampleUnitTest.java
├── bdplayer
├── .gitignore
├── build.gradle
├── libs
│ ├── arm64-v8a
│ │ ├── libcyberplayer-core.so
│ │ └── libcyberplayer.so
│ ├── armeabi-v7a
│ │ ├── libcyberplayer-core.so
│ │ └── libcyberplayer.so
│ └── cyberplayer-sdk.jar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── baidu
│ │ └── player
│ │ └── VideoPlayActivity.java
│ └── res
│ ├── drawable-hdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ └── ic_volume_up_white_36dp.png
│ ├── drawable-xhdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ └── ic_volume_up_white_36dp.png
│ ├── drawable-xxhdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ ├── ic_volume_up_white_36dp.png
│ └── play_ctrl_sound_ball.png
│ ├── drawable-xxxhdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ └── ic_volume_up_white_36dp.png
│ ├── drawable
│ ├── app_video_center_bg.xml
│ └── play_seekbar_color_bg.xml
│ ├── layout
│ └── activity_play_video.xml
│ └── values
│ └── colors.xml
├── build.gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── ijkplayer
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── player
│ │ ├── IJKVideoPlayActivity.java
│ │ ├── services
│ │ └── MediaPlayerService.java
│ │ ├── settings
│ │ └── Settings.java
│ │ └── widget
│ │ └── media
│ │ ├── FileMediaDataSource.java
│ │ ├── IMediaController.java
│ │ ├── IRenderView.java
│ │ ├── IjkVideoView.java
│ │ ├── InfoHudViewHolder.java
│ │ ├── MeasureHelper.java
│ │ ├── MediaPlayerCompat.java
│ │ ├── SurfaceRenderView.java
│ │ ├── TableLayoutBinder.java
│ │ └── TextureRenderView.java
│ ├── jniLibs
│ ├── arm64-v8a
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ ├── armeabi-v7a
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ ├── x86
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ └── x86_64
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ └── res
│ ├── drawable-hdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ └── ic_volume_up_white_36dp.png
│ ├── drawable-xhdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ └── ic_volume_up_white_36dp.png
│ ├── drawable-xxhdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ ├── ic_volume_up_white_36dp.png
│ └── play_ctrl_sound_ball.png
│ ├── drawable-xxxhdpi
│ ├── ic_brightness_6_white_36dp.png
│ ├── ic_chevron_left_white_36dp.png
│ ├── ic_fullscreen_exit_white_24dp.png
│ ├── ic_fullscreen_exit_white_36dp.png
│ ├── ic_fullscreen_white_24dp.png
│ ├── ic_play_arrow_white_24dp.png
│ ├── ic_play_circle_outline_white_36dp.png
│ ├── ic_stop_white_24dp.png
│ ├── ic_volume_off_white_36dp.png
│ └── ic_volume_up_white_36dp.png
│ ├── drawable
│ ├── app_video_center_bg.xml
│ └── play_seekbar_color_bg.xml
│ ├── layout
│ ├── activity_play_video.xml
│ ├── fragment_track_list.xml
│ ├── table_media_info.xml
│ ├── table_media_info_row1.xml
│ ├── table_media_info_row2.xml
│ └── table_media_info_section.xml
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── strings_pref.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | .idea
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /gradle
10 | /captures
11 | .externalNativeBuild
12 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | *.iml
3 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion '26.0.2'
6 | defaultConfig {
7 | applicationId "com.afap.lib_player"
8 | minSdkVersion 19
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 | repositories {
21 | flatDir {
22 | dirs 'libs'
23 | }
24 | }
25 | dependencies {
26 | compile fileTree(dir: 'libs', include: ['*.jar'])
27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
28 | exclude group: 'com.android.support', module: 'support-annotations'
29 | })
30 | compile 'com.android.support:appcompat-v7:25.4.0'
31 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
32 | testCompile 'junit:junit:4.12'
33 |
34 | // 这里只要放开一个测试,因为这俩播放器的界面都是用的同一个名称的布局,有冲突
35 | // compile project(':bdplayer')
36 | compile project(':ijkplayer')
37 | }
38 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/atom/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/afap/lib_player/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.afap.lib_player;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.afap.lib_player", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/afap/lib_player/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.afap.lib_player;
2 |
3 | import android.content.Intent;
4 | import android.net.Uri;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 | import android.view.View;
8 |
9 |
10 | import player.IJKVideoPlayActivity;
11 |
12 | public class MainActivity extends AppCompatActivity {
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_main);
18 |
19 |
20 | findViewById(R.id.play).setOnClickListener(new View.OnClickListener() {
21 | @Override
22 | public void onClick(View v) {
23 |
24 | String testurl = "http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4";
25 |
26 | // Intent intent = new Intent(MainActivity.this, VideoPlayActivity.class);
27 | // intent.putExtra("url", testurl);
28 | // startActivity(intent);
29 |
30 |
31 | // Uri uri = Uri.parse(testurl);
32 | // // 让系统选择播放器来播放流媒体视频
33 | // Intent intent = new Intent(Intent.ACTION_VIEW);
34 | // intent.setDataAndType(uri, "video/*");
35 | // startActivity(intent);
36 |
37 | IJKVideoPlayActivity.intentTo(MainActivity.this, testurl, "测试视频");
38 | }
39 | });
40 |
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Lib_player
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/test/java/com/afap/lib_player/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.afap.lib_player;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/bdplayer/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | *.iml
3 |
--------------------------------------------------------------------------------
/bdplayer/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion '26.0.2'
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 23
10 | versionCode 116
11 | versionName "1.16.0"
12 | }
13 | sourceSets.main {
14 | jni.srcDirs = []
15 | jniLibs.srcDir 'libs'
16 | }
17 | }
18 |
19 | dependencies {
20 | compile fileTree(dir: 'libs', include: ['*.jar'])
21 | }
--------------------------------------------------------------------------------
/bdplayer/libs/arm64-v8a/libcyberplayer-core.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/libs/arm64-v8a/libcyberplayer-core.so
--------------------------------------------------------------------------------
/bdplayer/libs/arm64-v8a/libcyberplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/libs/arm64-v8a/libcyberplayer.so
--------------------------------------------------------------------------------
/bdplayer/libs/armeabi-v7a/libcyberplayer-core.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/libs/armeabi-v7a/libcyberplayer-core.so
--------------------------------------------------------------------------------
/bdplayer/libs/armeabi-v7a/libcyberplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/libs/armeabi-v7a/libcyberplayer.so
--------------------------------------------------------------------------------
/bdplayer/libs/cyberplayer-sdk.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/libs/cyberplayer-sdk.jar
--------------------------------------------------------------------------------
/bdplayer/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/atom/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/bdplayer/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/bdplayer/src/main/java/com/baidu/player/VideoPlayActivity.java:
--------------------------------------------------------------------------------
1 | package com.baidu.player;
2 |
3 | import com.baidu.cyberplayer.core.BVideoView;
4 | import com.baidu.cyberplayer.core.BVideoView.OnCompletionListener;
5 | import com.baidu.cyberplayer.core.BVideoView.OnCompletionWithParamListener;
6 | import com.baidu.cyberplayer.core.BVideoView.OnErrorListener;
7 | import com.baidu.cyberplayer.core.BVideoView.OnInfoListener;
8 | import com.baidu.cyberplayer.core.BVideoView.OnPlayingBufferCacheListener;
9 | import com.baidu.cyberplayer.core.BVideoView.OnPreparedListener;
10 |
11 | import android.app.Activity;
12 | import android.content.Context;
13 | import android.content.pm.ActivityInfo;
14 | import android.content.res.Resources;
15 | import android.media.AudioManager;
16 | import android.os.Bundle;
17 | import android.os.Handler;
18 | import android.os.Looper;
19 | import android.os.Message;
20 | import android.os.PowerManager;
21 | import android.os.PowerManager.WakeLock;
22 | import android.util.DisplayMetrics;
23 | import android.util.TypedValue;
24 | import android.view.GestureDetector;
25 | import android.view.MotionEvent;
26 | import android.view.Surface;
27 | import android.view.View;
28 | import android.view.ViewGroup;
29 | import android.view.WindowManager;
30 | import android.widget.ImageView;
31 | import android.widget.RelativeLayout;
32 | import android.widget.SeekBar;
33 | import android.widget.TextView;
34 |
35 | public class VideoPlayActivity extends Activity implements OnPreparedListener,
36 | OnCompletionListener,
37 | OnErrorListener,
38 | OnInfoListener,
39 | OnPlayingBufferCacheListener,
40 | OnCompletionWithParamListener {
41 |
42 | private final String TAG = "VideoPlayActivity";
43 | private static final int MESSAGE_SHOW_PROGRESS = 1;
44 | private static final int MESSAGE_FADE_OUT = 2;
45 | private static final int MESSAGE_SEEK_NEW_POSITION = 3;
46 | private static final int MESSAGE_HIDE_CENTER_BOX = 4;
47 | private static final int MESSAGE_RESTART_PLAY = 5;
48 |
49 | private String mVideoSource = null;
50 | private BVideoView mVV = null;
51 | private RelativeLayout mViewHolder = null;
52 |
53 | private Query $;
54 | private boolean isShowing = false;
55 | private float brightness = -1;
56 | private int volume = -1;
57 | private int newPosition = -1;
58 | private boolean isLive = false;//是否为直播
59 | private int screenWidthPixels;
60 | private AudioManager audioManager;
61 | private int mMaxVolume;
62 | private boolean isDragging;
63 | private int defaultTimeout = 2000;
64 | private boolean fullScreenOnly = false;
65 | private SeekBar seekBar;
66 | private int duration;
67 | private boolean instantSeeking = false;
68 | private boolean portrait;
69 |
70 | private WakeLock mWakeLock = null;
71 |
72 | private View mRoot;
73 |
74 | private int STATUS_ERROR = -1;
75 | private int STATUS_IDLE = 0;
76 | private int STATUS_LOADING = 1;
77 | private int STATUS_PLAYING = 2;
78 | private int STATUS_PAUSE = 3;
79 | private int STATUS_COMPLETED = 4;
80 | private int status = STATUS_IDLE;
81 |
82 | private final View.OnClickListener onClickListener = new View.OnClickListener() {
83 | @Override
84 | public void onClick(View v) {
85 | if (v.getId() == R.id.app_video_fullscreen) {
86 | if (getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
87 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
88 | } else {
89 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
90 | }
91 | updateFullScreenButton();
92 | } else if (v.getId() == R.id.app_video_play) {
93 | doPauseResume();
94 | show(defaultTimeout);
95 | } else if (v.getId() == R.id.app_video_replay_icon) {
96 | mVV.seekTo(0);
97 | mVV.start();
98 | doPauseResume();
99 | }
100 | }
101 | };
102 | private final SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
103 | @Override
104 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
105 | if (!fromUser)
106 | return;
107 | int newPosition = (int) ((duration * progress * 1.0) / 100);
108 | String time = generateTime(newPosition);
109 | if (instantSeeking) {
110 | mVV.seekTo(newPosition);
111 | }
112 | $.id(R.id.app_video_currentTime).text(time);
113 | }
114 |
115 | @Override
116 | public void onStartTrackingTouch(SeekBar seekBar) {
117 | isDragging = true;
118 | show(3600000);
119 | handler.removeMessages(MESSAGE_SHOW_PROGRESS);
120 | if (instantSeeking) {
121 | audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
122 | }
123 | }
124 |
125 | @Override
126 | public void onStopTrackingTouch(SeekBar seekBar) {
127 | if (!instantSeeking) {
128 | mVV.seekTo((int) ((duration * seekBar.getProgress() * 1.0) / 100));
129 | }
130 | show(defaultTimeout);
131 | handler.removeMessages(MESSAGE_SHOW_PROGRESS);
132 | audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
133 | isDragging = false;
134 | handler.sendEmptyMessageDelayed(MESSAGE_SHOW_PROGRESS, 1000);
135 | }
136 | };
137 |
138 | @Override
139 | protected void onCreate(Bundle savedInstanceState) {
140 | super.onCreate(savedInstanceState);
141 | setContentView(R.layout.activity_play_video);
142 |
143 | mVideoSource = getIntent().getStringExtra("url");
144 |
145 | PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
146 | mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
147 |
148 | audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
149 | mMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
150 |
151 | mViewHolder = (RelativeLayout) findViewById(R.id.view_holder);
152 |
153 | BVideoView.setAK("4795f6d00635461ebfe00288c4a645bb");
154 | mVV = new BVideoView(this);
155 | mViewHolder.addView(mVV);
156 |
157 | mVV.setOnPreparedListener(this);
158 | mVV.setOnCompletionListener(this);
159 | mVV.setOnCompletionWithParamListener(this);
160 | mVV.setOnErrorListener(this);
161 | mVV.setOnInfoListener(this);
162 | mVV.setOnPlayingBufferCacheListener(this);
163 |
164 | mVV.setDecodeMode(BVideoView.DECODE_SW);
165 | mVV.showCacheInfo(true);
166 | mVV.setVideoPath(mVideoSource);
167 |
168 | $ = new Query(this);
169 | seekBar = (SeekBar) findViewById(R.id.app_video_seekBar);
170 | seekBar.setOnSeekBarChangeListener(mSeekListener);
171 |
172 | $.id(R.id.app_video_play).clicked(onClickListener);
173 | $.id(R.id.app_video_fullscreen).clicked(onClickListener);
174 | $.id(R.id.app_video_replay_icon).clicked(onClickListener);
175 |
176 | portrait = getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
177 |
178 | screenWidthPixels = getResources().getDisplayMetrics().widthPixels;
179 |
180 | onPrepared();
181 | }
182 |
183 | @Override
184 | public boolean onInfo(int what, int extra) {
185 | switch (what) {
186 | /**
187 | * 开始缓冲
188 | */
189 | case BVideoView.MEDIA_INFO_BUFFERING_START:
190 | System.out.println("caching start,now playing url : " + mVV.getCurrentPlayingUrl());
191 |
192 | break;
193 | /**
194 | * 结束缓冲
195 | */
196 | case BVideoView.MEDIA_INFO_BUFFERING_END:
197 | System.out.println("caching end,now playing url : " + mVV.getCurrentPlayingUrl());
198 |
199 | break;
200 | default:
201 | break;
202 | }
203 | return false;
204 | }
205 |
206 | /**
207 | * 当前缓冲的百分比, 可以配合onInfo中的开始缓冲和结束缓冲来显示百分比到界面
208 | */
209 | @Override
210 | public void onPlayingBufferCache(int percent) {
211 | seekBar.setSecondaryProgress(percent);
212 | }
213 |
214 | /**
215 | * 播放出错
216 | */
217 | @Override
218 | public boolean onError(int what, int extra) {
219 | return true;
220 | }
221 |
222 | /**
223 | * 播放完成
224 | */
225 | @Override
226 | public void onCompletion() {
227 | finish();
228 | }
229 |
230 | /**
231 | * 播放准备就绪
232 | */
233 | @Override
234 | public void onPrepared() {
235 | duration = mVV.getDuration();
236 |
237 | final GestureDetector gestureDetector = new GestureDetector(this, new PlayerGestureListener());
238 | mRoot = findViewById(R.id.touch_area);
239 | mRoot.setClickable(true);
240 | mRoot.setOnTouchListener(new View.OnTouchListener() {
241 | @Override
242 | public boolean onTouch(View view, MotionEvent motionEvent) {
243 | if (gestureDetector.onTouchEvent(motionEvent))
244 | return true;
245 |
246 | // 处理手势结束
247 | switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
248 | case MotionEvent.ACTION_UP:
249 | endGesture();
250 | break;
251 | }
252 |
253 | return false;
254 | }
255 | });
256 |
257 | mVV.start();
258 | }
259 |
260 | @Override
261 | public void OnCompletionWithParam(int param) {
262 |
263 | }
264 |
265 | private void doPauseResume() {
266 | if (status == STATUS_COMPLETED) {
267 | $.id(R.id.app_video_replay).gone();
268 | mVV.seekTo(0);
269 | mVV.start();
270 | } else if (mVV.isPlaying()) {
271 | statusChange(STATUS_PAUSE);
272 | mVV.pause();
273 | } else {
274 | mVV.resume();
275 | }
276 | updatePausePlay();
277 | }
278 |
279 | private void updateFullScreenButton() {
280 | if (getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
281 | $.id(R.id.app_video_fullscreen).image(R.drawable.ic_fullscreen_exit_white_36dp);
282 | } else {
283 | $.id(R.id.app_video_fullscreen).image(R.drawable.ic_fullscreen_white_24dp);
284 | }
285 | }
286 |
287 | private void statusChange(int newStatus) {
288 | status = newStatus;
289 | if (!isLive && newStatus == STATUS_COMPLETED) {
290 | hideAll();
291 | $.id(R.id.app_video_replay).visible();
292 | } else if (newStatus == STATUS_ERROR) {
293 | hideAll();
294 | } else if (newStatus == STATUS_LOADING) {
295 | hideAll();
296 | $.id(R.id.app_video_loading).visible();
297 | } else if (newStatus == STATUS_PLAYING) {
298 | hideAll();
299 | }
300 |
301 | }
302 |
303 | private void hideAll() {
304 | $.id(R.id.app_video_replay).gone();
305 | $.id(R.id.app_video_loading).gone();
306 | $.id(R.id.app_video_fullscreen).invisible();
307 | showBottomControl(false);
308 | }
309 |
310 | public void hide(boolean force) {
311 | if (force || isShowing) {
312 | handler.removeMessages(MESSAGE_SHOW_PROGRESS);
313 | showBottomControl(false);
314 | $.id(R.id.app_video_fullscreen).invisible();
315 | isShowing = false;
316 | }
317 | }
318 |
319 | /**
320 | * @param timeout
321 | */
322 | public void show(int timeout) {
323 | if (!isShowing) {
324 | if (!isLive) {
325 | showBottomControl(true);
326 | }
327 | if (!fullScreenOnly) {
328 | $.id(R.id.app_video_fullscreen).visible();
329 | }
330 | isShowing = true;
331 | }
332 | updatePausePlay();
333 | handler.sendEmptyMessage(MESSAGE_SHOW_PROGRESS);
334 | handler.removeMessages(MESSAGE_FADE_OUT);
335 | if (timeout != 0) {
336 | handler.sendMessageDelayed(handler.obtainMessage(MESSAGE_FADE_OUT), timeout);
337 | }
338 | }
339 |
340 | private void showBottomControl(boolean show) {
341 | $.id(R.id.app_video_play).visibility(show ? View.VISIBLE : View.GONE);
342 | $.id(R.id.app_video_currentTime).visibility(show ? View.VISIBLE : View.GONE);
343 | $.id(R.id.app_video_endTime).visibility(show ? View.VISIBLE : View.GONE);
344 | $.id(R.id.app_video_seekBar).visibility(show ? View.VISIBLE : View.GONE);
345 | }
346 |
347 | /**
348 | * 滑动改变声音大小
349 | *
350 | * @param percent
351 | */
352 | private void onVolumeSlide(float percent) {
353 | if (volume == -1) {
354 | volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
355 | if (volume < 0)
356 | volume = 0;
357 | }
358 | hide(true);
359 |
360 | int index = (int) (percent * mMaxVolume) + volume;
361 | if (index > mMaxVolume)
362 | index = mMaxVolume;
363 | else if (index < 0)
364 | index = 0;
365 |
366 | // 变更声音
367 | audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);
368 |
369 | // 变更进度条
370 | int i = (int) (index * 1.0 / mMaxVolume * 100);
371 | String s = i + "%";
372 | if (i == 0) {
373 | s = "";
374 | }
375 | // 显示
376 | $.id(R.id.app_video_volume_icon).image(i == 0 ? R.drawable.ic_volume_off_white_36dp : R.drawable
377 | .ic_volume_up_white_36dp);
378 | $.id(R.id.app_video_brightness_box).gone();
379 | $.id(R.id.app_video_volume_box).visible();
380 | $.id(R.id.app_video_volume_box).visible();
381 | $.id(R.id.app_video_volume).text(s).visible();
382 | }
383 |
384 | /**
385 | * 滑动改变亮度
386 | */
387 | private void onBrightnessSlide(float percent) {
388 | if (brightness < 0) {
389 | brightness = getWindow().getAttributes().screenBrightness;
390 | if (brightness <= 0.00f) {
391 | brightness = 0.50f;
392 | } else if (brightness < 0.01f) {
393 | brightness = 0.01f;
394 | }
395 | }
396 | $.id(R.id.app_video_brightness_box).visible();
397 | WindowManager.LayoutParams lpa = getWindow().getAttributes();
398 | lpa.screenBrightness = brightness + percent;
399 | if (lpa.screenBrightness > 1.0f) {
400 | lpa.screenBrightness = 1.0f;
401 | } else if (lpa.screenBrightness < 0.01f) {
402 | lpa.screenBrightness = 0.01f;
403 | }
404 | $.id(R.id.app_video_brightness).text(((int) (lpa.screenBrightness * 100)) + "%");
405 | getWindow().setAttributes(lpa);
406 |
407 | }
408 |
409 | private int setProgress() {
410 | if (isDragging) {
411 | return 0;
412 | }
413 |
414 | int position = mVV.getCurrentPosition();
415 | int duration = mVV.getDuration();
416 | if (seekBar != null) {
417 | if (duration > 0) {
418 | seekBar.setProgress((position * 100 / duration));
419 | }
420 | }
421 |
422 | this.duration = duration;
423 |
424 | $.id(R.id.app_video_currentTime).text(generateTime(position));
425 | $.id(R.id.app_video_endTime).text(generateTime(this.duration));
426 | return position;
427 | }
428 |
429 | private String generateTime(int time) {
430 | int totalSeconds = time;
431 | int seconds = totalSeconds % 60;
432 | int minutes = (totalSeconds / 60) % 60;
433 | int hours = totalSeconds / 3600;
434 | return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d",
435 | minutes, seconds);
436 | }
437 |
438 | private void onProgressSlide(float percent) {
439 | int position = mVV.getCurrentPosition();
440 | int duration = mVV.getDuration();
441 | int deltaMax = Math.min(200, duration - position);
442 | int delta = (int) (deltaMax * percent);
443 |
444 | newPosition = delta + position;
445 | if (newPosition > duration) {
446 | newPosition = duration;
447 | } else if (newPosition <= 0) {
448 | newPosition = 0;
449 | delta = -position;
450 | }
451 | int showDelta = delta;
452 | if (showDelta != 0) {
453 | $.id(R.id.app_video_fastForward_box).visible();
454 | String text = showDelta > 0 ? ("+" + showDelta) : "" + showDelta;
455 | $.id(R.id.app_video_fastForward).text(text + "s");
456 | $.id(R.id.app_video_fastForward_target).text(generateTime(newPosition) + "/");
457 | $.id(R.id.app_video_fastForward_all).text(generateTime(duration));
458 | }
459 | }
460 |
461 | private void updatePausePlay() {
462 | if (mVV.isPlaying()) {
463 | $.id(R.id.app_video_play).image(R.drawable.ic_stop_white_24dp);
464 | } else {
465 | $.id(R.id.app_video_play).image(R.drawable.ic_play_arrow_white_24dp);
466 | }
467 | }
468 |
469 | /**
470 | * 手势结束
471 | */
472 | private void endGesture() {
473 | volume = -1;
474 | brightness = -1f;
475 | if (newPosition >= 0) {
476 | handler.removeMessages(MESSAGE_SEEK_NEW_POSITION);
477 | handler.sendEmptyMessage(MESSAGE_SEEK_NEW_POSITION);
478 | }
479 | handler.removeMessages(MESSAGE_HIDE_CENTER_BOX);
480 | handler.sendEmptyMessageDelayed(MESSAGE_HIDE_CENTER_BOX, 500);
481 |
482 | }
483 |
484 | private int getScreenOrientation() {
485 | int rotation = getWindowManager().getDefaultDisplay().getRotation();
486 | DisplayMetrics dm = new DisplayMetrics();
487 | getWindowManager().getDefaultDisplay().getMetrics(dm);
488 | int width = dm.widthPixels;
489 | int height = dm.heightPixels;
490 | int orientation;
491 | // if the device's natural orientation is portrait:
492 | if ((rotation == Surface.ROTATION_0
493 | || rotation == Surface.ROTATION_180) && height > width ||
494 | (rotation == Surface.ROTATION_90
495 | || rotation == Surface.ROTATION_270) && width > height) {
496 | switch (rotation) {
497 | case Surface.ROTATION_0:
498 | orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
499 | break;
500 | case Surface.ROTATION_90:
501 | orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
502 | break;
503 | case Surface.ROTATION_180:
504 | orientation =
505 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
506 | break;
507 | case Surface.ROTATION_270:
508 | orientation =
509 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
510 | break;
511 | default:
512 | orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
513 | break;
514 | }
515 | }
516 | // if the device's natural orientation is landscape or if the device
517 | // is square:
518 | else {
519 | switch (rotation) {
520 | case Surface.ROTATION_0:
521 | orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
522 | break;
523 | case Surface.ROTATION_90:
524 | orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
525 | break;
526 | case Surface.ROTATION_180:
527 | orientation =
528 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
529 | break;
530 | case Surface.ROTATION_270:
531 | orientation =
532 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
533 | break;
534 | default:
535 | orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
536 | break;
537 | }
538 | }
539 |
540 | return orientation;
541 | }
542 |
543 | private Handler handler = new Handler(Looper.getMainLooper()) {
544 | @Override
545 | public void handleMessage(Message msg) {
546 | switch (msg.what) {
547 | case MESSAGE_FADE_OUT:
548 | hide(false);
549 | break;
550 | case MESSAGE_HIDE_CENTER_BOX:
551 | $.id(R.id.app_video_volume_box).gone();
552 | $.id(R.id.app_video_brightness_box).gone();
553 | $.id(R.id.app_video_fastForward_box).gone();
554 | break;
555 | case MESSAGE_SEEK_NEW_POSITION:
556 | if (!isLive && newPosition >= 0) {
557 | mVV.seekTo(newPosition);
558 | newPosition = -1;
559 | if (!mVV.isPlaying()) {
560 | doPauseResume();
561 | }
562 | }
563 | break;
564 | case MESSAGE_SHOW_PROGRESS:
565 | int pos = setProgress();
566 | if (!isDragging && isShowing) {
567 | msg = obtainMessage(MESSAGE_SHOW_PROGRESS);
568 | sendMessageDelayed(msg, 1 - pos);
569 | updatePausePlay();
570 | }
571 | break;
572 | }
573 | }
574 | };
575 |
576 | @Override
577 | protected void onPause() {
578 | super.onPause();
579 | if (mVV.isPlaying()) {
580 | mVV.pause();
581 | }
582 | }
583 |
584 | @Override
585 | protected void onResume() {
586 | super.onResume();
587 | if (null != mWakeLock && (!mWakeLock.isHeld())) {
588 | mWakeLock.acquire();
589 | }
590 | if (!mVV.isPlaying()) {
591 | mVV.resume();
592 | }
593 | }
594 |
595 | @Override
596 | protected void onStop() {
597 | super.onStop();
598 | if (mVV.isPlaying()) {
599 | mVV.pause();
600 | }
601 | }
602 |
603 | @Override
604 | protected void onDestroy() {
605 | super.onDestroy();
606 | mVV.stopPlayback();
607 | }
608 |
609 | class Query {
610 | private final Activity activity;
611 | private View view;
612 |
613 | public Query(Activity activity) {
614 | this.activity = activity;
615 | }
616 |
617 | public Query id(int id) {
618 | view = activity.findViewById(id);
619 | return this;
620 | }
621 |
622 | public Query image(int resId) {
623 | if (view instanceof ImageView) {
624 | ((ImageView) view).setImageResource(resId);
625 | }
626 | return this;
627 | }
628 |
629 | public Query visible() {
630 | if (view != null) {
631 | view.setVisibility(View.VISIBLE);
632 | }
633 | return this;
634 | }
635 |
636 | public Query gone() {
637 | if (view != null) {
638 | view.setVisibility(View.GONE);
639 | }
640 | return this;
641 | }
642 |
643 | public Query invisible() {
644 | if (view != null) {
645 | view.setVisibility(View.INVISIBLE);
646 | }
647 | return this;
648 | }
649 |
650 | public Query clicked(View.OnClickListener handler) {
651 | if (view != null) {
652 | view.setOnClickListener(handler);
653 | }
654 | return this;
655 | }
656 |
657 | public Query text(CharSequence text) {
658 | if (view != null && view instanceof TextView) {
659 | ((TextView) view).setText(text);
660 | }
661 | return this;
662 | }
663 |
664 | public Query visibility(int visible) {
665 | if (view != null) {
666 | view.setVisibility(visible);
667 | }
668 | return this;
669 | }
670 |
671 | private void size(boolean width, int n, boolean dip) {
672 | if (view != null) {
673 | ViewGroup.LayoutParams lp = view.getLayoutParams();
674 | if (n > 0 && dip) {
675 | n = dip2pixel(activity, n);
676 | }
677 | if (width) {
678 | lp.width = n;
679 | } else {
680 | lp.height = n;
681 | }
682 | view.setLayoutParams(lp);
683 | }
684 | }
685 |
686 | public void height(int height, boolean dip) {
687 | size(false, height, dip);
688 | }
689 |
690 | public int dip2pixel(Context context, float n) {
691 | int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, n, context.getResources()
692 | .getDisplayMetrics());
693 | return value;
694 | }
695 |
696 | public float pixel2dip(Context context, float n) {
697 | Resources resources = context.getResources();
698 | DisplayMetrics metrics = resources.getDisplayMetrics();
699 | float dp = n / (metrics.densityDpi / 160f);
700 | return dp;
701 |
702 | }
703 | }
704 |
705 | public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListener {
706 | private boolean firstTouch;
707 | private boolean volumeControl;
708 | private boolean toSeek;
709 |
710 | /**
711 | * 双击
712 | */
713 | @Override
714 | public boolean onDoubleTap(MotionEvent e) {
715 | // videoView.toggleAspectRatio();
716 | return true;
717 | }
718 |
719 | @Override
720 | public boolean onDown(MotionEvent e) {
721 | firstTouch = true;
722 | return super.onDown(e);
723 |
724 | }
725 |
726 | /**
727 | * 滑动
728 | */
729 | @Override
730 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
731 | float mOldX = e1.getX(), mOldY = e1.getY();
732 | float deltaY = mOldY - e2.getY();
733 | float deltaX = mOldX - e2.getX();
734 | if (firstTouch) {
735 | toSeek = Math.abs(distanceX) >= Math.abs(distanceY);
736 | volumeControl = mOldX > screenWidthPixels * 0.5f;
737 | firstTouch = false;
738 | }
739 |
740 | if (toSeek) {
741 | if (!isLive) {
742 | onProgressSlide(-deltaX / mRoot.getWidth());
743 | }
744 | } else {
745 | float percent = deltaY / mRoot.getHeight();
746 | if (volumeControl) {
747 | onVolumeSlide(percent);
748 | } else {
749 | onBrightnessSlide(percent);
750 | }
751 | }
752 | return super.onScroll(e1, e2, distanceX, distanceY);
753 | }
754 |
755 | @Override
756 | public boolean onSingleTapUp(MotionEvent e) {
757 | if (isShowing) {
758 | hide(false);
759 | } else {
760 | show(defaultTimeout);
761 | }
762 | return true;
763 | }
764 | }
765 | }
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-hdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-hdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xhdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xhdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxhdpi/play_ctrl_sound_ball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxhdpi/play_ctrl_sound_ball.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable-xxxhdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/bdplayer/src/main/res/drawable-xxxhdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable/app_video_center_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/bdplayer/src/main/res/drawable/play_seekbar_color_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/bdplayer/src/main/res/layout/activity_play_video.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
14 |
18 |
19 |
25 |
26 |
33 |
34 |
41 |
42 |
43 |
50 |
51 |
58 |
59 |
65 |
66 |
73 |
74 |
75 |
82 |
83 |
89 |
90 |
99 |
100 |
101 |
109 |
110 |
119 |
120 |
125 |
126 |
133 |
134 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
155 |
156 |
157 |
158 |
166 |
167 |
175 |
176 |
187 |
188 |
204 |
205 |
215 |
216 |
225 |
226 |
227 |
228 |
229 |
230 |
--------------------------------------------------------------------------------
/bdplayer/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #FAFAFA
5 | #F5F5F5
6 | #EEEEEE
7 | #E0E0E0
8 | #BDBDBD
9 | #9E9E9E
10 | #757575
11 | #616161
12 | #424242
13 | #212121
14 |
15 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.0.0'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | google()
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
26 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/ijkplayer/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/ijkplayer/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion '26.0.2'
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0.0"
12 | }
13 | }
14 |
15 | dependencies {
16 | compile fileTree(dir: 'libs', include: ['*.jar'])
17 | compile 'com.android.support:support-annotations:25.4.0'
18 |
19 | compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
20 | compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.4'
21 | // compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
22 | // compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.4'
23 | }
--------------------------------------------------------------------------------
/ijkplayer/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/IJKVideoPlayActivity.java:
--------------------------------------------------------------------------------
1 | package player;
2 |
3 | import android.app.Activity;
4 | import android.content.ContentResolver;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.pm.ActivityInfo;
8 | import android.content.res.Resources;
9 | import android.media.AudioManager;
10 | import android.net.Uri;
11 | import android.os.Build;
12 | import android.os.Bundle;
13 | import android.os.Handler;
14 | import android.os.Looper;
15 | import android.os.Message;
16 | import android.os.PowerManager.WakeLock;
17 | import android.text.TextUtils;
18 | import android.util.DisplayMetrics;
19 | import android.util.Log;
20 | import android.util.TypedValue;
21 | import android.view.GestureDetector;
22 | import android.view.MotionEvent;
23 | import android.view.Surface;
24 | import android.view.View;
25 | import android.view.ViewGroup;
26 | import android.view.WindowManager;
27 | import android.widget.ImageView;
28 | import android.widget.SeekBar;
29 | import android.widget.TableLayout;
30 | import android.widget.TextView;
31 |
32 |
33 | import com.afap.ijkplayer.R;
34 |
35 | import player.widget.media.IjkVideoView;
36 | import tv.danmaku.ijk.media.player.IMediaPlayer;
37 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
38 |
39 |
40 | public class IJKVideoPlayActivity extends Activity implements IMediaPlayer.OnPreparedListener,
41 | IMediaPlayer.OnCompletionListener,
42 | IMediaPlayer.OnErrorListener,
43 | IMediaPlayer.OnInfoListener {
44 |
45 | private final String TAG = "VideoPlayActivity";
46 | private static final int MESSAGE_SHOW_PROGRESS = 1;
47 | private static final int MESSAGE_FADE_OUT = 2;
48 | private static final int MESSAGE_SEEK_NEW_POSITION = 3;
49 | private static final int MESSAGE_HIDE_CENTER_BOX = 4;
50 | private static final int MESSAGE_RESTART_PLAY = 5;
51 |
52 | private String mVideoPath;
53 | private Uri mVideoUri;
54 |
55 | private IjkVideoView mVideoView;
56 | private TableLayout mHudView;
57 |
58 | private Query $;
59 | private boolean isShowing = false;
60 | private float brightness = -1;
61 | private int volume = -1;
62 | private int newPosition = -1;
63 | private boolean isLive = false;//是否为直播
64 | private int screenWidthPixels;
65 | private AudioManager audioManager;
66 | private int mMaxVolume;
67 | private boolean isDragging;
68 | private int defaultTimeout = 2000;
69 | private boolean fullScreenOnly = false;
70 | private SeekBar seekBar;
71 | private int duration;
72 | private boolean instantSeeking = false;
73 | private boolean portrait;
74 |
75 | private WakeLock mWakeLock = null;
76 |
77 | private View mRoot;
78 |
79 | private int STATUS_ERROR = -1;
80 | private int STATUS_IDLE = 0;
81 | private int STATUS_LOADING = 1;
82 | private int STATUS_PLAYING = 2;
83 | private int STATUS_PAUSE = 3;
84 | private int STATUS_COMPLETED = 4;
85 | private int status = STATUS_IDLE;
86 |
87 | private final View.OnClickListener onClickListener = new View.OnClickListener() {
88 | @Override
89 | public void onClick(View v) {
90 | if (v.getId() == R.id.app_video_fullscreen) {
91 | if (getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
92 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
93 | } else {
94 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
95 | }
96 | updateFullScreenButton();
97 | } else if (v.getId() == R.id.app_video_play) {
98 | doPauseResume();
99 | show(defaultTimeout);
100 | } else if (v.getId() == R.id.app_video_replay_icon) {
101 | mVideoView.seekTo(0);
102 | mVideoView.start();
103 | doPauseResume();
104 | }
105 | }
106 | };
107 | private final SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
108 | @Override
109 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
110 | if (!fromUser)
111 | return;
112 | int newPosition = (int) ((duration * progress * 1.0) / 100);
113 | String time = generateTime(newPosition);
114 | if (instantSeeking) {
115 | mVideoView.seekTo(newPosition);
116 | }
117 | $.id(R.id.app_video_currentTime).text(time);
118 | }
119 |
120 | @Override
121 | public void onStartTrackingTouch(SeekBar seekBar) {
122 | isDragging = true;
123 | show(3600000);
124 | handler.removeMessages(MESSAGE_SHOW_PROGRESS);
125 | if (instantSeeking) {
126 | audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
127 | }
128 | }
129 |
130 | @Override
131 | public void onStopTrackingTouch(SeekBar seekBar) {
132 | if (!instantSeeking) {
133 | mVideoView.seekTo((int) ((duration * seekBar.getProgress() * 1.0) / 100));
134 | }
135 | show(defaultTimeout);
136 | handler.removeMessages(MESSAGE_SHOW_PROGRESS);
137 | audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
138 | isDragging = false;
139 | handler.sendEmptyMessageDelayed(MESSAGE_SHOW_PROGRESS, 1000);
140 | }
141 | };
142 |
143 | public static Intent newIntent(Context context, String videoPath, String videoTitle) {
144 | Intent intent = new Intent(context, IJKVideoPlayActivity.class);
145 | intent.putExtra("videoPath", videoPath);
146 | intent.putExtra("videoTitle", videoTitle);
147 | return intent;
148 | }
149 |
150 | public static void intentTo(Context context, String videoPath, String videoTitle) {
151 | context.startActivity(newIntent(context, videoPath, videoTitle));
152 | }
153 |
154 | @Override
155 | protected void onCreate(Bundle savedInstanceState) {
156 | super.onCreate(savedInstanceState);
157 | setContentView(R.layout.activity_play_video);
158 |
159 |
160 | // PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
161 | // mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
162 |
163 | audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
164 | mMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
165 |
166 | mVideoPath = getIntent().getStringExtra("videoPath");
167 |
168 | Intent intent = getIntent();
169 | String intentAction = intent.getAction();
170 | if (!TextUtils.isEmpty(intentAction)) {
171 | if (intentAction.equals(Intent.ACTION_VIEW)) {
172 | mVideoPath = intent.getDataString();
173 | } else if (intentAction.equals(Intent.ACTION_SEND)) {
174 | mVideoUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
175 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
176 | String scheme = mVideoUri.getScheme();
177 | if (TextUtils.isEmpty(scheme)) {
178 | Log.e(TAG, "Null unknown scheme\n");
179 | finish();
180 | return;
181 | }
182 | if (scheme.equals(ContentResolver.SCHEME_ANDROID_RESOURCE)) {
183 | mVideoPath = mVideoUri.getPath();
184 | } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
185 | Log.e(TAG, "Can not resolve content below Android-ICS\n");
186 | finish();
187 | return;
188 | } else {
189 | Log.e(TAG, "Unknown scheme " + scheme + "\n");
190 | finish();
191 | return;
192 | }
193 | }
194 | }
195 | }
196 | // init player
197 | IjkMediaPlayer.loadLibrariesOnce(null);
198 | IjkMediaPlayer.native_profileBegin("libijkplayer.so");
199 |
200 | mVideoView = (IjkVideoView) findViewById(R.id.video_view);
201 | // mHudView = (TableLayout) findViewById(R.id.hud_view);
202 | // mVideoView.setHudView(mHudView);
203 | // mVideoView.setMediaController(mMediaController);
204 | // prefer mVideoPath
205 | if (mVideoPath != null)
206 | mVideoView.setVideoPath(mVideoPath);
207 | else if (mVideoUri != null)
208 | mVideoView.setVideoURI(mVideoUri);
209 | else {
210 | Log.e(TAG, "Null Data Source\n");
211 | finish();
212 | return;
213 | }
214 |
215 | mVideoView.setOnPreparedListener(this);
216 | mVideoView.setOnCompletionListener(this);
217 | mVideoView.setOnErrorListener(this);
218 | mVideoView.setOnInfoListener(this);
219 |
220 |
221 | $ = new Query(this);
222 | seekBar = (SeekBar) findViewById(R.id.app_video_seekBar);
223 | seekBar.setOnSeekBarChangeListener(mSeekListener);
224 |
225 | $.id(R.id.app_video_play).clicked(onClickListener);
226 | $.id(R.id.app_video_fullscreen).clicked(onClickListener);
227 | $.id(R.id.app_video_replay_icon).clicked(onClickListener);
228 |
229 | portrait = getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
230 |
231 | screenWidthPixels = getResources().getDisplayMetrics().widthPixels;
232 |
233 | }
234 |
235 | @Override
236 | public void onCompletion(IMediaPlayer iMediaPlayer) {
237 | finish();
238 | }
239 |
240 | @Override
241 | public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
242 | return false;
243 | }
244 |
245 | @Override
246 | public boolean onInfo(IMediaPlayer iMediaPlayer, int i, int i1) {
247 | System.out.println("onInfo : i=" + i + ",i1=" + i1);
248 | return false;
249 | }
250 |
251 | /**
252 | * 播放准备就绪
253 | */
254 | @Override
255 | public void onPrepared(IMediaPlayer iMediaPlayer) {
256 | duration = mVideoView.getDuration();
257 |
258 | final GestureDetector gestureDetector = new GestureDetector(this, new PlayerGestureListener());
259 | mRoot = findViewById(R.id.touch_area);
260 | mRoot.setClickable(true);
261 | mRoot.setOnTouchListener(new View.OnTouchListener() {
262 | @Override
263 | public boolean onTouch(View view, MotionEvent motionEvent) {
264 | if (gestureDetector.onTouchEvent(motionEvent))
265 | return true;
266 |
267 | // 处理手势结束
268 | switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
269 | case MotionEvent.ACTION_UP:
270 | endGesture();
271 | break;
272 | }
273 |
274 | return false;
275 | }
276 | });
277 |
278 | mVideoView.start();
279 | }
280 |
281 |
282 | private void doPauseResume() {
283 | if (status == STATUS_COMPLETED) {
284 | $.id(R.id.app_video_replay).gone();
285 | mVideoView.seekTo(0);
286 | mVideoView.start();
287 | } else if (mVideoView.isPlaying()) {
288 | statusChange(STATUS_PAUSE);
289 | mVideoView.pause();
290 | } else {
291 | mVideoView.resume();
292 | }
293 | updatePausePlay();
294 | }
295 |
296 | private void updateFullScreenButton() {
297 | if (getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
298 | $.id(R.id.app_video_fullscreen).image(R.drawable.ic_fullscreen_exit_white_36dp);
299 | } else {
300 | $.id(R.id.app_video_fullscreen).image(R.drawable.ic_fullscreen_white_24dp);
301 | }
302 | }
303 |
304 | private void statusChange(int newStatus) {
305 | status = newStatus;
306 | if (!isLive && newStatus == STATUS_COMPLETED) {
307 | hideAll();
308 | $.id(R.id.app_video_replay).visible();
309 | } else if (newStatus == STATUS_ERROR) {
310 | hideAll();
311 | } else if (newStatus == STATUS_LOADING) {
312 | hideAll();
313 | $.id(R.id.app_video_loading).visible();
314 | } else if (newStatus == STATUS_PLAYING) {
315 | hideAll();
316 | }
317 |
318 | }
319 |
320 | private void hideAll() {
321 | $.id(R.id.app_video_replay).gone();
322 | $.id(R.id.app_video_loading).gone();
323 | $.id(R.id.app_video_fullscreen).invisible();
324 | showBottomControl(false);
325 | }
326 |
327 | public void hide(boolean force) {
328 | if (force || isShowing) {
329 | handler.removeMessages(MESSAGE_SHOW_PROGRESS);
330 | showBottomControl(false);
331 | $.id(R.id.app_video_fullscreen).invisible();
332 | isShowing = false;
333 | }
334 | }
335 |
336 | /**
337 | * @param timeout
338 | */
339 | public void show(int timeout) {
340 | if (!isShowing) {
341 | if (!isLive) {
342 | showBottomControl(true);
343 | }
344 | if (!fullScreenOnly) {
345 | $.id(R.id.app_video_fullscreen).visible();
346 | }
347 | isShowing = true;
348 | }
349 | updatePausePlay();
350 | handler.sendEmptyMessage(MESSAGE_SHOW_PROGRESS);
351 | handler.removeMessages(MESSAGE_FADE_OUT);
352 | if (timeout != 0) {
353 | handler.sendMessageDelayed(handler.obtainMessage(MESSAGE_FADE_OUT), timeout);
354 | }
355 | }
356 |
357 | private void showBottomControl(boolean show) {
358 | $.id(R.id.app_video_play).visibility(show ? View.VISIBLE : View.GONE);
359 | $.id(R.id.app_video_currentTime).visibility(show ? View.VISIBLE : View.GONE);
360 | $.id(R.id.app_video_endTime).visibility(show ? View.VISIBLE : View.GONE);
361 | $.id(R.id.app_video_seekBar).visibility(show ? View.VISIBLE : View.GONE);
362 | }
363 |
364 | /**
365 | * 滑动改变声音大小
366 | *
367 | * @param percent
368 | */
369 | private void onVolumeSlide(float percent) {
370 | if (volume == -1) {
371 | volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
372 | if (volume < 0)
373 | volume = 0;
374 | }
375 | hide(true);
376 |
377 | int index = (int) (percent * mMaxVolume) + volume;
378 | if (index > mMaxVolume)
379 | index = mMaxVolume;
380 | else if (index < 0)
381 | index = 0;
382 |
383 | // 变更声音
384 | audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);
385 |
386 | // 变更进度条
387 | int i = (int) (index * 1.0 / mMaxVolume * 100);
388 | String s = i + "%";
389 | if (i == 0) {
390 | s = "";
391 | }
392 | // 显示
393 | $.id(R.id.app_video_volume_icon).image(i == 0 ? R.drawable.ic_volume_off_white_36dp : R.drawable
394 | .ic_volume_up_white_36dp);
395 | $.id(R.id.app_video_brightness_box).gone();
396 | $.id(R.id.app_video_volume_box).visible();
397 | $.id(R.id.app_video_volume_box).visible();
398 | $.id(R.id.app_video_volume).text(s).visible();
399 | }
400 |
401 | /**
402 | * 滑动改变亮度
403 | */
404 | private void onBrightnessSlide(float percent) {
405 | if (brightness < 0) {
406 | brightness = getWindow().getAttributes().screenBrightness;
407 | if (brightness <= 0.00f) {
408 | brightness = 0.50f;
409 | } else if (brightness < 0.01f) {
410 | brightness = 0.01f;
411 | }
412 | }
413 | $.id(R.id.app_video_brightness_box).visible();
414 | WindowManager.LayoutParams lpa = getWindow().getAttributes();
415 | lpa.screenBrightness = brightness + percent;
416 | if (lpa.screenBrightness > 1.0f) {
417 | lpa.screenBrightness = 1.0f;
418 | } else if (lpa.screenBrightness < 0.01f) {
419 | lpa.screenBrightness = 0.01f;
420 | }
421 | $.id(R.id.app_video_brightness).text(((int) (lpa.screenBrightness * 100)) + "%");
422 | getWindow().setAttributes(lpa);
423 |
424 | }
425 |
426 | private int setProgress() {
427 | if (isDragging) {
428 | return 0;
429 | }
430 |
431 | int position = mVideoView.getCurrentPosition();
432 | int duration = mVideoView.getDuration();
433 | if (seekBar != null) {
434 | if (duration > 0) {
435 | seekBar.setProgress((position * 100 / duration));
436 | }
437 | }
438 |
439 | this.duration = duration;
440 |
441 | $.id(R.id.app_video_currentTime).text(generateTime(position));
442 | $.id(R.id.app_video_endTime).text(generateTime(this.duration));
443 | return position;
444 | }
445 |
446 | private String generateTime(int time) {
447 | int totalSeconds = time / 1000;
448 | int seconds = totalSeconds % 60;
449 | int minutes = (totalSeconds / 60) % 60;
450 | int hours = totalSeconds / 3600;
451 | return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d",
452 | minutes, seconds);
453 | }
454 |
455 | private void onProgressSlide(float percent) {
456 | int position = mVideoView.getCurrentPosition();
457 | int duration = mVideoView.getDuration();
458 | int deltaMax = Math.min(300000, duration - position);
459 | int delta = (int) (deltaMax * percent);
460 |
461 | newPosition = delta + position;
462 | if (newPosition > duration) {
463 | newPosition = duration;
464 | } else if (newPosition <= 0) {
465 | newPosition = 0;
466 | delta = -position;
467 | }
468 | int showDelta = delta / 1000;
469 | if (showDelta != 0) {
470 | $.id(R.id.app_video_fastForward_box).visible();
471 | String text = showDelta > 0 ? ("+" + showDelta) : "" + showDelta;
472 | $.id(R.id.app_video_fastForward).text(text + "s");
473 | $.id(R.id.app_video_fastForward_target).text(generateTime(newPosition) + "/");
474 | $.id(R.id.app_video_fastForward_all).text(generateTime(duration));
475 | }
476 | }
477 |
478 | private void updatePausePlay() {
479 | if (mVideoView.isPlaying()) {
480 | $.id(R.id.app_video_play).image(R.drawable.ic_stop_white_24dp);
481 | } else {
482 | $.id(R.id.app_video_play).image(R.drawable.ic_play_arrow_white_24dp);
483 | }
484 | }
485 |
486 | /**
487 | * 手势结束
488 | */
489 | private void endGesture() {
490 | volume = -1;
491 | brightness = -1f;
492 | if (newPosition >= 0) {
493 | handler.removeMessages(MESSAGE_SEEK_NEW_POSITION);
494 | handler.sendEmptyMessage(MESSAGE_SEEK_NEW_POSITION);
495 | }
496 | handler.removeMessages(MESSAGE_HIDE_CENTER_BOX);
497 | handler.sendEmptyMessageDelayed(MESSAGE_HIDE_CENTER_BOX, 500);
498 |
499 | }
500 |
501 | private int getScreenOrientation() {
502 | int rotation = getWindowManager().getDefaultDisplay().getRotation();
503 | DisplayMetrics dm = new DisplayMetrics();
504 | getWindowManager().getDefaultDisplay().getMetrics(dm);
505 | int width = dm.widthPixels;
506 | int height = dm.heightPixels;
507 | int orientation;
508 | // if the device's natural orientation is portrait:
509 | if ((rotation == Surface.ROTATION_0
510 | || rotation == Surface.ROTATION_180) && height > width ||
511 | (rotation == Surface.ROTATION_90
512 | || rotation == Surface.ROTATION_270) && width > height) {
513 | switch (rotation) {
514 | case Surface.ROTATION_0:
515 | orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
516 | break;
517 | case Surface.ROTATION_90:
518 | orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
519 | break;
520 | case Surface.ROTATION_180:
521 | orientation =
522 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
523 | break;
524 | case Surface.ROTATION_270:
525 | orientation =
526 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
527 | break;
528 | default:
529 | orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
530 | break;
531 | }
532 | }
533 | // if the device's natural orientation is landscape or if the device
534 | // is square:
535 | else {
536 | switch (rotation) {
537 | case Surface.ROTATION_0:
538 | orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
539 | break;
540 | case Surface.ROTATION_90:
541 | orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
542 | break;
543 | case Surface.ROTATION_180:
544 | orientation =
545 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
546 | break;
547 | case Surface.ROTATION_270:
548 | orientation =
549 | ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
550 | break;
551 | default:
552 | orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
553 | break;
554 | }
555 | }
556 |
557 | return orientation;
558 | }
559 |
560 | private Handler handler = new Handler(Looper.getMainLooper()) {
561 | @Override
562 | public void handleMessage(Message msg) {
563 | switch (msg.what) {
564 | case MESSAGE_FADE_OUT:
565 | hide(false);
566 | break;
567 | case MESSAGE_HIDE_CENTER_BOX:
568 | $.id(R.id.app_video_volume_box).gone();
569 | $.id(R.id.app_video_brightness_box).gone();
570 | $.id(R.id.app_video_fastForward_box).gone();
571 | break;
572 | case MESSAGE_SEEK_NEW_POSITION:
573 | if (!isLive && newPosition >= 0) {
574 | mVideoView.seekTo(newPosition);
575 | newPosition = -1;
576 | if (!mVideoView.isPlaying()) {
577 | doPauseResume();
578 | }
579 | }
580 | break;
581 | case MESSAGE_SHOW_PROGRESS:
582 | int pos = setProgress();
583 | if (!isDragging && isShowing) {
584 | msg = obtainMessage(MESSAGE_SHOW_PROGRESS);
585 | sendMessageDelayed(msg, 1 - pos);
586 | updatePausePlay();
587 | }
588 | break;
589 | }
590 | }
591 | };
592 |
593 | @Override
594 | protected void onPause() {
595 | super.onPause();
596 | if (mVideoView.isPlaying()) {
597 | mVideoView.pause();
598 | }
599 | }
600 |
601 | @Override
602 | protected void onResume() {
603 | super.onResume();
604 | if (null != mWakeLock && (!mWakeLock.isHeld())) {
605 | mWakeLock.acquire();
606 | }
607 | if (!mVideoView.isPlaying()) {
608 | mVideoView.resume();
609 | }
610 | }
611 |
612 | @Override
613 | protected void onStop() {
614 | super.onStop();
615 | if (mVideoView.isPlaying()) {
616 | mVideoView.pause();
617 | }
618 | }
619 |
620 | @Override
621 | protected void onDestroy() {
622 | super.onDestroy();
623 | mVideoView.stopPlayback();
624 | }
625 |
626 |
627 | class Query {
628 | private final Activity activity;
629 | private View view;
630 |
631 | public Query(Activity activity) {
632 | this.activity = activity;
633 | }
634 |
635 | public Query id(int id) {
636 | view = activity.findViewById(id);
637 | return this;
638 | }
639 |
640 | public Query image(int resId) {
641 | if (view instanceof ImageView) {
642 | ((ImageView) view).setImageResource(resId);
643 | }
644 | return this;
645 | }
646 |
647 | public Query visible() {
648 | if (view != null) {
649 | view.setVisibility(View.VISIBLE);
650 | }
651 | return this;
652 | }
653 |
654 | public Query gone() {
655 | if (view != null) {
656 | view.setVisibility(View.GONE);
657 | }
658 | return this;
659 | }
660 |
661 | public Query invisible() {
662 | if (view != null) {
663 | view.setVisibility(View.INVISIBLE);
664 | }
665 | return this;
666 | }
667 |
668 | public Query clicked(View.OnClickListener handler) {
669 | if (view != null) {
670 | view.setOnClickListener(handler);
671 | }
672 | return this;
673 | }
674 |
675 | public Query text(CharSequence text) {
676 | if (view != null && view instanceof TextView) {
677 | ((TextView) view).setText(text);
678 | }
679 | return this;
680 | }
681 |
682 | public Query visibility(int visible) {
683 | if (view != null) {
684 | view.setVisibility(visible);
685 | }
686 | return this;
687 | }
688 |
689 | private void size(boolean width, int n, boolean dip) {
690 | if (view != null) {
691 | ViewGroup.LayoutParams lp = view.getLayoutParams();
692 | if (n > 0 && dip) {
693 | n = dip2pixel(activity, n);
694 | }
695 | if (width) {
696 | lp.width = n;
697 | } else {
698 | lp.height = n;
699 | }
700 | view.setLayoutParams(lp);
701 | }
702 | }
703 |
704 | public void height(int height, boolean dip) {
705 | size(false, height, dip);
706 | }
707 |
708 | public int dip2pixel(Context context, float n) {
709 | int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, n, context.getResources()
710 | .getDisplayMetrics());
711 | return value;
712 | }
713 |
714 | public float pixel2dip(Context context, float n) {
715 | Resources resources = context.getResources();
716 | DisplayMetrics metrics = resources.getDisplayMetrics();
717 | float dp = n / (metrics.densityDpi / 160f);
718 | return dp;
719 |
720 | }
721 | }
722 |
723 | public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListener {
724 | private boolean firstTouch;
725 | private boolean volumeControl;
726 | private boolean toSeek;
727 |
728 | /**
729 | * 双击
730 | */
731 | @Override
732 | public boolean onDoubleTap(MotionEvent e) {
733 | // videoView.toggleAspectRatio();
734 | return true;
735 | }
736 |
737 | @Override
738 | public boolean onDown(MotionEvent e) {
739 | firstTouch = true;
740 | return super.onDown(e);
741 |
742 | }
743 |
744 | /**
745 | * 滑动
746 | */
747 | @Override
748 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
749 | float mOldX = e1.getX(), mOldY = e1.getY();
750 | float deltaY = mOldY - e2.getY();
751 | float deltaX = mOldX - e2.getX();
752 | if (firstTouch) {
753 | toSeek = Math.abs(distanceX) >= Math.abs(distanceY);
754 | volumeControl = mOldX > screenWidthPixels * 0.5f;
755 | firstTouch = false;
756 | }
757 |
758 | if (toSeek) {
759 | if (!isLive) {
760 | onProgressSlide(-deltaX / mRoot.getWidth());
761 | }
762 | } else {
763 | float percent = deltaY / mRoot.getHeight();
764 | if (volumeControl) {
765 | onVolumeSlide(percent);
766 | } else {
767 | onBrightnessSlide(percent);
768 | }
769 | }
770 | return super.onScroll(e1, e2, distanceX, distanceY);
771 | }
772 |
773 | @Override
774 | public boolean onSingleTapUp(MotionEvent e) {
775 | if (isShowing) {
776 | hide(false);
777 | } else {
778 | show(defaultTimeout);
779 | }
780 | return true;
781 | }
782 | }
783 | }
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/services/MediaPlayerService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.services;
19 |
20 | import android.app.Service;
21 | import android.content.Context;
22 | import android.content.Intent;
23 | import android.os.IBinder;
24 | import android.support.annotation.Nullable;
25 |
26 | import tv.danmaku.ijk.media.player.IMediaPlayer;
27 |
28 | public class MediaPlayerService extends Service {
29 | private static IMediaPlayer sMediaPlayer;
30 |
31 | public static Intent newIntent(Context context) {
32 | Intent intent = new Intent(context, MediaPlayerService.class);
33 | return intent;
34 | }
35 |
36 | public static void intentToStart(Context context) {
37 | context.startService(newIntent(context));
38 | }
39 |
40 | public static void intentToStop(Context context) {
41 | context.stopService(newIntent(context));
42 | }
43 |
44 | @Nullable
45 | @Override
46 | public IBinder onBind(Intent intent) {
47 | return null;
48 | }
49 |
50 | public static void setMediaPlayer(IMediaPlayer mp) {
51 | if (sMediaPlayer != null && sMediaPlayer != mp) {
52 | if (sMediaPlayer.isPlaying())
53 | sMediaPlayer.stop();
54 | sMediaPlayer.release();
55 | sMediaPlayer = null;
56 | }
57 | sMediaPlayer = mp;
58 | }
59 |
60 | public static IMediaPlayer getMediaPlayer() {
61 | return sMediaPlayer;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/settings/Settings.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.settings;
19 |
20 | import android.content.Context;
21 | import android.content.SharedPreferences;
22 | import android.preference.PreferenceManager;
23 |
24 | import com.afap.ijkplayer.R;
25 |
26 |
27 | public class Settings {
28 | private Context mAppContext;
29 | private SharedPreferences mSharedPreferences;
30 |
31 | public static final int PV_PLAYER__Auto = 0;
32 | public static final int PV_PLAYER__AndroidMediaPlayer = 1;
33 | public static final int PV_PLAYER__IjkMediaPlayer = 2;
34 | public static final int PV_PLAYER__IjkExoMediaPlayer = 3;
35 |
36 | public Settings(Context context) {
37 | mAppContext = context.getApplicationContext();
38 | mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mAppContext);
39 | }
40 |
41 | public boolean getEnableBackgroundPlay() {
42 | String key = mAppContext.getString(R.string.pref_key_enable_background_play);
43 | return mSharedPreferences.getBoolean(key, false);
44 | }
45 |
46 | public int getPlayer() {
47 | String key = mAppContext.getString(R.string.pref_key_player);
48 | String value = mSharedPreferences.getString(key, "");
49 | try {
50 | return Integer.valueOf(value).intValue();
51 | } catch (NumberFormatException e) {
52 | return 0;
53 | }
54 | }
55 |
56 | public boolean getUsingMediaCodec() {
57 | String key = mAppContext.getString(R.string.pref_key_using_media_codec);
58 | return mSharedPreferences.getBoolean(key, false);
59 | }
60 |
61 | public boolean getUsingMediaCodecAutoRotate() {
62 | String key = mAppContext.getString(R.string.pref_key_using_media_codec_auto_rotate);
63 | return mSharedPreferences.getBoolean(key, false);
64 | }
65 |
66 | public boolean getMediaCodecHandleResolutionChange() {
67 | String key = mAppContext.getString(R.string.pref_key_media_codec_handle_resolution_change);
68 | return mSharedPreferences.getBoolean(key, false);
69 | }
70 |
71 | public boolean getUsingOpenSLES() {
72 | String key = mAppContext.getString(R.string.pref_key_using_opensl_es);
73 | return mSharedPreferences.getBoolean(key, false);
74 | }
75 |
76 | public String getPixelFormat() {
77 | String key = mAppContext.getString(R.string.pref_key_pixel_format);
78 | return mSharedPreferences.getString(key, "");
79 | }
80 |
81 | public boolean getEnableNoView() {
82 | String key = mAppContext.getString(R.string.pref_key_enable_no_view);
83 | return mSharedPreferences.getBoolean(key, false);
84 | }
85 |
86 | public boolean getEnableSurfaceView() {
87 | String key = mAppContext.getString(R.string.pref_key_enable_surface_view);
88 | return mSharedPreferences.getBoolean(key, false);
89 | }
90 |
91 | public boolean getEnableTextureView() {
92 | String key = mAppContext.getString(R.string.pref_key_enable_texture_view);
93 | return mSharedPreferences.getBoolean(key, false);
94 | }
95 |
96 | public boolean getEnableDetachedSurfaceTextureView() {
97 | String key = mAppContext.getString(R.string.pref_key_enable_detached_surface_texture);
98 | return mSharedPreferences.getBoolean(key, false);
99 | }
100 |
101 | public boolean getUsingMediaDataSource() {
102 | String key = mAppContext.getString(R.string.pref_key_using_mediadatasource);
103 | return mSharedPreferences.getBoolean(key, false);
104 | }
105 |
106 | public String getLastDirectory() {
107 | String key = mAppContext.getString(R.string.pref_key_last_directory);
108 | return mSharedPreferences.getString(key, "/");
109 | }
110 |
111 | public void setLastDirectory(String path) {
112 | String key = mAppContext.getString(R.string.pref_key_last_directory);
113 | mSharedPreferences.edit().putString(key, path).apply();
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/FileMediaDataSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.io.RandomAccessFile;
23 |
24 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
25 |
26 | public class FileMediaDataSource implements IMediaDataSource {
27 | private RandomAccessFile mFile;
28 | private long mFileSize;
29 |
30 | public FileMediaDataSource(File file) throws IOException {
31 | mFile = new RandomAccessFile(file, "r");
32 | mFileSize = mFile.length();
33 | }
34 |
35 | @Override
36 | public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
37 | if (mFile.getFilePointer() != position)
38 | mFile.seek(position);
39 |
40 | if (size == 0)
41 | return 0;
42 |
43 | return mFile.read(buffer, 0, size);
44 | }
45 |
46 | @Override
47 | public long getSize() throws IOException {
48 | return mFileSize;
49 | }
50 |
51 | @Override
52 | public void close() throws IOException {
53 | mFileSize = 0;
54 | mFile.close();
55 | mFile = null;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/IMediaController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import android.view.View;
21 | import android.widget.MediaController;
22 |
23 | public interface IMediaController {
24 | void hide();
25 |
26 | boolean isShowing();
27 |
28 | void setAnchorView(View view);
29 |
30 | void setEnabled(boolean enabled);
31 |
32 | void setMediaPlayer(MediaController.MediaPlayerControl player);
33 |
34 | void show(int timeout);
35 |
36 | void show();
37 |
38 | //----------
39 | // Extends
40 | //----------
41 | void showOnce(View view);
42 | }
43 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/IRenderView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import android.graphics.SurfaceTexture;
21 | import android.support.annotation.NonNull;
22 | import android.support.annotation.Nullable;
23 | import android.view.Surface;
24 | import android.view.SurfaceHolder;
25 | import android.view.View;
26 |
27 | import tv.danmaku.ijk.media.player.IMediaPlayer;
28 |
29 | public interface IRenderView {
30 | int AR_ASPECT_FIT_PARENT = 0; // without clip
31 | int AR_ASPECT_FILL_PARENT = 1; // may clip
32 | int AR_ASPECT_WRAP_CONTENT = 2;
33 | int AR_MATCH_PARENT = 3;
34 | int AR_16_9_FIT_PARENT = 4;
35 | int AR_4_3_FIT_PARENT = 5;
36 |
37 | View getView();
38 |
39 | boolean shouldWaitForResize();
40 |
41 | void setVideoSize(int videoWidth, int videoHeight);
42 |
43 | void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen);
44 |
45 | void setVideoRotation(int degree);
46 |
47 | void setAspectRatio(int aspectRatio);
48 |
49 | void addRenderCallback(@NonNull IRenderCallback callback);
50 |
51 | void removeRenderCallback(@NonNull IRenderCallback callback);
52 |
53 | interface ISurfaceHolder {
54 | void bindToMediaPlayer(IMediaPlayer mp);
55 |
56 | @NonNull
57 | IRenderView getRenderView();
58 |
59 | @Nullable
60 | SurfaceHolder getSurfaceHolder();
61 |
62 | @Nullable
63 | Surface openSurface();
64 |
65 | @Nullable
66 | SurfaceTexture getSurfaceTexture();
67 | }
68 |
69 | interface IRenderCallback {
70 | /**
71 | * @param holder
72 | * @param width could be 0
73 | * @param height could be 0
74 | */
75 | void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height);
76 |
77 | /**
78 | * @param holder
79 | * @param format could be 0
80 | * @param width
81 | * @param height
82 | */
83 | void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height);
84 |
85 | void onSurfaceDestroyed(@NonNull ISurfaceHolder holder);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/InfoHudViewHolder.java:
--------------------------------------------------------------------------------
1 | package player.widget.media;
2 |
3 | import android.content.Context;
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.util.SparseArray;
7 | import android.view.View;
8 | import android.widget.TableLayout;
9 |
10 |
11 | import com.afap.ijkplayer.R;
12 |
13 | import java.util.Locale;
14 |
15 | import tv.danmaku.ijk.media.player.IMediaPlayer;
16 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
17 | import tv.danmaku.ijk.media.player.MediaPlayerProxy;
18 |
19 | public class InfoHudViewHolder {
20 | private TableLayoutBinder mTableLayoutBinder;
21 | private SparseArray mRowMap = new SparseArray();
22 | private IMediaPlayer mMediaPlayer;
23 | private long mLoadCost = 0;
24 | private long mSeekCost = 0;
25 |
26 | public InfoHudViewHolder(Context context, TableLayout tableLayout) {
27 | mTableLayoutBinder = new TableLayoutBinder(context, tableLayout);
28 | }
29 |
30 | private void appendSection(int nameId) {
31 | mTableLayoutBinder.appendSection(nameId);
32 | }
33 |
34 | private void appendRow(int nameId) {
35 | View rowView = mTableLayoutBinder.appendRow2(nameId, null);
36 | mRowMap.put(nameId, rowView);
37 | }
38 |
39 | private void setRowValue(int id, String value) {
40 | View rowView = mRowMap.get(id);
41 | if (rowView == null) {
42 | rowView = mTableLayoutBinder.appendRow2(id, value);
43 | mRowMap.put(id, rowView);
44 | } else {
45 | mTableLayoutBinder.setValueText(rowView, value);
46 | }
47 | }
48 |
49 | public void setMediaPlayer(IMediaPlayer mp) {
50 | mMediaPlayer = mp;
51 | if (mMediaPlayer != null) {
52 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500);
53 | } else {
54 | mHandler.removeMessages(MSG_UPDATE_HUD);
55 | }
56 | }
57 |
58 | private static String formatedDurationMilli(long duration) {
59 | if (duration >= 1000) {
60 | return String.format(Locale.US, "%.2f sec", ((float)duration) / 1000);
61 | } else {
62 | return String.format(Locale.US, "%d msec", duration);
63 | }
64 | }
65 |
66 | private static String formatedSpeed(long bytes, long elapsed_milli) {
67 | if (elapsed_milli <= 0) {
68 | return "0 B/s";
69 | }
70 |
71 | if (bytes <= 0) {
72 | return "0 B/s";
73 | }
74 |
75 | float bytes_per_sec = ((float)bytes) * 1000.f / elapsed_milli;
76 | if (bytes_per_sec >= 1000 * 1000) {
77 | return String.format(Locale.US, "%.2f MB/s", ((float)bytes_per_sec) / 1000 / 1000);
78 | } else if (bytes_per_sec >= 1000) {
79 | return String.format(Locale.US, "%.1f KB/s", ((float)bytes_per_sec) / 1000);
80 | } else {
81 | return String.format(Locale.US, "%d B/s", (long)bytes_per_sec);
82 | }
83 | }
84 |
85 | public void updateLoadCost(long time) {
86 | mLoadCost = time;
87 | }
88 |
89 | public void updateSeekCost(long time) {
90 | mSeekCost = time;
91 | }
92 |
93 | private static String formatedSize(long bytes) {
94 | if (bytes >= 100 * 1000) {
95 | return String.format(Locale.US, "%.2f MB", ((float)bytes) / 1000 / 1000);
96 | } else if (bytes >= 100) {
97 | return String.format(Locale.US, "%.1f KB", ((float)bytes) / 1000);
98 | } else {
99 | return String.format(Locale.US, "%d B", bytes);
100 | }
101 | }
102 |
103 | private static final int MSG_UPDATE_HUD = 1;
104 | private Handler mHandler = new Handler() {
105 | @Override
106 | public void handleMessage(Message msg) {
107 | switch (msg.what) {
108 | case MSG_UPDATE_HUD: {
109 | InfoHudViewHolder holder = InfoHudViewHolder.this;
110 | IjkMediaPlayer mp = null;
111 | if (mMediaPlayer == null)
112 | break;
113 | if (mMediaPlayer instanceof IjkMediaPlayer) {
114 | mp = (IjkMediaPlayer) mMediaPlayer;
115 | } else if (mMediaPlayer instanceof MediaPlayerProxy) {
116 | MediaPlayerProxy proxy = (MediaPlayerProxy) mMediaPlayer;
117 | IMediaPlayer internal = proxy.getInternalMediaPlayer();
118 | if (internal != null && internal instanceof IjkMediaPlayer)
119 | mp = (IjkMediaPlayer) internal;
120 | }
121 | if (mp == null)
122 | break;
123 |
124 | int vdec = mp.getVideoDecoder();
125 | switch (vdec) {
126 | case IjkMediaPlayer.FFP_PROPV_DECODER_AVCODEC:
127 | setRowValue(R.string.vdec, "avcodec");
128 | break;
129 | case IjkMediaPlayer.FFP_PROPV_DECODER_MEDIACODEC:
130 | setRowValue(R.string.vdec, "MediaCodec");
131 | break;
132 | default:
133 | setRowValue(R.string.vdec, "");
134 | break;
135 | }
136 |
137 | float fpsOutput = mp.getVideoOutputFramesPerSecond();
138 | float fpsDecode = mp.getVideoDecodeFramesPerSecond();
139 | setRowValue(R.string.fps, String.format(Locale.US, "%.2f / %.2f", fpsDecode, fpsOutput));
140 |
141 | long videoCachedDuration = mp.getVideoCachedDuration();
142 | long audioCachedDuration = mp.getAudioCachedDuration();
143 | long videoCachedBytes = mp.getVideoCachedBytes();
144 | long audioCachedBytes = mp.getAudioCachedBytes();
145 | long tcpSpeed = mp.getTcpSpeed();
146 | long bitRate = mp.getBitRate();
147 | long seekLoadDuration = mp.getSeekLoadDuration();
148 |
149 | setRowValue(R.string.v_cache, String.format(Locale.US, "%s, %s", formatedDurationMilli(videoCachedDuration), formatedSize(videoCachedBytes)));
150 | setRowValue(R.string.a_cache, String.format(Locale.US, "%s, %s", formatedDurationMilli(audioCachedDuration), formatedSize(audioCachedBytes)));
151 | setRowValue(R.string.load_cost, String.format(Locale.US, "%d ms", mLoadCost));
152 | setRowValue(R.string.seek_cost, String.format(Locale.US, "%d ms", mSeekCost));
153 | setRowValue(R.string.seek_load_cost, String.format(Locale.US, "%d ms", seekLoadDuration));
154 | setRowValue(R.string.tcp_speed, String.format(Locale.US, "%s", formatedSpeed(tcpSpeed, 1000)));
155 | setRowValue(R.string.bit_rate, String.format(Locale.US, "%.2f kbs", bitRate/1000f));
156 |
157 | mHandler.removeMessages(MSG_UPDATE_HUD);
158 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500);
159 | }
160 | }
161 | }
162 | };
163 | }
164 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/MeasureHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import android.content.Context;
21 | import android.support.annotation.NonNull;
22 | import android.view.View;
23 |
24 |
25 | import com.afap.ijkplayer.R;
26 |
27 | import java.lang.ref.WeakReference;
28 |
29 |
30 | public final class MeasureHelper {
31 | private WeakReference mWeakView;
32 |
33 | private int mVideoWidth;
34 | private int mVideoHeight;
35 | private int mVideoSarNum;
36 | private int mVideoSarDen;
37 |
38 | private int mVideoRotationDegree;
39 |
40 | private int mMeasuredWidth;
41 | private int mMeasuredHeight;
42 |
43 | private int mCurrentAspectRatio = IRenderView.AR_ASPECT_FIT_PARENT;
44 |
45 | public MeasureHelper(View view) {
46 | mWeakView = new WeakReference(view);
47 | }
48 |
49 | public View getView() {
50 | if (mWeakView == null)
51 | return null;
52 | return mWeakView.get();
53 | }
54 |
55 | public void setVideoSize(int videoWidth, int videoHeight) {
56 | mVideoWidth = videoWidth;
57 | mVideoHeight = videoHeight;
58 | }
59 |
60 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
61 | mVideoSarNum = videoSarNum;
62 | mVideoSarDen = videoSarDen;
63 | }
64 |
65 | public void setVideoRotation(int videoRotationDegree) {
66 | mVideoRotationDegree = videoRotationDegree;
67 | }
68 |
69 | /**
70 | * Must be called by View.onMeasure(int, int)
71 | *
72 | * @param widthMeasureSpec
73 | * @param heightMeasureSpec
74 | */
75 | public void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
76 | //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
77 | // + MeasureSpec.toString(heightMeasureSpec) + ")");
78 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
79 | int tempSpec = widthMeasureSpec;
80 | widthMeasureSpec = heightMeasureSpec;
81 | heightMeasureSpec = tempSpec;
82 | }
83 |
84 | int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec);
85 | int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec);
86 | if (mCurrentAspectRatio == IRenderView.AR_MATCH_PARENT) {
87 | width = widthMeasureSpec;
88 | height = heightMeasureSpec;
89 | } else if (mVideoWidth > 0 && mVideoHeight > 0) {
90 | int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
91 | int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
92 | int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
93 | int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
94 |
95 | if (widthSpecMode == View.MeasureSpec.AT_MOST && heightSpecMode == View.MeasureSpec.AT_MOST) {
96 | float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize;
97 | float displayAspectRatio;
98 | switch (mCurrentAspectRatio) {
99 | case IRenderView.AR_16_9_FIT_PARENT:
100 | displayAspectRatio = 16.0f / 9.0f;
101 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
102 | displayAspectRatio = 1.0f / displayAspectRatio;
103 | break;
104 | case IRenderView.AR_4_3_FIT_PARENT:
105 | displayAspectRatio = 4.0f / 3.0f;
106 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
107 | displayAspectRatio = 1.0f / displayAspectRatio;
108 | break;
109 | case IRenderView.AR_ASPECT_FIT_PARENT:
110 | case IRenderView.AR_ASPECT_FILL_PARENT:
111 | case IRenderView.AR_ASPECT_WRAP_CONTENT:
112 | default:
113 | displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;
114 | if (mVideoSarNum > 0 && mVideoSarDen > 0)
115 | displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen;
116 | break;
117 | }
118 | boolean shouldBeWider = displayAspectRatio > specAspectRatio;
119 |
120 | switch (mCurrentAspectRatio) {
121 | case IRenderView.AR_ASPECT_FIT_PARENT:
122 | case IRenderView.AR_16_9_FIT_PARENT:
123 | case IRenderView.AR_4_3_FIT_PARENT:
124 | if (shouldBeWider) {
125 | // too wide, fix width
126 | width = widthSpecSize;
127 | height = (int) (width / displayAspectRatio);
128 | } else {
129 | // too high, fix height
130 | height = heightSpecSize;
131 | width = (int) (height * displayAspectRatio);
132 | }
133 | break;
134 | case IRenderView.AR_ASPECT_FILL_PARENT:
135 | if (shouldBeWider) {
136 | // not high enough, fix height
137 | height = heightSpecSize;
138 | width = (int) (height * displayAspectRatio);
139 | } else {
140 | // not wide enough, fix width
141 | width = widthSpecSize;
142 | height = (int) (width / displayAspectRatio);
143 | }
144 | break;
145 | case IRenderView.AR_ASPECT_WRAP_CONTENT:
146 | default:
147 | if (shouldBeWider) {
148 | // too wide, fix width
149 | width = Math.min(mVideoWidth, widthSpecSize);
150 | height = (int) (width / displayAspectRatio);
151 | } else {
152 | // too high, fix height
153 | height = Math.min(mVideoHeight, heightSpecSize);
154 | width = (int) (height * displayAspectRatio);
155 | }
156 | break;
157 | }
158 | } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) {
159 | // the size is fixed
160 | width = widthSpecSize;
161 | height = heightSpecSize;
162 |
163 | // for compatibility, we adjust size based on aspect ratio
164 | if (mVideoWidth * height < width * mVideoHeight) {
165 | //Log.i("@@@", "image too wide, correcting");
166 | width = height * mVideoWidth / mVideoHeight;
167 | } else if (mVideoWidth * height > width * mVideoHeight) {
168 | //Log.i("@@@", "image too tall, correcting");
169 | height = width * mVideoHeight / mVideoWidth;
170 | }
171 | } else if (widthSpecMode == View.MeasureSpec.EXACTLY) {
172 | // only the width is fixed, adjust the height to match aspect ratio if possible
173 | width = widthSpecSize;
174 | height = width * mVideoHeight / mVideoWidth;
175 | if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
176 | // couldn't match aspect ratio within the constraints
177 | height = heightSpecSize;
178 | }
179 | } else if (heightSpecMode == View.MeasureSpec.EXACTLY) {
180 | // only the height is fixed, adjust the width to match aspect ratio if possible
181 | height = heightSpecSize;
182 | width = height * mVideoWidth / mVideoHeight;
183 | if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
184 | // couldn't match aspect ratio within the constraints
185 | width = widthSpecSize;
186 | }
187 | } else {
188 | // neither the width nor the height are fixed, try to use actual video size
189 | width = mVideoWidth;
190 | height = mVideoHeight;
191 | if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
192 | // too tall, decrease both width and height
193 | height = heightSpecSize;
194 | width = height * mVideoWidth / mVideoHeight;
195 | }
196 | if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
197 | // too wide, decrease both width and height
198 | width = widthSpecSize;
199 | height = width * mVideoHeight / mVideoWidth;
200 | }
201 | }
202 | } else {
203 | // no size yet, just adopt the given spec sizes
204 | }
205 |
206 | mMeasuredWidth = width;
207 | mMeasuredHeight = height;
208 | }
209 |
210 | public int getMeasuredWidth() {
211 | return mMeasuredWidth;
212 | }
213 |
214 | public int getMeasuredHeight() {
215 | return mMeasuredHeight;
216 | }
217 |
218 | public void setAspectRatio(int aspectRatio) {
219 | mCurrentAspectRatio = aspectRatio;
220 | }
221 |
222 | @NonNull
223 | public static String getAspectRatioText(Context context, int aspectRatio) {
224 | String text;
225 | switch (aspectRatio) {
226 | case IRenderView.AR_ASPECT_FIT_PARENT:
227 | text = context.getString(R.string.VideoView_ar_aspect_fit_parent);
228 | break;
229 | case IRenderView.AR_ASPECT_FILL_PARENT:
230 | text = context.getString(R.string.VideoView_ar_aspect_fill_parent);
231 | break;
232 | case IRenderView.AR_ASPECT_WRAP_CONTENT:
233 | text = context.getString(R.string.VideoView_ar_aspect_wrap_content);
234 | break;
235 | case IRenderView.AR_MATCH_PARENT:
236 | text = context.getString(R.string.VideoView_ar_match_parent);
237 | break;
238 | case IRenderView.AR_16_9_FIT_PARENT:
239 | text = context.getString(R.string.VideoView_ar_16_9_fit_parent);
240 | break;
241 | case IRenderView.AR_4_3_FIT_PARENT:
242 | text = context.getString(R.string.VideoView_ar_4_3_fit_parent);
243 | break;
244 | default:
245 | text = context.getString(R.string.N_A);
246 | break;
247 | }
248 | return text;
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/MediaPlayerCompat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import tv.danmaku.ijk.media.player.IMediaPlayer;
21 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
22 | import tv.danmaku.ijk.media.player.MediaPlayerProxy;
23 | import tv.danmaku.ijk.media.player.TextureMediaPlayer;
24 |
25 | public class MediaPlayerCompat {
26 | public static String getName(IMediaPlayer mp) {
27 | if (mp == null) {
28 | return "null";
29 | } else if (mp instanceof TextureMediaPlayer) {
30 | StringBuilder sb = new StringBuilder("TextureMediaPlayer <");
31 | IMediaPlayer internalMediaPlayer = ((TextureMediaPlayer) mp).getInternalMediaPlayer();
32 | if (internalMediaPlayer == null) {
33 | sb.append("null>");
34 | } else {
35 | sb.append(internalMediaPlayer.getClass().getSimpleName());
36 | sb.append(">");
37 | }
38 | return sb.toString();
39 | } else {
40 | return mp.getClass().getSimpleName();
41 | }
42 | }
43 |
44 | public static IjkMediaPlayer getIjkMediaPlayer(IMediaPlayer mp) {
45 | IjkMediaPlayer ijkMediaPlayer = null;
46 | if (mp == null) {
47 | return null;
48 | } if (mp instanceof IjkMediaPlayer) {
49 | ijkMediaPlayer = (IjkMediaPlayer) mp;
50 | } else if (mp instanceof MediaPlayerProxy && ((MediaPlayerProxy) mp).getInternalMediaPlayer() instanceof IjkMediaPlayer) {
51 | ijkMediaPlayer = (IjkMediaPlayer) ((MediaPlayerProxy) mp).getInternalMediaPlayer();
52 | }
53 | return ijkMediaPlayer;
54 | }
55 |
56 | public static void selectTrack(IMediaPlayer mp, int stream) {
57 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
58 | if (ijkMediaPlayer == null)
59 | return;
60 | ijkMediaPlayer.selectTrack(stream);
61 | }
62 |
63 | public static void deselectTrack(IMediaPlayer mp, int stream) {
64 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
65 | if (ijkMediaPlayer == null)
66 | return;
67 | ijkMediaPlayer.deselectTrack(stream);
68 | }
69 |
70 | public static int getSelectedTrack(IMediaPlayer mp, int trackType) {
71 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
72 | if (ijkMediaPlayer == null)
73 | return -1;
74 | return ijkMediaPlayer.getSelectedTrack(trackType);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/SurfaceRenderView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import android.annotation.TargetApi;
21 | import android.content.Context;
22 | import android.graphics.SurfaceTexture;
23 | import android.os.Build;
24 | import android.support.annotation.NonNull;
25 | import android.support.annotation.Nullable;
26 | import android.util.AttributeSet;
27 | import android.util.Log;
28 | import android.view.Surface;
29 | import android.view.SurfaceHolder;
30 | import android.view.SurfaceView;
31 | import android.view.View;
32 | import android.view.accessibility.AccessibilityEvent;
33 | import android.view.accessibility.AccessibilityNodeInfo;
34 |
35 | import java.lang.ref.WeakReference;
36 | import java.util.Map;
37 | import java.util.concurrent.ConcurrentHashMap;
38 |
39 | import tv.danmaku.ijk.media.player.IMediaPlayer;
40 | import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
41 |
42 | public class SurfaceRenderView extends SurfaceView implements IRenderView {
43 | private MeasureHelper mMeasureHelper;
44 |
45 | public SurfaceRenderView(Context context) {
46 | super(context);
47 | initView(context);
48 | }
49 |
50 | public SurfaceRenderView(Context context, AttributeSet attrs) {
51 | super(context, attrs);
52 | initView(context);
53 | }
54 |
55 | public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
56 | super(context, attrs, defStyleAttr);
57 | initView(context);
58 | }
59 |
60 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
61 | public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
62 | super(context, attrs, defStyleAttr, defStyleRes);
63 | initView(context);
64 | }
65 |
66 | private void initView(Context context) {
67 | mMeasureHelper = new MeasureHelper(this);
68 | mSurfaceCallback = new SurfaceCallback(this);
69 | getHolder().addCallback(mSurfaceCallback);
70 | //noinspection deprecation
71 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
72 | }
73 |
74 | @Override
75 | public View getView() {
76 | return this;
77 | }
78 |
79 | @Override
80 | public boolean shouldWaitForResize() {
81 | return true;
82 | }
83 |
84 | //--------------------
85 | // Layout & Measure
86 | //--------------------
87 | @Override
88 | public void setVideoSize(int videoWidth, int videoHeight) {
89 | if (videoWidth > 0 && videoHeight > 0) {
90 | mMeasureHelper.setVideoSize(videoWidth, videoHeight);
91 | getHolder().setFixedSize(videoWidth, videoHeight);
92 | requestLayout();
93 | }
94 | }
95 |
96 | @Override
97 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
98 | if (videoSarNum > 0 && videoSarDen > 0) {
99 | mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
100 | requestLayout();
101 | }
102 | }
103 |
104 | @Override
105 | public void setVideoRotation(int degree) {
106 | Log.e("", "SurfaceView doesn't support rotation (" + degree + ")!\n");
107 | }
108 |
109 | @Override
110 | public void setAspectRatio(int aspectRatio) {
111 | mMeasureHelper.setAspectRatio(aspectRatio);
112 | requestLayout();
113 | }
114 |
115 | @Override
116 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
117 | mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
118 | setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
119 | }
120 |
121 | //--------------------
122 | // SurfaceViewHolder
123 | //--------------------
124 |
125 | private static final class InternalSurfaceHolder implements IRenderView.ISurfaceHolder {
126 | private SurfaceRenderView mSurfaceView;
127 | private SurfaceHolder mSurfaceHolder;
128 |
129 | public InternalSurfaceHolder(@NonNull SurfaceRenderView surfaceView,
130 | @Nullable SurfaceHolder surfaceHolder) {
131 | mSurfaceView = surfaceView;
132 | mSurfaceHolder = surfaceHolder;
133 | }
134 |
135 | public void bindToMediaPlayer(IMediaPlayer mp) {
136 | if (mp != null) {
137 | if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
138 | (mp instanceof ISurfaceTextureHolder)) {
139 | ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
140 | textureHolder.setSurfaceTexture(null);
141 | }
142 | mp.setDisplay(mSurfaceHolder);
143 | }
144 | }
145 |
146 | @NonNull
147 | @Override
148 | public IRenderView getRenderView() {
149 | return mSurfaceView;
150 | }
151 |
152 | @Nullable
153 | @Override
154 | public SurfaceHolder getSurfaceHolder() {
155 | return mSurfaceHolder;
156 | }
157 |
158 | @Nullable
159 | @Override
160 | public SurfaceTexture getSurfaceTexture() {
161 | return null;
162 | }
163 |
164 | @Nullable
165 | @Override
166 | public Surface openSurface() {
167 | if (mSurfaceHolder == null)
168 | return null;
169 | return mSurfaceHolder.getSurface();
170 | }
171 | }
172 |
173 | //-------------------------
174 | // SurfaceHolder.Callback
175 | //-------------------------
176 |
177 | @Override
178 | public void addRenderCallback(IRenderCallback callback) {
179 | mSurfaceCallback.addRenderCallback(callback);
180 | }
181 |
182 | @Override
183 | public void removeRenderCallback(IRenderCallback callback) {
184 | mSurfaceCallback.removeRenderCallback(callback);
185 | }
186 |
187 | private SurfaceCallback mSurfaceCallback;
188 |
189 | private static final class SurfaceCallback implements SurfaceHolder.Callback {
190 | private SurfaceHolder mSurfaceHolder;
191 | private boolean mIsFormatChanged;
192 | private int mFormat;
193 | private int mWidth;
194 | private int mHeight;
195 |
196 | private WeakReference mWeakSurfaceView;
197 | private Map mRenderCallbackMap = new ConcurrentHashMap();
198 |
199 | public SurfaceCallback(@NonNull SurfaceRenderView surfaceView) {
200 | mWeakSurfaceView = new WeakReference(surfaceView);
201 | }
202 |
203 | public void addRenderCallback(@NonNull IRenderCallback callback) {
204 | mRenderCallbackMap.put(callback, callback);
205 |
206 | ISurfaceHolder surfaceHolder = null;
207 | if (mSurfaceHolder != null) {
208 | if (surfaceHolder == null)
209 | surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
210 | callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
211 | }
212 |
213 | if (mIsFormatChanged) {
214 | if (surfaceHolder == null)
215 | surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
216 | callback.onSurfaceChanged(surfaceHolder, mFormat, mWidth, mHeight);
217 | }
218 | }
219 |
220 | public void removeRenderCallback(@NonNull IRenderCallback callback) {
221 | mRenderCallbackMap.remove(callback);
222 | }
223 |
224 | @Override
225 | public void surfaceCreated(SurfaceHolder holder) {
226 | mSurfaceHolder = holder;
227 | mIsFormatChanged = false;
228 | mFormat = 0;
229 | mWidth = 0;
230 | mHeight = 0;
231 |
232 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
233 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
234 | renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
235 | }
236 | }
237 |
238 | @Override
239 | public void surfaceDestroyed(SurfaceHolder holder) {
240 | mSurfaceHolder = null;
241 | mIsFormatChanged = false;
242 | mFormat = 0;
243 | mWidth = 0;
244 | mHeight = 0;
245 |
246 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
247 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
248 | renderCallback.onSurfaceDestroyed(surfaceHolder);
249 | }
250 | }
251 |
252 | @Override
253 | public void surfaceChanged(SurfaceHolder holder, int format,
254 | int width, int height) {
255 | mSurfaceHolder = holder;
256 | mIsFormatChanged = true;
257 | mFormat = format;
258 | mWidth = width;
259 | mHeight = height;
260 |
261 | // mMeasureHelper.setVideoSize(width, height);
262 |
263 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder);
264 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
265 | renderCallback.onSurfaceChanged(surfaceHolder, format, width, height);
266 | }
267 | }
268 | }
269 |
270 | //--------------------
271 | // Accessibility
272 | //--------------------
273 |
274 | @Override
275 | public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
276 | super.onInitializeAccessibilityEvent(event);
277 | event.setClassName(SurfaceRenderView.class.getName());
278 | }
279 |
280 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
281 | @Override
282 | public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
283 | super.onInitializeAccessibilityNodeInfo(info);
284 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
285 | info.setClassName(SurfaceRenderView.class.getName());
286 | }
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/TableLayoutBinder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import android.content.Context;
21 | import android.app.AlertDialog;
22 | import android.view.LayoutInflater;
23 | import android.view.View;
24 | import android.view.ViewGroup;
25 | import android.widget.TableLayout;
26 | import android.widget.TextView;
27 |
28 | import com.afap.ijkplayer.R;
29 |
30 | public class TableLayoutBinder {
31 | private Context mContext;
32 | public ViewGroup mTableView;
33 | public TableLayout mTableLayout;
34 |
35 | public TableLayoutBinder(Context context) {
36 | this(context, R.layout.table_media_info);
37 | }
38 |
39 | public TableLayoutBinder(Context context, int layoutResourceId) {
40 | mContext = context;
41 | mTableView = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutResourceId, null);
42 | mTableLayout = (TableLayout) mTableView.findViewById(R.id.table);
43 | }
44 |
45 | public TableLayoutBinder(Context context, TableLayout tableLayout) {
46 | mContext = context;
47 | mTableView = tableLayout;
48 | mTableLayout = tableLayout;
49 | }
50 |
51 | public View appendRow1(String name, String value) {
52 | return appendRow(R.layout.table_media_info_row1, name, value);
53 | }
54 |
55 | public View appendRow1(int nameId, String value) {
56 | return appendRow1(mContext.getString(nameId), value);
57 | }
58 |
59 | public View appendRow2(String name, String value) {
60 | return appendRow(R.layout.table_media_info_row2, name, value);
61 | }
62 |
63 | public View appendRow2(int nameId, String value) {
64 | return appendRow2(mContext.getString(nameId), value);
65 | }
66 |
67 | public View appendSection(String name) {
68 | return appendRow(R.layout.table_media_info_section, name, null);
69 | }
70 |
71 | public View appendSection(int nameId) {
72 | return appendSection(mContext.getString(nameId));
73 | }
74 |
75 | public View appendRow(int layoutId, String name, String value) {
76 | ViewGroup rowView = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutId, mTableLayout, false);
77 | setNameValueText(rowView, name, value);
78 |
79 | mTableLayout.addView(rowView);
80 | return rowView;
81 | }
82 |
83 | public ViewHolder obtainViewHolder(View rowView) {
84 | ViewHolder viewHolder = (ViewHolder) rowView.getTag();
85 | if (viewHolder == null) {
86 | viewHolder = new ViewHolder();
87 | viewHolder.mNameTextView = (TextView) rowView.findViewById(R.id.name);
88 | viewHolder.mValueTextView = (TextView) rowView.findViewById(R.id.value);
89 | rowView.setTag(viewHolder);
90 | }
91 | return viewHolder;
92 | }
93 |
94 | public void setNameValueText(View rowView, String name, String value) {
95 | ViewHolder viewHolder = obtainViewHolder(rowView);
96 | viewHolder.setName(name);
97 | viewHolder.setValue(value);
98 | }
99 |
100 | public void setValueText(View rowView, String value) {
101 | ViewHolder viewHolder = obtainViewHolder(rowView);
102 | viewHolder.setValue(value);
103 | }
104 |
105 | public ViewGroup buildLayout() {
106 | return mTableView;
107 | }
108 |
109 | public AlertDialog.Builder buildAlertDialogBuilder() {
110 | AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(mContext);
111 | dlgBuilder.setView(buildLayout());
112 | return dlgBuilder;
113 | }
114 |
115 | private static class ViewHolder {
116 | public TextView mNameTextView;
117 | public TextView mValueTextView;
118 |
119 | public void setName(String name) {
120 | if (mNameTextView != null) {
121 | mNameTextView.setText(name);
122 | }
123 | }
124 |
125 | public void setValue(String value) {
126 | if (mValueTextView != null) {
127 | mValueTextView.setText(value);
128 | }
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/java/player/widget/media/TextureRenderView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package player.widget.media;
19 |
20 | import android.annotation.TargetApi;
21 | import android.content.Context;
22 | import android.graphics.SurfaceTexture;
23 | import android.os.Build;
24 | import android.support.annotation.NonNull;
25 | import android.support.annotation.Nullable;
26 | import android.util.AttributeSet;
27 | import android.util.Log;
28 | import android.view.Surface;
29 | import android.view.SurfaceHolder;
30 | import android.view.TextureView;
31 | import android.view.View;
32 | import android.view.accessibility.AccessibilityEvent;
33 | import android.view.accessibility.AccessibilityNodeInfo;
34 |
35 | import java.lang.ref.WeakReference;
36 | import java.util.Map;
37 | import java.util.concurrent.ConcurrentHashMap;
38 |
39 | import tv.danmaku.ijk.media.player.IMediaPlayer;
40 | import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
41 | import tv.danmaku.ijk.media.player.ISurfaceTextureHost;
42 |
43 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
44 | public class TextureRenderView extends TextureView implements IRenderView {
45 | private static final String TAG = "TextureRenderView";
46 | private MeasureHelper mMeasureHelper;
47 |
48 | public TextureRenderView(Context context) {
49 | super(context);
50 | initView(context);
51 | }
52 |
53 | public TextureRenderView(Context context, AttributeSet attrs) {
54 | super(context, attrs);
55 | initView(context);
56 | }
57 |
58 | public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
59 | super(context, attrs, defStyleAttr);
60 | initView(context);
61 | }
62 |
63 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
64 | public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
65 | super(context, attrs, defStyleAttr, defStyleRes);
66 | initView(context);
67 | }
68 |
69 | private void initView(Context context) {
70 | mMeasureHelper = new MeasureHelper(this);
71 | mSurfaceCallback = new SurfaceCallback(this);
72 | setSurfaceTextureListener(mSurfaceCallback);
73 | }
74 |
75 | @Override
76 | public View getView() {
77 | return this;
78 | }
79 |
80 | @Override
81 | public boolean shouldWaitForResize() {
82 | return false;
83 | }
84 |
85 | @Override
86 | protected void onDetachedFromWindow() {
87 | mSurfaceCallback.willDetachFromWindow();
88 | super.onDetachedFromWindow();
89 | mSurfaceCallback.didDetachFromWindow();
90 | }
91 |
92 | //--------------------
93 | // Layout & Measure
94 | //--------------------
95 | @Override
96 | public void setVideoSize(int videoWidth, int videoHeight) {
97 | if (videoWidth > 0 && videoHeight > 0) {
98 | mMeasureHelper.setVideoSize(videoWidth, videoHeight);
99 | requestLayout();
100 | }
101 | }
102 |
103 | @Override
104 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
105 | if (videoSarNum > 0 && videoSarDen > 0) {
106 | mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
107 | requestLayout();
108 | }
109 | }
110 |
111 | @Override
112 | public void setVideoRotation(int degree) {
113 | mMeasureHelper.setVideoRotation(degree);
114 | setRotation(degree);
115 | }
116 |
117 | @Override
118 | public void setAspectRatio(int aspectRatio) {
119 | mMeasureHelper.setAspectRatio(aspectRatio);
120 | requestLayout();
121 | }
122 |
123 | @Override
124 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
125 | mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
126 | setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
127 | }
128 |
129 | //--------------------
130 | // TextureViewHolder
131 | //--------------------
132 |
133 | public IRenderView.ISurfaceHolder getSurfaceHolder() {
134 | return new InternalSurfaceHolder(this, mSurfaceCallback.mSurfaceTexture, mSurfaceCallback);
135 | }
136 |
137 | private static final class InternalSurfaceHolder implements IRenderView.ISurfaceHolder {
138 | private TextureRenderView mTextureView;
139 | private SurfaceTexture mSurfaceTexture;
140 | private ISurfaceTextureHost mSurfaceTextureHost;
141 |
142 | public InternalSurfaceHolder(@NonNull TextureRenderView textureView,
143 | @Nullable SurfaceTexture surfaceTexture,
144 | @NonNull ISurfaceTextureHost surfaceTextureHost) {
145 | mTextureView = textureView;
146 | mSurfaceTexture = surfaceTexture;
147 | mSurfaceTextureHost = surfaceTextureHost;
148 | }
149 |
150 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
151 | public void bindToMediaPlayer(IMediaPlayer mp) {
152 | if (mp == null)
153 | return;
154 |
155 | if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
156 | (mp instanceof ISurfaceTextureHolder)) {
157 | ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
158 | mTextureView.mSurfaceCallback.setOwnSurfaceTexture(false);
159 |
160 | SurfaceTexture surfaceTexture = textureHolder.getSurfaceTexture();
161 | if (surfaceTexture != null) {
162 | mTextureView.setSurfaceTexture(surfaceTexture);
163 | } else {
164 | textureHolder.setSurfaceTexture(mSurfaceTexture);
165 | textureHolder.setSurfaceTextureHost(mTextureView.mSurfaceCallback);
166 | }
167 | } else {
168 | mp.setSurface(openSurface());
169 | }
170 | }
171 |
172 | @NonNull
173 | @Override
174 | public IRenderView getRenderView() {
175 | return mTextureView;
176 | }
177 |
178 | @Nullable
179 | @Override
180 | public SurfaceHolder getSurfaceHolder() {
181 | return null;
182 | }
183 |
184 | @Nullable
185 | @Override
186 | public SurfaceTexture getSurfaceTexture() {
187 | return mSurfaceTexture;
188 | }
189 |
190 | @Nullable
191 | @Override
192 | public Surface openSurface() {
193 | if (mSurfaceTexture == null)
194 | return null;
195 | return new Surface(mSurfaceTexture);
196 | }
197 | }
198 |
199 | //-------------------------
200 | // SurfaceHolder.Callback
201 | //-------------------------
202 |
203 | @Override
204 | public void addRenderCallback(IRenderCallback callback) {
205 | mSurfaceCallback.addRenderCallback(callback);
206 | }
207 |
208 | @Override
209 | public void removeRenderCallback(IRenderCallback callback) {
210 | mSurfaceCallback.removeRenderCallback(callback);
211 | }
212 |
213 | private SurfaceCallback mSurfaceCallback;
214 |
215 | private static final class SurfaceCallback implements TextureView.SurfaceTextureListener, ISurfaceTextureHost {
216 | private SurfaceTexture mSurfaceTexture;
217 | private boolean mIsFormatChanged;
218 | private int mWidth;
219 | private int mHeight;
220 |
221 | private boolean mOwnSurfaceTexture = true;
222 | private boolean mWillDetachFromWindow = false;
223 | private boolean mDidDetachFromWindow = false;
224 |
225 | private WeakReference mWeakRenderView;
226 | private Map mRenderCallbackMap = new ConcurrentHashMap();
227 |
228 | public SurfaceCallback(@NonNull TextureRenderView renderView) {
229 | mWeakRenderView = new WeakReference(renderView);
230 | }
231 |
232 | public void setOwnSurfaceTexture(boolean ownSurfaceTexture) {
233 | mOwnSurfaceTexture = ownSurfaceTexture;
234 | }
235 |
236 | public void addRenderCallback(@NonNull IRenderCallback callback) {
237 | mRenderCallbackMap.put(callback, callback);
238 |
239 | ISurfaceHolder surfaceHolder = null;
240 | if (mSurfaceTexture != null) {
241 | if (surfaceHolder == null)
242 | surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
243 | callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
244 | }
245 |
246 | if (mIsFormatChanged) {
247 | if (surfaceHolder == null)
248 | surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
249 | callback.onSurfaceChanged(surfaceHolder, 0, mWidth, mHeight);
250 | }
251 | }
252 |
253 | public void removeRenderCallback(@NonNull IRenderCallback callback) {
254 | mRenderCallbackMap.remove(callback);
255 | }
256 |
257 | @Override
258 | public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
259 | mSurfaceTexture = surface;
260 | mIsFormatChanged = false;
261 | mWidth = 0;
262 | mHeight = 0;
263 |
264 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
265 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
266 | renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
267 | }
268 | }
269 |
270 | @Override
271 | public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
272 | mSurfaceTexture = surface;
273 | mIsFormatChanged = true;
274 | mWidth = width;
275 | mHeight = height;
276 |
277 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
278 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
279 | renderCallback.onSurfaceChanged(surfaceHolder, 0, width, height);
280 | }
281 | }
282 |
283 | @Override
284 | public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
285 | mSurfaceTexture = surface;
286 | mIsFormatChanged = false;
287 | mWidth = 0;
288 | mHeight = 0;
289 |
290 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
291 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
292 | renderCallback.onSurfaceDestroyed(surfaceHolder);
293 | }
294 |
295 | Log.d(TAG, "onSurfaceTextureDestroyed: destroy: " + mOwnSurfaceTexture);
296 | return mOwnSurfaceTexture;
297 | }
298 |
299 | @Override
300 | public void onSurfaceTextureUpdated(SurfaceTexture surface) {
301 | }
302 |
303 | //-------------------------
304 | // ISurfaceTextureHost
305 | //-------------------------
306 |
307 | @Override
308 | public void releaseSurfaceTexture(SurfaceTexture surfaceTexture) {
309 | if (surfaceTexture == null) {
310 | Log.d(TAG, "releaseSurfaceTexture: null");
311 | } else if (mDidDetachFromWindow) {
312 | if (surfaceTexture != mSurfaceTexture) {
313 | Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release different SurfaceTexture");
314 | surfaceTexture.release();
315 | } else if (!mOwnSurfaceTexture) {
316 | Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release detached SurfaceTexture");
317 | surfaceTexture.release();
318 | } else {
319 | Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): already released by TextureView");
320 | }
321 | } else if (mWillDetachFromWindow) {
322 | if (surfaceTexture != mSurfaceTexture) {
323 | Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): release different SurfaceTexture");
324 | surfaceTexture.release();
325 | } else if (!mOwnSurfaceTexture) {
326 | Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): re-attach SurfaceTexture to TextureView");
327 | setOwnSurfaceTexture(true);
328 | } else {
329 | Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): will released by TextureView");
330 | }
331 | } else {
332 | if (surfaceTexture != mSurfaceTexture) {
333 | Log.d(TAG, "releaseSurfaceTexture: alive: release different SurfaceTexture");
334 | surfaceTexture.release();
335 | } else if (!mOwnSurfaceTexture) {
336 | Log.d(TAG, "releaseSurfaceTexture: alive: re-attach SurfaceTexture to TextureView");
337 | setOwnSurfaceTexture(true);
338 | } else {
339 | Log.d(TAG, "releaseSurfaceTexture: alive: will released by TextureView");
340 | }
341 | }
342 | }
343 |
344 | public void willDetachFromWindow() {
345 | Log.d(TAG, "willDetachFromWindow()");
346 | mWillDetachFromWindow = true;
347 | }
348 |
349 | public void didDetachFromWindow() {
350 | Log.d(TAG, "didDetachFromWindow()");
351 | mDidDetachFromWindow = true;
352 | }
353 | }
354 |
355 | //--------------------
356 | // Accessibility
357 | //--------------------
358 |
359 | @Override
360 | public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
361 | super.onInitializeAccessibilityEvent(event);
362 | event.setClassName(TextureRenderView.class.getName());
363 | }
364 |
365 | @Override
366 | public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
367 | super.onInitializeAccessibilityNodeInfo(info);
368 | info.setClassName(TextureRenderView.class.getName());
369 | }
370 | }
371 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/arm64-v8a/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/arm64-v8a/libijkffmpeg.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/arm64-v8a/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/arm64-v8a/libijkplayer.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/arm64-v8a/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/arm64-v8a/libijksdl.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/armeabi-v7a/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/armeabi-v7a/libijkffmpeg.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/armeabi-v7a/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/armeabi-v7a/libijkplayer.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/armeabi-v7a/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/armeabi-v7a/libijksdl.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/x86/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/x86/libijkffmpeg.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/x86/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/x86/libijkplayer.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/x86/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/x86/libijksdl.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/x86_64/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/x86_64/libijkffmpeg.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/x86_64/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/x86_64/libijkplayer.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/jniLibs/x86_64/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/jniLibs/x86_64/libijksdl.so
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-hdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-hdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xhdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xhdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxhdpi/play_ctrl_sound_ball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxhdpi/play_ctrl_sound_ball.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_brightness_6_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_brightness_6_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_chevron_left_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_chevron_left_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_fullscreen_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_play_circle_outline_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_play_circle_outline_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_stop_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_stop_white_24dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_volume_off_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_volume_off_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable-xxxhdpi/ic_volume_up_white_36dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AFAP/Player/fc85003892c2a3521e08acc5b39a6e321c413404/ijkplayer/src/main/res/drawable-xxxhdpi/ic_volume_up_white_36dp.png
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable/app_video_center_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/drawable/play_seekbar_color_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/layout/activity_play_video.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
24 |
30 |
31 |
38 |
39 |
46 |
47 |
48 |
55 |
56 |
63 |
64 |
70 |
71 |
78 |
79 |
80 |
87 |
88 |
94 |
95 |
104 |
105 |
106 |
114 |
115 |
124 |
125 |
130 |
131 |
138 |
139 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
160 |
161 |
162 |
163 |
171 |
172 |
180 |
181 |
192 |
193 |
209 |
210 |
220 |
221 |
230 |
231 |
232 |
233 |
234 |
235 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/layout/fragment_track_list.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/layout/table_media_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/layout/table_media_info_row1.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
20 |
21 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/layout/table_media_info_row2.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/layout/table_media_info_section.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #FAFAFA
5 | #F5F5F5
6 | #EEEEEE
7 | #E0E0E0
8 | #BDBDBD
9 | #9E9E9E
10 | #757575
11 | #616161
12 | #424242
13 | #212121
14 |
15 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ijkmediademo
5 |
6 | N/A
7 | Close
8 | Exit
9 | Sample
10 | Recent
11 | Settings
12 | Tracks
13 | Player
14 | Render
15 | Scale
16 | Info
17 | vdec
18 | fps
19 | v-cache
20 | a-cache
21 | load-cost
22 | seek_cost
23 | seek_load_cost
24 | tcp_speed
25 | bit_rate
26 |
27 | Media Information
28 | Player
29 | Media
30 | Profile level
31 | Pixel format
32 | Resolution
33 | Length
34 | Stream #%d
35 | Type
36 | Language
37 | Codec
38 | Frame rate
39 | Bit rate
40 | Sample rate
41 | Channels
42 | *
43 | *
44 | *
45 |
46 | Video
47 | Audio
48 | Subtitle
49 | Timed text
50 | Meta data
51 | Unknown
52 |
53 | Invalid progressive playback
54 | Unknown
55 | OK
56 |
57 | Aspect / Fit parent
58 | Aspect / Fill parent
59 | Aspect / Wrap content
60 | Free / Fill parent
61 | 16:9 / Fit parent
62 | 4:3 / Fit parent
63 |
64 | Render: None
65 | Render: SurfaceView
66 | Render: TextureView
67 |
68 | Player: None
69 | Player: AndroidMediaPlayer
70 | Player: IjkMediaPlayer
71 | Player: IjkExoMediaPlayer
72 |
73 |
74 |
--------------------------------------------------------------------------------
/ijkplayer/src/main/res/values/strings_pref.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | General
5 |
6 | pref.enable_background_play
7 | Enable background play
8 | need Android 4.0+
9 |
10 | pref.using_android_player
11 | Using system player
12 |
13 |
14 | pref.player
15 | Choose Player
16 |
17 | - Auto Select
18 | - AndroidMediaPlayer
19 | - IjkMediaPlayer
20 | - IjkExoMediaPlayer
21 |
22 |
23 | - 0
24 | - 1
25 | - 2
26 | - 3
27 |
28 |
29 | - Auto Select
30 | - AndroidMediaPlayer
31 | - IjkMediaPlayer
32 | - IjkExoMediaPlayer
33 |
34 |
35 |
36 | Video: ijkplayer
37 |
38 | pref.using_media_codec
39 | Using MediaCodec
40 |
41 |
42 | pref.using_media_codec_auto_rotate
43 | Using MediaCodec auto rotate
44 |
45 |
46 | pref.media_codec_handle_resolution_change
47 | MediaCodec handle resolution change
48 |
49 |
50 | pref.pixel_format
51 | Pixel Format
52 |
53 | - Auto Select
54 | - RGB 565
55 | - RGB 888
56 | - RGBX 8888
57 | - YV12
58 | - OpenGL ES2
59 |
60 |
61 |
62 | - fcc-rv16
63 | - fcc-rv24
64 | - fcc-rv32
65 | - fcc-yv12
66 | - fcc-_es2
67 |
68 |
69 | - Auto Select
70 | - RGB 565
71 | - RGB 888
72 | - RGBX 8888
73 | - YV12
74 | - OpenGL ES2
75 |
76 |
77 |
78 | Audio: ijkplayer
79 |
80 | pref.using_opensl_es
81 | Using OpenSL ES
82 |
83 |
84 |
85 | RenderView
86 |
87 | pref.enable_no_view
88 | Enable NoView
89 |
90 |
91 | pref.enable_surface_view
92 | Enable SurfaceView
93 |
94 |
95 | pref.enable_texture_view
96 | Enable TextureView
97 |
98 |
99 | pref.enable_detached_surface_texture
100 | Enable detached SurfaceTexture
101 |
102 |
103 |
104 | Misc
105 | pref.using_mediadatasource
106 | Using MediaDataSource
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':bdplayer', ':ijkplayer'
2 |
--------------------------------------------------------------------------------