├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── lodz
│ │ └── android
│ │ └── mmsplayerdemo
│ │ ├── App.kt
│ │ ├── MainActivity.kt
│ │ ├── config
│ │ └── Constant.kt
│ │ ├── simple
│ │ └── SimpleVideoActivity.kt
│ │ ├── video
│ │ ├── assist
│ │ │ ├── VideoAdjustProgressLayout.kt
│ │ │ ├── VideoBrightnessLayout.kt
│ │ │ └── VideoVolumeLayout.kt
│ │ ├── dialog
│ │ │ └── VideoSettingDialog.kt
│ │ ├── menu
│ │ │ ├── SlideControlLayout.kt
│ │ │ ├── VideoBottomMenuLayout.kt
│ │ │ └── VideoTopMenuLayout.kt
│ │ ├── status
│ │ │ ├── VideoErrorLayout.kt
│ │ │ ├── VideoLoadingAdapter.kt
│ │ │ ├── VideoLoadingLayout.kt
│ │ │ └── VideoPhoneDataLayout.kt
│ │ └── view
│ │ │ └── MediaView.kt
│ │ └── widget
│ │ ├── CommentAdapter.kt
│ │ ├── CommentFragment.kt
│ │ ├── InfoFragment.kt
│ │ └── VideoActivity.kt
│ └── res
│ ├── anim
│ ├── anim_bottom_in.xml
│ ├── anim_bottom_out.xml
│ ├── anim_center_in.xml
│ ├── anim_center_out.xml
│ ├── anim_fade_in.xml
│ ├── anim_fade_out.xml
│ ├── anim_left_in.xml
│ ├── anim_left_out.xml
│ ├── anim_right_in.xml
│ ├── anim_right_out.xml
│ ├── anim_top_in.xml
│ └── anim_top_out.xml
│ ├── drawable-xhdpi
│ ├── ic_battery_1.png
│ ├── ic_battery_10.png
│ ├── ic_battery_2.png
│ ├── ic_battery_3.png
│ ├── ic_battery_4.png
│ ├── ic_battery_5.png
│ ├── ic_battery_6.png
│ ├── ic_battery_7.png
│ ├── ic_battery_8.png
│ ├── ic_battery_9.png
│ ├── ic_progress_video_loading_1.png
│ ├── ic_progress_video_loading_2.png
│ ├── ic_progress_video_loading_3.png
│ ├── ic_seek_thumb.png
│ ├── ic_video_brightness.png
│ ├── ic_video_error.png
│ ├── ic_video_pause.png
│ ├── ic_video_pause_sel.png
│ ├── ic_video_play.png
│ ├── ic_video_play_sel.png
│ ├── ic_video_screen.png
│ ├── ic_video_screen_sel.png
│ ├── ic_video_setting.png
│ ├── ic_video_setting_sel.png
│ └── ic_video_volume.png
│ ├── drawable
│ ├── bg_00000000_corners_5_stroke_008577.xml
│ ├── bg_4c4c4c_corners_8.xml
│ ├── bg_a0191919_corners_5.xml
│ ├── bg_a04c4c4c_corners_8.xml
│ ├── ic_launcher_background.xml
│ ├── progress_video_loading_animation.xml
│ ├── seekbar_color_style.xml
│ ├── selector_bg_dialog_setting_item.xml
│ ├── selector_bg_video_btn.xml
│ ├── selector_text_dialog_setting_item.xml
│ ├── selector_video_pause.xml
│ ├── selector_video_play.xml
│ ├── selector_video_screen.xml
│ └── selector_video_setting.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── activity_simple_video.xml
│ ├── activity_video.xml
│ ├── dialog_video_setting.xml
│ ├── fragment_comment.xml
│ ├── fragment_info.xml
│ ├── rv_item_comment.xml
│ ├── rv_item_video_loading_tips.xml
│ ├── view_media.xml
│ ├── view_video_adjust_progress.xml
│ ├── view_video_bottom_menu.xml
│ ├── view_video_brightness.xml
│ ├── view_video_error.xml
│ ├── view_video_loading.xml
│ ├── view_video_phone_data.xml
│ ├── view_video_top_menu.xml
│ └── view_video_volume.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── 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
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── img
├── 1_loading.png
├── 2_comment.png
├── 3_brightness_gesture.png
├── 4_volume_gesture.png
├── 5_progress_gesture.png
└── 6_full_screen.png
├── mmsplayer
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── publish.gradle
├── readme_mmsplayer_update.md
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ ├── com
│ │ └── lodz
│ │ │ └── android
│ │ │ └── mmsplayer
│ │ │ ├── contract
│ │ │ └── IVideoPlayer.java
│ │ │ ├── ijk
│ │ │ ├── bean
│ │ │ │ ├── MediaInfoBean.java
│ │ │ │ ├── TrackAudioInfoBean.java
│ │ │ │ └── TrackVideoInfoBean.java
│ │ │ ├── media
│ │ │ │ ├── AndroidMediaController.java
│ │ │ │ ├── FileMediaDataSource.java
│ │ │ │ ├── IMediaController.java
│ │ │ │ ├── IRenderView.java
│ │ │ │ ├── IjkVideoView.java
│ │ │ │ ├── InfoHudViewHolder.java
│ │ │ │ ├── MeasureHelper.java
│ │ │ │ ├── MediaPlayerCompat.java
│ │ │ │ ├── SurfaceRenderView.java
│ │ │ │ └── TextureRenderView.java
│ │ │ ├── services
│ │ │ │ └── MediaPlayerService.java
│ │ │ ├── setting
│ │ │ │ └── IjkPlayerSetting.java
│ │ │ └── utils
│ │ │ │ └── MediaInfoUtils.java
│ │ │ └── impl
│ │ │ └── MmsVideoView.java
│ └── tv
│ │ └── danmaku
│ │ └── ijk
│ │ └── media
│ │ └── player
│ │ ├── AbstractMediaPlayer.java
│ │ ├── AndroidMediaPlayer.java
│ │ ├── IMediaPlayer.java
│ │ ├── ISurfaceTextureHolder.java
│ │ ├── ISurfaceTextureHost.java
│ │ ├── IjkLibLoader.java
│ │ ├── IjkMediaCodecInfo.java
│ │ ├── IjkMediaMeta.java
│ │ ├── IjkMediaPlayer.java
│ │ ├── IjkTimedText.java
│ │ ├── MediaInfo.java
│ │ ├── MediaPlayerProxy.java
│ │ ├── TextureMediaPlayer.java
│ │ ├── annotations
│ │ ├── AccessedByNative.java
│ │ └── CalledByNative.java
│ │ ├── exceptions
│ │ └── IjkMediaException.java
│ │ ├── ffmpeg
│ │ └── FFmpegApi.java
│ │ ├── misc
│ │ ├── AndroidMediaFormat.java
│ │ ├── AndroidTrackInfo.java
│ │ ├── IAndroidIO.java
│ │ ├── IMediaDataSource.java
│ │ ├── IMediaFormat.java
│ │ ├── ITrackInfo.java
│ │ ├── IjkMediaFormat.java
│ │ └── IjkTrackInfo.java
│ │ └── pragma
│ │ ├── DebugLog.java
│ │ └── Pragma.java
│ ├── jniLibs
│ ├── arm64-v8a
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ ├── armeabi-v7a
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ ├── armeabi
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ ├── x86
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ └── x86_64
│ │ ├── libijkffmpeg.so
│ │ ├── libijkplayer.so
│ │ └── libijksdl.so
│ └── res
│ └── values
│ └── strings.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches/build_file_checksums.ser
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | .DS_Store
9 | /build
10 | /captures
11 | .externalNativeBuild
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MMSPlayer播放器
2 | 基于 [IJK播放器](https://github.com/Bilibili/ijkplayer) 封装的播放器依赖库,核心播放控件使用IJKPlayer,我通过接口封装来解耦,方便调用和替换。
3 | 大家可以在基础播放器上自定义菜单页面等等,详细demo可以git工程查看或者直接进入 [VideoActivity.kt](https://github.com/LZ9/MMSPlayer/blob/master/app/src/main/java/com/lodz/android/mmsplayerdemo/widget/VideoActivity.kt) 查看。
4 |
5 | ## 目录
6 | - [1、添加Gradle依赖](https://github.com/LZ9/MMSPlayer#1添加gradle依赖)
7 | - [2、使用方法](https://github.com/LZ9/MMSPlayer#2使用方法)
8 | - [3、测试Demo(Kotlin编写)](https://github.com/LZ9/MMSPlayer#3测试demokotlin编写)
9 | - [扩展](https://github.com/LZ9/MMSPlayer#扩展)
10 |
11 | ## 1、添加Gradle依赖
12 | 由于jcenter删库跑路,请大家添加mavenCentral依赖,并引用最新版本(为了配合迁移,引用的域名从**cn.lodz**改为**ink.lodz**)
13 | ```
14 | repositories {
15 | ...
16 | mavenCentral()
17 | ...
18 | }
19 | ```
20 | ```
21 | implementation 'ink.lodz:mmsplayer:1.1.2'
22 | ```
23 |
24 | ## 2、使用方法
25 | 我封装了MmsVideoView控件,大家可以通过IVideoPlayer接口来获取控件对象,接口里有播放器的控制方法,可以通过调用接口方法来操作播放器逻辑。
26 |
27 | #### 1)在xml里添加播放器控件
28 | ```
29 |
33 |
34 |
35 | ```
36 |
37 | #### 2)在代码中获取控件对象
38 | ```
39 | private val mVideoPlayer : IVideoPlayer by lazy {
40 | findViewById(R.id.video_view)
41 | }
42 | ```
43 |
44 | #### 3)操作播放器方法
45 | ```
46 | // 初始化(使用默认的播放器配置)
47 | mVideoPlayer.init()
48 |
49 | // 初始化(自定义播放器配置)
50 | val setting = IjkPlayerSetting.getDefault()
51 | setting.aspectRatioType = IRenderView.AR_ASPECT_FILL_PARENT
52 | mVideoPlayer.init(setting)
53 |
54 | // 设置监听器回调
55 | mVideoPlayer.setListener(object : MmsVideoView.Listener{
56 | override fun onPrepared() {
57 | // 播放器就绪(播放路径解析完成)
58 | }
59 |
60 | override fun onBufferingStart() {
61 | // 开始缓冲
62 | }
63 |
64 | override fun onBufferingEnd() {
65 | // 结束缓冲
66 | }
67 |
68 | override fun onCompletion() {
69 | // 播放完成
70 | }
71 |
72 | override fun onError(errorType: Int, msg: String?) {
73 | // 播放出现异常
74 | }
75 |
76 | override fun onMediaPlayerCreated(mediaPlayer: IMediaPlayer) {
77 | // MediaPlayer创建完成
78 | }
79 | })
80 |
81 | // 设置网络播放路径
82 | mVideoPlayer.setVideoPath(url)
83 |
84 | // 设置手机文件资源播放路径
85 | mVideoPlayer.setVideoURI(uri)
86 |
87 | // 开始播放
88 | mVideoPlayer.start()
89 |
90 | // 是否正在播放
91 | mVideoPlayer.isPlaying()
92 |
93 | // 是否暂停
94 | mVideoPlayer.isPause()
95 |
96 | // 是否播放结束
97 | mVideoPlayer.isCompleted()
98 |
99 | // 是否已经设置播放地址
100 | mVideoPlayer.isAlreadySetPath()
101 |
102 | // 暂停播放
103 | mVideoPlayer.pause()
104 |
105 | // 重新播放
106 | mVideoPlayer.resume()
107 |
108 | // 停止播放释放资源
109 | mVideoPlayer.release()
110 |
111 | // 获取缓存进度百分比
112 | mVideoPlayer.getBufferPercentage()
113 |
114 | // 获取当前播放进度
115 | mVideoPlayer.getCurrentPlayPosition()
116 |
117 | // 获取播放失败时的进度
118 | mVideoPlayer.getBreakPosition()
119 |
120 | // 获取视频总时长
121 | mVideoPlayer.getVideoDuration()
122 |
123 | // 设置播放位置
124 | mVideoPlayer.seekTo(1000)
125 |
126 | // 设置播放位置并开始播放
127 | mVideoPlayer.seekAndStart(1000)
128 |
129 | // 设置播放控制器(控制器需要实现IMediaController接口)
130 | mVideoPlayer.setMediaController(controller)
131 |
132 | // 设置宽高比
133 | //(IRenderView.AR_ASPECT_FIT_PARENT、IRenderView.AR_ASPECT_FILL_PARENT、
134 | // IRenderView.AR_ASPECT_WRAP_CONTENT、IRenderView.AR_MATCH_PARENT、
135 | // IRenderView.AR_16_9_FIT_PARENT、IRenderView.AR_4_3_FIT_PARENT)
136 | mVideoPlayer.setAspectRatio(IRenderView.AR_ASPECT_FILL_PARENT)
137 |
138 | // 获取视频信息
139 | mVideoPlayer.getMediaInfo()
140 |
141 | // 切换宽高比
142 | mVideoPlayer.toggleAspectRatio()
143 |
144 | // 获取当前渲染view名称
145 | mVideoPlayer.getRenderText(context)
146 |
147 | // 获取当前播放器名称
148 | mVideoPlayer.getPlayerText(context)
149 | ```
150 |
151 | - init()和init(IjkPlayerSetting setting)根据需要选择一个调用即可
152 | - setVideoPath(String path)可以传入url和file,暂不支持资源id(例如R.raw.xxx)
153 | - IjkPlayerSetting里面可以对一些播放器参数进行配置,例如播放器类型(支持原生、IJK、EXO),宽高比、硬解或软解等等
154 |
155 | ## 3、测试Demo(Kotlin编写)
156 | - [SimpleVideoActivity.kt](https://github.com/LZ9/MMSPlayer/blob/master/app/src/main/java/com/lodz/android/mmsplayerdemo/simple/SimpleVideoActivity.kt) 接入最基础的播放器控件,方便大家了解基本调用方式
157 | - [VideoActivity.kt](https://github.com/LZ9/MMSPlayer/blob/master/app/src/main/java/com/lodz/android/mmsplayerdemo/widget/VideoActivity.kt) 我自定义了一些播放器菜单控件,并集成在 [MediaView.kt](https://github.com/LZ9/MMSPlayer/blob/master/app/src/main/java/com/lodz/android/mmsplayerdemo/video/view/MediaView.kt) 里面,供大家参考
158 | - 大家可以git工程下来,运行查看。
159 |
160 | 效果图:
161 |
162 |
163 |

164 |

165 |
166 |
167 |

168 |
169 |
170 |

171 |
172 |
173 |

174 |
175 |
176 |

177 |
178 |
179 | ## 扩展
180 | - [更新记录](https://github.com/LZ9/MMSPlayer/blob/master/mmsplayer/readme_mmsplayer_update.md)
181 | - [回到顶部](https://github.com/LZ9/MMSPlayer#mmsplayer播放器)
182 |
183 | ## License
184 | - [Apache Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
185 |
186 | Copyright 2022 Lodz
187 |
188 | Licensed under the Apache License, Version 2.0 (the "License");
189 | you may not use this file except in compliance with the License.
190 | You may obtain a copy of the License at
191 |
192 |
193 |
194 | Unless required by applicable law or agreed to in writing, software
195 | distributed under the License is distributed on an "AS IS" BASIS,
196 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
197 | See the License for the specific language governing permissions and
198 | limitations under the License.
199 |
200 | s under the License.
201 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | }
5 |
6 | android {
7 | compileSdk 34
8 | defaultConfig {
9 | applicationId "com.lodz.android.mmsplayerdemo"
10 | minSdkVersion 21
11 | targetSdkVersion 34
12 | versionCode 1
13 | versionName "1.0"
14 | multiDexEnabled = true// 启用dex分包
15 | }
16 |
17 | viewBinding {
18 | enabled = true
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 |
28 | compileOptions {
29 | sourceCompatibility JavaVersion.VERSION_17
30 | targetCompatibility JavaVersion.VERSION_17
31 | }
32 |
33 | kotlinOptions {
34 | jvmTarget = JavaVersion.VERSION_17.toString()
35 | }
36 |
37 | lint {
38 | abortOnError false
39 | checkReleaseBuilds false
40 | }
41 | namespace 'com.lodz.android.mmsplayerdemo'
42 | }
43 |
44 | dependencies {
45 | implementation 'ink.lodz:pandora:2.0.8'
46 |
47 | implementation project(':mmsplayer')
48 | // implementation 'ink.lodz:mmsplayer:1.1.1'
49 | }
50 |
--------------------------------------------------------------------------------
/app/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 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
39 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/App.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo
2 |
3 | import android.content.Context
4 | import androidx.multidex.MultiDex
5 | import com.lodz.android.corekt.network.NetworkManager
6 | import com.lodz.android.pandora.base.application.BaseApplication
7 |
8 | /**
9 | * Application
10 | * Created by zhouL on 2018/10/22.
11 | */
12 | class App :BaseApplication(){
13 | companion object {
14 | private var sInstance: App? = null
15 | fun get() = sInstance
16 | }
17 |
18 | override fun attachBaseContext(base: Context?) {
19 | super.attachBaseContext(base)
20 | MultiDex.install(this)
21 | }
22 |
23 | override fun onStartCreate() {
24 | sInstance = this
25 | NetworkManager.get().init(this)
26 | }
27 |
28 | override fun onExit() {
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import androidx.activity.result.contract.ActivityResultContracts
6 | import com.lodz.android.corekt.anko.getColorCompat
7 | import com.lodz.android.corekt.anko.toastShort
8 | import com.lodz.android.mmsplayerdemo.databinding.ActivityMainBinding
9 | import com.lodz.android.mmsplayerdemo.simple.SimpleVideoActivity
10 | import com.lodz.android.mmsplayerdemo.widget.VideoActivity
11 | import com.lodz.android.pandora.base.activity.BaseActivity
12 | import com.lodz.android.pandora.utils.viewbinding.bindingLayout
13 |
14 | class MainActivity : BaseActivity() {
15 |
16 | private val mBinding: ActivityMainBinding by bindingLayout(ActivityMainBinding::inflate)
17 |
18 | override fun getViewBindingLayout(): View = mBinding.root
19 |
20 | override fun findViews(savedInstanceState: Bundle?) {
21 | super.findViews(savedInstanceState)
22 | getTitleBarLayout().setTitleName(R.string.app_name)
23 | getTitleBarLayout().setBackgroundColor(getColorCompat(R.color.colorPrimary))
24 | getTitleBarLayout().needBackButton(false)
25 | }
26 |
27 | override fun setListeners() {
28 | super.setListeners()
29 | mBinding.simpleBtn.setOnClickListener {
30 | mGetContentResult.launch("video/*")
31 | }
32 |
33 | mBinding.widgetBtn.setOnClickListener {
34 | VideoActivity.start(this, getString(R.string.info_name), "http://vd3.bdstatic.com/mda-nkdksvz89kgvez0j/360p/h264/1668436838593889961/mda-nkdksvz89kgvez0j.mp4")
35 | }
36 | }
37 |
38 | /** 单类型选择单文件回调 */
39 | private val mGetContentResult = registerForActivityResult(ActivityResultContracts.GetContent()) {
40 | if (it == null){
41 | toastShort("取消选择")
42 | return@registerForActivityResult
43 | }
44 | SimpleVideoActivity.start(this, it)
45 | }
46 |
47 | override fun initData() {
48 | super.initData()
49 | showStatusCompleted()
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/config/Constant.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.config
2 |
3 | import androidx.annotation.IntDef
4 | import androidx.annotation.StringDef
5 |
6 | /**
7 | * 常量
8 | * Created by zhouL on 2018/10/31.
9 | */
10 | object Constant {
11 |
12 | /** 不连播 */
13 | const val UN_NEXT = 0
14 | /** 自动连播 */
15 | const val AUTO_NEXT = 1
16 | /** 单集循环 */
17 | const val SINGLE_CYCLE = 2
18 | /** 播完退出 */
19 | const val EXIT_END = 3
20 |
21 | @IntDef(UN_NEXT, AUTO_NEXT, SINGLE_CYCLE, EXIT_END)
22 | @Retention(AnnotationRetention.SOURCE)
23 | annotation class PlayType
24 |
25 |
26 | /** 0.5X */
27 | const val SPEED_0_5X = "0.5"
28 | /** 0.75X */
29 | const val SPEED_0_75X = "0.75"
30 | /** 1.0X */
31 | const val SPEED_1_0X = "1.0"
32 | /** 1.25X */
33 | const val SPEED_1_25X = "1.25"
34 | /** 1.5X */
35 | const val SPEED_1_5X = "1.5"
36 | /** 2.0X */
37 | const val SPEED_2_0X = "2.0"
38 |
39 | @StringDef(SPEED_0_5X, SPEED_0_75X, SPEED_1_0X, SPEED_1_25X, SPEED_1_5X, SPEED_2_0X)
40 | @Retention(AnnotationRetention.SOURCE)
41 | annotation class SpeedType
42 |
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/simple/SimpleVideoActivity.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.simple
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.net.Uri
6 | import android.os.Bundle
7 | import android.view.View
8 | import com.lodz.android.corekt.anko.intentParcelableExtras
9 | import com.lodz.android.corekt.anko.toastShort
10 | import com.lodz.android.mmsplayer.contract.IVideoPlayer
11 | import com.lodz.android.mmsplayer.impl.MmsVideoView
12 | import com.lodz.android.mmsplayerdemo.R
13 | import com.lodz.android.mmsplayerdemo.databinding.ActivitySimpleVideoBinding
14 | import com.lodz.android.pandora.base.activity.AbsActivity
15 | import com.lodz.android.pandora.utils.viewbinding.bindingLayout
16 | import tv.danmaku.ijk.media.player.IMediaPlayer
17 |
18 | /**
19 | * 基础播放器界面
20 | * Created by zhouL on 2018/10/19.
21 | */
22 | class SimpleVideoActivity : AbsActivity() {
23 |
24 | companion object {
25 |
26 | private const val EXTRA_VIDEO_PATH = "extra_video_path"
27 |
28 | fun start(context: Context, uri: Uri) {
29 | val intent = Intent(context, SimpleVideoActivity::class.java)
30 | intent.putExtra(EXTRA_VIDEO_PATH, uri)
31 | context.startActivity(intent)
32 | }
33 | }
34 |
35 | private val mBinding: ActivitySimpleVideoBinding by bindingLayout(ActivitySimpleVideoBinding::inflate)
36 |
37 | private val mUri by intentParcelableExtras(EXTRA_VIDEO_PATH)
38 |
39 | override fun getAbsViewBindingLayout(): View = mBinding.root
40 |
41 | private lateinit var mVideoPlayer: IVideoPlayer
42 |
43 | override fun findViews(savedInstanceState: Bundle?) {
44 | super.findViews(savedInstanceState)
45 | mVideoPlayer = mBinding.videoView
46 | }
47 |
48 | override fun onPressBack(): Boolean {
49 | mVideoPlayer.release()
50 | finish()
51 | return true
52 | }
53 |
54 | override fun setListeners() {
55 | super.setListeners()
56 | mVideoPlayer.setListener(object :MmsVideoView.Listener{
57 | override fun onPrepared() {
58 | toastShort(R.string.simple_prepared)
59 | }
60 |
61 | override fun onBufferingStart() {
62 | toastShort(R.string.simple_buffering_start)
63 | }
64 |
65 | override fun onBufferingEnd() {
66 | toastShort(R.string.simple_buffering_end)
67 | }
68 |
69 | override fun onCompletion() {
70 | toastShort(R.string.simple_completion)
71 | }
72 |
73 | override fun onError(errorType: Int, msg: String?) {
74 | toastShort(getString(R.string.simple_error, msg))
75 | }
76 |
77 | override fun onMediaPlayerCreated(mediaPlayer: IMediaPlayer) {
78 | // do something
79 | }
80 | })
81 | }
82 |
83 | override fun initData() {
84 | super.initData()
85 | val uri = mUri
86 | if (uri == null) {
87 | toastShort("获取路径失败")
88 | finish()
89 | return
90 | }
91 | mVideoPlayer.init()
92 | mVideoPlayer.setVideoURI(uri)
93 | mVideoPlayer.start()
94 | }
95 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/assist/VideoAdjustProgressLayout.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.assist
2 |
3 | import android.annotation.TargetApi
4 | import android.content.Context
5 | import android.os.Build
6 | import android.util.AttributeSet
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.widget.LinearLayout
10 | import android.widget.TextView
11 | import androidx.viewpager.widget.ViewPager
12 | import com.lodz.android.corekt.anko.bindView
13 | import com.lodz.android.mmsplayer.ijk.utils.MediaInfoUtils
14 | import com.lodz.android.mmsplayerdemo.R
15 |
16 | /**
17 | * 进度调整页面
18 | * Created by zhouL on 2018/10/26.
19 | */
20 | class VideoAdjustProgressLayout : LinearLayout {
21 |
22 | constructor(context: Context?) : super(context)
23 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
24 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
25 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
26 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
27 |
28 | /** 进度 */
29 | private val mProgressTv by bindView(R.id.progress_tv)
30 |
31 | /** 总进度 */
32 | private var mDuration: Long = 0
33 | /** 当前进度 */
34 | private var mCurrent: Long = 0
35 |
36 | init {
37 | LayoutInflater.from(context).inflate(R.layout.view_video_adjust_progress, this)
38 | }
39 |
40 | /** 进度调整界面是否显示 */
41 | fun isShow(): Boolean = visibility == View.VISIBLE
42 |
43 | /** 显示进度调整界面 */
44 | fun show() {
45 | visibility = View.VISIBLE
46 | }
47 |
48 | /** 隐藏进度调整界面 */
49 | fun hide() {
50 | visibility = View.GONE
51 | }
52 |
53 | /** 设置总进度[duration] */
54 | fun setDuration(duration: Long) {
55 | mDuration = duration
56 | }
57 |
58 | /** 设置当前进度[current] */
59 | fun setCurrent(current: Long) {
60 | mCurrent = current
61 | }
62 |
63 | /** 更新进度,进度更新参数[delta] */
64 | fun updateProgress(delta: Float) {
65 | if (mDuration <= 0) {
66 | return
67 | }
68 | mCurrent += (mDuration * delta).toLong()// 计算当前进度
69 | if (mCurrent <= 0) {
70 | mCurrent = 0
71 | }
72 | if (mCurrent >= mDuration) {
73 | mCurrent = mDuration
74 | }
75 | mProgressTv.text = context.getString(R.string.video_play_progress, MediaInfoUtils.buildTimeMilli(mCurrent), MediaInfoUtils.buildTimeMilli(mDuration))
76 | }
77 |
78 | /** 获取当前进度 */
79 | fun getCurrent(): Long = mCurrent
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/assist/VideoBrightnessLayout.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.assist
2 |
3 | import android.annotation.TargetApi
4 | import android.app.Activity
5 | import android.content.Context
6 | import android.os.Build
7 | import android.util.AttributeSet
8 | import android.view.LayoutInflater
9 | import android.view.View
10 | import android.view.WindowManager
11 | import android.widget.ImageView
12 | import android.widget.LinearLayout
13 | import android.widget.ProgressBar
14 | import com.lodz.android.corekt.anko.bindView
15 | import com.lodz.android.mmsplayerdemo.R
16 |
17 | /**
18 | * 亮度页面
19 | * Created by zhouL on 2018/10/29.
20 | */
21 | class VideoBrightnessLayout : LinearLayout {
22 |
23 | /** 亮度进度条 */
24 | private val mBrightnessProgressBar by bindView(R.id.brightness_pb)
25 |
26 | constructor(context: Context?) : super(context)
27 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
28 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
29 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
30 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
31 |
32 | init {
33 | LayoutInflater.from(context).inflate(R.layout.view_video_brightness, this)
34 | }
35 |
36 | /** 亮度界面是否显示 */
37 | fun isShow(): Boolean = visibility == View.VISIBLE
38 |
39 | /** 显示亮度界面 */
40 | fun show() {
41 | visibility = View.VISIBLE
42 | }
43 |
44 | /** 隐藏亮度界面 */
45 | fun hide() {
46 | visibility = View.GONE
47 | }
48 |
49 | /** 更新亮度,更新界面[activity],进度更新参数[delta] */
50 | fun updateBrightness(activity: Activity, delta: Float) {
51 | val layoutParams = activity.window.attributes
52 | var current = layoutParams.screenBrightness//获取当前亮度
53 | if (current == WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE) {// 如果亮度是-1则设置默认值为0.5
54 | current = 0.5f
55 | }
56 | current += delta * WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL
57 | if (current >= WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL) {
58 | current = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL
59 | }
60 | if (current <= WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF) {
61 | current = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF
62 | }
63 | setBrightnessProgress(current)//设置亮度
64 | layoutParams.screenBrightness = current
65 | activity.window.attributes = layoutParams
66 | }
67 |
68 | /** 设置亮度值[brightness] */
69 | private fun setBrightnessProgress(brightness: Float) {
70 | val progress = brightness * 100
71 | mBrightnessProgressBar.progress = progress.toInt()
72 | }
73 |
74 |
75 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/assist/VideoVolumeLayout.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.assist
2 |
3 | import android.annotation.TargetApi
4 | import android.app.Activity
5 | import android.content.Context
6 | import android.media.AudioManager
7 | import android.os.Build
8 | import android.util.AttributeSet
9 | import android.view.LayoutInflater
10 | import android.view.View
11 | import android.widget.ImageView
12 | import android.widget.LinearLayout
13 | import android.widget.ProgressBar
14 | import com.lodz.android.corekt.anko.bindView
15 | import com.lodz.android.mmsplayerdemo.R
16 |
17 | /**
18 | * 音量页面
19 | * Created by zhouL on 2018/10/29.
20 | */
21 | class VideoVolumeLayout : LinearLayout {
22 |
23 | /** 音量进度条 */
24 | private val mVolumeProgressBar by bindView(R.id.volume_pb)
25 |
26 | /** 音量管理 */
27 | private var mAudioManager: AudioManager? = null
28 | /** 最大值 */
29 | private var mMaxVolume = 0
30 | /** 当前音量 */
31 | private var mCurrent = 0f
32 |
33 | constructor(context: Context?) : super(context)
34 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
35 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
36 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
37 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
38 |
39 | init {
40 | LayoutInflater.from(context).inflate(R.layout.view_video_volume, this)
41 | }
42 |
43 | /** 音量界面是否显示 */
44 | fun isShow(): Boolean = visibility == View.VISIBLE
45 |
46 | /** 显示音量界面 */
47 | fun show() {
48 | visibility = View.VISIBLE
49 | }
50 |
51 | /** 隐藏音量界面 */
52 | fun hide() {
53 | visibility = View.GONE
54 | }
55 |
56 | /** 更新音量[delta] */
57 | fun updateVolume(activity: Activity, delta: Float) {
58 | if (mAudioManager == null) {
59 | configManager(activity)
60 | }
61 |
62 | if (mAudioManager != null) {
63 | mCurrent += delta * mMaxVolume
64 | if (mCurrent >= mMaxVolume) {
65 | mCurrent = mMaxVolume.toFloat()
66 | }
67 | if (mCurrent <= 0) {
68 | mCurrent = 0f
69 | }
70 | mVolumeProgressBar.progress = mCurrent.toInt()
71 | mAudioManager!!.setStreamVolume(AudioManager.STREAM_MUSIC, mCurrent.toInt(), 0)// 设置手机音量
72 | }
73 | }
74 |
75 | private fun configManager(activity: Activity) {
76 | mAudioManager = activity.getSystemService(Context.AUDIO_SERVICE) as AudioManager?
77 | if (mAudioManager == null) {
78 | return
79 | }
80 | mMaxVolume = mAudioManager!!.getStreamMaxVolume(AudioManager.STREAM_MUSIC)// 获取音量最大值
81 | mVolumeProgressBar.max = mMaxVolume
82 | mCurrent = mAudioManager!!.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat()// 获取当前音量值
83 | }
84 |
85 |
86 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/dialog/VideoSettingDialog.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.dialog
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.content.DialogInterface
6 | import android.widget.RadioGroup
7 | import android.widget.TextView
8 | import com.lodz.android.corekt.anko.bindView
9 | import com.lodz.android.mmsplayer.ijk.media.IRenderView
10 | import com.lodz.android.mmsplayer.ijk.setting.IjkPlayerSetting
11 | import com.lodz.android.mmsplayerdemo.R
12 | import com.lodz.android.mmsplayerdemo.config.Constant
13 | import com.lodz.android.pandora.widget.dialog.BaseRightDialog
14 |
15 | /**
16 | * 播放器设置弹框
17 | * Created by zhouL on 2018/10/31.
18 | */
19 | class VideoSettingDialog(context: Context) : BaseRightDialog(context, R.style.NoDimDialog) {
20 |
21 | /** 播放类型 */
22 | private val mPlayTypeRg by bindView(R.id.play_type_rg)
23 | /** 宽高比 */
24 | private val mAspectRatioRg by bindView(R.id.aspect_ratio_rg)
25 | /** 倍数 */
26 | private val mSpeedRg by bindView(R.id.speed_rg)
27 |
28 | /** 监听器 */
29 | private var mListener: Listener? = null
30 |
31 | /** 播放类型 */
32 | @Constant.PlayType
33 | private var mPlayType: Int = Constant.UN_NEXT
34 |
35 | /** 倍数 */
36 | @Constant.PlayType
37 | private var mSpeedType: String = Constant.SPEED_1_0X
38 |
39 | /** 宽高比 */
40 | @IjkPlayerSetting.AspectRatioType
41 | private var mAspectRatioType: Int = IRenderView.AR_ASPECT_FIT_PARENT
42 |
43 | override fun getLayoutId(): Int = R.layout.dialog_video_setting
44 |
45 | override fun setListeners() {
46 | super.setListeners()
47 | mPlayTypeRg.setOnCheckedChangeListener { group, checkedId ->
48 | val playType = when (checkedId) {
49 | R.id.un_next_rb -> Constant.UN_NEXT
50 | R.id.auto_next_rb -> Constant.AUTO_NEXT
51 | R.id.single_cycle_rb -> Constant.SINGLE_CYCLE
52 | R.id.exit_end_rb -> Constant.EXIT_END
53 | else -> Constant.UN_NEXT
54 | }
55 | if (mListener != null){
56 | mListener!!.onPlayTypeChanged(playType)
57 | }
58 | }
59 |
60 | mAspectRatioRg.setOnCheckedChangeListener { group, checkedId ->
61 | val aspectRatioType = when (checkedId) {
62 | R.id.aspect_ratio_default_rb -> IRenderView.AR_ASPECT_FIT_PARENT
63 | R.id.aspect_ratio_full_rb -> IRenderView.AR_ASPECT_FILL_PARENT
64 | R.id.aspect_ratio_16_9_rb -> IRenderView.AR_16_9_FIT_PARENT
65 | R.id.aspect_ratio_4_3_rb -> IRenderView.AR_4_3_FIT_PARENT
66 | else -> IRenderView.AR_ASPECT_FIT_PARENT
67 | }
68 | if (mListener != null){
69 | mListener!!.onAspectRatioChanged(aspectRatioType)
70 | }
71 | }
72 |
73 | mSpeedRg.setOnCheckedChangeListener { group, checkedId ->
74 | val speedType = when (checkedId) {
75 | R.id.speed_05_rb -> Constant.SPEED_0_5X
76 | R.id.speed_075_rb -> Constant.SPEED_0_75X
77 | R.id.speed_10_rb -> Constant.SPEED_1_0X
78 | R.id.speed_125_rb -> Constant.SPEED_1_25X
79 | R.id.speed_15_rb -> Constant.SPEED_1_5X
80 | R.id.speed_20_rb -> Constant.SPEED_2_0X
81 | else -> Constant.SPEED_1_0X
82 | }
83 | if (mListener != null){
84 | mListener!!.onSpeedTypeChanged(speedType)
85 | }
86 | }
87 |
88 | setOnCancelListener { dialog ->
89 | if (mListener != null){
90 | mListener!!.onCancel(dialog)
91 | }
92 | }
93 | }
94 |
95 | override fun initData() {
96 | super.initData()
97 | setPlayType(mPlayType)
98 | setAspectRatio(mAspectRatioType)
99 | setSpeed(mSpeedType)
100 | }
101 |
102 | /** 初始化播放类型[playType]和宽高比[aspectRatioType] */
103 | fun init(@Constant.PlayType playType: Int, @IjkPlayerSetting.AspectRatioType aspectRatioType: Int, @Constant.SpeedType speedType: String){
104 | mPlayType = playType
105 | mAspectRatioType = aspectRatioType
106 | mSpeedType = speedType
107 | }
108 |
109 | /** 设置播放类型[playType] */
110 | private fun setPlayType(@Constant.PlayType playType: Int){
111 | when (playType) {
112 | Constant.AUTO_NEXT -> mPlayTypeRg.check(R.id.auto_next_rb)
113 | Constant.SINGLE_CYCLE -> mPlayTypeRg.check(R.id.single_cycle_rb)
114 | Constant.EXIT_END -> mPlayTypeRg.check(R.id.exit_end_rb)
115 | Constant.UN_NEXT -> mPlayTypeRg.check(R.id.un_next_rb)
116 | else -> mPlayTypeRg.check(R.id.un_next_rb)
117 | }
118 | }
119 |
120 | /** 设置宽高比[aspectRatioType] */
121 | private fun setAspectRatio(@IjkPlayerSetting.AspectRatioType aspectRatioType: Int){
122 | when (aspectRatioType) {
123 | IRenderView.AR_ASPECT_FILL_PARENT -> mAspectRatioRg.check(R.id.aspect_ratio_full_rb)
124 | IRenderView.AR_16_9_FIT_PARENT -> mAspectRatioRg.check(R.id.aspect_ratio_16_9_rb)
125 | IRenderView.AR_4_3_FIT_PARENT -> mAspectRatioRg.check(R.id.aspect_ratio_4_3_rb)
126 | IRenderView.AR_ASPECT_FIT_PARENT -> mAspectRatioRg.check(R.id.aspect_ratio_default_rb)
127 | else -> mAspectRatioRg.check(R.id.aspect_ratio_default_rb)
128 | }
129 | }
130 |
131 | /** 设置倍数[speedType] */
132 | private fun setSpeed(@Constant.SpeedType speedType: String) {
133 | when (speedType) {
134 | Constant.SPEED_0_5X -> mSpeedRg.check(R.id.speed_05_rb)
135 | Constant.SPEED_0_75X -> mSpeedRg.check(R.id.speed_075_rb)
136 | Constant.SPEED_1_0X -> mSpeedRg.check(R.id.speed_10_rb)
137 | Constant.SPEED_1_25X -> mSpeedRg.check(R.id.speed_125_rb)
138 | Constant.SPEED_1_5X -> mSpeedRg.check(R.id.speed_15_rb)
139 | Constant.SPEED_2_0X -> mSpeedRg.check(R.id.speed_20_rb)
140 | else -> mSpeedRg.check(R.id.speed_10_rb)
141 | }
142 | }
143 |
144 | /** 设置监听器 */
145 | fun setListener(listener: Listener) {
146 | mListener = listener
147 | }
148 |
149 | interface Listener {
150 | /** 播放类型改变 */
151 | fun onPlayTypeChanged(@Constant.PlayType playType: Int)
152 |
153 | /** 宽高比改变 */
154 | fun onAspectRatioChanged(@IjkPlayerSetting.AspectRatioType aspectRatioType: Int)
155 |
156 | /** 倍数改变 */
157 | fun onSpeedTypeChanged(@Constant.SpeedType speedType: String)
158 |
159 | /** 取消弹框 */
160 | fun onCancel(dialog: DialogInterface)
161 | }
162 |
163 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/status/VideoErrorLayout.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.status
2 |
3 | import android.annotation.TargetApi
4 | import android.content.Context
5 | import android.os.Build
6 | import android.util.AttributeSet
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.widget.ImageView
10 | import android.widget.LinearLayout
11 | import android.widget.TextView
12 | import com.lodz.android.corekt.anko.bindView
13 | import com.lodz.android.corekt.anko.startAnim
14 | import com.lodz.android.mmsplayerdemo.R
15 |
16 | /**
17 | * 播放失败页面
18 | * Created by zhouL on 2018/10/23.
19 | */
20 | class VideoErrorLayout : LinearLayout {
21 |
22 | /** 返回按钮 */
23 | private val mBackBtn by bindView(R.id.back_btn)
24 |
25 | /** 重试按钮 */
26 | private val mRetryBtn by bindView(R.id.retry_btn)
27 |
28 | /** 返回按钮监听器 */
29 | private var mBackListener: View.OnClickListener? = null
30 | /** 重试按钮监听器 */
31 | private var mRetryListener: View.OnClickListener? = null
32 |
33 | constructor(context: Context?) : super(context)
34 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
35 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
36 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
37 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
38 |
39 | init {
40 | LayoutInflater.from(context).inflate(R.layout.view_video_error, this)
41 | setListeners()
42 | }
43 |
44 | private fun setListeners() {
45 | mBackBtn.setOnClickListener {
46 | if (mBackListener != null) {
47 | mBackListener!!.onClick(it)
48 | }
49 | }
50 |
51 | mRetryBtn.setOnClickListener {
52 | if (mRetryListener != null) {
53 | mRetryListener!!.onClick(it)
54 | }
55 | }
56 | }
57 |
58 | /** 设置返回按钮监听器 */
59 | fun setBackListener(listener: View.OnClickListener) {
60 | mBackListener = listener
61 | }
62 |
63 | /** 设置重试按钮监听器 */
64 | fun setRetryListener(listener: View.OnClickListener) {
65 | mRetryListener = listener
66 | }
67 |
68 | /** 播放失败页是否显示 */
69 | fun isShow(): Boolean = visibility == View.VISIBLE
70 |
71 | /** 显示播放失败页 */
72 | fun show() {
73 | if (!isShow()) {
74 | startAnim(context, R.anim.anim_fade_in, View.VISIBLE)
75 | }
76 | }
77 |
78 | /** 隐藏播放失败页 */
79 | fun hide() {
80 | if (isShow()) {
81 | visibility = View.GONE
82 | }
83 | }
84 |
85 | /** 设置是否全屏[isFull] */
86 | fun setFullScreen(isFull: Boolean) {
87 | mBackBtn.visibility = if (isFull) View.VISIBLE else View.GONE
88 | }
89 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/status/VideoLoadingAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.status
2 |
3 | import android.content.Context
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import androidx.recyclerview.widget.RecyclerView
9 | import com.lodz.android.corekt.anko.bindView
10 | import com.lodz.android.mmsplayerdemo.R
11 |
12 | /**
13 | * 视频加载界面的文字提示适配器
14 | * Created by zhouL on 2018/10/23.
15 | */
16 | class VideoLoadingAdapter(private val context: Context) : RecyclerView.Adapter() {
17 |
18 | private var mData: List? = null
19 |
20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder = TipsViewHolder(getLayoutView(parent, R.layout.rv_item_video_loading_tips))
21 |
22 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
23 | if (holder is TipsViewHolder) {
24 | showItem(holder, position)
25 | }
26 | }
27 |
28 | private fun showItem(holder: TipsViewHolder, position: Int) {
29 | val tips = getItem(position)
30 | if (tips.isNullOrEmpty()){
31 | return
32 | }
33 |
34 | holder.tipsTv.text = tips
35 | }
36 |
37 | fun setData(list: List) {
38 | mData = list
39 | }
40 |
41 | fun getData(): List? = mData
42 |
43 | inner class TipsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
44 | /** 提示语 */
45 | val tipsTv by bindView(R.id.tips_tv)
46 | }
47 |
48 | override fun getItemCount(): Int = if (mData != null) mData!!.size else 0
49 |
50 | /** 根据列表索引[position]获取数据 */
51 | private fun getItem(position: Int): String? {
52 | if (mData == null || mData!!.size == 0) {
53 | return null
54 | }
55 | try {
56 | return mData!!.get(position)
57 | } catch (e: Exception) {
58 | e.printStackTrace()
59 | }
60 | return null
61 | }
62 |
63 | /** 在onCreateViewHolder方法中根据layoutId获取View */
64 | private fun getLayoutView(parent: ViewGroup, layoutId: Int): View =
65 | LayoutInflater.from(context).inflate(layoutId, parent, false)
66 |
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/status/VideoLoadingLayout.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.status
2 |
3 | import android.annotation.TargetApi
4 | import android.content.Context
5 | import android.os.Build
6 | import android.util.AttributeSet
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.widget.ImageView
10 | import android.widget.LinearLayout
11 | import androidx.recyclerview.widget.LinearLayoutManager
12 | import androidx.recyclerview.widget.RecyclerView
13 | import com.lodz.android.corekt.anko.bindView
14 | import com.lodz.android.corekt.anko.startAnim
15 | import com.lodz.android.corekt.utils.UiHandler
16 | import com.lodz.android.mmsplayerdemo.R
17 |
18 | /**
19 | * 播放器加载页面
20 | * Created by zhouL on 2018/10/23.
21 | */
22 | class VideoLoadingLayout : LinearLayout {
23 |
24 | /** 返回按钮 */
25 | private val mBackBtn by bindView(R.id.back_btn)
26 | /** 数据提示列表 */
27 | private val mRecyclerView by bindView(R.id.recycler_view)
28 |
29 | /** 提示列表适配器 */
30 | private lateinit var mAdapter: VideoLoadingAdapter
31 | /** 提示语列表 */
32 | private val mTipsList = ArrayList()
33 | /** 监听器 */
34 | private var mListener: View.OnClickListener? = null
35 |
36 | constructor(context: Context?) : super(context)
37 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
38 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
39 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
40 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
41 |
42 | init {
43 | LayoutInflater.from(context).inflate(R.layout.view_video_loading, this)
44 | initRecyclerView()
45 | setListeners()
46 | bindData(context.getString(R.string.video_loading_player_init_complete))
47 | }
48 |
49 | private fun initRecyclerView() {
50 | val layoutManager = LinearLayoutManager(context)
51 | layoutManager.orientation = RecyclerView.VERTICAL
52 | mAdapter = VideoLoadingAdapter(context)
53 | mRecyclerView.layoutManager = layoutManager
54 | mRecyclerView.setHasFixedSize(true)
55 | mRecyclerView.adapter = mAdapter
56 | }
57 |
58 | private fun setListeners() {
59 | mBackBtn.setOnClickListener {
60 | if (mListener != null) {
61 | mListener!!.onClick(it)
62 | }
63 | }
64 | }
65 |
66 | /** 绑定数据[tips] */
67 | private fun bindData(tips: String) {
68 | mTipsList.add(tips)
69 | mAdapter.setData(mTipsList)
70 | mAdapter.notifyDataSetChanged()
71 | mRecyclerView.smoothScrollToPosition(mTipsList.size)
72 | }
73 |
74 | /** 设置返回按钮监听器[listener] */
75 | fun setBackListener(listener: View.OnClickListener) {
76 | mListener = listener
77 | }
78 |
79 | /** 加载页是否显示 */
80 | fun isShow(): Boolean = visibility == View.VISIBLE
81 |
82 | /** 显示加载页 */
83 | fun show() {
84 | if (!isShow()) {
85 | visibility = View.VISIBLE
86 | }
87 | }
88 |
89 | /** 隐藏加载页 */
90 | fun hide() {
91 | if (isShow()) {
92 | UiHandler.postDelayed({
93 | startAnim(context, R.anim.anim_fade_out, View.GONE)
94 | }, 300)
95 | }
96 | }
97 |
98 | /** 显示播放组件加载完成 */
99 | fun showPlayerComplete() {
100 | bindData(context.getString(R.string.video_loading_player_view_complete))
101 | }
102 |
103 | /** 显示加载视频地址完成 */
104 | fun showLoadUrlComplete() {
105 | bindData(context.getString(R.string.video_loading_load_url_complete))
106 | }
107 |
108 | /** 显示开始解析视频地址 */
109 | fun showStartAnalysisUrl() {
110 | bindData(context.getString(R.string.video_loading_start_analysis_url))
111 | }
112 |
113 | /** 显示解析视频地址完成 */
114 | fun showAnalysisUrlComplete() {
115 | bindData(context.getString(R.string.video_loading_analysis_url_complete))
116 | }
117 |
118 | /** 显示切换画质 */
119 | fun showStartChangeQuality() {
120 | bindData(context.getString(R.string.video_loading_start_change_quality))
121 | }
122 |
123 | /** 显示解析异常 */
124 | fun showAnalysisError() {
125 | bindData(context.getString(R.string.video_analysis_error_tips))
126 | }
127 |
128 | /** 显示换行 */
129 | fun showEnter() {
130 | bindData("")
131 | }
132 |
133 | /** 设置是否全屏[isFull] */
134 | fun setFullScreen(isFull: Boolean) {
135 | mBackBtn.visibility = if (isFull) View.VISIBLE else View.GONE
136 | }
137 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/video/status/VideoPhoneDataLayout.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.video.status
2 |
3 | import android.annotation.TargetApi
4 | import android.content.Context
5 | import android.os.Build
6 | import android.util.AttributeSet
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.ImageView
11 | import android.widget.LinearLayout
12 | import androidx.recyclerview.widget.RecyclerView
13 | import com.lodz.android.corekt.anko.bindView
14 | import com.lodz.android.mmsplayerdemo.R
15 |
16 | /**
17 | * 数据流量播放提示页
18 | * Created by zhouL on 2018/10/23.
19 | */
20 | class VideoPhoneDataLayout : LinearLayout {
21 |
22 | /** 返回按钮 */
23 | private val mBackBtn by bindView(R.id.back_btn)
24 |
25 | /** 流量播放按钮 */
26 | private val mPlayBtn by bindView(R.id.play_btn)
27 |
28 | /** 返回按钮监听器 */
29 | private var mBackListener: View.OnClickListener? = null
30 | /** 流量播放按钮监听器 */
31 | private var mDataPlayListener: View.OnClickListener? = null
32 |
33 | constructor(context: Context?) : super(context)
34 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
35 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
36 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
37 | constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
38 |
39 | init {
40 | LayoutInflater.from(context).inflate(R.layout.view_video_phone_data, this)
41 | setListeners()
42 | }
43 |
44 | private fun setListeners() {
45 | mBackBtn.setOnClickListener {
46 | if (mBackListener != null) {
47 | mBackListener!!.onClick(it)
48 | }
49 | }
50 |
51 | mPlayBtn.setOnClickListener {
52 | if (mDataPlayListener != null) {
53 | mDataPlayListener!!.onClick(it)
54 | }
55 | }
56 | }
57 |
58 | /** 是否需要返回按钮[isNeed] */
59 | fun needBackBtn(isNeed: Boolean) {
60 | mBackBtn.visibility = if (isNeed) View.VISIBLE else View.GONE
61 | }
62 |
63 | /** 设置返回按钮监听器 */
64 | fun setBackListener(listener: View.OnClickListener) {
65 | mBackListener = listener
66 | }
67 |
68 | /** 设置流量播放按钮监听器 */
69 | fun setDataPlayListener(listener: View.OnClickListener) {
70 | mDataPlayListener = listener
71 | }
72 |
73 | /** 播放失败页是否显示 */
74 | fun isShow(): Boolean = visibility == View.VISIBLE
75 |
76 | /** 显示播放失败页 */
77 | fun show() {
78 | if (!isShow()) {
79 | visibility = View.VISIBLE
80 | }
81 | }
82 |
83 | /** 隐藏播放失败页 */
84 | fun hide() {
85 | if (isShow()) {
86 | visibility = View.GONE
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/widget/CommentAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.widget
2 |
3 | import android.content.Context
4 | import android.view.LayoutInflater
5 | import android.view.ViewGroup
6 | import android.widget.TextView
7 | import androidx.viewbinding.ViewBinding
8 | import com.lodz.android.mmsplayerdemo.databinding.RvItemCommentBinding
9 | import com.lodz.android.pandora.widget.rv.recycler.base.BaseVbRvAdapter
10 | import com.lodz.android.pandora.widget.rv.recycler.vh.DataVBViewHolder
11 | import java.util.*
12 |
13 | /**
14 | * 评论列表
15 | * Created by zhouL on 2018/10/29.
16 | */
17 | class CommentAdapter(context: Context) : BaseVbRvAdapter(context) {
18 |
19 | companion object{
20 | private val NAME_ITEM = arrayListOf("张", "陈", "王", "李", "赵", "周", "黄", "苏")
21 | private val COMMENT_ITEM = "是读千万家让逻辑单例创建旭晶无饿哦斯迪克沃尔巨坑参加过问排起物业卡卡是语文切勿偶尔软件新春快乐实际打卡罗杰斯欧文吗去我跑提出张先生快圣诞节饭"
22 | }
23 |
24 | override fun getVbInflate(): (LayoutInflater, parent: ViewGroup, attachToRoot: Boolean) -> ViewBinding = RvItemCommentBinding::inflate
25 |
26 | override fun onBind(holder: DataVBViewHolder, position: Int) {
27 | holder.getVB().apply {
28 | setName(nameTv)
29 | dateTv.text = getItem(position) ?: ""
30 | setComment(commentTv)
31 | }
32 | }
33 |
34 | private fun setName(textView: TextView) {
35 | val name = NAME_ITEM[Random().nextInt(NAME_ITEM.size)] + NAME_ITEM[Random().nextInt(NAME_ITEM.size)] + NAME_ITEM[Random().nextInt(NAME_ITEM.size)]
36 | textView.text = name
37 | }
38 |
39 | private fun setComment(textView: TextView) {
40 | val startIndex = Random().nextInt(COMMENT_ITEM.length / 2)
41 | val endIndex = Random().nextInt(COMMENT_ITEM.length / 2) + COMMENT_ITEM.length / 2
42 | textView.text = COMMENT_ITEM.substring(startIndex, endIndex)
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/widget/CommentFragment.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.widget
2 |
3 | import android.annotation.SuppressLint
4 | import android.os.Bundle
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import androidx.recyclerview.widget.LinearLayoutManager
9 | import androidx.recyclerview.widget.RecyclerView
10 | import com.lodz.android.corekt.utils.DateUtils
11 | import com.lodz.android.mmsplayerdemo.databinding.FragmentCommentBinding
12 | import com.lodz.android.pandora.base.fragment.LazyFragment
13 | import com.lodz.android.pandora.utils.viewbinding.bindingLayout
14 | import com.lodz.android.pandora.widget.rv.anko.linear
15 | import com.lodz.android.pandora.widget.rv.anko.setup
16 | import java.util.*
17 | import kotlin.collections.ArrayList
18 |
19 | /**
20 | * 评论
21 | * Created by zhouL on 2018/10/24.
22 | */
23 | @SuppressLint("NotifyDataSetChanged")
24 | class CommentFragment : LazyFragment() {
25 | companion object {
26 | fun newInstance(): CommentFragment = CommentFragment()
27 | }
28 |
29 | private val mBinding: FragmentCommentBinding by bindingLayout(FragmentCommentBinding::inflate)
30 |
31 | override fun getAbsViewBindingLayout(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = mBinding.root
32 |
33 | private lateinit var mAdapter: CommentAdapter
34 |
35 | override fun findViews(view: View, savedInstanceState: Bundle?) {
36 | super.findViews(view, savedInstanceState)
37 | mAdapter = mBinding.recyclerView
38 | .linear()
39 | .setup(CommentAdapter(requireContext()))
40 | mAdapter.setData(getData())
41 | mAdapter.notifyDataSetChanged()
42 | }
43 |
44 | private fun getData(): ArrayList {
45 | val millis = System.currentTimeMillis()
46 | val list = ArrayList()
47 | for (i in 0..50) {
48 | val date = DateUtils.getFormatString(DateUtils.TYPE_2, Date(millis - i * 50000000))
49 | list.add(date)
50 | }
51 | return list
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lodz/android/mmsplayerdemo/widget/InfoFragment.kt:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayerdemo.widget
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import com.lodz.android.mmsplayerdemo.databinding.FragmentInfoBinding
8 | import com.lodz.android.pandora.base.fragment.LazyFragment
9 | import com.lodz.android.pandora.utils.viewbinding.bindingLayout
10 |
11 | /**
12 | * 简介
13 | * Created by zhouL on 2018/10/24.
14 | */
15 | class InfoFragment : LazyFragment() {
16 | companion object {
17 | fun newInstance(): InfoFragment = InfoFragment()
18 | }
19 |
20 | private val mBinding: FragmentInfoBinding by bindingLayout(FragmentInfoBinding::inflate)
21 |
22 | override fun getAbsViewBindingLayout(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = mBinding.root
23 | }
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_bottom_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_bottom_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_center_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_center_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_fade_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_fade_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_left_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_left_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_right_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_right_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_top_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/anim_top_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_10.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_3.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_4.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_5.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_6.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_7.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_8.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_battery_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_battery_9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_progress_video_loading_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_progress_video_loading_1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_progress_video_loading_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_progress_video_loading_2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_progress_video_loading_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_progress_video_loading_3.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_seek_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_seek_thumb.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_brightness.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_brightness.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_error.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_pause.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_pause_sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_pause_sel.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_play.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_play_sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_play_sel.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_screen.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_screen_sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_screen_sel.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_setting.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_setting_sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_setting_sel.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_video_volume.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/drawable-xhdpi/ic_video_volume.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_00000000_corners_5_stroke_008577.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_4c4c4c_corners_8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_a0191919_corners_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_a04c4c4c_corners_8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/progress_video_loading_animation.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seekbar_color_style.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 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_bg_dialog_setting_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_bg_video_btn.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_text_dialog_setting_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_video_pause.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_video_play.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_video_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_video_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_simple_video.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_video.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
34 |
35 |
36 |
37 |
38 |
39 |
48 |
49 |
53 |
54 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
19 |
20 |
26 |
27 |
35 |
36 |
42 |
43 |
51 |
52 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rv_item_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
25 |
26 |
35 |
36 |
42 |
43 |
44 |
45 |
51 |
52 |
53 |
54 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rv_item_video_loading_tips.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_media.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
35 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
62 |
63 |
64 |
70 |
71 |
72 |
73 |
79 |
80 |
81 |
86 |
87 |
88 |
89 |
90 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_adjust_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_bottom_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
15 |
25 |
26 |
27 |
37 |
38 |
39 |
40 |
41 |
50 |
51 |
52 |
60 |
61 |
64 |
65 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_brightness.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
15 |
16 |
17 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_error.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
15 |
16 |
22 |
23 |
29 |
30 |
43 |
44 |
45 |
46 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
22 |
23 |
24 |
25 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_phone_data.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
15 |
16 |
22 |
23 |
35 |
36 |
42 |
43 |
50 |
51 |
52 |
53 |
54 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_top_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
19 |
32 |
33 |
41 |
42 |
43 |
50 |
51 |
52 |
61 |
62 |
63 |
69 |
70 |
71 |
72 |
76 |
77 |
78 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_video_volume.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
15 |
16 |
17 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 | #00000000
8 | #FFFFFF
9 | #000000
10 |
11 | #a0191919
12 | #a04c4c4c
13 |
14 | #4c4c4c
15 | #66008577
16 | #5a5a5a
17 | #9a9a9a
18 | #d9d9d9
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MMSPlayer
3 |
4 | 网络尚未连接,请检查您的网络状态
5 |
6 |
7 | 基础播放器界面
8 | 带控件播放器
9 | 半屏播放
10 | 开发中
11 |
12 | 加载完毕
13 | 开始缓冲
14 | 缓冲结束
15 | 播放结束
16 | 异常:%s
17 |
18 | 播放参数异常,请稍后再试
19 | %1$s / %2$s
20 | 初始化播放器… 【完成】
21 | 初始化播放组件… 【完成】
22 | 加载视频地址… 【完成】
23 | 开始解析视频地址…
24 | 解析视频地址… 【完成】
25 | 正在为您切换画质…
26 | 点击重试
27 | 视频解析出现异常…
28 | 正在使用非WIFI网络,播放将产生流量费用
29 | 流量播放
30 | 网络断开
31 | 未知网络
32 | Wifi
33 | 2G
34 | 3G
35 | 4G
36 |
37 | 深圳市绿色低碳科技促进会
38 | \t\t\t\t深圳市绿色低碳科技促进会(以下简称协会)是积极响应国家建设资源节约型、环境友好型社会,响应深圳市政府提出的在全国率先建设绿色低碳科技新城市,促进深圳经济可持续发展的号召,于二零一一年六月十四日成立的经深圳市民政局注册、登记的具有法人资格的、行业性、地方性的行业协会,主要由深圳低碳节能环保相关企业、事业单位、社会组织及个人自愿参加。协会现有会员企业100多家,是深圳一家较新的充满生命力的不以盈利为目的的公益性组织。
39 | 协会概况
40 | \t\t\t\t协会自成立伊始就致力于促进深圳市绿色经济可持续发展,推动低碳技术创新,走绿色低碳发展道路。协会除了业务范围内的工作,还与深圳环保局、深圳市经济贸易和信息化委员会、南山区政府、福田区政府等都有重大项目合作,不是只简单的服务企业,而是真正的帮助企业提升、进步,从而促进深圳市更好的发展绿色低碳经济。
41 | 协会宗旨
42 | \t\t\t\t遵守宪法、法律、法规和国家政策。遵守社会道德规范,维护国家根本利益,认真贯彻执行国家和深圳市鼓励绿色低碳发展的若干政策,通过为政府有关部门和会员服务,充分发挥促进会作为政府与企业之间的桥梁与纽带作用,达到促进深圳可再生能源持续发展的目的。
43 |
44 | 播放器设置
45 | 不连播
46 | 自动连播
47 | 单集循环
48 | 播完退出全屏
49 | 默认
50 | 全屏
51 | 16:9
52 | 4:3
53 | 倍数
54 | 0.5X
55 | 0.75X
56 | 1.0X
57 | 1.25X
58 | 1.5X
59 | 2.0X
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '8.4.0' apply false
4 | id 'com.android.library' version '8.4.0' apply false
5 | id 'org.jetbrains.kotlin.android' version '1.9.23' apply false
6 | }
7 |
8 | task clean(type: Delete) {
9 | delete rootProject.buildDir
10 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 | android.useAndroidX=true
17 | android.enableJetifier=true
18 | android.enableR8 = true
19 | android.defaults.buildfeatures.buildconfig=true
20 | android.nonTransitiveRClass=false
21 | android.nonFinalResIds=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Dec 01 10:03:19 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/img/1_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/img/1_loading.png
--------------------------------------------------------------------------------
/img/2_comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/img/2_comment.png
--------------------------------------------------------------------------------
/img/3_brightness_gesture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/img/3_brightness_gesture.png
--------------------------------------------------------------------------------
/img/4_volume_gesture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/img/4_volume_gesture.png
--------------------------------------------------------------------------------
/img/5_progress_gesture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/img/5_progress_gesture.png
--------------------------------------------------------------------------------
/img/6_full_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/img/6_full_screen.png
--------------------------------------------------------------------------------
/mmsplayer/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/mmsplayer/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 | //apply from: 'publish.gradle'
5 |
6 | android {
7 | compileSdk 34
8 | defaultConfig {
9 | minSdkVersion 19
10 | targetSdkVersion 34
11 | versionCode 13
12 | versionName "1.1.3"// 未上传
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | lint {
21 | abortOnError false
22 | checkReleaseBuilds false
23 | }
24 | namespace 'com.lodz.android.mmsplayer'
25 | }
26 |
27 | dependencies {
28 | implementation 'androidx.annotation:annotation:1.7.1'
29 | // IJK播放器
30 | // implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
31 | // implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
32 |
33 |
34 | // implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
35 | // implementation 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
36 | // implementation 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
37 | // implementation 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
38 | // implementation 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
39 | }
--------------------------------------------------------------------------------
/mmsplayer/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 |
--------------------------------------------------------------------------------
/mmsplayer/publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven-publish'
2 | apply plugin: 'signing'
3 |
4 | task androidSourcesJar(type: Jar) {
5 | archiveClassifier.set("sources")
6 | from android.sourceSets.main.java.source
7 |
8 | exclude "**/R.class"
9 | exclude "**/BuildConfig.class"
10 | }
11 |
12 | ext {
13 | PUBLISH_GROUP_ID = 'ink.lodz'
14 | PUBLISH_ARTIFACT_ID = 'mmsplayer'
15 | PUBLISH_VERSION = '1.1.2'
16 | }
17 |
18 | ext["signing.keyId"] = ''
19 | ext["signing.password"] = ''
20 | ext["signing.secretKeyRingFile"] = ''
21 | ext["ossrhUsername"] = ''
22 | ext["ossrhPassword"] = ''
23 |
24 | File secretPropsFile = project.rootProject.file('local.properties')
25 | if (secretPropsFile.exists()) {
26 | println "Found secret props file, loading props"
27 | Properties p = new Properties()
28 | p.load(new FileInputStream(secretPropsFile))
29 | p.each { name, value ->
30 | ext[name] = value
31 | }
32 | } else {
33 | println "No props file, loading env vars"
34 | }
35 | publishing {
36 | publications {
37 | release(MavenPublication) {
38 | // The coordinates of the library, being set from variables that
39 | // we'll set up in a moment
40 | groupId PUBLISH_GROUP_ID
41 | artifactId PUBLISH_ARTIFACT_ID
42 | version PUBLISH_VERSION
43 |
44 | // Two artifacts, the `aar` and the sources
45 | artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
46 | artifact androidSourcesJar
47 |
48 | // Self-explanatory metadata for the most part
49 | pom {
50 | name = PUBLISH_ARTIFACT_ID
51 | description = 'Hi, this is a vido play lib'
52 | // If your project has a dedicated site, use its URL here
53 | url = 'https://github.com/LZ9/MMSPlayer'
54 | licenses {
55 | license {
56 | //协议类型,一般默认Apache License2.0的话不用改:
57 | name = 'The Apache License, Version 2.0'
58 | url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
59 | }
60 | }
61 | developers {
62 | developer {
63 | id = 'Lodz'
64 | name = 'Lodz'
65 | email = 'lz.mms@foxmail.com'
66 | }
67 | }
68 | // Version control info, if you're using GitHub, follow the format as seen here
69 | scm {
70 | //修改成你的Git地址:
71 | connection = 'scm:git:github.com/LZ9/MMSPlayer.git'
72 | developerConnection = 'scm:git:ssh://github.com/LZ9/MMSPlayer.git'
73 | //分支地址:
74 | url = 'https://github.com/LZ9/MMSPlayer/tree/master'
75 | }
76 | // A slightly hacky fix so that your POM will include any transitive dependencies
77 | // that your library builds upon
78 | withXml {
79 | def dependenciesNode = asNode().appendNode('dependencies')
80 |
81 | project.configurations.implementation.allDependencies.each {
82 | def dependencyNode = dependenciesNode.appendNode('dependency')
83 | dependencyNode.appendNode('groupId', it.group)
84 | dependencyNode.appendNode('artifactId', it.name)
85 | dependencyNode.appendNode('version', it.version)
86 | }
87 | }
88 | }
89 | }
90 | }
91 | repositories {
92 | // The repository to publish to, Sonatype/MavenCentral
93 | maven {
94 | // This is an arbitrary name, you may also use "mavencentral" or
95 | // any other name that's descriptive for you
96 | name = "mavenCentral"
97 |
98 | def releasesRepoUrl = "https://s01.oss.sonatype.org/content/repositories/releases/"
99 | def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
100 | // You only need this if you want to publish snapshots, otherwise just set the URL
101 | // to the release repo directly
102 | url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
103 |
104 | // The username and password we've fetched earlier
105 | credentials {
106 | username ossrhUsername
107 | password ossrhPassword
108 | }
109 | }
110 | }
111 | }
112 | signing {
113 | sign publishing.publications
114 | }
--------------------------------------------------------------------------------
/mmsplayer/readme_mmsplayer_update.md:
--------------------------------------------------------------------------------
1 | # MMSPlayer更新记录
2 |
3 | ##### 2022/07/06
4 | 1. 升级工程和依赖库
5 | 2. 增加uri的设置方法
6 | 3. 发布1.1.2版本
7 |
8 | ##### 2022/05/09
9 | 1. 升级工程和依赖库
10 | 2. 适配android12
11 | 3. 监听器增加onMediaPlayerCreated回调,将创建后的IMediaPlayer返回给外部
12 | 4. 发布1.1.1版本
13 |
14 | ##### 2021/04/22
15 | 1. ijk改用源码引用,剥离jcenter依赖
16 | 2. 发布1.1.0版本
17 |
18 | ##### 2021/04/15
19 | 1. 切换到maven发布
20 | 2. 发布1.0.8版本
21 |
22 | ##### 2019/03/15
23 | 1. 更新gradle版本
24 | 2. 更新依赖库版本
25 | 3. 发布1.0.7版本
26 |
27 | ##### 2019/01/16
28 | 1. 更新gradle版本
29 | 2. 发布1.0.6版本
30 |
31 | ##### 2018/11/14
32 | 1. 播放器初始化方法增加设置入参
33 | 2. 替换动态库支持https协议
34 | 3. 发布1.0.5版本
35 |
36 | ##### 2018/10/22
37 | 1. 支持androidx
38 | 2. 更新ijk的依赖包和so库
39 | 3. 发布1.0.4版本
40 |
41 | ## 扩展
42 | - [回到顶部](https://github.com/LZ9/MMSPlayer/blob/master/mmsplayer/readme_mmsplayer_update.md#mmsplayer更新记录)
43 | - [MMSPlayer 主页](https://github.com/LZ9/MMSPlayer)
44 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/contract/IVideoPlayer.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.contract;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 |
6 | import com.lodz.android.mmsplayer.ijk.bean.MediaInfoBean;
7 | import com.lodz.android.mmsplayer.ijk.media.IMediaController;
8 | import com.lodz.android.mmsplayer.ijk.setting.IjkPlayerSetting;
9 | import com.lodz.android.mmsplayer.impl.MmsVideoView;
10 |
11 | /**
12 | * 播放器接口
13 | * Created by zhouL on 2016/11/30.
14 | */
15 | public interface IVideoPlayer {
16 |
17 | /** 初始化 */
18 | void init();
19 |
20 | /** 初始化 */
21 | void init(IjkPlayerSetting setting);
22 |
23 | /** 设置原生控制器 */
24 | void setMediaController(IMediaController controller);
25 |
26 | /** 设置播放路径 */
27 | void setVideoPath(String path);
28 |
29 | /** 设置播放路径 */
30 | void setVideoURI(Uri uri);
31 |
32 | /** 开始播放 */
33 | void start();
34 |
35 | /** 是否正在播放 */
36 | boolean isPlaying();
37 |
38 | /** 是否暂停 */
39 | boolean isPause();
40 |
41 | /** 是否播放结束 */
42 | boolean isCompleted();
43 |
44 | /** 是否已经设置播放地址 */
45 | boolean isAlreadySetPath();
46 |
47 | /** 暂停 */
48 | void pause();
49 |
50 | /** 重新播放 */
51 | void resume();
52 |
53 | /** 停止播放释放资源 */
54 | void release();
55 |
56 | /** 获取视频信息 */
57 | MediaInfoBean getMediaInfo();
58 |
59 | /** 切换宽高比 */
60 | int toggleAspectRatio();
61 |
62 | /**
63 | * 设置宽高比
64 | * @param aspectRatioType 宽高比类型
65 | */
66 | void setAspectRatio(int aspectRatioType);
67 |
68 | /** 获取当前渲染view名称 */
69 | String getRenderText(Context context);
70 |
71 | /** 获取当前播放器名称 */
72 | String getPlayerText(Context context);
73 |
74 | /** 获取缓存进度百分比 */
75 | int getBufferPercentage();
76 |
77 | /** 获取当前播放进度 */
78 | long getCurrentPlayPosition();
79 |
80 | /** 获取播放失败时的进度 */
81 | long getBreakPosition();
82 |
83 | /** 获取视频总时长 */
84 | long getVideoDuration();
85 |
86 | /** 设置监听器回调 */
87 | void setListener(MmsVideoView.Listener listener);
88 |
89 | /**
90 | * 设置播放位置
91 | * @param position 进度
92 | */
93 | void seekTo(long position);
94 |
95 | /**
96 | * 设置播放位置并开始播放
97 | * @param position 进度
98 | */
99 | void seekAndStart(long position);
100 |
101 | /**
102 | * 设置倍数(未生效,请勿调用)
103 | * @param speed 倍数
104 | */
105 | void setSpeed(float speed);
106 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/bean/MediaInfoBean.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.bean;
2 |
3 | /**
4 | * 视频信息实体
5 | * Created by zhouL on 2016/11/25.
6 | */
7 |
8 | public class MediaInfoBean {
9 |
10 | // ------------------- 播放器信息 -----------------
11 | /** 播放器名称 */
12 | public String playerName = "";
13 |
14 | // ------------------- 视频信息 -----------------
15 | /** 分辨率 */
16 | public String resolution = "";
17 | /** 视频长度 */
18 | public String length = "";
19 |
20 | // ------------------- 视频轨 -----------------
21 | /** 视频轨信息实体 */
22 | public TrackVideoInfoBean trackVideoInfoBean;
23 |
24 | // ------------------- 音频轨 -----------------
25 | /** 音频轨信息实体 */
26 | public TrackAudioInfoBean trackAudioInfoBean;
27 |
28 |
29 | @Override
30 | public String toString() {
31 | return "MediaInfoBean{" +
32 | "\n playerName='" + playerName + '\'' +
33 | ",\n resolution='" + resolution + '\'' +
34 | ",\n length='" + length + '\'' +
35 | ",\n trackVideoInfoBean=" + trackVideoInfoBean +
36 | ",\n trackAudioInfoBean=" + trackAudioInfoBean +
37 | '}';
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/bean/TrackAudioInfoBean.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.bean;
2 |
3 | /**
4 | * 音频轨信息实体
5 | * Created by zhouL on 2016/11/25.
6 | */
7 | public class TrackAudioInfoBean {
8 |
9 | public String type = "";
10 |
11 | public String language = "";
12 |
13 | public String codec = "";
14 |
15 | public String profileLevel = "";
16 |
17 | public String sampleRate = "";
18 |
19 | public String channels = "";
20 |
21 | public String bitRate = "";
22 |
23 | public boolean isSelected;
24 |
25 | @Override
26 | public String toString() {
27 | return "TrackAudioInfoBean{" +
28 | " type='" + type + '\'' +
29 | ", language='" + language + '\'' +
30 | ", codec='" + codec + '\'' +
31 | ", profileLevel='" + profileLevel + '\'' +
32 | ", sampleRate='" + sampleRate + '\'' +
33 | ", channels='" + channels + '\'' +
34 | ", bitRate='" + bitRate + '\'' +
35 | ", isSelected=" + isSelected +
36 | '}';
37 | }
38 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/bean/TrackVideoInfoBean.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.bean;
2 |
3 | /**
4 | * 视频轨信息实体
5 | * Created by zhouL on 2016/11/25.
6 | */
7 | public class TrackVideoInfoBean {
8 |
9 | public String type = "";
10 |
11 | public String language = "";
12 |
13 | public String codec = "";
14 |
15 | public String profileLevel = "";
16 |
17 | public String pixelFormat = "";
18 |
19 | public String resolution = "";
20 |
21 | public String frameRate = "";
22 |
23 | public String bitRate = "";
24 |
25 | public boolean isSelected;
26 |
27 | @Override
28 | public String toString() {
29 | return "TrackVideoInfoBean{" +
30 | " type='" + type + '\'' +
31 | ", language='" + language + '\'' +
32 | ", codec='" + codec + '\'' +
33 | ", profileLevel='" + profileLevel + '\'' +
34 | ", pixelFormat='" + pixelFormat + '\'' +
35 | ", resolution='" + resolution + '\'' +
36 | ", frameRate='" + frameRate + '\'' +
37 | ", bitRate='" + bitRate + '\'' +
38 | ", isSelected=" + isSelected +
39 | '}';
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/media/AndroidMediaController.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.media;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.MediaController;
6 |
7 | /**
8 | * 原生控制器
9 | * Created by zhouL on 2016/12/1.
10 | */
11 | public class AndroidMediaController extends MediaController implements IMediaController {
12 |
13 | public AndroidMediaController(Context context, AttributeSet attrs) {
14 | super(context, attrs);
15 | }
16 |
17 | public AndroidMediaController(Context context, boolean useFastForward) {
18 | super(context, useFastForward);
19 | }
20 |
21 | public AndroidMediaController(Context context) {
22 | super(context);
23 | }
24 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/media/FileMediaDataSource.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.media;
2 |
3 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
4 |
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.io.RandomAccessFile;
8 |
9 | public class FileMediaDataSource implements IMediaDataSource {
10 | private RandomAccessFile mFile;
11 | private long mFileSize;
12 |
13 | public FileMediaDataSource(File file) throws IOException {
14 | mFile = new RandomAccessFile(file, "r");
15 | mFileSize = mFile.length();
16 | }
17 |
18 | @Override
19 | public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
20 | if (mFile.getFilePointer() != position)
21 | mFile.seek(position);
22 |
23 | if (size == 0)
24 | return 0;
25 |
26 | return mFile.read(buffer, 0, size);
27 | }
28 |
29 | @Override
30 | public long getSize() throws IOException {
31 | return mFileSize;
32 | }
33 |
34 | @Override
35 | public void close() throws IOException {
36 | mFileSize = 0;
37 | mFile.close();
38 | mFile = null;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/media/IMediaController.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.media;
2 |
3 | import android.view.View;
4 | import android.widget.MediaController;
5 |
6 | /**
7 | * 控制器接口
8 | * Created by zhouL on 2016/12/1.
9 | */
10 |
11 | public interface IMediaController {
12 | void hide();
13 |
14 | boolean isShowing();
15 |
16 | void setAnchorView(View view);
17 |
18 | void setEnabled(boolean enabled);
19 |
20 | void setMediaPlayer(MediaController.MediaPlayerControl player);
21 |
22 | void show(int timeout);
23 |
24 | void show();
25 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/media/IRenderView.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.media;
2 |
3 | import android.graphics.SurfaceTexture;
4 | import android.view.Surface;
5 | import android.view.SurfaceHolder;
6 | import android.view.View;
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.Nullable;
9 | import tv.danmaku.ijk.media.player.IMediaPlayer;
10 |
11 | /**
12 | * 渲染控件接口
13 | * Created by zhouL on 2016/12/1.
14 | */
15 | public interface IRenderView {
16 | int AR_ASPECT_FIT_PARENT = 0; // without clip
17 | int AR_ASPECT_FILL_PARENT = 1; // may clip
18 | int AR_ASPECT_WRAP_CONTENT = 2;
19 | int AR_MATCH_PARENT = 3;
20 | int AR_16_9_FIT_PARENT = 4;
21 | int AR_4_3_FIT_PARENT = 5;
22 |
23 | View getView();
24 |
25 | boolean shouldWaitForResize();
26 |
27 | void setVideoSize(int videoWidth, int videoHeight);
28 |
29 | void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen);
30 |
31 | void setVideoRotation(int degree);
32 |
33 | void setAspectRatio(int aspectRatio);
34 |
35 | void addRenderCallback(@NonNull IRenderCallback callback);
36 |
37 | void removeRenderCallback(@NonNull IRenderCallback callback);
38 |
39 | interface ISurfaceHolder {
40 | void bindToMediaPlayer(IMediaPlayer mp);
41 |
42 | @NonNull
43 | IRenderView getRenderView();
44 |
45 | @Nullable
46 | SurfaceHolder getSurfaceHolder();
47 |
48 | @Nullable
49 | Surface openSurface();
50 |
51 | @Nullable
52 | SurfaceTexture getSurfaceTexture();
53 | }
54 |
55 | interface IRenderCallback {
56 | /**
57 | * @param holder
58 | * @param width could be 0
59 | * @param height could be 0
60 | */
61 | void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height);
62 |
63 | /**
64 | * @param holder
65 | * @param format could be 0
66 | * @param width
67 | * @param height
68 | */
69 | void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height);
70 |
71 | void onSurfaceDestroyed(@NonNull ISurfaceHolder holder);
72 | }
73 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/media/InfoHudViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.media;
2 |
3 | import android.content.Context;
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.util.Log;
7 | import com.lodz.android.mmsplayer.R;
8 | import tv.danmaku.ijk.media.player.IMediaPlayer;
9 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
10 | import tv.danmaku.ijk.media.player.MediaPlayerProxy;
11 |
12 | import java.lang.ref.WeakReference;
13 | import java.util.Locale;
14 |
15 | /**
16 | * 播放信息打印类
17 | * Created by zhouL on 2016/12/1.
18 | */
19 |
20 | public class InfoHudViewHolder {
21 | private IMediaPlayer mMediaPlayer;
22 | private long mLoadCost = 0;
23 | private long mSeekCost = 0;
24 |
25 | private Context mContext;
26 |
27 | private HudHandler mHandler;
28 |
29 | public InfoHudViewHolder(Context context) {
30 | this.mContext = context;
31 | mHandler = new HudHandler(mHudListener);
32 | }
33 |
34 | private void setRowValue(int id, String value) {
35 | Log.i(IjkVideoView.TAG_INFO_HUD, mContext.getString(id) + " : " + value);
36 | }
37 |
38 | public void setMediaPlayer(IMediaPlayer mp) {
39 | mMediaPlayer = mp;
40 | if (mMediaPlayer != null) {
41 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500);
42 | } else {
43 | mHandler.removeMessages(MSG_UPDATE_HUD);
44 | }
45 | }
46 |
47 | private static String formatedDurationMilli(long duration) {
48 | if (duration >= 1000) {
49 | return String.format(Locale.US, "%.2f sec", ((float) duration) / 1000);
50 | } else {
51 | return String.format(Locale.US, "%d msec", duration);
52 | }
53 | }
54 |
55 | private static String formatedSpeed(long bytes, long elapsed_milli) {
56 | if (elapsed_milli <= 0) {
57 | return "0 B/s";
58 | }
59 |
60 | if (bytes <= 0) {
61 | return "0 B/s";
62 | }
63 |
64 | float bytes_per_sec = ((float) bytes) * 1000.f / elapsed_milli;
65 | if (bytes_per_sec >= 1000 * 1000) {
66 | return String.format(Locale.US, "%.2f MB/s", bytes_per_sec / 1000 / 1000);
67 | } else if (bytes_per_sec >= 1000) {
68 | return String.format(Locale.US, "%.1f KB/s", bytes_per_sec / 1000);
69 | } else {
70 | return String.format(Locale.US, "%d B/s", (long) bytes_per_sec);
71 | }
72 | }
73 |
74 | void updateLoadCost(long time) {
75 | mLoadCost = time;
76 | }
77 |
78 | void updateSeekCost(long time) {
79 | mSeekCost = time;
80 | }
81 |
82 | private static String formatedSize(long bytes) {
83 | if (bytes >= 100 * 1000) {
84 | return String.format(Locale.US, "%.2f MB", ((float) bytes) / 1000 / 1000);
85 | } else if (bytes >= 100) {
86 | return String.format(Locale.US, "%.1f KB", ((float) bytes) / 1000);
87 | } else {
88 | return String.format(Locale.US, "%d B", bytes);
89 | }
90 | }
91 |
92 | private static final int MSG_UPDATE_HUD = 1;
93 |
94 | private static class HudHandler extends Handler {
95 | WeakReference mWeakReference;
96 |
97 | private HudHandler(HudListener listener) {
98 | mWeakReference = new WeakReference<>(listener);
99 | }
100 |
101 | @Override
102 | public void handleMessage(Message msg) {
103 | super.handleMessage(msg);
104 | if (msg.what == MSG_UPDATE_HUD) {
105 | HudListener listener = mWeakReference.get();
106 | if (listener != null) {
107 | listener.onUpdate();
108 | }
109 | }
110 | }
111 | }
112 |
113 | private HudListener mHudListener = new HudListener() {
114 | @Override
115 | public void onUpdate() {
116 | updateHud();
117 | mHandler.removeMessages(MSG_UPDATE_HUD);
118 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500);
119 | }
120 | };
121 |
122 | private void updateHud() {
123 | InfoHudViewHolder holder = InfoHudViewHolder.this;
124 | IjkMediaPlayer mp = null;
125 | if (mMediaPlayer == null)
126 | return;
127 | if (mMediaPlayer instanceof IjkMediaPlayer) {
128 | mp = (IjkMediaPlayer) mMediaPlayer;
129 | } else if (mMediaPlayer instanceof MediaPlayerProxy) {
130 | MediaPlayerProxy proxy = (MediaPlayerProxy) mMediaPlayer;
131 | IMediaPlayer internal = proxy.getInternalMediaPlayer();
132 | if (internal instanceof IjkMediaPlayer)
133 | mp = (IjkMediaPlayer) internal;
134 | }
135 | if (mp == null)
136 | return;
137 |
138 | int vdec = mp.getVideoDecoder();
139 | switch (vdec) {
140 | case IjkMediaPlayer.FFP_PROPV_DECODER_AVCODEC:
141 | setRowValue(R.string.mmsplayer_vdec, "avcodec");
142 | break;
143 | case IjkMediaPlayer.FFP_PROPV_DECODER_MEDIACODEC:
144 | setRowValue(R.string.mmsplayer_vdec, "MediaCodec");
145 | break;
146 | default:
147 | setRowValue(R.string.mmsplayer_vdec, "");
148 | break;
149 | }
150 |
151 | float fpsOutput = mp.getVideoOutputFramesPerSecond();
152 | float fpsDecode = mp.getVideoDecodeFramesPerSecond();
153 | setRowValue(R.string.mmsplayer_fps, String.format(Locale.US, "%.2f / %.2f", fpsDecode, fpsOutput));
154 |
155 | long videoCachedDuration = mp.getVideoCachedDuration();
156 | long audioCachedDuration = mp.getAudioCachedDuration();
157 | long videoCachedBytes = mp.getVideoCachedBytes();
158 | long audioCachedBytes = mp.getAudioCachedBytes();
159 | long tcpSpeed = mp.getTcpSpeed();
160 | long bitRate = mp.getBitRate();
161 | long seekLoadDuration = mp.getSeekLoadDuration();
162 |
163 | setRowValue(R.string.mmsplayer_v_cache, String.format(Locale.US, "%s, %s", formatedDurationMilli(videoCachedDuration), formatedSize(videoCachedBytes)));
164 | setRowValue(R.string.mmsplayer_a_cache, String.format(Locale.US, "%s, %s", formatedDurationMilli(audioCachedDuration), formatedSize(audioCachedBytes)));
165 | setRowValue(R.string.mmsplayer_load_cost, String.format(Locale.US, "%d ms", mLoadCost));
166 | setRowValue(R.string.mmsplayer_seek_cost, String.format(Locale.US, "%d ms", mSeekCost));
167 | setRowValue(R.string.mmsplayer_seek_load_cost, String.format(Locale.US, "%d ms", seekLoadDuration));
168 | setRowValue(R.string.mmsplayer_tcp_speed, String.format(Locale.US, "%s", formatedSpeed(tcpSpeed, 1000)));
169 | setRowValue(R.string.mmsplayer_bit_rate, String.format(Locale.US, "%.2f kbs", bitRate / 1000f));
170 | Log.i(IjkVideoView.TAG_INFO_HUD, " \n ");
171 | }
172 |
173 | private interface HudListener {
174 | void onUpdate();
175 | }
176 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/media/MediaPlayerCompat.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.media;
2 |
3 | import tv.danmaku.ijk.media.player.IMediaPlayer;
4 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
5 | import tv.danmaku.ijk.media.player.MediaPlayerProxy;
6 | import tv.danmaku.ijk.media.player.TextureMediaPlayer;
7 |
8 | public class MediaPlayerCompat {
9 | public static String getName(IMediaPlayer mp) {
10 | if (mp == null) {
11 | return "null";
12 | } else if (mp instanceof TextureMediaPlayer) {
13 | StringBuilder sb = new StringBuilder("TextureMediaPlayer <");
14 | IMediaPlayer internalMediaPlayer = ((TextureMediaPlayer) mp).getInternalMediaPlayer();
15 | if (internalMediaPlayer == null) {
16 | sb.append("null>");
17 | } else {
18 | sb.append(internalMediaPlayer.getClass().getSimpleName());
19 | sb.append(">");
20 | }
21 | return sb.toString();
22 | } else {
23 | return mp.getClass().getSimpleName();
24 | }
25 | }
26 |
27 | public static IjkMediaPlayer getIjkMediaPlayer(IMediaPlayer mp) {
28 | IjkMediaPlayer ijkMediaPlayer = null;
29 | if (mp == null) {
30 | return null;
31 | } if (mp instanceof IjkMediaPlayer) {
32 | ijkMediaPlayer = (IjkMediaPlayer) mp;
33 | } else if (mp instanceof MediaPlayerProxy && ((MediaPlayerProxy) mp).getInternalMediaPlayer() instanceof IjkMediaPlayer) {
34 | ijkMediaPlayer = (IjkMediaPlayer) ((MediaPlayerProxy) mp).getInternalMediaPlayer();
35 | }
36 | return ijkMediaPlayer;
37 | }
38 |
39 | public static void selectTrack(IMediaPlayer mp, int stream) {
40 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
41 | if (ijkMediaPlayer == null)
42 | return;
43 | ijkMediaPlayer.selectTrack(stream);
44 | }
45 |
46 | public static void deselectTrack(IMediaPlayer mp, int stream) {
47 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
48 | if (ijkMediaPlayer == null)
49 | return;
50 | ijkMediaPlayer.deselectTrack(stream);
51 | }
52 |
53 | public static int getSelectedTrack(IMediaPlayer mp, int trackType) {
54 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
55 | if (ijkMediaPlayer == null)
56 | return -1;
57 | return ijkMediaPlayer.getSelectedTrack(trackType);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/services/MediaPlayerService.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.services;
2 |
3 | import android.app.Service;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.IBinder;
7 | import androidx.annotation.Nullable;
8 | import tv.danmaku.ijk.media.player.IMediaPlayer;
9 |
10 | /**
11 | * 后台播放服务
12 | * Created by zhouL on 2016/12/1.
13 | */
14 | public class MediaPlayerService extends Service {
15 | private static IMediaPlayer sMediaPlayer;
16 |
17 | public static Intent newIntent(Context context) {
18 | return new Intent(context, MediaPlayerService.class);
19 | }
20 |
21 | public static void intentToStart(Context context) {
22 | context.startService(newIntent(context));
23 | }
24 |
25 | public static void intentToStop(Context context) {
26 | context.stopService(newIntent(context));
27 | }
28 |
29 | @Nullable
30 | @Override
31 | public IBinder onBind(Intent intent) {
32 | return null;
33 | }
34 |
35 | public static void setMediaPlayer(IMediaPlayer mp) {
36 | if (sMediaPlayer != null && sMediaPlayer != mp) {
37 | if (sMediaPlayer.isPlaying())
38 | sMediaPlayer.stop();
39 | sMediaPlayer.release();
40 | sMediaPlayer = null;
41 | }
42 | sMediaPlayer = mp;
43 | }
44 |
45 | public static IMediaPlayer getMediaPlayer() {
46 | return sMediaPlayer;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/setting/IjkPlayerSetting.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.setting;
2 |
3 |
4 | import androidx.annotation.IntDef;
5 | import com.lodz.android.mmsplayer.ijk.media.IRenderView;
6 |
7 | import java.lang.annotation.Retention;
8 | import java.lang.annotation.RetentionPolicy;
9 |
10 | /**
11 | * IJK播放器设置
12 | * Created by zhouL on 2016/12/1.
13 | */
14 | public class IjkPlayerSetting {
15 |
16 | /** 获取ijk播放器默认配置 */
17 | public static IjkPlayerSetting getDefault(){
18 | IjkPlayerSetting setting = new IjkPlayerSetting();
19 | setting.playerType = PlayerType.PLAY_IJK;
20 | setting.isBackgroundPlay = false;
21 | setting.isUsingMediaCodec = true;
22 | setting.isUsingMediaCodecAutoRotate = true;
23 | setting.isMediaCodecHandleResolutionChange = true;
24 | setting.isUsingOpenSLES = true;
25 | setting.pixelFormatType = PixelFormatType.PIXEL_AUTO;
26 | setting.isUsingMediaDataSource = true;
27 | setting.renderViewType = RenderViewType.TEXTURE_VIEW;
28 | setting.isEnableDetachedSurfaceTexture = true;
29 | setting.aspectRatioType = IRenderView.AR_ASPECT_FIT_PARENT;
30 | return setting;
31 | }
32 |
33 | //--------------------------- 播放器设置 -----------------------------------
34 | @Retention(RetentionPolicy.SOURCE)
35 | @IntDef({PlayerType.PALY_ANDROID_MEDIA, PlayerType.PLAY_IJK})
36 | public @interface PlayerType {
37 | /** android原生播放器 */
38 | int PALY_ANDROID_MEDIA = 1;
39 | /** Ijk播放器 */
40 | int PLAY_IJK = 2;
41 | }
42 |
43 | /** 播放器类型 */
44 | @PlayerType
45 | public int playerType = PlayerType.PLAY_IJK;
46 |
47 | //--------------------------- 后台播放设置 -----------------------------------
48 | /** 是否后台播放(4.0+) */
49 | public boolean isBackgroundPlay = false;
50 |
51 | //--------------------------- 硬解码设置 -----------------------------------
52 | /** 是否使用硬解码 */
53 | public boolean isUsingMediaCodec = true;
54 | /** 是否使用硬解码下自动旋转 */
55 | public boolean isUsingMediaCodecAutoRotate = true;
56 | /** 是否使用硬解码下处理分辨率更改 */
57 | public boolean isMediaCodecHandleResolutionChange = true;
58 |
59 | //--------------------------- 使用OpenGLES -----------------------------------
60 | /** 是否使用OpenGLES */
61 | public boolean isUsingOpenSLES = true;
62 |
63 | //--------------------------- 设置像素格式 -----------------------------------
64 | @Retention(RetentionPolicy.SOURCE)
65 | @IntDef({PixelFormatType.PIXEL_AUTO, PixelFormatType.PIXEL_RGB_565, PixelFormatType.PIXEL_RGB_888, PixelFormatType.PIXEL_RGBX_8888,
66 | PixelFormatType.PIXEL_YV12, PixelFormatType.PIXEL_OPENGL_ES2})
67 | public @interface PixelFormatType {
68 | /** 自动选择 */
69 | int PIXEL_AUTO = 0;
70 | /** RGB 565 */
71 | int PIXEL_RGB_565 = 1;
72 | /** RGB 888 */
73 | int PIXEL_RGB_888 = 2;
74 | /** RGBX 8888 */
75 | int PIXEL_RGBX_8888 = 3;
76 | /** YV12 */
77 | int PIXEL_YV12 = 4;
78 | /** OpenGL ES2 */
79 | int PIXEL_OPENGL_ES2 = 5;
80 | }
81 |
82 | /** 像素格式 */
83 | @PixelFormatType
84 | public int pixelFormatType = PixelFormatType.PIXEL_AUTO;
85 |
86 | //--------------------------- 使用数据源 -----------------------------------
87 | /** 是否使用数据源(需要6.0+且播放本地文件) */
88 | public boolean isUsingMediaDataSource = true;
89 |
90 | //--------------------------- 渲染的view -----------------------------------
91 | @Retention(RetentionPolicy.SOURCE)
92 | @IntDef({RenderViewType.NO_VIEW, RenderViewType.SURFACE_VIEW, RenderViewType.TEXTURE_VIEW})
93 | public @interface RenderViewType {
94 | /** 不使用渲染的view */
95 | int NO_VIEW = 0;
96 | /** 用surfaceview渲染 */
97 | int SURFACE_VIEW = 1;
98 | /** 用textureview渲染 */
99 | int TEXTURE_VIEW = 2;
100 | }
101 |
102 | /** 渲染的view的类型 */
103 | @RenderViewType
104 | public int renderViewType = RenderViewType.TEXTURE_VIEW;
105 |
106 | /** 是否使用SurfaceTexture处理视频图像 */
107 | public boolean isEnableDetachedSurfaceTexture = true;
108 |
109 | //--------------------------- 播放器长宽比类型 -----------------------------------
110 | @Retention(RetentionPolicy.SOURCE)
111 | @IntDef({IRenderView.AR_ASPECT_FIT_PARENT, IRenderView.AR_ASPECT_FILL_PARENT, IRenderView.AR_ASPECT_WRAP_CONTENT,
112 | IRenderView.AR_16_9_FIT_PARENT, IRenderView.AR_4_3_FIT_PARENT})
113 | public @interface AspectRatioType {}
114 | @AspectRatioType
115 | public int aspectRatioType = IRenderView.AR_ASPECT_FIT_PARENT;
116 |
117 | @Override
118 | public String toString() {
119 | return "IjkPlayerSetting{" +
120 | "\n playerType=" + playerType +
121 | ", \n isBackgroundPlay=" + isBackgroundPlay +
122 | ", \n isUsingMediaCodec=" + isUsingMediaCodec +
123 | ", \n isUsingMediaCodecAutoRotate=" + isUsingMediaCodecAutoRotate +
124 | ", \n isMediaCodecHandleResolutionChange=" + isMediaCodecHandleResolutionChange +
125 | ", \n isUsingOpenSLES=" + isUsingOpenSLES +
126 | ", \n pixelFormatType=" + pixelFormatType +
127 | ", \n isUsingMediaDataSource=" + isUsingMediaDataSource +
128 | ", \n renderViewType=" + renderViewType +
129 | ", \n isEnableDetachedSurfaceTexture=" + isEnableDetachedSurfaceTexture +
130 | ", \n aspectRatioType=" + aspectRatioType +
131 | '}';
132 | }
133 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/ijk/utils/MediaInfoUtils.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.ijk.utils;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 | import com.lodz.android.mmsplayer.R;
6 | import tv.danmaku.ijk.media.player.misc.ITrackInfo;
7 |
8 | import java.util.Locale;
9 |
10 | /**
11 | * 视频信息帮助类
12 | * Created by zhouL on 2016/12/1.
13 | */
14 | public class MediaInfoUtils {
15 |
16 | /**
17 | * 格式化分辨率
18 | * @param width 视频宽度
19 | * @param height 视频高度
20 | */
21 | public static String buildResolution(int width, int height, int sarNum, int sarDen) {
22 | StringBuilder sb = new StringBuilder();
23 | sb.append(width);
24 | sb.append(" x ");
25 | sb.append(height);
26 |
27 | if (sarNum > 1 || sarDen > 1) {
28 | sb.append("[");
29 | sb.append(sarNum);
30 | sb.append(":");
31 | sb.append(sarDen);
32 | sb.append("]");
33 | }
34 |
35 | return sb.toString();
36 | }
37 |
38 | /**
39 | * 格式化时间
40 | * @param duration 时长
41 | */
42 | public static String buildTimeMilli(long duration) {
43 | long total_seconds = duration / 1000;
44 | long hours = total_seconds / 3600;
45 | long minutes = (total_seconds % 3600) / 60;
46 | long seconds = total_seconds % 60;
47 | if (duration <= 0) {
48 | return "00:00";
49 | }
50 | if (hours >= 100) {
51 | return String.format(Locale.US, "%d:%02d:%02d", hours, minutes, seconds);
52 | } else if (hours > 0) {
53 | return String.format(Locale.US, "%02d:%02d:%02d", hours, minutes, seconds);
54 | } else {
55 | return String.format(Locale.US, "%02d:%02d", minutes, seconds);
56 | }
57 | }
58 |
59 | /**
60 | * 获取轨道名称
61 | * @param context 上下文
62 | * @param type 轨道类型
63 | */
64 | public static String buildTrackType(Context context, int type) {
65 | switch (type) {
66 | case ITrackInfo.MEDIA_TRACK_TYPE_VIDEO:
67 | return context.getString(R.string.mmsplayer_tracktype_video);
68 | case ITrackInfo.MEDIA_TRACK_TYPE_AUDIO:
69 | return context.getString(R.string.mmsplayer_tracktype_audio);
70 | case ITrackInfo.MEDIA_TRACK_TYPE_SUBTITLE:
71 | return context.getString(R.string.mmsplayer_tracktype_subtitle);
72 | case ITrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT:
73 | return context.getString(R.string.mmsplayer_tracktype_timedtext);
74 | case ITrackInfo.MEDIA_TRACK_TYPE_METADATA:
75 | return context.getString(R.string.mmsplayer_tracktype_metadata);
76 | case ITrackInfo.MEDIA_TRACK_TYPE_UNKNOWN:
77 | default:
78 | return context.getString(R.string.mmsplayer_tracktype_unknown);
79 | }
80 | }
81 |
82 | public static String buildLanguage(String language) {
83 | return TextUtils.isEmpty(language)? "N/A" : language;
84 | }
85 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/com/lodz/android/mmsplayer/impl/MmsVideoView.java:
--------------------------------------------------------------------------------
1 | package com.lodz.android.mmsplayer.impl;
2 |
3 | import android.content.Context;
4 | import android.media.MediaPlayer;
5 | import android.util.AttributeSet;
6 |
7 | import androidx.annotation.IntDef;
8 | import androidx.annotation.NonNull;
9 |
10 | import com.lodz.android.mmsplayer.R;
11 | import com.lodz.android.mmsplayer.contract.IVideoPlayer;
12 | import com.lodz.android.mmsplayer.ijk.media.IjkVideoView;
13 | import com.lodz.android.mmsplayer.ijk.setting.IjkPlayerSetting;
14 |
15 | import java.lang.annotation.Retention;
16 | import java.lang.annotation.RetentionPolicy;
17 |
18 | import tv.danmaku.ijk.media.player.IMediaPlayer;
19 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
20 |
21 | /**
22 | * 播放器
23 | * Created by zhouL on 2017/2/15.
24 | */
25 | public class MmsVideoView extends IjkVideoView implements IVideoPlayer {
26 |
27 | private Listener mListener;
28 |
29 | public MmsVideoView(Context context) {
30 | super(context);
31 | }
32 |
33 | public MmsVideoView(Context context, AttributeSet attrs) {
34 | super(context, attrs);
35 | }
36 |
37 | public MmsVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
38 | super(context, attrs, defStyleAttr);
39 | }
40 |
41 | public MmsVideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
42 | super(context, attrs, defStyleAttr, defStyleRes);
43 | }
44 |
45 | @Override
46 | public void init() {
47 | init(IjkPlayerSetting.getDefault());
48 | }
49 |
50 | @Override
51 | public void release() {
52 | stopPlayback();
53 | release(true);
54 | stopBackgroundPlay();
55 | IjkMediaPlayer.native_profileEnd();
56 | }
57 |
58 | @Override
59 | public void setListener(final Listener listener) {
60 | mListener = listener;
61 | if (listener == null) {
62 | return;
63 | }
64 |
65 | setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {
66 | @Override
67 | public void onPrepared(IMediaPlayer iMediaPlayer) {
68 | listener.onPrepared();
69 | }
70 | });
71 |
72 | setOnCompletionListener(new IMediaPlayer.OnCompletionListener() {
73 | @Override
74 | public void onCompletion(IMediaPlayer iMediaPlayer) {
75 | listener.onCompletion();
76 | }
77 | });
78 |
79 | setOnInfoListener(new IMediaPlayer.OnInfoListener() {
80 | @Override
81 | public boolean onInfo(IMediaPlayer iMediaPlayer, int arg1, int arg2) {
82 | switch (arg1) {
83 | case IMediaPlayer.MEDIA_INFO_BUFFERING_START:
84 | listener.onBufferingStart();
85 | break;
86 | case IMediaPlayer.MEDIA_INFO_BUFFERING_END:
87 | listener.onBufferingEnd();
88 | break;
89 | }
90 | return false;
91 | }
92 | });
93 |
94 | setOnErrorListener(new IMediaPlayer.OnErrorListener() {
95 | @Override
96 | public boolean onError(IMediaPlayer iMediaPlayer, int framework_err, int impl_err) {
97 | int errorType = Listener.ErrorType.UNKNOWN;
98 | String msg = getContext().getString(R.string.mmsplayer_videoview_error_text_unknown);
99 | switch (framework_err) {
100 | case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
101 | errorType = Listener.ErrorType.INVALID_PROGRESSIVE_PLAYBACK;
102 | msg = getContext().getString(R.string.mmsplayer_videoview_error_text_invalid_progressive_playback);
103 | break;
104 | case -10000:
105 | errorType = Listener.ErrorType.NETWORK_ERROR;
106 | msg = getContext().getString(R.string.mmsplayer_videoview_error_text_io);
107 | break;
108 | }
109 | listener.onError(errorType, msg);
110 | return true;
111 | }
112 | });
113 | }
114 |
115 | @Override
116 | public void seekAndStart(long position) {
117 | seekTo(position);
118 | if (!isPlaying()) {
119 | start();
120 | }
121 | }
122 |
123 | @Override
124 | public void onMediaPlayerCreated(IMediaPlayer mMediaPlayer) {
125 | super.onMediaPlayerCreated(mMediaPlayer);
126 | if (mListener != null) {
127 | mListener.onMediaPlayerCreated(mMediaPlayer);
128 | }
129 | }
130 |
131 | public interface Listener {
132 | @Retention(RetentionPolicy.SOURCE)
133 | @IntDef({ErrorType.UNKNOWN, ErrorType.INVALID_PROGRESSIVE_PLAYBACK, ErrorType.NETWORK_ERROR})
134 | @interface ErrorType {
135 | int UNKNOWN = 0;
136 |
137 | int INVALID_PROGRESSIVE_PLAYBACK = 1;
138 |
139 | int NETWORK_ERROR = 2;
140 | }
141 |
142 |
143 | /**
144 | * 播放器就绪
145 | */
146 | void onPrepared();
147 |
148 | /**
149 | * 缓冲开始
150 | */
151 | void onBufferingStart();
152 |
153 | /**
154 | * 缓冲结束
155 | */
156 | void onBufferingEnd();
157 |
158 | /**
159 | * 播放完成
160 | */
161 | void onCompletion();
162 |
163 | /**
164 | * 错误回调
165 | *
166 | * @param errorType 错误类型
167 | * @param msg 错误信息
168 | */
169 | void onError(@ErrorType int errorType, String msg);
170 |
171 | /** MediaPlayer创建 */
172 | void onMediaPlayerCreated(@NonNull IMediaPlayer mediaPlayer);
173 | }
174 |
175 | }
176 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 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 tv.danmaku.ijk.media.player;
19 |
20 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
21 |
22 | @SuppressWarnings("WeakerAccess")
23 | public abstract class AbstractMediaPlayer implements IMediaPlayer {
24 | private OnPreparedListener mOnPreparedListener;
25 | private OnCompletionListener mOnCompletionListener;
26 | private OnBufferingUpdateListener mOnBufferingUpdateListener;
27 | private OnSeekCompleteListener mOnSeekCompleteListener;
28 | private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
29 | private OnErrorListener mOnErrorListener;
30 | private OnInfoListener mOnInfoListener;
31 | private OnTimedTextListener mOnTimedTextListener;
32 |
33 | public final void setOnPreparedListener(OnPreparedListener listener) {
34 | mOnPreparedListener = listener;
35 | }
36 |
37 | public final void setOnCompletionListener(OnCompletionListener listener) {
38 | mOnCompletionListener = listener;
39 | }
40 |
41 | public final void setOnBufferingUpdateListener(
42 | OnBufferingUpdateListener listener) {
43 | mOnBufferingUpdateListener = listener;
44 | }
45 |
46 | public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
47 | mOnSeekCompleteListener = listener;
48 | }
49 |
50 | public final void setOnVideoSizeChangedListener(
51 | OnVideoSizeChangedListener listener) {
52 | mOnVideoSizeChangedListener = listener;
53 | }
54 |
55 | public final void setOnErrorListener(OnErrorListener listener) {
56 | mOnErrorListener = listener;
57 | }
58 |
59 | public final void setOnInfoListener(OnInfoListener listener) {
60 | mOnInfoListener = listener;
61 | }
62 |
63 | public final void setOnTimedTextListener(OnTimedTextListener listener) {
64 | mOnTimedTextListener = listener;
65 | }
66 |
67 | public void resetListeners() {
68 | mOnPreparedListener = null;
69 | mOnBufferingUpdateListener = null;
70 | mOnCompletionListener = null;
71 | mOnSeekCompleteListener = null;
72 | mOnVideoSizeChangedListener = null;
73 | mOnErrorListener = null;
74 | mOnInfoListener = null;
75 | mOnTimedTextListener = null;
76 | }
77 |
78 | protected final void notifyOnPrepared() {
79 | if (mOnPreparedListener != null)
80 | mOnPreparedListener.onPrepared(this);
81 | }
82 |
83 | protected final void notifyOnCompletion() {
84 | if (mOnCompletionListener != null)
85 | mOnCompletionListener.onCompletion(this);
86 | }
87 |
88 | protected final void notifyOnBufferingUpdate(int percent) {
89 | if (mOnBufferingUpdateListener != null)
90 | mOnBufferingUpdateListener.onBufferingUpdate(this, percent);
91 | }
92 |
93 | protected final void notifyOnSeekComplete() {
94 | if (mOnSeekCompleteListener != null)
95 | mOnSeekCompleteListener.onSeekComplete(this);
96 | }
97 |
98 | protected final void notifyOnVideoSizeChanged(int width, int height,
99 | int sarNum, int sarDen) {
100 | if (mOnVideoSizeChangedListener != null)
101 | mOnVideoSizeChangedListener.onVideoSizeChanged(this, width, height,
102 | sarNum, sarDen);
103 | }
104 |
105 | protected final boolean notifyOnError(int what, int extra) {
106 | return mOnErrorListener != null && mOnErrorListener.onError(this, what, extra);
107 | }
108 |
109 | protected final boolean notifyOnInfo(int what, int extra) {
110 | return mOnInfoListener != null && mOnInfoListener.onInfo(this, what, extra);
111 | }
112 |
113 | protected final void notifyOnTimedText(IjkTimedText text) {
114 | if (mOnTimedTextListener != null)
115 | mOnTimedTextListener.onTimedText(this, text);
116 | }
117 |
118 | public void setDataSource(IMediaDataSource mediaDataSource) {
119 | throw new UnsupportedOperationException();
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.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 tv.danmaku.ijk.media.player;
19 |
20 | import android.graphics.SurfaceTexture;
21 |
22 | public interface ISurfaceTextureHolder {
23 | void setSurfaceTexture(SurfaceTexture surfaceTexture);
24 |
25 | SurfaceTexture getSurfaceTexture();
26 |
27 | void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost);
28 | }
29 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.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 tv.danmaku.ijk.media.player;
19 |
20 | import android.graphics.SurfaceTexture;
21 |
22 | public interface ISurfaceTextureHost {
23 | void releaseSurfaceTexture(SurfaceTexture surfaceTexture);
24 | }
25 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 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 tv.danmaku.ijk.media.player;
19 |
20 | public interface IjkLibLoader {
21 | void loadLibrary(String libName) throws UnsatisfiedLinkError,
22 | SecurityException;
23 | }
24 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/IjkTimedText.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Zheng Yuan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package tv.danmaku.ijk.media.player;
18 |
19 | import android.graphics.Rect;
20 | import java.lang.String;
21 |
22 | public final class IjkTimedText {
23 |
24 | private Rect mTextBounds = null;
25 | private String mTextChars = null;
26 |
27 | public IjkTimedText(Rect bounds, String text) {
28 | mTextBounds = bounds;
29 | mTextChars = text;
30 | }
31 |
32 | public Rect getBounds() {
33 | return mTextBounds;
34 | }
35 |
36 | public String getText() {
37 | return mTextChars;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 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 tv.danmaku.ijk.media.player;
19 |
20 | public class MediaInfo {
21 | public String mMediaPlayerName;
22 |
23 | public String mVideoDecoder;
24 | public String mVideoDecoderImpl;
25 |
26 | public String mAudioDecoder;
27 | public String mAudioDecoderImpl;
28 |
29 | public IjkMediaMeta mMeta;
30 | }
31 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.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 tv.danmaku.ijk.media.player;
19 |
20 | import android.annotation.TargetApi;
21 | import android.graphics.SurfaceTexture;
22 | import android.os.Build;
23 | import android.view.Surface;
24 | import android.view.SurfaceHolder;
25 |
26 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
27 | public class TextureMediaPlayer extends MediaPlayerProxy implements IMediaPlayer, ISurfaceTextureHolder {
28 | private SurfaceTexture mSurfaceTexture;
29 | private ISurfaceTextureHost mSurfaceTextureHost;
30 |
31 | public TextureMediaPlayer(IMediaPlayer backEndMediaPlayer) {
32 | super(backEndMediaPlayer);
33 | }
34 |
35 | public void releaseSurfaceTexture() {
36 | if (mSurfaceTexture != null) {
37 | if (mSurfaceTextureHost != null) {
38 | mSurfaceTextureHost.releaseSurfaceTexture(mSurfaceTexture);
39 | } else {
40 | mSurfaceTexture.release();
41 | }
42 | mSurfaceTexture = null;
43 | }
44 | }
45 |
46 | //--------------------
47 | // IMediaPlayer
48 | //--------------------
49 | @Override
50 | public void reset() {
51 | super.reset();
52 | releaseSurfaceTexture();
53 | }
54 |
55 | @Override
56 | public void release() {
57 | super.release();
58 | releaseSurfaceTexture();
59 | }
60 |
61 | @Override
62 | public void setDisplay(SurfaceHolder sh) {
63 | if (mSurfaceTexture == null)
64 | super.setDisplay(sh);
65 | }
66 |
67 | @Override
68 | public void setSurface(Surface surface) {
69 | if (mSurfaceTexture == null)
70 | super.setSurface(surface);
71 | }
72 |
73 | //--------------------
74 | // ISurfaceTextureHolder
75 | //--------------------
76 |
77 | @Override
78 | public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
79 | if (mSurfaceTexture == surfaceTexture)
80 | return;
81 |
82 | releaseSurfaceTexture();
83 | mSurfaceTexture = surfaceTexture;
84 | if (surfaceTexture == null) {
85 | super.setSurface(null);
86 | } else {
87 | super.setSurface(new Surface(surfaceTexture));
88 | }
89 | }
90 |
91 | @Override
92 | public SurfaceTexture getSurfaceTexture() {
93 | return mSurfaceTexture;
94 | }
95 |
96 | @Override
97 | public void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost) {
98 | mSurfaceTextureHost = surfaceTextureHost;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 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 tv.danmaku.ijk.media.player.annotations;
19 |
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | /**
26 | * is used by the JNI generator to create the necessary JNI
27 | * bindings and expose this method to native code.
28 | */
29 | @Target(ElementType.FIELD)
30 | @Retention(RetentionPolicy.CLASS)
31 | public @interface AccessedByNative {
32 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 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 tv.danmaku.ijk.media.player.annotations;
19 |
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | /**
26 | * is used by the JNI generator to create the necessary JNI
27 | * bindings and expose this method to native code.
28 | */
29 | @Target(ElementType.METHOD)
30 | @Retention(RetentionPolicy.CLASS)
31 | public @interface CalledByNative {
32 | /*
33 | * If present, tells which inner class the method belongs to.
34 | */
35 | String value() default "";
36 | }
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 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 tv.danmaku.ijk.media.player.exceptions;
19 |
20 | public class IjkMediaException extends Exception {
21 | private static final long serialVersionUID = 7234796519009099506L;
22 | }
23 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java:
--------------------------------------------------------------------------------
1 | package tv.danmaku.ijk.media.player.ffmpeg;
2 |
3 | public class FFmpegApi {
4 | public static native String av_base64_encode(byte in[]);
5 | }
6 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.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 tv.danmaku.ijk.media.player.misc;
19 |
20 | import android.annotation.TargetApi;
21 | import android.media.MediaFormat;
22 | import android.os.Build;
23 |
24 | public class AndroidMediaFormat implements IMediaFormat {
25 | private final MediaFormat mMediaFormat;
26 |
27 | public AndroidMediaFormat(MediaFormat mediaFormat) {
28 | mMediaFormat = mediaFormat;
29 | }
30 |
31 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
32 | @Override
33 | public int getInteger(String name) {
34 | if (mMediaFormat == null)
35 | return 0;
36 |
37 | return mMediaFormat.getInteger(name);
38 | }
39 |
40 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
41 | @Override
42 | public String getString(String name) {
43 | if (mMediaFormat == null)
44 | return null;
45 |
46 | return mMediaFormat.getString(name);
47 | }
48 |
49 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
50 | @Override
51 | public String toString() {
52 | StringBuilder out = new StringBuilder(128);
53 | out.append(getClass().getName());
54 | out.append('{');
55 | if (mMediaFormat != null) {
56 | out.append(mMediaFormat.toString());
57 | } else {
58 | out.append("null");
59 | }
60 | out.append('}');
61 | return out.toString();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.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 tv.danmaku.ijk.media.player.misc;
19 |
20 | import android.annotation.TargetApi;
21 | import android.media.MediaFormat;
22 | import android.media.MediaPlayer;
23 | import android.os.Build;
24 |
25 | public class AndroidTrackInfo implements ITrackInfo {
26 | private final MediaPlayer.TrackInfo mTrackInfo;
27 |
28 | public static AndroidTrackInfo[] fromMediaPlayer(MediaPlayer mp) {
29 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
30 | return fromTrackInfo(mp.getTrackInfo());
31 |
32 | return null;
33 | }
34 |
35 | private static AndroidTrackInfo[] fromTrackInfo(MediaPlayer.TrackInfo[] trackInfos) {
36 | if (trackInfos == null)
37 | return null;
38 |
39 | AndroidTrackInfo androidTrackInfo[] = new AndroidTrackInfo[trackInfos.length];
40 | for (int i = 0; i < trackInfos.length; ++i) {
41 | androidTrackInfo[i] = new AndroidTrackInfo(trackInfos[i]);
42 | }
43 |
44 | return androidTrackInfo;
45 | }
46 |
47 | private AndroidTrackInfo(MediaPlayer.TrackInfo trackInfo) {
48 | mTrackInfo = trackInfo;
49 | }
50 |
51 | @TargetApi(Build.VERSION_CODES.KITKAT)
52 | @Override
53 | public IMediaFormat getFormat() {
54 | if (mTrackInfo == null)
55 | return null;
56 |
57 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
58 | return null;
59 |
60 | MediaFormat mediaFormat = mTrackInfo.getFormat();
61 | if (mediaFormat == null)
62 | return null;
63 |
64 | return new AndroidMediaFormat(mediaFormat);
65 | }
66 |
67 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
68 | @Override
69 | public String getLanguage() {
70 | if (mTrackInfo == null)
71 | return "und";
72 |
73 | return mTrackInfo.getLanguage();
74 | }
75 |
76 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
77 | @Override
78 | public int getTrackType() {
79 | if (mTrackInfo == null)
80 | return MEDIA_TRACK_TYPE_UNKNOWN;
81 |
82 | return mTrackInfo.getTrackType();
83 | }
84 |
85 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
86 | @Override
87 | public String toString() {
88 | StringBuilder out = new StringBuilder(128);
89 | out.append(getClass().getSimpleName());
90 | out.append('{');
91 | if (mTrackInfo != null) {
92 | out.append(mTrackInfo.toString());
93 | } else {
94 | out.append("null");
95 | }
96 | out.append('}');
97 | return out.toString();
98 | }
99 |
100 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
101 | @Override
102 | public String getInfoInline() {
103 | if (mTrackInfo != null) {
104 | return mTrackInfo.toString();
105 | } else {
106 | return "null";
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IAndroidIO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bilibili
3 | * Copyright (C) 2016 Raymond Zheng
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 tv.danmaku.ijk.media.player.misc;
19 |
20 | import java.io.IOException;
21 |
22 | @SuppressWarnings("RedundantThrows")
23 | public interface IAndroidIO {
24 | int open(String url) throws IOException;
25 | int read(byte[] buffer, int size) throws IOException;
26 | long seek(long offset, int whence) throws IOException;
27 | int close() throws IOException;
28 | }
29 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.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 tv.danmaku.ijk.media.player.misc;
19 |
20 | import java.io.IOException;
21 |
22 | @SuppressWarnings("RedundantThrows")
23 | public interface IMediaDataSource {
24 | int readAt(long position, byte[] buffer, int offset, int size) throws IOException;
25 |
26 | long getSize() throws IOException;
27 |
28 | void close() throws IOException;
29 | }
30 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.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 tv.danmaku.ijk.media.player.misc;
19 |
20 | public interface IMediaFormat {
21 | // Common keys
22 | String KEY_MIME = "mime";
23 |
24 | // Video Keys
25 | String KEY_WIDTH = "width";
26 | String KEY_HEIGHT = "height";
27 |
28 | String getString(String name);
29 |
30 | int getInteger(String name);
31 | }
32 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.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 tv.danmaku.ijk.media.player.misc;
19 |
20 | public interface ITrackInfo {
21 | int MEDIA_TRACK_TYPE_AUDIO = 2;
22 | int MEDIA_TRACK_TYPE_METADATA = 5;
23 | int MEDIA_TRACK_TYPE_SUBTITLE = 4;
24 | int MEDIA_TRACK_TYPE_TIMEDTEXT = 3;
25 | int MEDIA_TRACK_TYPE_UNKNOWN = 0;
26 | int MEDIA_TRACK_TYPE_VIDEO = 1;
27 |
28 | IMediaFormat getFormat();
29 |
30 | String getLanguage();
31 |
32 | int getTrackType();
33 |
34 | String getInfoInline();
35 | }
36 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.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 tv.danmaku.ijk.media.player.misc;
19 |
20 | import android.text.TextUtils;
21 |
22 | import tv.danmaku.ijk.media.player.IjkMediaMeta;
23 |
24 | public class IjkTrackInfo implements ITrackInfo {
25 | private int mTrackType = MEDIA_TRACK_TYPE_UNKNOWN;
26 | private IjkMediaMeta.IjkStreamMeta mStreamMeta;
27 |
28 | public IjkTrackInfo(IjkMediaMeta.IjkStreamMeta streamMeta) {
29 | mStreamMeta = streamMeta;
30 | }
31 |
32 | public void setMediaMeta(IjkMediaMeta.IjkStreamMeta streamMeta) {
33 | mStreamMeta = streamMeta;
34 | }
35 |
36 | @Override
37 | public IMediaFormat getFormat() {
38 | return new IjkMediaFormat(mStreamMeta);
39 | }
40 |
41 | @Override
42 | public String getLanguage() {
43 | if (mStreamMeta == null || TextUtils.isEmpty(mStreamMeta.mLanguage))
44 | return "und";
45 |
46 | return mStreamMeta.mLanguage;
47 | }
48 |
49 | @Override
50 | public int getTrackType() {
51 | return mTrackType;
52 | }
53 |
54 | public void setTrackType(int trackType) {
55 | mTrackType = trackType;
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | return getClass().getSimpleName() + '{' + getInfoInline() + "}";
61 | }
62 |
63 | @Override
64 | public String getInfoInline() {
65 | StringBuilder out = new StringBuilder(128);
66 | switch (mTrackType) {
67 | case MEDIA_TRACK_TYPE_VIDEO:
68 | out.append("VIDEO");
69 | out.append(", ");
70 | out.append(mStreamMeta.getCodecShortNameInline());
71 | out.append(", ");
72 | out.append(mStreamMeta.getBitrateInline());
73 | out.append(", ");
74 | out.append(mStreamMeta.getResolutionInline());
75 | break;
76 | case MEDIA_TRACK_TYPE_AUDIO:
77 | out.append("AUDIO");
78 | out.append(", ");
79 | out.append(mStreamMeta.getCodecShortNameInline());
80 | out.append(", ");
81 | out.append(mStreamMeta.getBitrateInline());
82 | out.append(", ");
83 | out.append(mStreamMeta.getSampleRateInline());
84 | break;
85 | case MEDIA_TRACK_TYPE_TIMEDTEXT:
86 | out.append("TIMEDTEXT");
87 | out.append(", ");
88 | out.append(mStreamMeta.mLanguage);
89 | break;
90 | case MEDIA_TRACK_TYPE_SUBTITLE:
91 | out.append("SUBTITLE");
92 | break;
93 | default:
94 | out.append("UNKNOWN");
95 | break;
96 | }
97 | return out.toString();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Bilibili
3 | * Copyright (C) 2013 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 tv.danmaku.ijk.media.player.pragma;
19 |
20 | import java.util.Locale;
21 |
22 |
23 | import android.util.Log;
24 |
25 | @SuppressWarnings({"SameParameterValue", "WeakerAccess"})
26 | public class DebugLog {
27 | public static final boolean ENABLE_ERROR = Pragma.ENABLE_VERBOSE;
28 | public static final boolean ENABLE_INFO = Pragma.ENABLE_VERBOSE;
29 | public static final boolean ENABLE_WARN = Pragma.ENABLE_VERBOSE;
30 | public static final boolean ENABLE_DEBUG = Pragma.ENABLE_VERBOSE;
31 | public static final boolean ENABLE_VERBOSE = Pragma.ENABLE_VERBOSE;
32 |
33 | public static void e(String tag, String msg) {
34 | if (ENABLE_ERROR) {
35 | Log.e(tag, msg);
36 | }
37 | }
38 |
39 | public static void e(String tag, String msg, Throwable tr) {
40 | if (ENABLE_ERROR) {
41 | Log.e(tag, msg, tr);
42 | }
43 | }
44 |
45 | public static void efmt(String tag, String fmt, Object... args) {
46 | if (ENABLE_ERROR) {
47 | String msg = String.format(Locale.US, fmt, args);
48 | Log.e(tag, msg);
49 | }
50 | }
51 |
52 | public static void i(String tag, String msg) {
53 | if (ENABLE_INFO) {
54 | Log.i(tag, msg);
55 | }
56 | }
57 |
58 | public static void i(String tag, String msg, Throwable tr) {
59 | if (ENABLE_INFO) {
60 | Log.i(tag, msg, tr);
61 | }
62 | }
63 |
64 | public static void ifmt(String tag, String fmt, Object... args) {
65 | if (ENABLE_INFO) {
66 | String msg = String.format(Locale.US, fmt, args);
67 | Log.i(tag, msg);
68 | }
69 | }
70 |
71 | public static void w(String tag, String msg) {
72 | if (ENABLE_WARN) {
73 | Log.w(tag, msg);
74 | }
75 | }
76 |
77 | public static void w(String tag, String msg, Throwable tr) {
78 | if (ENABLE_WARN) {
79 | Log.w(tag, msg, tr);
80 | }
81 | }
82 |
83 | public static void wfmt(String tag, String fmt, Object... args) {
84 | if (ENABLE_WARN) {
85 | String msg = String.format(Locale.US, fmt, args);
86 | Log.w(tag, msg);
87 | }
88 | }
89 |
90 | public static void d(String tag, String msg) {
91 | if (ENABLE_DEBUG) {
92 | Log.d(tag, msg);
93 | }
94 | }
95 |
96 | public static void d(String tag, String msg, Throwable tr) {
97 | if (ENABLE_DEBUG) {
98 | Log.d(tag, msg, tr);
99 | }
100 | }
101 |
102 | public static void dfmt(String tag, String fmt, Object... args) {
103 | if (ENABLE_DEBUG) {
104 | String msg = String.format(Locale.US, fmt, args);
105 | Log.d(tag, msg);
106 | }
107 | }
108 |
109 | public static void v(String tag, String msg) {
110 | if (ENABLE_VERBOSE) {
111 | Log.v(tag, msg);
112 | }
113 | }
114 |
115 | public static void v(String tag, String msg, Throwable tr) {
116 | if (ENABLE_VERBOSE) {
117 | Log.v(tag, msg, tr);
118 | }
119 | }
120 |
121 | public static void vfmt(String tag, String fmt, Object... args) {
122 | if (ENABLE_VERBOSE) {
123 | String msg = String.format(Locale.US, fmt, args);
124 | Log.v(tag, msg);
125 | }
126 | }
127 |
128 | public static void printStackTrace(Throwable e) {
129 | if (ENABLE_WARN) {
130 | e.printStackTrace();
131 | }
132 | }
133 |
134 | public static void printCause(Throwable e) {
135 | if (ENABLE_WARN) {
136 | Throwable cause = e.getCause();
137 | if (cause != null)
138 | e = cause;
139 |
140 | printStackTrace(e);
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Bilibili
3 | * Copyright (C) 2013 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 | package tv.danmaku.ijk.media.player.pragma;
18 |
19 | /*-
20 | * configurated by app project
21 | */
22 | public class Pragma {
23 | public static final boolean ENABLE_VERBOSE = true;
24 | }
25 |
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/arm64-v8a/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/arm64-v8a/libijkffmpeg.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/arm64-v8a/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/arm64-v8a/libijkplayer.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/arm64-v8a/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/arm64-v8a/libijksdl.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/armeabi-v7a/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/armeabi-v7a/libijkffmpeg.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/armeabi-v7a/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/armeabi-v7a/libijkplayer.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/armeabi-v7a/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/armeabi-v7a/libijksdl.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/armeabi/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/armeabi/libijkffmpeg.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/armeabi/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/armeabi/libijkplayer.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/armeabi/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/armeabi/libijksdl.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/x86/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/x86/libijkffmpeg.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/x86/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/x86/libijkplayer.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/x86/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/x86/libijksdl.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/x86_64/libijkffmpeg.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/x86_64/libijkffmpeg.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/x86_64/libijkplayer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/x86_64/libijkplayer.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/jniLibs/x86_64/libijksdl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LZ9/MMSPlayer/e8d0121ba8c1ca55fdeb3442f9ad6833b85b98c3/mmsplayer/src/main/jniLibs/x86_64/libijksdl.so
--------------------------------------------------------------------------------
/mmsplayer/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | vdec
4 | fps
5 | v-cache
6 | a-cache
7 | load-cost
8 | seek_cost
9 | seek_load_cost
10 | tcp_speed
11 | bit_rate
12 |
13 | n/a
14 | aspect / fit parent
15 | aspect / fill parent
16 | aspect / wrap content
17 | free / fill parent
18 | 16:9 / fit parent
19 | 4:3 / fit parent
20 |
21 | invalid progressive playback
22 | file or network related operation errors
23 | unknown
24 |
25 | render: none
26 | render: surfaceview
27 | render: textureview
28 |
29 | player: none
30 | player: androidmediaplayer
31 | player: ijkmediaplayer
32 | player: ijkexomediaplayer
33 |
34 | video
35 | audio
36 | subtitle
37 | timed text
38 | meta data
39 | unknown
40 |
41 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name = "MMSPlayer"
16 | include ':app'
17 | include ':mmsplayer'
--------------------------------------------------------------------------------