├── example ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ └── layout │ │ │ │ └── activity_main.xml │ │ ├── java │ │ │ └── tv │ │ │ │ └── danmaku │ │ │ │ └── ijk │ │ │ │ └── libmediaplayer │ │ │ │ └── MainActivity.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── tv │ │ │ └── danmaku │ │ │ └── ijk │ │ │ └── libmediaplayer │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── tv │ │ └── danmaku │ │ └── ijk │ │ └── libmediaplayer │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── mediaplayer ├── .gitignore ├── src │ ├── test │ │ └── java │ │ │ └── tv │ │ │ └── danmaku │ │ │ └── ijk │ │ │ └── mediaplayer │ │ │ └── ExampleUnitTest.java │ ├── androidTest │ │ └── java │ │ │ └── tv │ │ │ └── danmaku │ │ │ └── ijk │ │ │ └── mediaplayer │ │ │ └── ApplicationTest.java │ └── main │ │ ├── res │ │ ├── layout │ │ │ ├── table_media_info.xml │ │ │ ├── table_media_info_section.xml │ │ │ ├── activity_player.xml │ │ │ ├── table_media_info_row1.xml │ │ │ └── table_media_info_row2.xml │ │ └── values │ │ │ ├── strings.xml │ │ │ └── strings_pref.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── tv │ │ └── danmaku │ │ └── ijk │ │ └── mediaplayer │ │ ├── media │ │ ├── IMediaController.java │ │ ├── AndroidMediaController.java │ │ ├── IRenderView.java │ │ ├── MediaPlayerCompat.java │ │ ├── InfoHudViewHolder.java │ │ ├── TableLayoutBinder.java │ │ ├── SurfaceRenderView.java │ │ ├── MeasureHelper.java │ │ └── TextureRenderView.java │ │ ├── service │ │ └── MediaPlayerService.java │ │ ├── application │ │ └── Settings.java │ │ └── PlayerActivity.java ├── proguard-rules.pro └── build.gradle ├── ijkplayer-java ├── .gitignore ├── gradle.properties ├── src │ ├── main │ │ ├── jniLibs │ │ │ └── armeabi-v7a │ │ │ │ ├── libijksdl.so │ │ │ │ ├── libijkffmpeg.so │ │ │ │ └── libijkplayer.so │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ ├── java │ │ │ └── tv │ │ │ │ └── danmaku │ │ │ │ └── ijk │ │ │ │ └── media │ │ │ │ └── player │ │ │ │ ├── ffmpeg │ │ │ │ └── FFmpegApi.java │ │ │ │ ├── pragma │ │ │ │ ├── Pragma.java │ │ │ │ └── DebugLog.java │ │ │ │ ├── IjkLibLoader.java │ │ │ │ ├── exceptions │ │ │ │ └── IjkMediaException.java │ │ │ │ ├── ISurfaceTextureHost.java │ │ │ │ ├── MediaInfo.java │ │ │ │ ├── misc │ │ │ │ ├── IMediaFormat.java │ │ │ │ ├── IMediaDataSource.java │ │ │ │ ├── ITrackInfo.java │ │ │ │ ├── AndroidMediaFormat.java │ │ │ │ ├── IjkTrackInfo.java │ │ │ │ ├── AndroidTrackInfo.java │ │ │ │ └── IjkMediaFormat.java │ │ │ │ ├── ISurfaceTextureHolder.java │ │ │ │ ├── annotations │ │ │ │ ├── AccessedByNative.java │ │ │ │ └── CalledByNative.java │ │ │ │ ├── TextureMediaPlayer.java │ │ │ │ ├── AbstractMediaPlayer.java │ │ │ │ ├── IMediaPlayer.java │ │ │ │ ├── MediaPlayerProxy.java │ │ │ │ ├── IjkMediaCodecInfo.java │ │ │ │ ├── AndroidMediaPlayer.java │ │ │ │ └── IjkMediaMeta.java │ │ ├── AndroidManifest.xml │ │ ├── .settings │ │ │ └── org.eclipse.jdt.core.prefs │ │ └── project.properties │ └── androidTest │ │ └── java │ │ └── tv │ │ └── danmaku │ │ └── ijk │ │ └── media │ │ └── player │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .travis.yml ├── .gitignore ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /example/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /mediaplayer/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ijkplayer-java/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':example', ':mediaplayer', ':ijkplayer-java' 2 | -------------------------------------------------------------------------------- /ijkplayer-java/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_NAME=ijkplayer-java 2 | POM_ARTIFACT_ID=ijkplayer-java 3 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /example/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LibMediaPlayer 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/example/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/example/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/example/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/example/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ijkplayer-java/src/main/jniLibs/armeabi-v7a/libijksdl.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/ijkplayer-java/src/main/jniLibs/armeabi-v7a/libijksdl.so -------------------------------------------------------------------------------- /ijkplayer-java/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/jniLibs/armeabi-v7a/libijkffmpeg.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/ijkplayer-java/src/main/jniLibs/armeabi-v7a/libijkffmpeg.so -------------------------------------------------------------------------------- /ijkplayer-java/src/main/jniLibs/armeabi-v7a/libijkplayer.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdtianyu/LibMediaPlayer/master/ijkplayer-java/src/main/jniLibs/armeabi-v7a/libijkplayer.so -------------------------------------------------------------------------------- /ijkplayer-java/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 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /example/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /example/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 21 11:34:03 PDT 2015 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-2.8-all.zip 7 | -------------------------------------------------------------------------------- /example/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /mediaplayer/src/test/java/tv/danmaku/ijk/mediaplayer/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.mediaplayer; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /example/src/test/java/tv/danmaku/ijk/libmediaplayer/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.libmediaplayer; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /example/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /mediaplayer/src/androidTest/java/tv/danmaku/ijk/mediaplayer/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.mediaplayer; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | addons: 4 | apt: 5 | packages: 6 | - libgd2-xpm 7 | - ia32-libs 8 | - ia32-libs-multiarch 9 | 10 | android: 11 | components: 12 | - tools 13 | - platform-tools 14 | - android-23 15 | - build-tools-23.0.2 16 | - extra 17 | 18 | jdk: oraclejdk7 19 | 20 | notifications: 21 | email: false 22 | 23 | before_install: 24 | - touch local.properties 25 | 26 | script: 27 | - ./gradlew install 28 | -------------------------------------------------------------------------------- /example/src/androidTest/java/tv/danmaku/ijk/libmediaplayer/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.libmediaplayer; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /ijkplayer-java/src/androidTest/java/tv/danmaku/ijk/media/player/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.media.player; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /mediaplayer/src/main/res/layout/table_media_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /mediaplayer/src/main/res/layout/table_media_info_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /mediaplayer/src/main/res/layout/activity_player.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-22 15 | android.library=true 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Windows thumbnail db 19 | Thumbs.db 20 | 21 | # OSX files 22 | .DS_Store 23 | 24 | # Eclipse project files 25 | .classpath 26 | .project 27 | 28 | # Android Studio 29 | *.iml 30 | .idea 31 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 32 | .gradle 33 | build/ 34 | 35 | #NDK 36 | obj/ 37 | 38 | /*/out 39 | /*/*/build 40 | /*/*/production 41 | *.iws 42 | *.ipr 43 | *~ 44 | *.swp 45 | -------------------------------------------------------------------------------- /example/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/ty/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /example/src/main/java/tv/danmaku/ijk/libmediaplayer/MainActivity.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.libmediaplayer; 2 | 3 | import android.content.pm.ActivityInfo; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import tv.danmaku.ijk.mediaplayer.PlayerActivity; 8 | 9 | public class MainActivity extends AppCompatActivity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_main); 15 | PlayerActivity.intentTo(this, 16 | "YOUR_MEDIA_URI", 17 | "YOUR_TITLE", 18 | ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ijkplayer-java/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android/ADK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /mediaplayer/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/ty/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /mediaplayer/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /mediaplayer/src/main/res/layout/table_media_info_row1.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "tv.danmaku.ijk.libmediaplayer" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.1.1' 26 | compile project(':mediaplayer') 27 | } 28 | -------------------------------------------------------------------------------- /example/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | final 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /mediaplayer/src/main/res/layout/table_media_info_row2.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 23 | 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Zhang Rui 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 | package tv.danmaku.ijk.media.player.pragma; 17 | 18 | /*- 19 | * configurated by app project 20 | */ 21 | public class Pragma { 22 | public static final boolean ENABLE_VERBOSE = true; 23 | } 24 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Zhang Rui 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 | public interface IjkLibLoader { 20 | void loadLibrary(String libName) throws UnsatisfiedLinkError, 21 | SecurityException; 22 | } 23 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Zhang Rui 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.exceptions; 18 | 19 | public class IjkMediaException extends Exception { 20 | private static final long serialVersionUID = 7234796519009099506L; 21 | } 22 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.SurfaceTexture; 20 | 21 | public interface ISurfaceTextureHost { 22 | void releaseSurfaceTexture(SurfaceTexture surfaceTexture); 23 | } 24 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Zhang Rui 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 | public class MediaInfo { 20 | public String mMediaPlayerName; 21 | 22 | public String mVideoDecoder; 23 | public String mVideoDecoderImpl; 24 | 25 | public String mAudioDecoder; 26 | public String mAudioDecoderImpl; 27 | 28 | public IjkMediaMeta mMeta; 29 | } 30 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.misc; 18 | 19 | public interface IMediaFormat { 20 | // Common keys 21 | String KEY_MIME = "mime"; 22 | 23 | // Video Keys 24 | String KEY_WIDTH = "width"; 25 | String KEY_HEIGHT = "height"; 26 | 27 | String getString(String name); 28 | 29 | int getInteger(String name); 30 | } 31 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.SurfaceTexture; 20 | 21 | public interface ISurfaceTextureHolder { 22 | void setSurfaceTexture(SurfaceTexture surfaceTexture); 23 | 24 | SurfaceTexture getSurfaceTexture(); 25 | 26 | void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost); 27 | } 28 | -------------------------------------------------------------------------------- /ijkplayer-java/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | // http://tools.android.com/tech-docs/new-build-system/tips 5 | //noinspection GroovyAssignabilityCheck 6 | compileSdkVersion rootProject.ext.compileSdkVersion 7 | //noinspection GroovyAssignabilityCheck 8 | buildToolsVersion rootProject.ext.buildToolsVersion 9 | 10 | defaultConfig { 11 | minSdkVersion 9 12 | targetSdkVersion rootProject.ext.targetSdkVersion 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | } 25 | 26 | ext { 27 | optionalPlugins = ['tools/gradle-mvn-push.gradle', 'tools/gradle-bintray-upload.gradle']; 28 | } 29 | 30 | ext.optionalPlugins.each{ value -> 31 | def plugin_file = new File(rootProject.projectDir, value); 32 | if (plugin_file.exists()) { 33 | apply from: plugin_file 34 | } 35 | } -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.misc; 18 | 19 | import java.io.IOException; 20 | 21 | @SuppressWarnings("RedundantThrows") 22 | public interface IMediaDataSource { 23 | int readAt(long position, byte[] buffer, int offset, int size) throws IOException; 24 | 25 | long getSize() throws IOException; 26 | 27 | void close() throws IOException; 28 | } 29 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.misc; 18 | 19 | public interface ITrackInfo { 20 | int MEDIA_TRACK_TYPE_AUDIO = 2; 21 | int MEDIA_TRACK_TYPE_METADATA = 5; 22 | int MEDIA_TRACK_TYPE_SUBTITLE = 4; 23 | int MEDIA_TRACK_TYPE_TIMEDTEXT = 3; 24 | int MEDIA_TRACK_TYPE_UNKNOWN = 0; 25 | int MEDIA_TRACK_TYPE_VIDEO = 1; 26 | 27 | IMediaFormat getFormat(); 28 | 29 | String getLanguage(); 30 | 31 | int getTrackType(); 32 | 33 | String getInfoInline(); 34 | } 35 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Zhang Rui 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.annotations; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * is used by the JNI generator to create the necessary JNI 26 | * bindings and expose this method to native code. 27 | */ 28 | @Target(ElementType.FIELD) 29 | @Retention(RetentionPolicy.CLASS) 30 | public @interface AccessedByNative { 31 | } -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/IMediaController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import android.view.View; 20 | import android.widget.MediaController; 21 | 22 | public interface IMediaController { 23 | void hide(); 24 | 25 | boolean isShowing(); 26 | 27 | void setAnchorView(View view); 28 | 29 | void setEnabled(boolean enabled); 30 | 31 | void setMediaPlayer(MediaController.MediaPlayerControl player); 32 | 33 | void show(int timeout); 34 | 35 | void show(); 36 | 37 | //---------- 38 | // Extends 39 | //---------- 40 | void showOnce(View view); 41 | } 42 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Zhang Rui 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.annotations; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * is used by the JNI generator to create the necessary JNI 26 | * bindings and expose this method to native code. 27 | */ 28 | @Target(ElementType.METHOD) 29 | @Retention(RetentionPolicy.CLASS) 30 | public @interface CalledByNative { 31 | /* 32 | * If present, tells which inner class the method belongs to. 33 | */ 34 | String value() default ""; 35 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibMediaPlayer 2 | An android media player library based on ijkplayer 3 | 4 | [![Build Status](https://travis-ci.org/xdtianyu/LibMediaPlayer.svg?branch=master)](https://travis-ci.org/xdtianyu/LibMediaPlayer) 5 | [![JAR](https://img.shields.io/maven-central/v/org.xdty.media/mediaplayer.svg)](http://central.maven.org/maven2/org/xdty/media/mediaplayer/) 6 | [ ![Download](https://api.bintray.com/packages/xdtianyu/maven/mediaplayer/images/download.svg) ](https://bintray.com/xdtianyu/maven/mediaplayer/_latestVersion) 7 | 8 | ## Download 9 | 10 | Grab via gradle 11 | 12 | ``` 13 | dependencies { 14 | compile 'org.xdty.media:mediaplayer:0.0.1' 15 | } 16 | ``` 17 | 18 | or maven 19 | 20 | ``` 21 | 22 | org.xdty.media 23 | mediaplayer 24 | 0.0.1 25 | aar 26 | 27 | ``` 28 | 29 | or JAR from [maven central](http://central.maven.org/maven2/org/xdty/media/mediaplayer/) 30 | 31 | ## Usage 32 | 33 | ``` 34 | PlayerActivity.intentTo(this, 35 | "YOUR_MEDIA_URI", 36 | "YOUR_TITLE", 37 | ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 38 | ``` 39 | 40 | For more details, see [example](https://github.com/xdtianyu/LibMediaPlayer/tree/master/example) 41 | 42 | ## Using your own jkplayer-armv7a builds 43 | 44 | Put *.so files in your module's directory `app/src/main/jniLibs/armeabi-v7a`, then clean project and build again. 45 | 46 | -------------------------------------------------------------------------------- /mediaplayer/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | ext { 4 | bintrayRepo = 'maven' 5 | bintrayName = 'mediaplayer' 6 | 7 | publishedGroupId = 'org.xdty.media' 8 | libraryName = 'MediaPlayer' 9 | artifact = 'mediaplayer' 10 | 11 | libraryDescription = 'An android media player based on ijkplayer' 12 | 13 | siteUrl = 'https://github.com/xdtianyu/LibMediaPlayer' 14 | gitUrl = 'https://github.com/xdtianyu/LibMediaPlayer' 15 | 16 | libraryVersion = '0.0.1' 17 | 18 | developerId = 'xdtianyu' 19 | developerName = 'xdtianyu' 20 | developerEmail = 'xdtianyu@gmail.com' 21 | 22 | licenseName = 'The Apache Software License, Version 2.0' 23 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 24 | allLicenses = ["Apache-2.0"] 25 | } 26 | 27 | android { 28 | compileSdkVersion 23 29 | buildToolsVersion "23.0.2" 30 | 31 | defaultConfig { 32 | minSdkVersion 15 33 | targetSdkVersion 23 34 | versionCode 1 35 | versionName "0.0.1" 36 | } 37 | buildTypes { 38 | release { 39 | minifyEnabled false 40 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 41 | } 42 | } 43 | } 44 | 45 | dependencies { 46 | compile 'com.android.support:appcompat-v7:23.1.1' 47 | compile 'tv.danmaku.ijk.media:ijkplayer-java:0.4.4.1' 48 | compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.4.4.1' 49 | } 50 | 51 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' 52 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle' 53 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.misc; 18 | 19 | import android.annotation.TargetApi; 20 | import android.media.MediaFormat; 21 | import android.os.Build; 22 | 23 | public class AndroidMediaFormat implements IMediaFormat { 24 | private final MediaFormat mMediaFormat; 25 | 26 | public AndroidMediaFormat(MediaFormat mediaFormat) { 27 | mMediaFormat = mediaFormat; 28 | } 29 | 30 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 31 | @Override 32 | public int getInteger(String name) { 33 | if (mMediaFormat == null) 34 | return 0; 35 | 36 | return mMediaFormat.getInteger(name); 37 | } 38 | 39 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 40 | @Override 41 | public String getString(String name) { 42 | if (mMediaFormat == null) 43 | return null; 44 | 45 | return mMediaFormat.getString(name); 46 | } 47 | 48 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 49 | @Override 50 | public String toString() { 51 | StringBuilder out = new StringBuilder(128); 52 | out.append(getClass().getName()); 53 | out.append('{'); 54 | if (mMediaFormat != null) { 55 | out.append(mMediaFormat.toString()); 56 | } else { 57 | out.append("null"); 58 | } 59 | out.append('}'); 60 | return out.toString(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/service/MediaPlayerService.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.mediaplayer.service; 2 | 3 | /* 4 | * Copyright (C) 2015 Zhang Rui 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.app.Service; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import android.os.IBinder; 23 | import android.support.annotation.Nullable; 24 | 25 | import tv.danmaku.ijk.media.player.IMediaPlayer; 26 | 27 | public class MediaPlayerService extends Service { 28 | private static IMediaPlayer sMediaPlayer; 29 | 30 | public static Intent newIntent(Context context) { 31 | Intent intent = new Intent(context, MediaPlayerService.class); 32 | return intent; 33 | } 34 | 35 | public static void intentToStart(Context context) { 36 | context.startService(newIntent(context)); 37 | } 38 | 39 | public static void intentToStop(Context context) { 40 | context.stopService(newIntent(context)); 41 | } 42 | 43 | @Nullable 44 | @Override 45 | public IBinder onBind(Intent intent) { 46 | return null; 47 | } 48 | 49 | public static void setMediaPlayer(IMediaPlayer mp) { 50 | if (sMediaPlayer != null && sMediaPlayer != mp) { 51 | if (sMediaPlayer.isPlaying()) 52 | sMediaPlayer.stop(); 53 | sMediaPlayer.release(); 54 | sMediaPlayer = null; 55 | } 56 | sMediaPlayer = mp; 57 | } 58 | 59 | public static IMediaPlayer getMediaPlayer() { 60 | return sMediaPlayer; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/AndroidMediaController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | import android.support.annotation.Nullable; 22 | import android.support.v7.app.ActionBar; 23 | import android.util.AttributeSet; 24 | import android.view.View; 25 | import android.widget.MediaController; 26 | 27 | import java.util.ArrayList; 28 | 29 | public class AndroidMediaController extends MediaController implements IMediaController { 30 | private ActionBar mActionBar; 31 | 32 | public AndroidMediaController(Context context, AttributeSet attrs) { 33 | super(context, attrs); 34 | initView(context); 35 | } 36 | 37 | public AndroidMediaController(Context context, boolean useFastForward) { 38 | super(context, useFastForward); 39 | initView(context); 40 | } 41 | 42 | public AndroidMediaController(Context context) { 43 | super(context); 44 | initView(context); 45 | } 46 | 47 | private void initView(Context context) { 48 | } 49 | 50 | public void setSupportActionBar(@Nullable ActionBar actionBar) { 51 | mActionBar = actionBar; 52 | if (isShowing()) { 53 | actionBar.show(); 54 | } else { 55 | actionBar.hide(); 56 | } 57 | } 58 | 59 | @Override 60 | public void show() { 61 | super.show(); 62 | if (mActionBar != null) 63 | mActionBar.show(); 64 | } 65 | 66 | @Override 67 | public void hide() { 68 | super.hide(); 69 | if (mActionBar != null) 70 | mActionBar.hide(); 71 | for (View view : mShowOnceArray) 72 | view.setVisibility(View.GONE); 73 | mShowOnceArray.clear();; 74 | } 75 | 76 | //---------- 77 | // Extends 78 | //---------- 79 | private ArrayList mShowOnceArray = new ArrayList(); 80 | 81 | public void showOnce(@NonNull View view) { 82 | mShowOnceArray.add(view); 83 | view.setVisibility(View.VISIBLE); 84 | show(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/IRenderView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import android.graphics.SurfaceTexture; 20 | import android.support.annotation.NonNull; 21 | import android.support.annotation.Nullable; 22 | import android.view.Surface; 23 | import android.view.SurfaceHolder; 24 | import android.view.View; 25 | 26 | import tv.danmaku.ijk.media.player.IMediaPlayer; 27 | 28 | public interface IRenderView { 29 | static final int AR_ASPECT_FIT_PARENT = 0; // without clip 30 | static final int AR_ASPECT_FILL_PARENT = 1; // may clip 31 | static final int AR_ASPECT_WRAP_CONTENT = 2; 32 | static final int AR_MATCH_PARENT = 3; 33 | static final int AR_16_9_FIT_PARENT = 4; 34 | static final int AR_4_3_FIT_PARENT = 5; 35 | 36 | View getView(); 37 | 38 | boolean shouldWaitForResize(); 39 | 40 | void setVideoSize(int videoWidth, int videoHeight); 41 | 42 | void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen); 43 | 44 | void setVideoRotation(int degree); 45 | 46 | void setAspectRatio(int aspectRatio); 47 | 48 | void addRenderCallback(@NonNull IRenderCallback callback); 49 | 50 | void removeRenderCallback(@NonNull IRenderCallback callback); 51 | 52 | interface ISurfaceHolder { 53 | void bindToMediaPlayer(IMediaPlayer mp); 54 | 55 | @NonNull 56 | IRenderView getRenderView(); 57 | 58 | @Nullable 59 | SurfaceHolder getSurfaceHolder(); 60 | 61 | @Nullable 62 | Surface openSurface(); 63 | 64 | @Nullable 65 | SurfaceTexture getSurfaceTexture(); 66 | } 67 | 68 | public interface IRenderCallback { 69 | /** 70 | * @param holder 71 | * @param width could be 0 72 | * @param height could be 0 73 | */ 74 | void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height); 75 | 76 | /** 77 | * @param holder 78 | * @param format could be 0 79 | * @param width 80 | * @param height 81 | */ 82 | void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height); 83 | 84 | void onSurfaceDestroyed(@NonNull ISurfaceHolder holder); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/MediaPlayerCompat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import tv.danmaku.ijk.media.player.IMediaPlayer; 20 | import tv.danmaku.ijk.media.player.IjkMediaPlayer; 21 | import tv.danmaku.ijk.media.player.MediaPlayerProxy; 22 | import tv.danmaku.ijk.media.player.TextureMediaPlayer; 23 | 24 | public class MediaPlayerCompat { 25 | public static String getName(IMediaPlayer mp) { 26 | if (mp == null) { 27 | return "null"; 28 | } else if (mp instanceof TextureMediaPlayer) { 29 | StringBuilder sb = new StringBuilder("TextureMediaPlayer <"); 30 | IMediaPlayer internalMediaPlayer = ((TextureMediaPlayer) mp).getInternalMediaPlayer(); 31 | if (internalMediaPlayer == null) { 32 | sb.append("null>"); 33 | } else { 34 | sb.append(internalMediaPlayer.getClass().getSimpleName()); 35 | sb.append(">"); 36 | } 37 | return sb.toString(); 38 | } else { 39 | return mp.getClass().getSimpleName(); 40 | } 41 | } 42 | 43 | public static IjkMediaPlayer getIjkMediaPlayer(IMediaPlayer mp) { 44 | IjkMediaPlayer ijkMediaPlayer = null; 45 | if (mp == null) { 46 | return null; 47 | } if (mp instanceof IjkMediaPlayer) { 48 | ijkMediaPlayer = (IjkMediaPlayer) mp; 49 | } else if (mp instanceof MediaPlayerProxy && ((MediaPlayerProxy) mp).getInternalMediaPlayer() instanceof IjkMediaPlayer) { 50 | ijkMediaPlayer = (IjkMediaPlayer) ((MediaPlayerProxy) mp).getInternalMediaPlayer(); 51 | } 52 | return ijkMediaPlayer; 53 | } 54 | 55 | public static void selectTrack(IMediaPlayer mp, int stream) { 56 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp); 57 | if (ijkMediaPlayer == null) 58 | return; 59 | ijkMediaPlayer.selectTrack(stream); 60 | } 61 | 62 | public static void deselectTrack(IMediaPlayer mp, int stream) { 63 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp); 64 | if (ijkMediaPlayer == null) 65 | return; 66 | ijkMediaPlayer.deselectTrack(stream); 67 | } 68 | 69 | public static int getSelectedTrack(IMediaPlayer mp, int trackType) { 70 | IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp); 71 | if (ijkMediaPlayer == null) 72 | return -1; 73 | return ijkMediaPlayer.getSelectedTrack(trackType); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /mediaplayer/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MediaPlayer 3 | 4 | N/A 5 | Close 6 | Exit 7 | Sample 8 | Recent 9 | Settings 10 | Tracks 11 | Player 12 | Render 13 | Scale 14 | Info 15 | fps (output) 16 | fps (decode) 17 | 18 | Media Information 19 | Player 20 | Media 21 | Profile level 22 | Pixel format 23 | Resolution 24 | Length 25 | Stream #%d 26 | Type 27 | Codec 28 | Frame rate 29 | Bit rate 30 | Sample rate 31 | Channels 32 | * 33 | * 34 | 35 | Video 36 | Audio 37 | Subtitle 38 | Timed text 39 | Meta data 40 | Unknown 41 | 42 | Invalid progressive playback 43 | Unknown 44 | OK 45 | 46 | Aspect / Fit parent 47 | Aspect / Fill parent 48 | Aspect / Wrap content 49 | Free / Fill parent 50 | 16:9 / Fit parent 51 | 4:3 / Fit parent 52 | 53 | Render: None 54 | Render: SurfaceView 55 | Render: TextureView 56 | 57 | Player: None 58 | Player: AndroidMediaPlayer 59 | Player: IjkMediaPlayer 60 | Player: IjkExoMediaPlayer 61 | 62 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.annotation.TargetApi; 20 | import android.graphics.SurfaceTexture; 21 | import android.os.Build; 22 | import android.view.Surface; 23 | import android.view.SurfaceHolder; 24 | 25 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 26 | public class TextureMediaPlayer extends MediaPlayerProxy implements IMediaPlayer, ISurfaceTextureHolder { 27 | private SurfaceTexture mSurfaceTexture; 28 | private ISurfaceTextureHost mSurfaceTextureHost; 29 | 30 | public TextureMediaPlayer(IMediaPlayer backEndMediaPlayer) { 31 | super(backEndMediaPlayer); 32 | } 33 | 34 | public void releaseSurfaceTexture() { 35 | if (mSurfaceTexture != null) { 36 | if (mSurfaceTextureHost != null) { 37 | mSurfaceTextureHost.releaseSurfaceTexture(mSurfaceTexture); 38 | } else { 39 | mSurfaceTexture.release(); 40 | } 41 | mSurfaceTexture = null; 42 | } 43 | } 44 | 45 | //-------------------- 46 | // IMediaPlayer 47 | //-------------------- 48 | @Override 49 | public void reset() { 50 | super.reset(); 51 | releaseSurfaceTexture(); 52 | } 53 | 54 | @Override 55 | public void release() { 56 | super.release(); 57 | releaseSurfaceTexture(); 58 | } 59 | 60 | @Override 61 | public void setDisplay(SurfaceHolder sh) { 62 | if (mSurfaceTexture == null) 63 | super.setDisplay(sh); 64 | } 65 | 66 | @Override 67 | public void setSurface(Surface surface) { 68 | if (mSurfaceTexture == null) 69 | super.setSurface(surface); 70 | } 71 | 72 | //-------------------- 73 | // ISurfaceTextureHolder 74 | //-------------------- 75 | 76 | @Override 77 | public void setSurfaceTexture(SurfaceTexture surfaceTexture) { 78 | if (mSurfaceTexture == surfaceTexture) 79 | return; 80 | 81 | releaseSurfaceTexture(); 82 | mSurfaceTexture = surfaceTexture; 83 | if (surfaceTexture == null) { 84 | super.setSurface(null); 85 | } else { 86 | super.setSurface(new Surface(surfaceTexture)); 87 | } 88 | } 89 | 90 | @Override 91 | public SurfaceTexture getSurfaceTexture() { 92 | return mSurfaceTexture; 93 | } 94 | 95 | @Override 96 | public void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost) { 97 | mSurfaceTextureHost = surfaceTextureHost; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.misc; 18 | 19 | import android.text.TextUtils; 20 | 21 | import tv.danmaku.ijk.media.player.IjkMediaMeta; 22 | 23 | public class IjkTrackInfo implements ITrackInfo { 24 | private int mTrackType = MEDIA_TRACK_TYPE_UNKNOWN; 25 | private IjkMediaMeta.IjkStreamMeta mStreamMeta; 26 | 27 | public IjkTrackInfo(IjkMediaMeta.IjkStreamMeta streamMeta) { 28 | mStreamMeta = streamMeta; 29 | } 30 | 31 | public void setMediaMeta(IjkMediaMeta.IjkStreamMeta streamMeta) { 32 | mStreamMeta = streamMeta; 33 | } 34 | 35 | @Override 36 | public IMediaFormat getFormat() { 37 | return new IjkMediaFormat(mStreamMeta); 38 | } 39 | 40 | @Override 41 | public String getLanguage() { 42 | if (mStreamMeta == null || TextUtils.isEmpty(mStreamMeta.mLanguage)) 43 | return "und"; 44 | 45 | return mStreamMeta.mLanguage; 46 | } 47 | 48 | @Override 49 | public int getTrackType() { 50 | return mTrackType; 51 | } 52 | 53 | public void setTrackType(int trackType) { 54 | mTrackType = trackType; 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return getClass().getSimpleName() + '{' + getInfoInline() + "}"; 60 | } 61 | 62 | @Override 63 | public String getInfoInline() { 64 | StringBuilder out = new StringBuilder(128); 65 | switch (mTrackType) { 66 | case MEDIA_TRACK_TYPE_VIDEO: 67 | out.append("VIDEO"); 68 | out.append(", "); 69 | out.append(mStreamMeta.getCodecShortNameInline()); 70 | out.append(", "); 71 | out.append(mStreamMeta.getBitrateInline()); 72 | out.append(", "); 73 | out.append(mStreamMeta.getResolutionInline()); 74 | break; 75 | case MEDIA_TRACK_TYPE_AUDIO: 76 | out.append("AUDIO"); 77 | out.append(", "); 78 | out.append(mStreamMeta.getCodecShortNameInline()); 79 | out.append(", "); 80 | out.append(mStreamMeta.getBitrateInline()); 81 | out.append(", "); 82 | out.append(mStreamMeta.getSampleRateInline()); 83 | break; 84 | case MEDIA_TRACK_TYPE_TIMEDTEXT: 85 | out.append("TIMEDTEXT"); 86 | break; 87 | case MEDIA_TRACK_TYPE_SUBTITLE: 88 | out.append("SUBTITLE"); 89 | break; 90 | default: 91 | out.append("UNKNOWN"); 92 | break; 93 | } 94 | return out.toString(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/InfoHudViewHolder.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.mediaplayer.media; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Message; 6 | import android.view.View; 7 | import android.widget.TableLayout; 8 | 9 | import java.util.HashMap; 10 | import java.util.Locale; 11 | 12 | import tv.danmaku.ijk.media.player.IMediaPlayer; 13 | import tv.danmaku.ijk.media.player.IjkMediaPlayer; 14 | import tv.danmaku.ijk.media.player.MediaPlayerProxy; 15 | import tv.danmaku.ijk.mediaplayer.R; 16 | 17 | public class InfoHudViewHolder { 18 | private TableLayoutBinder mTableLayoutBinder; 19 | private HashMap mRowMap = new HashMap(); 20 | private IMediaPlayer mMediaPlayer; 21 | 22 | public InfoHudViewHolder(Context context, TableLayout tableLayout) { 23 | mTableLayoutBinder = new TableLayoutBinder(context, tableLayout); 24 | 25 | appendRow(R.string.fps_decode); 26 | appendRow(R.string.fps_output); 27 | } 28 | 29 | private void appendSection(int nameId) { 30 | mTableLayoutBinder.appendSection(nameId); 31 | } 32 | 33 | private void appendRow(int nameId) { 34 | View rowView = mTableLayoutBinder.appendRow2(nameId, null); 35 | mRowMap.put(nameId, rowView); 36 | } 37 | 38 | private void setRowValue(int id, String value) { 39 | View rowView = mRowMap.get(id); 40 | if (rowView == null) { 41 | rowView = mTableLayoutBinder.appendRow2(id, value); 42 | mRowMap.put(id, rowView); 43 | } else { 44 | mTableLayoutBinder.setValueText(rowView, value); 45 | } 46 | } 47 | 48 | public void setMediaPlayer(IMediaPlayer mp) { 49 | mMediaPlayer = mp; 50 | if (mMediaPlayer != null) { 51 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500); 52 | } else { 53 | mHandler.removeMessages(MSG_UPDATE_HUD); 54 | } 55 | } 56 | 57 | private static final int MSG_UPDATE_HUD = 1; 58 | private Handler mHandler = new Handler() { 59 | @Override 60 | public void handleMessage(Message msg) { 61 | switch (msg.what) { 62 | case MSG_UPDATE_HUD: { 63 | InfoHudViewHolder holder = InfoHudViewHolder.this; 64 | IjkMediaPlayer mp = null; 65 | if (mMediaPlayer == null) 66 | break; 67 | if (mMediaPlayer instanceof IjkMediaPlayer) { 68 | mp = (IjkMediaPlayer) mMediaPlayer; 69 | } else if (mMediaPlayer instanceof MediaPlayerProxy) { 70 | MediaPlayerProxy proxy = (MediaPlayerProxy) mMediaPlayer; 71 | IMediaPlayer internal = proxy.getInternalMediaPlayer(); 72 | if (internal != null && internal instanceof IjkMediaPlayer) 73 | mp = (IjkMediaPlayer) internal; 74 | } 75 | if (mp == null) 76 | break; 77 | 78 | float fpsOutput = mp.getVideoOutputFramesPerSecond(); 79 | float fpsDecode = mp.getVideoDecodeFramesPerSecond(); 80 | setRowValue(R.string.fps_decode, String.format(Locale.US, "%.2f", fpsDecode)); 81 | setRowValue(R.string.fps_output, String.format(Locale.US, "%.2f", fpsOutput)); 82 | 83 | mHandler.removeMessages(MSG_UPDATE_HUD); 84 | mHandler.sendEmptyMessageDelayed(MSG_UPDATE_HUD, 500); 85 | } 86 | } 87 | } 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.misc; 18 | 19 | import android.annotation.TargetApi; 20 | import android.media.MediaFormat; 21 | import android.media.MediaPlayer; 22 | import android.os.Build; 23 | 24 | public class AndroidTrackInfo implements ITrackInfo { 25 | private final MediaPlayer.TrackInfo mTrackInfo; 26 | 27 | public static AndroidTrackInfo[] fromMediaPlayer(MediaPlayer mp) { 28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) 29 | return fromTrackInfo(mp.getTrackInfo()); 30 | 31 | return null; 32 | } 33 | 34 | private static AndroidTrackInfo[] fromTrackInfo(MediaPlayer.TrackInfo[] trackInfos) { 35 | if (trackInfos == null) 36 | return null; 37 | 38 | AndroidTrackInfo androidTrackInfo[] = new AndroidTrackInfo[trackInfos.length]; 39 | for (int i = 0; i < trackInfos.length; ++i) { 40 | androidTrackInfo[i] = new AndroidTrackInfo(trackInfos[i]); 41 | } 42 | 43 | return androidTrackInfo; 44 | } 45 | 46 | private AndroidTrackInfo(MediaPlayer.TrackInfo trackInfo) { 47 | mTrackInfo = trackInfo; 48 | } 49 | 50 | @TargetApi(Build.VERSION_CODES.KITKAT) 51 | @Override 52 | public IMediaFormat getFormat() { 53 | if (mTrackInfo == null) 54 | return null; 55 | 56 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) 57 | return null; 58 | 59 | MediaFormat mediaFormat = mTrackInfo.getFormat(); 60 | if (mediaFormat == null) 61 | return null; 62 | 63 | return new AndroidMediaFormat(mediaFormat); 64 | } 65 | 66 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 67 | @Override 68 | public String getLanguage() { 69 | if (mTrackInfo == null) 70 | return "und"; 71 | 72 | return mTrackInfo.getLanguage(); 73 | } 74 | 75 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 76 | @Override 77 | public int getTrackType() { 78 | if (mTrackInfo == null) 79 | return MEDIA_TRACK_TYPE_UNKNOWN; 80 | 81 | return mTrackInfo.getTrackType(); 82 | } 83 | 84 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 85 | @Override 86 | public String toString() { 87 | StringBuilder out = new StringBuilder(128); 88 | out.append(getClass().getSimpleName()); 89 | out.append('{'); 90 | if (mTrackInfo != null) { 91 | out.append(mTrackInfo.toString()); 92 | } else { 93 | out.append("null"); 94 | } 95 | out.append('}'); 96 | return out.toString(); 97 | } 98 | 99 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 100 | @Override 101 | public String getInfoInline() { 102 | if (mTrackInfo != null) { 103 | return mTrackInfo.toString(); 104 | } else { 105 | return "null"; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/application/Settings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.application; 18 | 19 | import android.content.Context; 20 | import android.content.SharedPreferences; 21 | import android.preference.PreferenceManager; 22 | 23 | import tv.danmaku.ijk.mediaplayer.R; 24 | 25 | public class Settings { 26 | private Context mAppContext; 27 | private SharedPreferences mSharedPreferences; 28 | 29 | public static final int PV_PLAYER__Auto = 0; 30 | public static final int PV_PLAYER__AndroidMediaPlayer = 1; 31 | public static final int PV_PLAYER__IjkMediaPlayer = 2; 32 | public static final int PV_PLAYER__IjkExoMediaPlayer = 3; 33 | 34 | public Settings(Context context) { 35 | mAppContext = context.getApplicationContext(); 36 | mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mAppContext); 37 | } 38 | 39 | public boolean getEnableBackgroundPlay() { 40 | String key = mAppContext.getString(R.string.pref_key_enable_background_play); 41 | return mSharedPreferences.getBoolean(key, false); 42 | } 43 | 44 | public int getPlayer() { 45 | String key = mAppContext.getString(R.string.pref_key_player); 46 | String value = mSharedPreferences.getString(key, ""); 47 | try { 48 | return Integer.valueOf(value).intValue(); 49 | } catch (NumberFormatException e) { 50 | return 0; 51 | } 52 | } 53 | 54 | public boolean getUsingMediaCodec() { 55 | String key = mAppContext.getString(R.string.pref_key_using_media_codec); 56 | return mSharedPreferences.getBoolean(key, false); 57 | } 58 | 59 | public boolean getUsingMediaCodecAutoRotate() { 60 | String key = mAppContext.getString(R.string.pref_key_using_media_codec_auto_rotate); 61 | return mSharedPreferences.getBoolean(key, false); 62 | } 63 | 64 | public boolean getUsingOpenSLES() { 65 | String key = mAppContext.getString(R.string.pref_key_using_opensl_es); 66 | return mSharedPreferences.getBoolean(key, false); 67 | } 68 | 69 | public String getPixelFormat() { 70 | String key = mAppContext.getString(R.string.pref_key_pixel_format); 71 | return mSharedPreferences.getString(key, ""); 72 | } 73 | 74 | public boolean getEnableNoView() { 75 | String key = mAppContext.getString(R.string.pref_key_enable_no_view); 76 | return mSharedPreferences.getBoolean(key, false); 77 | } 78 | 79 | public boolean getEnableSurfaceView() { 80 | String key = mAppContext.getString(R.string.pref_key_enable_surface_view); 81 | return mSharedPreferences.getBoolean(key, false); 82 | } 83 | 84 | public boolean getEnableTextureView() { 85 | String key = mAppContext.getString(R.string.pref_key_enable_texture_view); 86 | return mSharedPreferences.getBoolean(key, false); 87 | } 88 | 89 | public boolean getEnableDetachedSurfaceTextureView() { 90 | String key = mAppContext.getString(R.string.pref_key_enable_detached_surface_texture); 91 | return mSharedPreferences.getBoolean(key, false); 92 | } 93 | 94 | public String getLastDirectory() { 95 | String key = mAppContext.getString(R.string.pref_key_last_directory); 96 | return mSharedPreferences.getString(key, "/"); 97 | } 98 | 99 | public void setLastDirectory(String path) { 100 | String key = mAppContext.getString(R.string.pref_key_last_directory); 101 | mSharedPreferences.edit().putString(key, path).commit(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /mediaplayer/src/main/res/values/strings_pref.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | General 5 | 6 | pref.enable_background_play 7 | Enable background play 8 | need Android 4.0+ 9 | 10 | pref.using_android_player 11 | Using system player 12 | 13 | 14 | pref.player 15 | Choose Player 16 | 17 | Auto Select 18 | AndroidMediaPlayer 19 | IjkMediaPlayer 20 | IjkExoMediaPlayer 21 | 22 | 23 | 0 24 | 1 25 | 2 26 | 3 27 | 28 | 29 | Auto Select 30 | AndroidMediaPlayer 31 | IjkMediaPlayer 32 | IjkExoMediaPlayer 33 | 34 | 35 | 36 | Video: ijkplayer 37 | 38 | pref.using_media_codec 39 | Using MediaCodec 40 | 41 | 42 | pref.using_media_codec_auto_rotate 43 | Using MediaCodec auto rotate 44 | 45 | 46 | pref.pixel_format 47 | Pixel Format 48 | 49 | Auto Select 50 | RGB 565 51 | RGB 888X 52 | YV12 53 | 54 | 55 | 56 | fcc-rv16 57 | fcc-rv32 58 | fcc-yv12 59 | 60 | 61 | Auto Select 62 | RGB 565 63 | RGB 888X 64 | YV12 65 | 66 | 67 | 68 | Audio: ijkplayer 69 | 70 | pref.using_opensl_es 71 | Using OpenSL ES 72 | 73 | 74 | 75 | RenderView 76 | 77 | pref.enable_no_view 78 | Enable NoView 79 | 80 | 81 | pref.enable_surface_view 82 | Enable SurfaceView 83 | 84 | 85 | pref.enable_texture_view 86 | Enable TextureView 87 | 88 | 89 | pref.enable_detached_surface_texture 90 | Enable detached SurfaceTexture 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Zhang Rui 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 tv.danmaku.ijk.media.player.misc.IMediaDataSource; 20 | 21 | @SuppressWarnings("WeakerAccess") 22 | public abstract class AbstractMediaPlayer implements IMediaPlayer { 23 | private OnPreparedListener mOnPreparedListener; 24 | private OnCompletionListener mOnCompletionListener; 25 | private OnBufferingUpdateListener mOnBufferingUpdateListener; 26 | private OnSeekCompleteListener mOnSeekCompleteListener; 27 | private OnVideoSizeChangedListener mOnVideoSizeChangedListener; 28 | private OnErrorListener mOnErrorListener; 29 | private OnInfoListener mOnInfoListener; 30 | 31 | public final void setOnPreparedListener(OnPreparedListener listener) { 32 | mOnPreparedListener = listener; 33 | } 34 | 35 | public final void setOnCompletionListener(OnCompletionListener listener) { 36 | mOnCompletionListener = listener; 37 | } 38 | 39 | public final void setOnBufferingUpdateListener( 40 | OnBufferingUpdateListener listener) { 41 | mOnBufferingUpdateListener = listener; 42 | } 43 | 44 | public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) { 45 | mOnSeekCompleteListener = listener; 46 | } 47 | 48 | public final void setOnVideoSizeChangedListener( 49 | OnVideoSizeChangedListener listener) { 50 | mOnVideoSizeChangedListener = listener; 51 | } 52 | 53 | public final void setOnErrorListener(OnErrorListener listener) { 54 | mOnErrorListener = listener; 55 | } 56 | 57 | public final void setOnInfoListener(OnInfoListener listener) { 58 | mOnInfoListener = listener; 59 | } 60 | 61 | public void resetListeners() { 62 | mOnPreparedListener = null; 63 | mOnBufferingUpdateListener = null; 64 | mOnCompletionListener = null; 65 | mOnSeekCompleteListener = null; 66 | mOnVideoSizeChangedListener = null; 67 | mOnErrorListener = null; 68 | mOnInfoListener = null; 69 | } 70 | 71 | protected final void notifyOnPrepared() { 72 | if (mOnPreparedListener != null) 73 | mOnPreparedListener.onPrepared(this); 74 | } 75 | 76 | protected final void notifyOnCompletion() { 77 | if (mOnCompletionListener != null) 78 | mOnCompletionListener.onCompletion(this); 79 | } 80 | 81 | protected final void notifyOnBufferingUpdate(int percent) { 82 | if (mOnBufferingUpdateListener != null) 83 | mOnBufferingUpdateListener.onBufferingUpdate(this, percent); 84 | } 85 | 86 | protected final void notifyOnSeekComplete() { 87 | if (mOnSeekCompleteListener != null) 88 | mOnSeekCompleteListener.onSeekComplete(this); 89 | } 90 | 91 | protected final void notifyOnVideoSizeChanged(int width, int height, 92 | int sarNum, int sarDen) { 93 | if (mOnVideoSizeChangedListener != null) 94 | mOnVideoSizeChangedListener.onVideoSizeChanged(this, width, height, 95 | sarNum, sarDen); 96 | } 97 | 98 | protected final boolean notifyOnError(int what, int extra) { 99 | return mOnErrorListener != null && mOnErrorListener.onError(this, what, extra); 100 | } 101 | 102 | protected final boolean notifyOnInfo(int what, int extra) { 103 | return mOnInfoListener != null && mOnInfoListener.onInfo(this, what, extra); 104 | } 105 | 106 | public void setDataSource(IMediaDataSource mediaDataSource) { 107 | throw new UnsupportedOperationException(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Zhang Rui 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.pragma; 18 | 19 | import java.util.Locale; 20 | 21 | 22 | import android.util.Log; 23 | 24 | @SuppressWarnings({"SameParameterValue", "WeakerAccess"}) 25 | public class DebugLog { 26 | public static final boolean ENABLE_ERROR = Pragma.ENABLE_VERBOSE; 27 | public static final boolean ENABLE_INFO = Pragma.ENABLE_VERBOSE; 28 | public static final boolean ENABLE_WARN = Pragma.ENABLE_VERBOSE; 29 | public static final boolean ENABLE_DEBUG = Pragma.ENABLE_VERBOSE; 30 | public static final boolean ENABLE_VERBOSE = Pragma.ENABLE_VERBOSE; 31 | 32 | public static void e(String tag, String msg) { 33 | if (ENABLE_ERROR) { 34 | Log.e(tag, msg); 35 | } 36 | } 37 | 38 | public static void e(String tag, String msg, Throwable tr) { 39 | if (ENABLE_ERROR) { 40 | Log.e(tag, msg, tr); 41 | } 42 | } 43 | 44 | public static void efmt(String tag, String fmt, Object... args) { 45 | if (ENABLE_ERROR) { 46 | String msg = String.format(Locale.US, fmt, args); 47 | Log.e(tag, msg); 48 | } 49 | } 50 | 51 | public static void i(String tag, String msg) { 52 | if (ENABLE_INFO) { 53 | Log.i(tag, msg); 54 | } 55 | } 56 | 57 | public static void i(String tag, String msg, Throwable tr) { 58 | if (ENABLE_INFO) { 59 | Log.i(tag, msg, tr); 60 | } 61 | } 62 | 63 | public static void ifmt(String tag, String fmt, Object... args) { 64 | if (ENABLE_INFO) { 65 | String msg = String.format(Locale.US, fmt, args); 66 | Log.i(tag, msg); 67 | } 68 | } 69 | 70 | public static void w(String tag, String msg) { 71 | if (ENABLE_WARN) { 72 | Log.w(tag, msg); 73 | } 74 | } 75 | 76 | public static void w(String tag, String msg, Throwable tr) { 77 | if (ENABLE_WARN) { 78 | Log.w(tag, msg, tr); 79 | } 80 | } 81 | 82 | public static void wfmt(String tag, String fmt, Object... args) { 83 | if (ENABLE_WARN) { 84 | String msg = String.format(Locale.US, fmt, args); 85 | Log.w(tag, msg); 86 | } 87 | } 88 | 89 | public static void d(String tag, String msg) { 90 | if (ENABLE_DEBUG) { 91 | Log.d(tag, msg); 92 | } 93 | } 94 | 95 | public static void d(String tag, String msg, Throwable tr) { 96 | if (ENABLE_DEBUG) { 97 | Log.d(tag, msg, tr); 98 | } 99 | } 100 | 101 | public static void dfmt(String tag, String fmt, Object... args) { 102 | if (ENABLE_DEBUG) { 103 | String msg = String.format(Locale.US, fmt, args); 104 | Log.d(tag, msg); 105 | } 106 | } 107 | 108 | public static void v(String tag, String msg) { 109 | if (ENABLE_VERBOSE) { 110 | Log.v(tag, msg); 111 | } 112 | } 113 | 114 | public static void v(String tag, String msg, Throwable tr) { 115 | if (ENABLE_VERBOSE) { 116 | Log.v(tag, msg, tr); 117 | } 118 | } 119 | 120 | public static void vfmt(String tag, String fmt, Object... args) { 121 | if (ENABLE_VERBOSE) { 122 | String msg = String.format(Locale.US, fmt, args); 123 | Log.v(tag, msg); 124 | } 125 | } 126 | 127 | public static void printStackTrace(Throwable e) { 128 | if (ENABLE_WARN) { 129 | e.printStackTrace(); 130 | } 131 | } 132 | 133 | public static void printCause(Throwable e) { 134 | if (ENABLE_WARN) { 135 | Throwable cause = e.getCause(); 136 | if (cause != null) 137 | e = cause; 138 | 139 | printStackTrace(e); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/TableLayoutBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import android.content.Context; 20 | import android.support.v7.app.AlertDialog; 21 | import android.view.LayoutInflater; 22 | import android.view.View; 23 | import android.view.ViewGroup; 24 | import android.widget.TableLayout; 25 | import android.widget.TextView; 26 | 27 | import tv.danmaku.ijk.mediaplayer.R; 28 | 29 | public class TableLayoutBinder { 30 | private Context mContext; 31 | public ViewGroup mTableView; 32 | public TableLayout mTableLayout; 33 | 34 | public TableLayoutBinder(Context context) { 35 | this(context, R.layout.table_media_info); 36 | } 37 | 38 | public TableLayoutBinder(Context context, int layoutResourceId) { 39 | mContext = context; 40 | mTableView = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutResourceId, null); 41 | mTableLayout = (TableLayout) mTableView.findViewById(R.id.table); 42 | } 43 | 44 | public TableLayoutBinder(Context context, TableLayout tableLayout) { 45 | mContext = context; 46 | mTableView = tableLayout; 47 | mTableLayout = tableLayout; 48 | } 49 | 50 | public View appendRow1(String name, String value) { 51 | return appendRow(R.layout.table_media_info_row1, name, value); 52 | } 53 | 54 | public View appendRow1(int nameId, String value) { 55 | return appendRow1(mContext.getString(nameId), value); 56 | } 57 | 58 | public View appendRow2(String name, String value) { 59 | return appendRow(R.layout.table_media_info_row2, name, value); 60 | } 61 | 62 | public View appendRow2(int nameId, String value) { 63 | return appendRow2(mContext.getString(nameId), value); 64 | } 65 | 66 | public View appendSection(String name) { 67 | return appendRow(R.layout.table_media_info_section, name, null); 68 | } 69 | 70 | public View appendSection(int nameId) { 71 | return appendSection(mContext.getString(nameId)); 72 | } 73 | 74 | public View appendRow(int layoutId, String name, String value) { 75 | ViewGroup rowView = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutId, mTableLayout, false); 76 | setNameValueText(rowView, name, value); 77 | 78 | mTableLayout.addView(rowView); 79 | return rowView; 80 | } 81 | 82 | public ViewHolder obtainViewHolder(View rowView) { 83 | ViewHolder viewHolder = (ViewHolder) rowView.getTag(); 84 | if (viewHolder == null) { 85 | viewHolder = new ViewHolder(); 86 | viewHolder.mNameTextView = (TextView) rowView.findViewById(R.id.name); 87 | viewHolder.mValueTextView = (TextView) rowView.findViewById(R.id.value); 88 | rowView.setTag(viewHolder); 89 | } 90 | return viewHolder; 91 | } 92 | 93 | public void setNameValueText(View rowView, String name, String value) { 94 | ViewHolder viewHolder = obtainViewHolder(rowView); 95 | viewHolder.setName(name); 96 | viewHolder.setValue(value); 97 | } 98 | 99 | public void setValueText(View rowView, String value) { 100 | ViewHolder viewHolder = obtainViewHolder(rowView); 101 | viewHolder.setValue(value); 102 | } 103 | 104 | public ViewGroup buildLayout() { 105 | return mTableView; 106 | } 107 | 108 | public AlertDialog.Builder buildAlertDialogBuilder() { 109 | AlertDialog.Builder dlgBuilder = new AlertDialog.Builder(mContext); 110 | dlgBuilder.setView(buildLayout()); 111 | return dlgBuilder; 112 | } 113 | 114 | private static class ViewHolder { 115 | public TextView mNameTextView; 116 | public TextView mValueTextView; 117 | 118 | public void setName(String name) { 119 | if (mNameTextView != null) { 120 | mNameTextView.setText(name); 121 | } 122 | } 123 | 124 | public void setValue(String value) { 125 | if (mValueTextView != null) { 126 | mValueTextView.setText(value); 127 | } 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/PlayerActivity.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.mediaplayer; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.pm.ActivityInfo; 7 | import android.content.res.Configuration; 8 | import android.net.Uri; 9 | import android.os.Build; 10 | import android.os.Bundle; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.text.TextUtils; 13 | import android.util.Log; 14 | import android.view.WindowManager; 15 | 16 | import tv.danmaku.ijk.media.player.IMediaPlayer; 17 | import tv.danmaku.ijk.media.player.IjkMediaPlayer; 18 | import tv.danmaku.ijk.mediaplayer.media.AndroidMediaController; 19 | import tv.danmaku.ijk.mediaplayer.media.IjkVideoView; 20 | 21 | public class PlayerActivity extends AppCompatActivity { 22 | private static final String TAG = "VideoActivity"; 23 | 24 | private Uri mVideoUri; 25 | 26 | private IjkVideoView mVideoView; 27 | 28 | private boolean mBackPressed; 29 | 30 | public static Intent newIntent(Context context, String path, String title, int orientation) { 31 | Intent intent = new Intent(context, PlayerActivity.class); 32 | intent.putExtra("videoPath", path); 33 | intent.putExtra("videoTitle", title); 34 | intent.putExtra("orientation", orientation); 35 | return intent; 36 | } 37 | 38 | public static void intentTo(Context context, String path, String title, int orientation) { 39 | context.startActivity(newIntent(context, path, title, orientation)); 40 | } 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 46 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 47 | 48 | setContentView(R.layout.activity_player); 49 | 50 | // handle arguments 51 | String mVideoPath = getIntent().getStringExtra("videoPath"); 52 | int orientation = getIntent().getIntExtra("orientation", 53 | ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 54 | 55 | if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { 56 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 57 | } 58 | 59 | Intent intent = getIntent(); 60 | String intentAction = intent.getAction(); 61 | if (!TextUtils.isEmpty(intentAction)) { 62 | if (intentAction.equals(Intent.ACTION_VIEW)) { 63 | mVideoPath = intent.getDataString(); 64 | } else if (intentAction.equals(Intent.ACTION_SEND)) { 65 | mVideoUri = intent.getParcelableExtra(Intent.EXTRA_STREAM); 66 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 67 | String scheme = mVideoUri.getScheme(); 68 | if (TextUtils.isEmpty(scheme)) { 69 | Log.e(TAG, "Null unknown ccheme\n"); 70 | finish(); 71 | return; 72 | } 73 | if (scheme.equals(ContentResolver.SCHEME_ANDROID_RESOURCE)) { 74 | mVideoPath = mVideoUri.getPath(); 75 | } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { 76 | Log.e(TAG, "Can not resolve content below Android-ICS\n"); 77 | finish(); 78 | return; 79 | } else { 80 | Log.e(TAG, "Unknown scheme " + scheme + "\n"); 81 | finish(); 82 | return; 83 | } 84 | } 85 | } 86 | } 87 | 88 | AndroidMediaController mMediaController = new AndroidMediaController(this, false); 89 | 90 | // init player 91 | IjkMediaPlayer.loadLibrariesOnce(null); 92 | IjkMediaPlayer.native_profileBegin("libijkplayer.so"); 93 | 94 | mVideoView = (IjkVideoView) findViewById(R.id.video_view); 95 | mVideoView.setMediaController(mMediaController); 96 | mVideoView.setOnCompletionListener(new IMediaPlayer.OnCompletionListener() { 97 | @Override 98 | public void onCompletion(IMediaPlayer mp) { 99 | finish(); 100 | } 101 | }); 102 | mVideoView.setOnErrorListener(new IMediaPlayer.OnErrorListener() { 103 | @Override 104 | public boolean onError(IMediaPlayer mp, int what, int extra) { 105 | finish(); 106 | return false; 107 | } 108 | }); 109 | // prefer mVideoPath 110 | if (mVideoPath != null) 111 | mVideoView.setVideoPath(mVideoPath); 112 | else if (mVideoUri != null) 113 | mVideoView.setVideoURI(mVideoUri); 114 | else { 115 | Log.e(TAG, "Null Data Source\n"); 116 | finish(); 117 | return; 118 | } 119 | mVideoView.start(); 120 | } 121 | 122 | @Override 123 | public void onConfigurationChanged(Configuration newConfig) { 124 | super.onConfigurationChanged(newConfig); 125 | } 126 | 127 | @Override 128 | protected void onStop() { 129 | super.onStop(); 130 | 131 | if (mBackPressed || !mVideoView.isBackgroundPlayEnabled()) { 132 | mVideoView.stopPlayback(); 133 | mVideoView.release(true); 134 | mVideoView.stopBackgroundPlay(); 135 | } else { 136 | mVideoView.enterBackground(); 137 | } 138 | IjkMediaPlayer.native_profileEnd(); 139 | } 140 | 141 | @Override 142 | public void onBackPressed() { 143 | mBackPressed = true; 144 | 145 | super.onBackPressed(); 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Zhang Rui 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.annotation.TargetApi; 20 | import android.content.Context; 21 | import android.net.Uri; 22 | import android.os.Build; 23 | import android.view.Surface; 24 | import android.view.SurfaceHolder; 25 | 26 | import java.io.FileDescriptor; 27 | import java.io.IOException; 28 | import java.util.Map; 29 | 30 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource; 31 | import tv.danmaku.ijk.media.player.misc.ITrackInfo; 32 | 33 | public interface IMediaPlayer { 34 | /* 35 | * Do not change these values without updating their counterparts in native 36 | */ 37 | int MEDIA_INFO_UNKNOWN = 1; 38 | int MEDIA_INFO_STARTED_AS_NEXT = 2; 39 | int MEDIA_INFO_VIDEO_RENDERING_START = 3; 40 | int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; 41 | int MEDIA_INFO_BUFFERING_START = 701; 42 | int MEDIA_INFO_BUFFERING_END = 702; 43 | int MEDIA_INFO_NETWORK_BANDWIDTH = 703; 44 | int MEDIA_INFO_BAD_INTERLEAVING = 800; 45 | int MEDIA_INFO_NOT_SEEKABLE = 801; 46 | int MEDIA_INFO_METADATA_UPDATE = 802; 47 | int MEDIA_INFO_TIMED_TEXT_ERROR = 900; 48 | int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; 49 | int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; 50 | 51 | int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001; 52 | int MEDIA_INFO_AUDIO_RENDERING_START = 10002; 53 | 54 | int MEDIA_ERROR_UNKNOWN = 1; 55 | int MEDIA_ERROR_SERVER_DIED = 100; 56 | int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; 57 | int MEDIA_ERROR_IO = -1004; 58 | int MEDIA_ERROR_MALFORMED = -1007; 59 | int MEDIA_ERROR_UNSUPPORTED = -1010; 60 | int MEDIA_ERROR_TIMED_OUT = -110; 61 | 62 | void setDisplay(SurfaceHolder sh); 63 | 64 | void setDataSource(Context context, Uri uri) 65 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException; 66 | 67 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 68 | void setDataSource(Context context, Uri uri, Map headers) 69 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException; 70 | 71 | void setDataSource(FileDescriptor fd) 72 | throws IOException, IllegalArgumentException, IllegalStateException; 73 | 74 | void setDataSource(String path) 75 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException; 76 | 77 | String getDataSource(); 78 | 79 | void prepareAsync() throws IllegalStateException; 80 | 81 | void start() throws IllegalStateException; 82 | 83 | void stop() throws IllegalStateException; 84 | 85 | void pause() throws IllegalStateException; 86 | 87 | void setScreenOnWhilePlaying(boolean screenOn); 88 | 89 | int getVideoWidth(); 90 | 91 | int getVideoHeight(); 92 | 93 | boolean isPlaying(); 94 | 95 | void seekTo(long msec) throws IllegalStateException; 96 | 97 | long getCurrentPosition(); 98 | 99 | long getDuration(); 100 | 101 | void release(); 102 | 103 | void reset(); 104 | 105 | void setVolume(float leftVolume, float rightVolume); 106 | 107 | int getAudioSessionId(); 108 | 109 | MediaInfo getMediaInfo(); 110 | 111 | @SuppressWarnings("EmptyMethod") 112 | @Deprecated 113 | void setLogEnabled(boolean enable); 114 | 115 | @Deprecated 116 | boolean isPlayable(); 117 | 118 | void setOnPreparedListener(OnPreparedListener listener); 119 | 120 | void setOnCompletionListener(OnCompletionListener listener); 121 | 122 | void setOnBufferingUpdateListener( 123 | OnBufferingUpdateListener listener); 124 | 125 | void setOnSeekCompleteListener( 126 | OnSeekCompleteListener listener); 127 | 128 | void setOnVideoSizeChangedListener( 129 | OnVideoSizeChangedListener listener); 130 | 131 | void setOnErrorListener(OnErrorListener listener); 132 | 133 | void setOnInfoListener(OnInfoListener listener); 134 | 135 | /*-------------------- 136 | * Listeners 137 | */ 138 | interface OnPreparedListener { 139 | void onPrepared(IMediaPlayer mp); 140 | } 141 | 142 | interface OnCompletionListener { 143 | void onCompletion(IMediaPlayer mp); 144 | } 145 | 146 | interface OnBufferingUpdateListener { 147 | void onBufferingUpdate(IMediaPlayer mp, int percent); 148 | } 149 | 150 | interface OnSeekCompleteListener { 151 | void onSeekComplete(IMediaPlayer mp); 152 | } 153 | 154 | interface OnVideoSizeChangedListener { 155 | void onVideoSizeChanged(IMediaPlayer mp, int width, int height, 156 | int sar_num, int sar_den); 157 | } 158 | 159 | interface OnErrorListener { 160 | boolean onError(IMediaPlayer mp, int what, int extra); 161 | } 162 | 163 | interface OnInfoListener { 164 | boolean onInfo(IMediaPlayer mp, int what, int extra); 165 | } 166 | 167 | /*-------------------- 168 | * Optional 169 | */ 170 | void setAudioStreamType(int streamtype); 171 | 172 | @Deprecated 173 | void setKeepInBackground(boolean keepInBackground); 174 | 175 | int getVideoSarNum(); 176 | 177 | int getVideoSarDen(); 178 | 179 | @Deprecated 180 | void setWakeMode(Context context, int mode); 181 | 182 | void setLooping(boolean looping); 183 | 184 | boolean isLooping(); 185 | 186 | /*-------------------- 187 | * AndroidMediaPlayer: JELLY_BEAN 188 | */ 189 | ITrackInfo[] getTrackInfo(); 190 | 191 | /*-------------------- 192 | * AndroidMediaPlayer: ICE_CREAM_SANDWICH: 193 | */ 194 | void setSurface(Surface surface); 195 | 196 | /*-------------------- 197 | * AndroidMediaPlayer: M: 198 | */ 199 | void setDataSource(IMediaDataSource mediaDataSource); 200 | } 201 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.misc; 18 | 19 | import android.annotation.TargetApi; 20 | import android.os.Build; 21 | import android.text.TextUtils; 22 | 23 | import java.util.HashMap; 24 | import java.util.Locale; 25 | import java.util.Map; 26 | 27 | import tv.danmaku.ijk.media.player.IjkMediaMeta; 28 | 29 | public class IjkMediaFormat implements IMediaFormat { 30 | // Common 31 | public static final String KEY_IJK_CODEC_LONG_NAME_UI = "ijk-codec-long-name-ui"; 32 | public static final String KEY_IJK_BIT_RATE_UI = "ijk-bit-rate-ui"; 33 | 34 | // Video 35 | public static final String KEY_IJK_CODEC_PROFILE_LEVEL_UI = "ijk-profile-level-ui"; 36 | public static final String KEY_IJK_CODEC_PIXEL_FORMAT_UI = "ijk-pixel-format-ui"; 37 | public static final String KEY_IJK_RESOLUTION_UI = "ijk-resolution-ui"; 38 | public static final String KEY_IJK_FRAME_RATE_UI = "ijk-frame-rate-ui"; 39 | 40 | // Audio 41 | public static final String KEY_IJK_SAMPLE_RATE_UI = "ijk-sample-rate-ui"; 42 | public static final String KEY_IJK_CHANNEL_UI = "ijk-channel-ui"; 43 | 44 | // Codec 45 | public static final String CODEC_NAME_H264 = "h264"; 46 | 47 | public final IjkMediaMeta.IjkStreamMeta mMediaFormat; 48 | 49 | public IjkMediaFormat(IjkMediaMeta.IjkStreamMeta streamMeta) { 50 | mMediaFormat = streamMeta; 51 | } 52 | 53 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 54 | @Override 55 | public int getInteger(String name) { 56 | if (mMediaFormat == null) 57 | return 0; 58 | 59 | return mMediaFormat.getInt(name); 60 | } 61 | 62 | @Override 63 | public String getString(String name) { 64 | if (mMediaFormat == null) 65 | return null; 66 | 67 | if (sFormatterMap.containsKey(name)) { 68 | Formatter formatter = sFormatterMap.get(name); 69 | return formatter.format(this); 70 | } 71 | 72 | return mMediaFormat.getString(name); 73 | } 74 | 75 | //------------------------- 76 | // Formatter 77 | //------------------------- 78 | 79 | private static abstract class Formatter { 80 | public String format(IjkMediaFormat mediaFormat) { 81 | String value = doFormat(mediaFormat); 82 | if (TextUtils.isEmpty(value)) 83 | return getDefaultString(); 84 | return value; 85 | } 86 | 87 | protected abstract String doFormat(IjkMediaFormat mediaFormat); 88 | 89 | @SuppressWarnings("SameReturnValue") 90 | protected String getDefaultString() { 91 | return "N/A"; 92 | } 93 | } 94 | 95 | private static final Map sFormatterMap = new HashMap(); 96 | 97 | { 98 | sFormatterMap.put(KEY_IJK_CODEC_LONG_NAME_UI, new Formatter() { 99 | @Override 100 | public String doFormat(IjkMediaFormat mediaFormat) { 101 | return mMediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_LONG_NAME); 102 | } 103 | }); 104 | sFormatterMap.put(KEY_IJK_BIT_RATE_UI, new Formatter() { 105 | @Override 106 | protected String doFormat(IjkMediaFormat mediaFormat) { 107 | int bitRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_BITRATE); 108 | if (bitRate <= 0) { 109 | return null; 110 | } else if (bitRate < 1000) { 111 | return String.format(Locale.US, "%d bit/s", bitRate); 112 | } else { 113 | return String.format(Locale.US, "%d kb/s", bitRate / 1000); 114 | } 115 | } 116 | }); 117 | sFormatterMap.put(KEY_IJK_CODEC_PROFILE_LEVEL_UI, new Formatter() { 118 | @Override 119 | protected String doFormat(IjkMediaFormat mediaFormat) { 120 | String profile = mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_PROFILE); 121 | if (TextUtils.isEmpty(profile)) 122 | return null; 123 | 124 | StringBuilder sb = new StringBuilder(); 125 | sb.append(profile); 126 | 127 | String codecName = mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_NAME); 128 | if (!TextUtils.isEmpty(codecName) && codecName.equalsIgnoreCase(CODEC_NAME_H264)) { 129 | int level = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CODEC_LEVEL); 130 | if (level < 10) 131 | return sb.toString(); 132 | 133 | sb.append(" Profile Level "); 134 | sb.append((level / 10) % 10); 135 | if ((level % 10) != 0) { 136 | sb.append("."); 137 | sb.append(level % 10); 138 | } 139 | } 140 | 141 | return sb.toString(); 142 | } 143 | }); 144 | sFormatterMap.put(KEY_IJK_CODEC_PIXEL_FORMAT_UI, new Formatter() { 145 | @Override 146 | protected String doFormat(IjkMediaFormat mediaFormat) { 147 | return mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_PIXEL_FORMAT); 148 | } 149 | }); 150 | sFormatterMap.put(KEY_IJK_RESOLUTION_UI, new Formatter() { 151 | @Override 152 | protected String doFormat(IjkMediaFormat mediaFormat) { 153 | int width = mediaFormat.getInteger(KEY_WIDTH); 154 | int height = mediaFormat.getInteger(KEY_HEIGHT); 155 | int sarNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_NUM); 156 | int sarDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_DEN); 157 | 158 | if (width <= 0 || height <= 0) { 159 | return null; 160 | } else if (sarNum <= 0 || sarDen <= 0) { 161 | return String.format(Locale.US, "%d x %d", width, height); 162 | } else { 163 | return String.format(Locale.US, "%d x %d [SAR %d:%d]", width, 164 | height, sarNum, sarDen); 165 | } 166 | } 167 | }); 168 | sFormatterMap.put(KEY_IJK_FRAME_RATE_UI, new Formatter() { 169 | @Override 170 | protected String doFormat(IjkMediaFormat mediaFormat) { 171 | int fpsNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_NUM); 172 | int fpsDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_DEN); 173 | if (fpsNum <= 0 || fpsDen <= 0) { 174 | return null; 175 | } else { 176 | return String.valueOf(((float) (fpsNum)) / fpsDen); 177 | } 178 | } 179 | }); 180 | sFormatterMap.put(KEY_IJK_SAMPLE_RATE_UI, new Formatter() { 181 | @Override 182 | protected String doFormat(IjkMediaFormat mediaFormat) { 183 | int sampleRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAMPLE_RATE); 184 | if (sampleRate <= 0) { 185 | return null; 186 | } else { 187 | return String.format(Locale.US, "%d Hz", sampleRate); 188 | } 189 | } 190 | }); 191 | sFormatterMap.put(KEY_IJK_CHANNEL_UI, new Formatter() { 192 | @Override 193 | protected String doFormat(IjkMediaFormat mediaFormat) { 194 | int channelLayout = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CHANNEL_LAYOUT); 195 | if (channelLayout <= 0) { 196 | return null; 197 | } else { 198 | if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_MONO) { 199 | return "mono"; 200 | } else if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_STEREO) { 201 | return "stereo"; 202 | } else { 203 | return String.format(Locale.US, "%x", channelLayout); 204 | } 205 | } 206 | } 207 | }); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/SurfaceRenderView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import android.annotation.TargetApi; 20 | import android.content.Context; 21 | import android.graphics.SurfaceTexture; 22 | import android.os.Build; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | import android.util.AttributeSet; 26 | import android.util.Log; 27 | import android.view.Surface; 28 | import android.view.SurfaceHolder; 29 | import android.view.SurfaceView; 30 | import android.view.View; 31 | import android.view.accessibility.AccessibilityEvent; 32 | import android.view.accessibility.AccessibilityNodeInfo; 33 | 34 | import java.lang.ref.WeakReference; 35 | import java.util.Map; 36 | import java.util.concurrent.ConcurrentHashMap; 37 | 38 | import tv.danmaku.ijk.media.player.IMediaPlayer; 39 | import tv.danmaku.ijk.media.player.ISurfaceTextureHolder; 40 | 41 | public class SurfaceRenderView extends SurfaceView implements IRenderView { 42 | private MeasureHelper mMeasureHelper; 43 | 44 | public SurfaceRenderView(Context context) { 45 | super(context); 46 | initView(context); 47 | } 48 | 49 | public SurfaceRenderView(Context context, AttributeSet attrs) { 50 | super(context, attrs); 51 | initView(context); 52 | } 53 | 54 | public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr) { 55 | super(context, attrs, defStyleAttr); 56 | initView(context); 57 | } 58 | 59 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 60 | public SurfaceRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 61 | super(context, attrs, defStyleAttr, defStyleRes); 62 | initView(context); 63 | } 64 | 65 | private void initView(Context context) { 66 | mMeasureHelper = new MeasureHelper(this); 67 | mSurfaceCallback = new SurfaceCallback(this); 68 | getHolder().addCallback(mSurfaceCallback); 69 | //noinspection deprecation 70 | getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL); 71 | } 72 | 73 | @Override 74 | public View getView() { 75 | return this; 76 | } 77 | 78 | @Override 79 | public boolean shouldWaitForResize() { 80 | return true; 81 | } 82 | 83 | //-------------------- 84 | // Layout & Measure 85 | //-------------------- 86 | @Override 87 | public void setVideoSize(int videoWidth, int videoHeight) { 88 | if (videoWidth > 0 && videoHeight > 0) { 89 | mMeasureHelper.setVideoSize(videoWidth, videoHeight); 90 | getHolder().setFixedSize(videoWidth, videoHeight); 91 | requestLayout(); 92 | } 93 | } 94 | 95 | @Override 96 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) { 97 | if (videoSarNum > 0 && videoSarDen > 0) { 98 | mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen); 99 | requestLayout(); 100 | } 101 | } 102 | 103 | @Override 104 | public void setVideoRotation(int degree) { 105 | Log.e("", "SurfaceView doesn't support rotation (" + degree + ")!\n"); 106 | } 107 | 108 | @Override 109 | public void setAspectRatio(int aspectRatio) { 110 | mMeasureHelper.setAspectRatio(aspectRatio); 111 | requestLayout(); 112 | } 113 | 114 | @Override 115 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 116 | mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec); 117 | setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight()); 118 | } 119 | 120 | //-------------------- 121 | // SurfaceViewHolder 122 | //-------------------- 123 | 124 | private static final class InternalSurfaceHolder implements IRenderView.ISurfaceHolder { 125 | private SurfaceRenderView mSurfaceView; 126 | private SurfaceHolder mSurfaceHolder; 127 | 128 | public InternalSurfaceHolder(@NonNull SurfaceRenderView surfaceView, 129 | @Nullable SurfaceHolder surfaceHolder) { 130 | mSurfaceView = surfaceView; 131 | mSurfaceHolder = surfaceHolder; 132 | } 133 | 134 | public void bindToMediaPlayer(IMediaPlayer mp) { 135 | if (mp != null) { 136 | if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) && 137 | (mp instanceof ISurfaceTextureHolder)) { 138 | ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp; 139 | textureHolder.setSurfaceTexture(null); 140 | } 141 | mp.setDisplay(mSurfaceHolder); 142 | } 143 | } 144 | 145 | @NonNull 146 | @Override 147 | public IRenderView getRenderView() { 148 | return mSurfaceView; 149 | } 150 | 151 | @Nullable 152 | @Override 153 | public SurfaceHolder getSurfaceHolder() { 154 | return mSurfaceHolder; 155 | } 156 | 157 | @Nullable 158 | @Override 159 | public SurfaceTexture getSurfaceTexture() { 160 | return null; 161 | } 162 | 163 | @Nullable 164 | @Override 165 | public Surface openSurface() { 166 | if (mSurfaceHolder == null) 167 | return null; 168 | return mSurfaceHolder.getSurface(); 169 | } 170 | } 171 | 172 | //------------------------- 173 | // SurfaceHolder.Callback 174 | //------------------------- 175 | 176 | @Override 177 | public void addRenderCallback(IRenderCallback callback) { 178 | mSurfaceCallback.addRenderCallback(callback); 179 | } 180 | 181 | @Override 182 | public void removeRenderCallback(IRenderCallback callback) { 183 | mSurfaceCallback.removeRenderCallback(callback); 184 | } 185 | 186 | private SurfaceCallback mSurfaceCallback; 187 | 188 | private static final class SurfaceCallback implements SurfaceHolder.Callback { 189 | private SurfaceHolder mSurfaceHolder; 190 | private boolean mIsFormatChanged; 191 | private int mFormat; 192 | private int mWidth; 193 | private int mHeight; 194 | 195 | private WeakReference mWeakSurfaceView; 196 | private Map mRenderCallbackMap = new ConcurrentHashMap(); 197 | 198 | public SurfaceCallback(@NonNull SurfaceRenderView surfaceView) { 199 | mWeakSurfaceView = new WeakReference(surfaceView); 200 | } 201 | 202 | public void addRenderCallback(@NonNull IRenderCallback callback) { 203 | mRenderCallbackMap.put(callback, callback); 204 | 205 | ISurfaceHolder surfaceHolder = null; 206 | if (mSurfaceHolder != null) { 207 | if (surfaceHolder == null) 208 | surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder); 209 | callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight); 210 | } 211 | 212 | if (mIsFormatChanged) { 213 | if (surfaceHolder == null) 214 | surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder); 215 | callback.onSurfaceChanged(surfaceHolder, mFormat, mWidth, mHeight); 216 | } 217 | } 218 | 219 | public void removeRenderCallback(@NonNull IRenderCallback callback) { 220 | mRenderCallbackMap.remove(callback); 221 | } 222 | 223 | @Override 224 | public void surfaceCreated(SurfaceHolder holder) { 225 | mSurfaceHolder = holder; 226 | mIsFormatChanged = false; 227 | mFormat = 0; 228 | mWidth = 0; 229 | mHeight = 0; 230 | 231 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder); 232 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) { 233 | renderCallback.onSurfaceCreated(surfaceHolder, 0, 0); 234 | } 235 | } 236 | 237 | @Override 238 | public void surfaceDestroyed(SurfaceHolder holder) { 239 | mSurfaceHolder = null; 240 | mIsFormatChanged = false; 241 | mFormat = 0; 242 | mWidth = 0; 243 | mHeight = 0; 244 | 245 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder); 246 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) { 247 | renderCallback.onSurfaceDestroyed(surfaceHolder); 248 | } 249 | } 250 | 251 | @Override 252 | public void surfaceChanged(SurfaceHolder holder, int format, 253 | int width, int height) { 254 | mSurfaceHolder = holder; 255 | mIsFormatChanged = true; 256 | mFormat = format; 257 | mWidth = width; 258 | mHeight = height; 259 | 260 | // mMeasureHelper.setVideoSize(width, height); 261 | 262 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceHolder); 263 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) { 264 | renderCallback.onSurfaceChanged(surfaceHolder, format, width, height); 265 | } 266 | } 267 | } 268 | 269 | //-------------------- 270 | // Accessibility 271 | //-------------------- 272 | 273 | @Override 274 | public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 275 | super.onInitializeAccessibilityEvent(event); 276 | event.setClassName(SurfaceRenderView.class.getName()); 277 | } 278 | 279 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 280 | @Override 281 | public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 282 | super.onInitializeAccessibilityNodeInfo(info); 283 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 284 | info.setClassName(SurfaceRenderView.class.getName()); 285 | } 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.annotation.TargetApi; 20 | import android.content.Context; 21 | import android.net.Uri; 22 | import android.os.Build; 23 | import android.view.Surface; 24 | import android.view.SurfaceHolder; 25 | 26 | import java.io.FileDescriptor; 27 | import java.io.IOException; 28 | import java.util.Map; 29 | 30 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource; 31 | import tv.danmaku.ijk.media.player.misc.ITrackInfo; 32 | 33 | public class MediaPlayerProxy implements IMediaPlayer { 34 | protected final IMediaPlayer mBackEndMediaPlayer; 35 | 36 | public MediaPlayerProxy(IMediaPlayer backEndMediaPlayer) { 37 | mBackEndMediaPlayer = backEndMediaPlayer; 38 | } 39 | 40 | public IMediaPlayer getInternalMediaPlayer() { 41 | return mBackEndMediaPlayer; 42 | } 43 | 44 | @Override 45 | public void setDisplay(SurfaceHolder sh) { 46 | mBackEndMediaPlayer.setDisplay(sh); 47 | } 48 | 49 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 50 | @Override 51 | public void setSurface(Surface surface) { 52 | mBackEndMediaPlayer.setSurface(surface); 53 | } 54 | 55 | @Override 56 | public void setDataSource(Context context, Uri uri) 57 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { 58 | mBackEndMediaPlayer.setDataSource(context, uri); 59 | } 60 | 61 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 62 | @Override 63 | public void setDataSource(Context context, Uri uri, Map headers) 64 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { 65 | mBackEndMediaPlayer.setDataSource(context, uri, headers); 66 | } 67 | 68 | @Override 69 | public void setDataSource(FileDescriptor fd) 70 | throws IOException, IllegalArgumentException, IllegalStateException { 71 | mBackEndMediaPlayer.setDataSource(fd); 72 | } 73 | 74 | @Override 75 | public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { 76 | mBackEndMediaPlayer.setDataSource(path); 77 | } 78 | 79 | @Override 80 | public void setDataSource(IMediaDataSource mediaDataSource) { 81 | mBackEndMediaPlayer.setDataSource(mediaDataSource); 82 | } 83 | 84 | @Override 85 | public String getDataSource() { 86 | return mBackEndMediaPlayer.getDataSource(); 87 | } 88 | 89 | @Override 90 | public void prepareAsync() throws IllegalStateException { 91 | mBackEndMediaPlayer.prepareAsync(); 92 | } 93 | 94 | @Override 95 | public void start() throws IllegalStateException { 96 | mBackEndMediaPlayer.start(); 97 | } 98 | 99 | @Override 100 | public void stop() throws IllegalStateException { 101 | mBackEndMediaPlayer.stop(); 102 | } 103 | 104 | @Override 105 | public void pause() throws IllegalStateException { 106 | mBackEndMediaPlayer.pause(); 107 | } 108 | 109 | @Override 110 | public void setScreenOnWhilePlaying(boolean screenOn) { 111 | mBackEndMediaPlayer.setScreenOnWhilePlaying(screenOn); 112 | } 113 | 114 | @Override 115 | public int getVideoWidth() { 116 | return mBackEndMediaPlayer.getVideoWidth(); 117 | } 118 | 119 | @Override 120 | public int getVideoHeight() { 121 | return mBackEndMediaPlayer.getVideoHeight(); 122 | } 123 | 124 | @Override 125 | public boolean isPlaying() { 126 | return mBackEndMediaPlayer.isPlaying(); 127 | } 128 | 129 | @Override 130 | public void seekTo(long msec) throws IllegalStateException { 131 | mBackEndMediaPlayer.seekTo(msec); 132 | } 133 | 134 | @Override 135 | public long getCurrentPosition() { 136 | return mBackEndMediaPlayer.getCurrentPosition(); 137 | } 138 | 139 | @Override 140 | public long getDuration() { 141 | return mBackEndMediaPlayer.getDuration(); 142 | } 143 | 144 | @Override 145 | public void release() { 146 | mBackEndMediaPlayer.release(); 147 | } 148 | 149 | @Override 150 | public void reset() { 151 | mBackEndMediaPlayer.reset(); 152 | } 153 | 154 | @Override 155 | public void setVolume(float leftVolume, float rightVolume) { 156 | mBackEndMediaPlayer.setVolume(leftVolume, rightVolume); 157 | } 158 | 159 | @Override 160 | public int getAudioSessionId() { 161 | return mBackEndMediaPlayer.getAudioSessionId(); 162 | } 163 | 164 | @Override 165 | public MediaInfo getMediaInfo() { 166 | return mBackEndMediaPlayer.getMediaInfo(); 167 | } 168 | 169 | @Override 170 | public void setLogEnabled(boolean enable) { 171 | 172 | } 173 | 174 | @Override 175 | public boolean isPlayable() { 176 | return false; 177 | } 178 | 179 | @Override 180 | public void setOnPreparedListener(OnPreparedListener listener) { 181 | if (listener != null) { 182 | final OnPreparedListener finalListener = listener; 183 | mBackEndMediaPlayer.setOnPreparedListener(new OnPreparedListener() { 184 | @Override 185 | public void onPrepared(IMediaPlayer mp) { 186 | finalListener.onPrepared(MediaPlayerProxy.this); 187 | } 188 | }); 189 | } else { 190 | mBackEndMediaPlayer.setOnPreparedListener(null); 191 | } 192 | } 193 | 194 | @Override 195 | public void setOnCompletionListener(OnCompletionListener listener) { 196 | if (listener != null) { 197 | final OnCompletionListener finalListener = listener; 198 | mBackEndMediaPlayer.setOnCompletionListener(new OnCompletionListener() { 199 | @Override 200 | public void onCompletion(IMediaPlayer mp) { 201 | finalListener.onCompletion(MediaPlayerProxy.this); 202 | } 203 | }); 204 | } else { 205 | mBackEndMediaPlayer.setOnCompletionListener(null); 206 | } 207 | } 208 | 209 | @Override 210 | public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) { 211 | if (listener != null) { 212 | final OnBufferingUpdateListener finalListener = listener; 213 | mBackEndMediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() { 214 | @Override 215 | public void onBufferingUpdate(IMediaPlayer mp, int percent) { 216 | finalListener.onBufferingUpdate(MediaPlayerProxy.this, percent); 217 | } 218 | }); 219 | } else { 220 | mBackEndMediaPlayer.setOnBufferingUpdateListener(null); 221 | } 222 | } 223 | 224 | @Override 225 | public void setOnSeekCompleteListener(OnSeekCompleteListener listener) { 226 | if (listener != null) { 227 | final OnSeekCompleteListener finalListener = listener; 228 | mBackEndMediaPlayer.setOnSeekCompleteListener(new OnSeekCompleteListener() { 229 | @Override 230 | public void onSeekComplete(IMediaPlayer mp) { 231 | finalListener.onSeekComplete(MediaPlayerProxy.this); 232 | } 233 | }); 234 | } else { 235 | mBackEndMediaPlayer.setOnSeekCompleteListener(null); 236 | } 237 | } 238 | 239 | @Override 240 | public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) { 241 | if (listener != null) { 242 | final OnVideoSizeChangedListener finalListener = listener; 243 | mBackEndMediaPlayer.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() { 244 | @Override 245 | public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) { 246 | finalListener.onVideoSizeChanged(MediaPlayerProxy.this, width, height, sar_num, sar_den); 247 | } 248 | }); 249 | } else { 250 | mBackEndMediaPlayer.setOnVideoSizeChangedListener(null); 251 | } 252 | } 253 | 254 | @Override 255 | public void setOnErrorListener(OnErrorListener listener) { 256 | if (listener != null) { 257 | final OnErrorListener finalListener = listener; 258 | mBackEndMediaPlayer.setOnErrorListener(new OnErrorListener() { 259 | @Override 260 | public boolean onError(IMediaPlayer mp, int what, int extra) { 261 | return finalListener.onError(MediaPlayerProxy.this, what, extra); 262 | } 263 | }); 264 | } else { 265 | mBackEndMediaPlayer.setOnErrorListener(null); 266 | } 267 | } 268 | 269 | @Override 270 | public void setOnInfoListener(OnInfoListener listener) { 271 | if (listener != null) { 272 | final OnInfoListener finalListener = listener; 273 | mBackEndMediaPlayer.setOnInfoListener(new OnInfoListener() { 274 | @Override 275 | public boolean onInfo(IMediaPlayer mp, int what, int extra) { 276 | return finalListener.onInfo(MediaPlayerProxy.this, what, extra); 277 | } 278 | }); 279 | } else { 280 | mBackEndMediaPlayer.setOnInfoListener(null); 281 | } 282 | } 283 | 284 | @Override 285 | public void setAudioStreamType(int streamtype) { 286 | mBackEndMediaPlayer.setAudioStreamType(streamtype); 287 | } 288 | 289 | @Override 290 | public void setKeepInBackground(boolean keepInBackground) { 291 | mBackEndMediaPlayer.setKeepInBackground(keepInBackground); 292 | } 293 | 294 | @Override 295 | public int getVideoSarNum() { 296 | return mBackEndMediaPlayer.getVideoSarNum(); 297 | } 298 | 299 | @Override 300 | public int getVideoSarDen() { 301 | return mBackEndMediaPlayer.getVideoSarDen(); 302 | } 303 | 304 | @Override 305 | public void setWakeMode(Context context, int mode) { 306 | mBackEndMediaPlayer.setWakeMode(context, mode); 307 | } 308 | 309 | @Override 310 | public ITrackInfo[] getTrackInfo() { 311 | return mBackEndMediaPlayer.getTrackInfo(); 312 | } 313 | 314 | @Override 315 | public void setLooping(boolean looping) { 316 | mBackEndMediaPlayer.setLooping(looping); 317 | } 318 | 319 | @Override 320 | public boolean isLooping() { 321 | return mBackEndMediaPlayer.isLooping(); 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/MeasureHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | import android.view.View; 22 | 23 | import java.lang.ref.WeakReference; 24 | 25 | import tv.danmaku.ijk.mediaplayer.R; 26 | 27 | 28 | public final class MeasureHelper { 29 | private WeakReference mWeakView; 30 | 31 | private int mVideoWidth; 32 | private int mVideoHeight; 33 | private int mVideoSarNum; 34 | private int mVideoSarDen; 35 | 36 | private int mVideoRotationDegree; 37 | 38 | private int mMeasuredWidth; 39 | private int mMeasuredHeight; 40 | 41 | private int mCurrentAspectRatio = IRenderView.AR_ASPECT_FIT_PARENT; 42 | 43 | public MeasureHelper(View view) { 44 | mWeakView = new WeakReference(view); 45 | } 46 | 47 | public View getView() { 48 | if (mWeakView == null) 49 | return null; 50 | return mWeakView.get(); 51 | } 52 | 53 | public void setVideoSize(int videoWidth, int videoHeight) { 54 | mVideoWidth = videoWidth; 55 | mVideoHeight = videoHeight; 56 | } 57 | 58 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) { 59 | mVideoSarNum = videoSarNum; 60 | mVideoSarDen = videoSarDen; 61 | } 62 | 63 | public void setVideoRotation(int videoRotationDegree) { 64 | mVideoRotationDegree = videoRotationDegree; 65 | } 66 | 67 | /** 68 | * Must be called by View.onMeasure(int, int) 69 | * 70 | * @param widthMeasureSpec 71 | * @param heightMeasureSpec 72 | */ 73 | public void doMeasure(int widthMeasureSpec, int heightMeasureSpec) { 74 | //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", " 75 | // + MeasureSpec.toString(heightMeasureSpec) + ")"); 76 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) { 77 | int tempSpec = widthMeasureSpec; 78 | widthMeasureSpec = heightMeasureSpec; 79 | heightMeasureSpec = tempSpec; 80 | } 81 | 82 | int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec); 83 | int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec); 84 | if (mCurrentAspectRatio == IRenderView.AR_MATCH_PARENT) { 85 | width = widthMeasureSpec; 86 | height = heightMeasureSpec; 87 | } else if (mVideoWidth > 0 && mVideoHeight > 0) { 88 | int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec); 89 | int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec); 90 | int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec); 91 | int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec); 92 | 93 | if (widthSpecMode == View.MeasureSpec.AT_MOST && heightSpecMode == View.MeasureSpec.AT_MOST) { 94 | float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize; 95 | float displayAspectRatio; 96 | switch (mCurrentAspectRatio) { 97 | case IRenderView.AR_16_9_FIT_PARENT: 98 | displayAspectRatio = 16.0f / 9.0f; 99 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) 100 | displayAspectRatio = 1.0f / displayAspectRatio; 101 | break; 102 | case IRenderView.AR_4_3_FIT_PARENT: 103 | displayAspectRatio = 4.0f / 3.0f; 104 | if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) 105 | displayAspectRatio = 1.0f / displayAspectRatio; 106 | break; 107 | case IRenderView.AR_ASPECT_FIT_PARENT: 108 | case IRenderView.AR_ASPECT_FILL_PARENT: 109 | case IRenderView.AR_ASPECT_WRAP_CONTENT: 110 | default: 111 | displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight; 112 | if (mVideoSarNum > 0 && mVideoSarDen > 0) 113 | displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen; 114 | break; 115 | } 116 | boolean shouldBeWider = displayAspectRatio > specAspectRatio; 117 | 118 | switch (mCurrentAspectRatio) { 119 | case IRenderView.AR_ASPECT_FIT_PARENT: 120 | case IRenderView.AR_16_9_FIT_PARENT: 121 | case IRenderView.AR_4_3_FIT_PARENT: 122 | if (shouldBeWider) { 123 | // too wide, fix width 124 | width = widthSpecSize; 125 | height = (int) (width / displayAspectRatio); 126 | } else { 127 | // too high, fix height 128 | height = heightSpecSize; 129 | width = (int) (height * displayAspectRatio); 130 | } 131 | break; 132 | case IRenderView.AR_ASPECT_FILL_PARENT: 133 | if (shouldBeWider) { 134 | // not high enough, fix height 135 | height = heightSpecSize; 136 | width = (int) (height * displayAspectRatio); 137 | } else { 138 | // not wide enough, fix width 139 | width = widthSpecSize; 140 | height = (int) (width / displayAspectRatio); 141 | } 142 | break; 143 | case IRenderView.AR_ASPECT_WRAP_CONTENT: 144 | default: 145 | if (shouldBeWider) { 146 | // too wide, fix width 147 | width = Math.min(mVideoWidth, widthSpecSize); 148 | height = (int) (width / displayAspectRatio); 149 | } else { 150 | // too high, fix height 151 | height = Math.min(mVideoHeight, heightSpecSize); 152 | width = (int) (height * displayAspectRatio); 153 | } 154 | break; 155 | } 156 | } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) { 157 | // the size is fixed 158 | width = widthSpecSize; 159 | height = heightSpecSize; 160 | 161 | // for compatibility, we adjust size based on aspect ratio 162 | if (mVideoWidth * height < width * mVideoHeight) { 163 | //Log.i("@@@", "image too wide, correcting"); 164 | width = height * mVideoWidth / mVideoHeight; 165 | } else if (mVideoWidth * height > width * mVideoHeight) { 166 | //Log.i("@@@", "image too tall, correcting"); 167 | height = width * mVideoHeight / mVideoWidth; 168 | } 169 | } else if (widthSpecMode == View.MeasureSpec.EXACTLY) { 170 | // only the width is fixed, adjust the height to match aspect ratio if possible 171 | width = widthSpecSize; 172 | height = width * mVideoHeight / mVideoWidth; 173 | if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) { 174 | // couldn't match aspect ratio within the constraints 175 | height = heightSpecSize; 176 | } 177 | } else if (heightSpecMode == View.MeasureSpec.EXACTLY) { 178 | // only the height is fixed, adjust the width to match aspect ratio if possible 179 | height = heightSpecSize; 180 | width = height * mVideoWidth / mVideoHeight; 181 | if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) { 182 | // couldn't match aspect ratio within the constraints 183 | width = widthSpecSize; 184 | } 185 | } else { 186 | // neither the width nor the height are fixed, try to use actual video size 187 | width = mVideoWidth; 188 | height = mVideoHeight; 189 | if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) { 190 | // too tall, decrease both width and height 191 | height = heightSpecSize; 192 | width = height * mVideoWidth / mVideoHeight; 193 | } 194 | if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) { 195 | // too wide, decrease both width and height 196 | width = widthSpecSize; 197 | height = width * mVideoHeight / mVideoWidth; 198 | } 199 | } 200 | } else { 201 | // no size yet, just adopt the given spec sizes 202 | } 203 | 204 | mMeasuredWidth = width; 205 | mMeasuredHeight = height; 206 | } 207 | 208 | public int getMeasuredWidth() { 209 | return mMeasuredWidth; 210 | } 211 | 212 | public int getMeasuredHeight() { 213 | return mMeasuredHeight; 214 | } 215 | 216 | public void setAspectRatio(int aspectRatio) { 217 | mCurrentAspectRatio = aspectRatio; 218 | } 219 | 220 | @NonNull 221 | public static String getAspectRatioText(Context context, int aspectRatio) { 222 | String text; 223 | switch (aspectRatio) { 224 | case IRenderView.AR_ASPECT_FIT_PARENT: 225 | text = context.getString(R.string.VideoView_ar_aspect_fit_parent); 226 | break; 227 | case IRenderView.AR_ASPECT_FILL_PARENT: 228 | text = context.getString(R.string.VideoView_ar_aspect_fill_parent); 229 | break; 230 | case IRenderView.AR_ASPECT_WRAP_CONTENT: 231 | text = context.getString(R.string.VideoView_ar_aspect_wrap_content); 232 | break; 233 | case IRenderView.AR_MATCH_PARENT: 234 | text = context.getString(R.string.VideoView_ar_match_parent); 235 | break; 236 | case IRenderView.AR_16_9_FIT_PARENT: 237 | text = context.getString(R.string.VideoView_ar_16_9_fit_parent); 238 | break; 239 | case IRenderView.AR_4_3_FIT_PARENT: 240 | text = context.getString(R.string.VideoView_ar_4_3_fit_parent); 241 | break; 242 | default: 243 | text = context.getString(R.string.N_A); 244 | break; 245 | } 246 | return text; 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.media.player; 2 | 3 | import android.annotation.TargetApi; 4 | import android.media.MediaCodecInfo; 5 | import android.media.MediaCodecInfo.CodecCapabilities; 6 | import android.media.MediaCodecInfo.CodecProfileLevel; 7 | import android.os.Build; 8 | import android.text.TextUtils; 9 | import android.util.Log; 10 | 11 | import java.util.Locale; 12 | import java.util.Map; 13 | import java.util.TreeMap; 14 | 15 | public class IjkMediaCodecInfo { 16 | private final static String TAG = "IjkMediaCodecInfo"; 17 | 18 | public static int RANK_MAX = 1000; 19 | public static final int RANK_TESTED = 800; 20 | public static final int RANK_ACCEPTABLE = 700; 21 | public static final int RANK_LAST_CHANCE = 600; 22 | public static final int RANK_SECURE = 300; 23 | public static final int RANK_SOFTWARE = 200; 24 | public static final int RANK_NON_STANDARD = 100; 25 | public static final int RANK_NO_SENSE = 0; 26 | 27 | public MediaCodecInfo mCodecInfo; 28 | public int mRank = 0; 29 | public String mMimeType; 30 | 31 | private static Map sKnownCodecList; 32 | 33 | private static synchronized Map getKnownCodecList() { 34 | if (sKnownCodecList != null) 35 | return sKnownCodecList; 36 | 37 | sKnownCodecList = new TreeMap( 38 | String.CASE_INSENSITIVE_ORDER); 39 | 40 | // ----- Nvidia ----- 41 | // Tegra3 42 | // Nexus 7 (2012) 43 | // Tegra K1 44 | // Nexus 9 45 | sKnownCodecList.put("OMX.Nvidia.h264.decode", RANK_TESTED); 46 | sKnownCodecList.put("OMX.Nvidia.h264.decode.secure", RANK_SECURE); 47 | 48 | // ----- Intel ----- 49 | // Atom Z3735 50 | // Teclast X98 Air 51 | sKnownCodecList.put("OMX.Intel.hw_vd.h264", RANK_TESTED + 1); 52 | // Atom Z2560 53 | // Dell Venue 7 3730 54 | sKnownCodecList.put("OMX.Intel.VideoDecoder.AVC", RANK_TESTED); 55 | 56 | // ----- Qualcomm ----- 57 | // MSM8260 58 | // Xiaomi MI 1S 59 | sKnownCodecList.put("OMX.qcom.video.decoder.avc", RANK_TESTED); 60 | sKnownCodecList.put("OMX.ittiam.video.decoder.avc", RANK_NO_SENSE); 61 | 62 | // ----- Samsung ----- 63 | // Exynos 3110 64 | // Nexus S 65 | sKnownCodecList.put("OMX.SEC.avc.dec", RANK_TESTED); 66 | sKnownCodecList.put("OMX.SEC.AVC.Decoder", RANK_TESTED - 1); 67 | // OMX.SEC.avcdec doesn't reorder output pictures on GT-9100 68 | sKnownCodecList.put("OMX.SEC.avcdec", RANK_TESTED - 2); 69 | sKnownCodecList.put("OMX.SEC.avc.sw.dec", RANK_SOFTWARE); 70 | // Exynos 5 ? 71 | sKnownCodecList.put("OMX.Exynos.avc.dec", RANK_TESTED); 72 | sKnownCodecList.put("OMX.Exynos.AVC.Decoder", RANK_TESTED - 1); 73 | 74 | // ------ Huawei hisilicon ------ 75 | // Kirin 910, Mali 450 MP 76 | // Huawei HONOR 3C (H30-L01) 77 | sKnownCodecList.put("OMX.k3.video.decoder.avc", RANK_TESTED); 78 | // Kirin 920, Mali T624 79 | // Huawei HONOR 6 80 | sKnownCodecList.put("OMX.IMG.MSVDX.Decoder.AVC", RANK_TESTED); 81 | 82 | // ----- TI ----- 83 | // TI OMAP4460 84 | // Galaxy Nexus 85 | sKnownCodecList.put("OMX.TI.DUCATI1.VIDEO.DECODER", RANK_TESTED); 86 | 87 | // ------ RockChip ------ 88 | // Youku TVBox 89 | sKnownCodecList.put("OMX.rk.video_decoder.avc", RANK_TESTED); 90 | 91 | // ------ AMLogic ----- 92 | // MiBox1, 1s, 2 93 | sKnownCodecList.put("OMX.amlogic.avc.decoder.awesome", RANK_TESTED); 94 | 95 | // ------ Marvell ------ 96 | // Lenovo A788t 97 | sKnownCodecList.put("OMX.MARVELL.VIDEO.HW.CODA7542DECODER", RANK_TESTED); 98 | sKnownCodecList.put("OMX.MARVELL.VIDEO.H264DECODER", RANK_SOFTWARE); 99 | 100 | // ----- TODO: need test ----- 101 | sKnownCodecList.remove("OMX.Action.Video.Decoder"); 102 | sKnownCodecList.remove("OMX.allwinner.video.decoder.avc"); 103 | sKnownCodecList.remove("OMX.BRCM.vc4.decoder.avc"); 104 | sKnownCodecList.remove("OMX.brcm.video.h264.hw.decoder"); 105 | sKnownCodecList.remove("OMX.brcm.video.h264.decoder"); 106 | sKnownCodecList.remove("OMX.cosmo.video.decoder.avc"); 107 | sKnownCodecList.remove("OMX.duos.h264.decoder"); 108 | sKnownCodecList.remove("OMX.hantro.81x0.video.decoder"); 109 | sKnownCodecList.remove("OMX.hantro.G1.video.decoder"); 110 | sKnownCodecList.remove("OMX.hisi.video.decoder"); 111 | sKnownCodecList.remove("OMX.LG.decoder.video.avc"); 112 | sKnownCodecList.remove("OMX.MS.AVC.Decoder"); 113 | sKnownCodecList.remove("OMX.RENESAS.VIDEO.DECODER.H264"); 114 | sKnownCodecList.remove("OMX.RTK.video.decoder"); 115 | sKnownCodecList.remove("OMX.sprd.h264.decoder"); 116 | sKnownCodecList.remove("OMX.ST.VFM.H264Dec"); 117 | sKnownCodecList.remove("OMX.vpu.video_decoder.avc"); 118 | sKnownCodecList.remove("OMX.WMT.decoder.avc"); 119 | 120 | // Really ? 121 | sKnownCodecList.remove("OMX.bluestacks.hw.decoder"); 122 | 123 | // --------------- 124 | // Useless codec 125 | // ----- google ----- 126 | sKnownCodecList.put("OMX.google.h264.decoder", RANK_SOFTWARE); 127 | sKnownCodecList.put("OMX.google.h264.lc.decoder", RANK_SOFTWARE); 128 | // ----- huawei k920 ----- 129 | sKnownCodecList.put("OMX.k3.ffmpeg.decoder", RANK_SOFTWARE); 130 | sKnownCodecList.put("OMX.ffmpeg.video.decoder", RANK_SOFTWARE); 131 | // ----- unknown ----- 132 | sKnownCodecList.put("OMX.sprd.soft.h264.decoder", RANK_SOFTWARE); 133 | 134 | return sKnownCodecList; 135 | } 136 | 137 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 138 | public static IjkMediaCodecInfo setupCandidate(MediaCodecInfo codecInfo, 139 | String mimeType) { 140 | if (codecInfo == null 141 | || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) 142 | return null; 143 | 144 | String name = codecInfo.getName(); 145 | if (TextUtils.isEmpty(name)) 146 | return null; 147 | 148 | name = name.toLowerCase(Locale.US); 149 | int rank = RANK_NO_SENSE; 150 | if (!name.startsWith("omx.")) { 151 | rank = RANK_NON_STANDARD; 152 | } else if (name.startsWith("omx.pv")) { 153 | rank = RANK_SOFTWARE; 154 | } else if (name.startsWith("omx.google.")) { 155 | rank = RANK_SOFTWARE; 156 | } else if (name.startsWith("omx.ffmpeg.")) { 157 | rank = RANK_SOFTWARE; 158 | } else if (name.startsWith("omx.k3.ffmpeg.")) { 159 | rank = RANK_SOFTWARE; 160 | } else if (name.startsWith("omx.avcodec.")) { 161 | rank = RANK_SOFTWARE; 162 | } else if (name.startsWith("omx.ittiam.")) { 163 | // unknown codec in qualcomm SoC 164 | rank = RANK_NO_SENSE; 165 | } else if (name.startsWith("omx.mtk.")) { 166 | // 1. MTK only works on 4.3 and above 167 | // 2. MTK works on MIUI 6 (4.2.1) 168 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) 169 | rank = RANK_NO_SENSE; 170 | else 171 | rank = RANK_TESTED; 172 | } else { 173 | Integer knownRank = getKnownCodecList().get(name); 174 | if (knownRank != null) { 175 | rank = knownRank; 176 | } else { 177 | try { 178 | CodecCapabilities cap = codecInfo 179 | .getCapabilitiesForType(mimeType); 180 | if (cap != null) 181 | rank = RANK_ACCEPTABLE; 182 | else 183 | rank = RANK_LAST_CHANCE; 184 | } catch (Throwable e) { 185 | rank = RANK_LAST_CHANCE; 186 | } 187 | } 188 | } 189 | 190 | IjkMediaCodecInfo candidate = new IjkMediaCodecInfo(); 191 | candidate.mCodecInfo = codecInfo; 192 | candidate.mRank = rank; 193 | candidate.mMimeType = mimeType; 194 | return candidate; 195 | } 196 | 197 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 198 | public void dumpProfileLevels(String mimeType) { 199 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) 200 | return; 201 | 202 | try { 203 | CodecCapabilities caps = mCodecInfo 204 | .getCapabilitiesForType(mimeType); 205 | int maxProfile = 0; 206 | int maxLevel = 0; 207 | if (caps != null) { 208 | if (caps.profileLevels != null) { 209 | for (CodecProfileLevel profileLevel : caps.profileLevels) { 210 | if (profileLevel == null) 211 | continue; 212 | 213 | maxProfile = Math.max(maxProfile, profileLevel.profile); 214 | maxLevel = Math.max(maxLevel, profileLevel.level); 215 | } 216 | } 217 | } 218 | 219 | Log.i(TAG, 220 | String.format(Locale.US, "%s", 221 | getProfileLevelName(maxProfile, maxLevel))); 222 | } catch (Throwable e) { 223 | Log.i(TAG, "profile-level: exception"); 224 | } 225 | } 226 | 227 | public static String getProfileLevelName(int profile, int level) { 228 | return String.format(Locale.US, " %s Profile Level %s (%d,%d)", 229 | getProfileName(profile), getLevelName(level), profile, level); 230 | } 231 | 232 | public static String getProfileName(int profile) { 233 | switch (profile) { 234 | case CodecProfileLevel.AVCProfileBaseline: 235 | return "Baseline"; 236 | case CodecProfileLevel.AVCProfileMain: 237 | return "Main"; 238 | case CodecProfileLevel.AVCProfileExtended: 239 | return "Extends"; 240 | case CodecProfileLevel.AVCProfileHigh: 241 | return "High"; 242 | case CodecProfileLevel.AVCProfileHigh10: 243 | return "High10"; 244 | case CodecProfileLevel.AVCProfileHigh422: 245 | return "High422"; 246 | case CodecProfileLevel.AVCProfileHigh444: 247 | return "High444"; 248 | default: 249 | return "Unknown"; 250 | } 251 | } 252 | 253 | public static String getLevelName(int level) { 254 | switch (level) { 255 | case CodecProfileLevel.AVCLevel1: 256 | return "1"; 257 | case CodecProfileLevel.AVCLevel1b: 258 | return "1b"; 259 | case CodecProfileLevel.AVCLevel11: 260 | return "11"; 261 | case CodecProfileLevel.AVCLevel12: 262 | return "12"; 263 | case CodecProfileLevel.AVCLevel13: 264 | return "13"; 265 | case CodecProfileLevel.AVCLevel2: 266 | return "2"; 267 | case CodecProfileLevel.AVCLevel21: 268 | return "21"; 269 | case CodecProfileLevel.AVCLevel22: 270 | return "22"; 271 | case CodecProfileLevel.AVCLevel3: 272 | return "3"; 273 | case CodecProfileLevel.AVCLevel31: 274 | return "31"; 275 | case CodecProfileLevel.AVCLevel32: 276 | return "32"; 277 | case CodecProfileLevel.AVCLevel4: 278 | return "4"; 279 | case CodecProfileLevel.AVCLevel41: 280 | return "41"; 281 | case CodecProfileLevel.AVCLevel42: 282 | return "42"; 283 | case CodecProfileLevel.AVCLevel5: 284 | return "5"; 285 | case CodecProfileLevel.AVCLevel51: 286 | return "51"; 287 | case 65536: // CodecProfileLevel.AVCLevel52: 288 | return "52"; 289 | default: 290 | return "0"; 291 | } 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 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; 19 | 20 | import android.annotation.TargetApi; 21 | import android.content.Context; 22 | import android.media.AudioManager; 23 | import android.media.MediaDataSource; 24 | import android.media.MediaPlayer; 25 | import android.net.Uri; 26 | import android.os.Build; 27 | import android.text.TextUtils; 28 | import android.view.Surface; 29 | import android.view.SurfaceHolder; 30 | 31 | import java.io.FileDescriptor; 32 | import java.io.IOException; 33 | import java.lang.ref.WeakReference; 34 | import java.util.Map; 35 | 36 | import tv.danmaku.ijk.media.player.misc.AndroidTrackInfo; 37 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource; 38 | import tv.danmaku.ijk.media.player.misc.ITrackInfo; 39 | import tv.danmaku.ijk.media.player.pragma.DebugLog; 40 | 41 | public class AndroidMediaPlayer extends AbstractMediaPlayer { 42 | private final MediaPlayer mInternalMediaPlayer; 43 | private final AndroidMediaPlayerListenerHolder mInternalListenerAdapter; 44 | private String mDataSource; 45 | private MediaDataSource mMediaDataSource; 46 | 47 | private final Object mInitLock = new Object(); 48 | private boolean mIsReleased; 49 | 50 | private static MediaInfo sMediaInfo; 51 | 52 | public AndroidMediaPlayer() { 53 | synchronized (mInitLock) { 54 | mInternalMediaPlayer = new MediaPlayer(); 55 | } 56 | mInternalMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 57 | mInternalListenerAdapter = new AndroidMediaPlayerListenerHolder(this); 58 | attachInternalListeners(); 59 | } 60 | 61 | public MediaPlayer getInternalMediaPlayer() { 62 | return mInternalMediaPlayer; 63 | } 64 | 65 | @Override 66 | public void setDisplay(SurfaceHolder sh) { 67 | synchronized (mInitLock) { 68 | if (!mIsReleased) { 69 | mInternalMediaPlayer.setDisplay(sh); 70 | } 71 | } 72 | } 73 | 74 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 75 | @Override 76 | public void setSurface(Surface surface) { 77 | mInternalMediaPlayer.setSurface(surface); 78 | } 79 | 80 | @Override 81 | public void setDataSource(Context context, Uri uri) 82 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { 83 | mInternalMediaPlayer.setDataSource(context, uri); 84 | } 85 | 86 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 87 | @Override 88 | public void setDataSource(Context context, Uri uri, Map headers) 89 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { 90 | mInternalMediaPlayer.setDataSource(context, uri, headers); 91 | } 92 | 93 | @Override 94 | public void setDataSource(FileDescriptor fd) 95 | throws IOException, IllegalArgumentException, IllegalStateException { 96 | mInternalMediaPlayer.setDataSource(fd); 97 | } 98 | 99 | @Override 100 | public void setDataSource(String path) throws IOException, 101 | IllegalArgumentException, SecurityException, IllegalStateException { 102 | mDataSource = path; 103 | 104 | Uri uri = Uri.parse(path); 105 | String scheme = uri.getScheme(); 106 | if (!TextUtils.isEmpty(scheme) && scheme.equalsIgnoreCase("file")) { 107 | mInternalMediaPlayer.setDataSource(uri.getPath()); 108 | } else { 109 | mInternalMediaPlayer.setDataSource(path); 110 | } 111 | } 112 | 113 | @TargetApi(Build.VERSION_CODES.M) 114 | @Override 115 | public void setDataSource(IMediaDataSource mediaDataSource) { 116 | releaseMediaDataSource(); 117 | 118 | mMediaDataSource = new MediaDataSourceProxy(mediaDataSource); 119 | mInternalMediaPlayer.setDataSource(mMediaDataSource); 120 | } 121 | 122 | @TargetApi(Build.VERSION_CODES.M) 123 | private static class MediaDataSourceProxy extends MediaDataSource { 124 | private final IMediaDataSource mMediaDataSource; 125 | 126 | public MediaDataSourceProxy(IMediaDataSource mediaDataSource) { 127 | mMediaDataSource = mediaDataSource; 128 | } 129 | 130 | @Override 131 | public int readAt(long position, byte[] buffer, int offset, int size) throws IOException { 132 | return mMediaDataSource.readAt(position, buffer, offset, size); 133 | } 134 | 135 | @Override 136 | public long getSize() throws IOException { 137 | return mMediaDataSource.getSize(); 138 | } 139 | 140 | @Override 141 | public void close() throws IOException { 142 | mMediaDataSource.close(); 143 | } 144 | } 145 | 146 | @Override 147 | public String getDataSource() { 148 | return mDataSource; 149 | } 150 | 151 | private void releaseMediaDataSource() { 152 | if (mMediaDataSource != null) { 153 | try { 154 | mMediaDataSource.close(); 155 | } catch (IOException e) { 156 | e.printStackTrace(); 157 | } 158 | mMediaDataSource = null; 159 | } 160 | } 161 | 162 | @Override 163 | public void prepareAsync() throws IllegalStateException { 164 | mInternalMediaPlayer.prepareAsync(); 165 | } 166 | 167 | @Override 168 | public void start() throws IllegalStateException { 169 | mInternalMediaPlayer.start(); 170 | } 171 | 172 | @Override 173 | public void stop() throws IllegalStateException { 174 | mInternalMediaPlayer.stop(); 175 | } 176 | 177 | @Override 178 | public void pause() throws IllegalStateException { 179 | mInternalMediaPlayer.pause(); 180 | } 181 | 182 | @Override 183 | public void setScreenOnWhilePlaying(boolean screenOn) { 184 | mInternalMediaPlayer.setScreenOnWhilePlaying(screenOn); 185 | } 186 | 187 | @Override 188 | public ITrackInfo[] getTrackInfo() { 189 | return AndroidTrackInfo.fromMediaPlayer(mInternalMediaPlayer); 190 | } 191 | 192 | @Override 193 | public int getVideoWidth() { 194 | return mInternalMediaPlayer.getVideoWidth(); 195 | } 196 | 197 | @Override 198 | public int getVideoHeight() { 199 | return mInternalMediaPlayer.getVideoHeight(); 200 | } 201 | 202 | @Override 203 | public int getVideoSarNum() { 204 | return 1; 205 | } 206 | 207 | @Override 208 | public int getVideoSarDen() { 209 | return 1; 210 | } 211 | 212 | @Override 213 | public boolean isPlaying() { 214 | try { 215 | return mInternalMediaPlayer.isPlaying(); 216 | } catch (IllegalStateException e) { 217 | DebugLog.printStackTrace(e); 218 | return false; 219 | } 220 | } 221 | 222 | @Override 223 | public void seekTo(long msec) throws IllegalStateException { 224 | mInternalMediaPlayer.seekTo((int) msec); 225 | } 226 | 227 | @Override 228 | public long getCurrentPosition() { 229 | try { 230 | return mInternalMediaPlayer.getCurrentPosition(); 231 | } catch (IllegalStateException e) { 232 | DebugLog.printStackTrace(e); 233 | return 0; 234 | } 235 | } 236 | 237 | @Override 238 | public long getDuration() { 239 | try { 240 | return mInternalMediaPlayer.getDuration(); 241 | } catch (IllegalStateException e) { 242 | DebugLog.printStackTrace(e); 243 | return 0; 244 | } 245 | } 246 | 247 | @Override 248 | public void release() { 249 | mIsReleased = true; 250 | mInternalMediaPlayer.release(); 251 | releaseMediaDataSource(); 252 | resetListeners(); 253 | attachInternalListeners(); 254 | } 255 | 256 | @Override 257 | public void reset() { 258 | try { 259 | mInternalMediaPlayer.reset(); 260 | } catch (IllegalStateException e) { 261 | DebugLog.printStackTrace(e); 262 | } 263 | releaseMediaDataSource(); 264 | resetListeners(); 265 | attachInternalListeners(); 266 | } 267 | 268 | @Override 269 | public void setLooping(boolean looping) { 270 | mInternalMediaPlayer.setLooping(looping); 271 | } 272 | 273 | @Override 274 | public boolean isLooping() { 275 | return mInternalMediaPlayer.isLooping(); 276 | } 277 | 278 | @Override 279 | public void setVolume(float leftVolume, float rightVolume) { 280 | mInternalMediaPlayer.setVolume(leftVolume, rightVolume); 281 | } 282 | 283 | @Override 284 | public int getAudioSessionId() { 285 | return mInternalMediaPlayer.getAudioSessionId(); 286 | } 287 | 288 | @Override 289 | public MediaInfo getMediaInfo() { 290 | if (sMediaInfo == null) { 291 | MediaInfo module = new MediaInfo(); 292 | 293 | module.mVideoDecoder = "android"; 294 | module.mVideoDecoderImpl = "HW"; 295 | 296 | module.mAudioDecoder = "android"; 297 | module.mAudioDecoderImpl = "HW"; 298 | 299 | sMediaInfo = module; 300 | } 301 | 302 | return sMediaInfo; 303 | } 304 | 305 | @Override 306 | public void setLogEnabled(boolean enable) { 307 | } 308 | 309 | @Override 310 | public boolean isPlayable() { 311 | return true; 312 | } 313 | 314 | /*-------------------- 315 | * misc 316 | */ 317 | @Override 318 | public void setWakeMode(Context context, int mode) { 319 | mInternalMediaPlayer.setWakeMode(context, mode); 320 | } 321 | 322 | @Override 323 | public void setAudioStreamType(int streamtype) { 324 | mInternalMediaPlayer.setAudioStreamType(streamtype); 325 | } 326 | 327 | @Override 328 | public void setKeepInBackground(boolean keepInBackground) { 329 | } 330 | 331 | /*-------------------- 332 | * Listeners adapter 333 | */ 334 | private void attachInternalListeners() { 335 | mInternalMediaPlayer.setOnPreparedListener(mInternalListenerAdapter); 336 | mInternalMediaPlayer 337 | .setOnBufferingUpdateListener(mInternalListenerAdapter); 338 | mInternalMediaPlayer.setOnCompletionListener(mInternalListenerAdapter); 339 | mInternalMediaPlayer 340 | .setOnSeekCompleteListener(mInternalListenerAdapter); 341 | mInternalMediaPlayer 342 | .setOnVideoSizeChangedListener(mInternalListenerAdapter); 343 | mInternalMediaPlayer.setOnErrorListener(mInternalListenerAdapter); 344 | mInternalMediaPlayer.setOnInfoListener(mInternalListenerAdapter); 345 | } 346 | 347 | private class AndroidMediaPlayerListenerHolder implements 348 | MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, 349 | MediaPlayer.OnBufferingUpdateListener, 350 | MediaPlayer.OnSeekCompleteListener, 351 | MediaPlayer.OnVideoSizeChangedListener, 352 | MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener { 353 | public final WeakReference mWeakMediaPlayer; 354 | 355 | public AndroidMediaPlayerListenerHolder(AndroidMediaPlayer mp) { 356 | mWeakMediaPlayer = new WeakReference(mp); 357 | } 358 | 359 | @Override 360 | public boolean onInfo(MediaPlayer mp, int what, int extra) { 361 | AndroidMediaPlayer self = mWeakMediaPlayer.get(); 362 | return self != null && notifyOnInfo(what, extra); 363 | 364 | } 365 | 366 | @Override 367 | public boolean onError(MediaPlayer mp, int what, int extra) { 368 | AndroidMediaPlayer self = mWeakMediaPlayer.get(); 369 | return self != null && notifyOnError(what, extra); 370 | 371 | } 372 | 373 | @Override 374 | public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 375 | AndroidMediaPlayer self = mWeakMediaPlayer.get(); 376 | if (self == null) 377 | return; 378 | 379 | notifyOnVideoSizeChanged(width, height, 1, 1); 380 | } 381 | 382 | @Override 383 | public void onSeekComplete(MediaPlayer mp) { 384 | AndroidMediaPlayer self = mWeakMediaPlayer.get(); 385 | if (self == null) 386 | return; 387 | 388 | notifyOnSeekComplete(); 389 | } 390 | 391 | @Override 392 | public void onBufferingUpdate(MediaPlayer mp, int percent) { 393 | AndroidMediaPlayer self = mWeakMediaPlayer.get(); 394 | if (self == null) 395 | return; 396 | 397 | notifyOnBufferingUpdate(percent); 398 | } 399 | 400 | @Override 401 | public void onCompletion(MediaPlayer mp) { 402 | AndroidMediaPlayer self = mWeakMediaPlayer.get(); 403 | if (self == null) 404 | return; 405 | 406 | notifyOnCompletion(); 407 | } 408 | 409 | @Override 410 | public void onPrepared(MediaPlayer mp) { 411 | AndroidMediaPlayer self = mWeakMediaPlayer.get(); 412 | if (self == null) 413 | return; 414 | 415 | notifyOnPrepared(); 416 | } 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /mediaplayer/src/main/java/tv/danmaku/ijk/mediaplayer/media/TextureRenderView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Zhang Rui 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.mediaplayer.media; 18 | 19 | import android.annotation.TargetApi; 20 | import android.content.Context; 21 | import android.graphics.SurfaceTexture; 22 | import android.os.Build; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | import android.util.AttributeSet; 26 | import android.util.Log; 27 | import android.view.Surface; 28 | import android.view.SurfaceHolder; 29 | import android.view.TextureView; 30 | import android.view.View; 31 | import android.view.accessibility.AccessibilityEvent; 32 | import android.view.accessibility.AccessibilityNodeInfo; 33 | 34 | import java.lang.ref.WeakReference; 35 | import java.util.Map; 36 | import java.util.concurrent.ConcurrentHashMap; 37 | 38 | import tv.danmaku.ijk.media.player.IMediaPlayer; 39 | import tv.danmaku.ijk.media.player.ISurfaceTextureHolder; 40 | import tv.danmaku.ijk.media.player.ISurfaceTextureHost; 41 | 42 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 43 | public class TextureRenderView extends TextureView implements IRenderView { 44 | private static final String TAG = "TextureRenderView"; 45 | private MeasureHelper mMeasureHelper; 46 | 47 | public TextureRenderView(Context context) { 48 | super(context); 49 | initView(context); 50 | } 51 | 52 | public TextureRenderView(Context context, AttributeSet attrs) { 53 | super(context, attrs); 54 | initView(context); 55 | } 56 | 57 | public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr) { 58 | super(context, attrs, defStyleAttr); 59 | initView(context); 60 | } 61 | 62 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 63 | public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 64 | super(context, attrs, defStyleAttr, defStyleRes); 65 | initView(context); 66 | } 67 | 68 | private void initView(Context context) { 69 | mMeasureHelper = new MeasureHelper(this); 70 | mSurfaceCallback = new SurfaceCallback(this); 71 | setSurfaceTextureListener(mSurfaceCallback); 72 | } 73 | 74 | @Override 75 | public View getView() { 76 | return this; 77 | } 78 | 79 | @Override 80 | public boolean shouldWaitForResize() { 81 | return false; 82 | } 83 | 84 | @Override 85 | protected void onDetachedFromWindow() { 86 | mSurfaceCallback.willDetachFromWindow(); 87 | super.onDetachedFromWindow(); 88 | mSurfaceCallback.didDetachFromWindow(); 89 | } 90 | 91 | //-------------------- 92 | // Layout & Measure 93 | //-------------------- 94 | @Override 95 | public void setVideoSize(int videoWidth, int videoHeight) { 96 | if (videoWidth > 0 && videoHeight > 0) { 97 | mMeasureHelper.setVideoSize(videoWidth, videoHeight); 98 | requestLayout(); 99 | } 100 | } 101 | 102 | @Override 103 | public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) { 104 | if (videoSarNum > 0 && videoSarDen > 0) { 105 | mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen); 106 | requestLayout(); 107 | } 108 | } 109 | 110 | @Override 111 | public void setVideoRotation(int degree) { 112 | mMeasureHelper.setVideoRotation(degree); 113 | setRotation(degree); 114 | } 115 | 116 | @Override 117 | public void setAspectRatio(int aspectRatio) { 118 | mMeasureHelper.setAspectRatio(aspectRatio); 119 | requestLayout(); 120 | } 121 | 122 | @Override 123 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 124 | mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec); 125 | setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight()); 126 | } 127 | 128 | //-------------------- 129 | // TextureViewHolder 130 | //-------------------- 131 | 132 | public IRenderView.ISurfaceHolder getSurfaceHolder() { 133 | return new InternalSurfaceHolder(this, mSurfaceCallback.mSurfaceTexture, mSurfaceCallback); 134 | } 135 | 136 | private static final class InternalSurfaceHolder implements IRenderView.ISurfaceHolder { 137 | private TextureRenderView mTextureView; 138 | private SurfaceTexture mSurfaceTexture; 139 | private ISurfaceTextureHost mSurfaceTextureHost; 140 | 141 | public InternalSurfaceHolder(@NonNull TextureRenderView textureView, 142 | @Nullable SurfaceTexture surfaceTexture, 143 | @NonNull ISurfaceTextureHost surfaceTextureHost) { 144 | mTextureView = textureView; 145 | mSurfaceTexture = surfaceTexture; 146 | mSurfaceTextureHost = surfaceTextureHost; 147 | } 148 | 149 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 150 | public void bindToMediaPlayer(IMediaPlayer mp) { 151 | if (mp == null) 152 | return; 153 | 154 | if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) && 155 | (mp instanceof ISurfaceTextureHolder)) { 156 | ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp; 157 | mTextureView.mSurfaceCallback.setOwnSurfaceTexture(false); 158 | 159 | SurfaceTexture surfaceTexture = textureHolder.getSurfaceTexture(); 160 | if (surfaceTexture != null) { 161 | mTextureView.setSurfaceTexture(surfaceTexture); 162 | } else { 163 | textureHolder.setSurfaceTexture(mSurfaceTexture); 164 | textureHolder.setSurfaceTextureHost(mTextureView.mSurfaceCallback); 165 | } 166 | } else { 167 | mp.setSurface(openSurface()); 168 | } 169 | } 170 | 171 | @NonNull 172 | @Override 173 | public IRenderView getRenderView() { 174 | return mTextureView; 175 | } 176 | 177 | @Nullable 178 | @Override 179 | public SurfaceHolder getSurfaceHolder() { 180 | return null; 181 | } 182 | 183 | @Nullable 184 | @Override 185 | public SurfaceTexture getSurfaceTexture() { 186 | return mSurfaceTexture; 187 | } 188 | 189 | @Nullable 190 | @Override 191 | public Surface openSurface() { 192 | if (mSurfaceTexture == null) 193 | return null; 194 | return new Surface(mSurfaceTexture); 195 | } 196 | } 197 | 198 | //------------------------- 199 | // SurfaceHolder.Callback 200 | //------------------------- 201 | 202 | @Override 203 | public void addRenderCallback(IRenderCallback callback) { 204 | mSurfaceCallback.addRenderCallback(callback); 205 | } 206 | 207 | @Override 208 | public void removeRenderCallback(IRenderCallback callback) { 209 | mSurfaceCallback.removeRenderCallback(callback); 210 | } 211 | 212 | private SurfaceCallback mSurfaceCallback; 213 | 214 | private static final class SurfaceCallback implements SurfaceTextureListener, ISurfaceTextureHost { 215 | private SurfaceTexture mSurfaceTexture; 216 | private boolean mIsFormatChanged; 217 | private int mWidth; 218 | private int mHeight; 219 | 220 | private boolean mOwnSurfaceTexture = true; 221 | private boolean mWillDetachFromWindow = false; 222 | private boolean mDidDetachFromWindow = false; 223 | 224 | private WeakReference mWeakRenderView; 225 | private Map mRenderCallbackMap = new ConcurrentHashMap(); 226 | 227 | public SurfaceCallback(@NonNull TextureRenderView renderView) { 228 | mWeakRenderView = new WeakReference(renderView); 229 | } 230 | 231 | public void setOwnSurfaceTexture(boolean ownSurfaceTexture) { 232 | mOwnSurfaceTexture = ownSurfaceTexture; 233 | } 234 | 235 | public void addRenderCallback(@NonNull IRenderCallback callback) { 236 | mRenderCallbackMap.put(callback, callback); 237 | 238 | ISurfaceHolder surfaceHolder = null; 239 | if (mSurfaceTexture != null) { 240 | if (surfaceHolder == null) 241 | surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this); 242 | callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight); 243 | } 244 | 245 | if (mIsFormatChanged) { 246 | if (surfaceHolder == null) 247 | surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this); 248 | callback.onSurfaceChanged(surfaceHolder, 0, mWidth, mHeight); 249 | } 250 | } 251 | 252 | public void removeRenderCallback(@NonNull IRenderCallback callback) { 253 | mRenderCallbackMap.remove(callback); 254 | } 255 | 256 | @Override 257 | public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 258 | mSurfaceTexture = surface; 259 | mIsFormatChanged = false; 260 | mWidth = 0; 261 | mHeight = 0; 262 | 263 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this); 264 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) { 265 | renderCallback.onSurfaceCreated(surfaceHolder, 0, 0); 266 | } 267 | } 268 | 269 | @Override 270 | public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 271 | mSurfaceTexture = surface; 272 | mIsFormatChanged = true; 273 | mWidth = width; 274 | mHeight = height; 275 | 276 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this); 277 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) { 278 | renderCallback.onSurfaceChanged(surfaceHolder, 0, width, height); 279 | } 280 | } 281 | 282 | @Override 283 | public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 284 | mSurfaceTexture = surface; 285 | mIsFormatChanged = false; 286 | mWidth = 0; 287 | mHeight = 0; 288 | 289 | ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this); 290 | for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) { 291 | renderCallback.onSurfaceDestroyed(surfaceHolder); 292 | } 293 | 294 | Log.d(TAG, "onSurfaceTextureDestroyed: destroy: " + mOwnSurfaceTexture); 295 | return mOwnSurfaceTexture; 296 | } 297 | 298 | @Override 299 | public void onSurfaceTextureUpdated(SurfaceTexture surface) { 300 | } 301 | 302 | //------------------------- 303 | // ISurfaceTextureHost 304 | //------------------------- 305 | 306 | @Override 307 | public void releaseSurfaceTexture(SurfaceTexture surfaceTexture) { 308 | if (surfaceTexture == null) { 309 | Log.d(TAG, "releaseSurfaceTexture: null"); 310 | return; 311 | } else if (mDidDetachFromWindow) { 312 | if (surfaceTexture != mSurfaceTexture) { 313 | Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release different SurfaceTexture"); 314 | surfaceTexture.release(); 315 | } else if (!mOwnSurfaceTexture) { 316 | Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release detached SurfaceTexture"); 317 | surfaceTexture.release(); 318 | } else { 319 | Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): already released by TextureView"); 320 | } 321 | } else if (mWillDetachFromWindow) { 322 | if (surfaceTexture != mSurfaceTexture) { 323 | Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): release different SurfaceTexture"); 324 | surfaceTexture.release(); 325 | } else if (!mOwnSurfaceTexture) { 326 | Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): re-attach SurfaceTexture to TextureView"); 327 | setOwnSurfaceTexture(true); 328 | } else { 329 | Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): will released by TextureView"); 330 | } 331 | } else { 332 | if (surfaceTexture != mSurfaceTexture) { 333 | Log.d(TAG, "releaseSurfaceTexture: alive: release different SurfaceTexture"); 334 | surfaceTexture.release(); 335 | } else if (!mOwnSurfaceTexture) { 336 | Log.d(TAG, "releaseSurfaceTexture: alive: re-attach SurfaceTexture to TextureView"); 337 | setOwnSurfaceTexture(true); 338 | } else { 339 | Log.d(TAG, "releaseSurfaceTexture: alive: will released by TextureView"); 340 | } 341 | } 342 | } 343 | 344 | public void willDetachFromWindow() { 345 | Log.d(TAG, "willDetachFromWindow()"); 346 | mWillDetachFromWindow = true; 347 | } 348 | 349 | public void didDetachFromWindow() { 350 | Log.d(TAG, "didDetachFromWindow()"); 351 | mDidDetachFromWindow = true; 352 | } 353 | } 354 | 355 | //-------------------- 356 | // Accessibility 357 | //-------------------- 358 | 359 | @Override 360 | public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 361 | super.onInitializeAccessibilityEvent(event); 362 | event.setClassName(TextureRenderView.class.getName()); 363 | } 364 | 365 | @Override 366 | public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 367 | super.onInitializeAccessibilityNodeInfo(info); 368 | info.setClassName(TextureRenderView.class.getName()); 369 | } 370 | } 371 | -------------------------------------------------------------------------------- /ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaMeta.java: -------------------------------------------------------------------------------- 1 | package tv.danmaku.ijk.media.player; 2 | 3 | import android.os.Bundle; 4 | import android.text.TextUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Locale; 8 | 9 | @SuppressWarnings("SameParameterValue") 10 | public class IjkMediaMeta { 11 | // media meta 12 | public static final String IJKM_KEY_FORMAT = "format"; 13 | public static final String IJKM_KEY_DURATION_US = "duration_us"; 14 | public static final String IJKM_KEY_START_US = "start_us"; 15 | public static final String IJKM_KEY_BITRATE = "bitrate"; 16 | public static final String IJKM_KEY_VIDEO_STREAM = "video"; 17 | public static final String IJKM_KEY_AUDIO_STREAM = "audio"; 18 | 19 | // stream meta 20 | public static final String IJKM_KEY_TYPE = "type"; 21 | public static final String IJKM_VAL_TYPE__VIDEO = "video"; 22 | public static final String IJKM_VAL_TYPE__AUDIO = "audio"; 23 | public static final String IJKM_VAL_TYPE__UNKNOWN = "unknown"; 24 | public static final String IJKM_KEY_LANGUAGE = "language"; 25 | 26 | public static final String IJKM_KEY_CODEC_NAME = "codec_name"; 27 | public static final String IJKM_KEY_CODEC_PROFILE = "codec_profile"; 28 | public static final String IJKM_KEY_CODEC_LEVEL = "codec_level"; 29 | public static final String IJKM_KEY_CODEC_LONG_NAME = "codec_long_name"; 30 | public static final String IJKM_KEY_CODEC_PIXEL_FORMAT = "codec_pixel_format"; 31 | 32 | // stream: video 33 | public static final String IJKM_KEY_WIDTH = "width"; 34 | public static final String IJKM_KEY_HEIGHT = "height"; 35 | public static final String IJKM_KEY_FPS_NUM = "fps_num"; 36 | public static final String IJKM_KEY_FPS_DEN = "fps_den"; 37 | public static final String IJKM_KEY_TBR_NUM = "tbr_num"; 38 | public static final String IJKM_KEY_TBR_DEN = "tbr_den"; 39 | public static final String IJKM_KEY_SAR_NUM = "sar_num"; 40 | public static final String IJKM_KEY_SAR_DEN = "sar_den"; 41 | // stream: audio 42 | public static final String IJKM_KEY_SAMPLE_RATE = "sample_rate"; 43 | public static final String IJKM_KEY_CHANNEL_LAYOUT = "channel_layout"; 44 | 45 | public static final String IJKM_KEY_STREAMS = "streams"; 46 | 47 | public static final long AV_CH_FRONT_LEFT = 0x00000001; 48 | public static final long AV_CH_FRONT_RIGHT = 0x00000002; 49 | public static final long AV_CH_FRONT_CENTER = 0x00000004; 50 | public static final long AV_CH_LOW_FREQUENCY = 0x00000008; 51 | public static final long AV_CH_BACK_LEFT = 0x00000010; 52 | public static final long AV_CH_BACK_RIGHT = 0x00000020; 53 | public static final long AV_CH_FRONT_LEFT_OF_CENTER = 0x00000040; 54 | public static final long AV_CH_FRONT_RIGHT_OF_CENTER = 0x00000080; 55 | public static final long AV_CH_BACK_CENTER = 0x00000100; 56 | public static final long AV_CH_SIDE_LEFT = 0x00000200; 57 | public static final long AV_CH_SIDE_RIGHT = 0x00000400; 58 | public static final long AV_CH_TOP_CENTER = 0x00000800; 59 | public static final long AV_CH_TOP_FRONT_LEFT = 0x00001000; 60 | public static final long AV_CH_TOP_FRONT_CENTER = 0x00002000; 61 | public static final long AV_CH_TOP_FRONT_RIGHT = 0x00004000; 62 | public static final long AV_CH_TOP_BACK_LEFT = 0x00008000; 63 | public static final long AV_CH_TOP_BACK_CENTER = 0x00010000; 64 | public static final long AV_CH_TOP_BACK_RIGHT = 0x00020000; 65 | public static final long AV_CH_STEREO_LEFT = 0x20000000; 66 | public static final long AV_CH_STEREO_RIGHT = 0x40000000; 67 | public static final long AV_CH_WIDE_LEFT = 0x0000000080000000L; 68 | public static final long AV_CH_WIDE_RIGHT = 0x0000000100000000L; 69 | public static final long AV_CH_SURROUND_DIRECT_LEFT = 0x0000000200000000L; 70 | public static final long AV_CH_SURROUND_DIRECT_RIGHT = 0x0000000400000000L; 71 | public static final long AV_CH_LOW_FREQUENCY_2 = 0x0000000800000000L; 72 | 73 | public static final long AV_CH_LAYOUT_MONO = (AV_CH_FRONT_CENTER); 74 | public static final long AV_CH_LAYOUT_STEREO = (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT); 75 | public static final long AV_CH_LAYOUT_2POINT1 = (AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY); 76 | public static final long AV_CH_LAYOUT_2_1 = (AV_CH_LAYOUT_STEREO | AV_CH_BACK_CENTER); 77 | public static final long AV_CH_LAYOUT_SURROUND = (AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER); 78 | public static final long AV_CH_LAYOUT_3POINT1 = (AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY); 79 | public static final long AV_CH_LAYOUT_4POINT0 = (AV_CH_LAYOUT_SURROUND | AV_CH_BACK_CENTER); 80 | public static final long AV_CH_LAYOUT_4POINT1 = (AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY); 81 | public static final long AV_CH_LAYOUT_2_2 = (AV_CH_LAYOUT_STEREO 82 | | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT); 83 | public static final long AV_CH_LAYOUT_QUAD = (AV_CH_LAYOUT_STEREO 84 | | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 85 | public static final long AV_CH_LAYOUT_5POINT0 = (AV_CH_LAYOUT_SURROUND 86 | | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT); 87 | public static final long AV_CH_LAYOUT_5POINT1 = (AV_CH_LAYOUT_5POINT0 | AV_CH_LOW_FREQUENCY); 88 | public static final long AV_CH_LAYOUT_5POINT0_BACK = (AV_CH_LAYOUT_SURROUND 89 | | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 90 | public static final long AV_CH_LAYOUT_5POINT1_BACK = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_LOW_FREQUENCY); 91 | public static final long AV_CH_LAYOUT_6POINT0 = (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_CENTER); 92 | public static final long AV_CH_LAYOUT_6POINT0_FRONT = (AV_CH_LAYOUT_2_2 93 | | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER); 94 | public static final long AV_CH_LAYOUT_HEXAGONAL = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_BACK_CENTER); 95 | public static final long AV_CH_LAYOUT_6POINT1 = (AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER); 96 | public static final long AV_CH_LAYOUT_6POINT1_BACK = (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_BACK_CENTER); 97 | public static final long AV_CH_LAYOUT_6POINT1_FRONT = (AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_LOW_FREQUENCY); 98 | public static final long AV_CH_LAYOUT_7POINT0 = (AV_CH_LAYOUT_5POINT0 99 | | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 100 | public static final long AV_CH_LAYOUT_7POINT0_FRONT = (AV_CH_LAYOUT_5POINT0 101 | | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER); 102 | public static final long AV_CH_LAYOUT_7POINT1 = (AV_CH_LAYOUT_5POINT1 103 | | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 104 | public static final long AV_CH_LAYOUT_7POINT1_WIDE = (AV_CH_LAYOUT_5POINT1 105 | | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER); 106 | public static final long AV_CH_LAYOUT_7POINT1_WIDE_BACK = (AV_CH_LAYOUT_5POINT1_BACK 107 | | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER); 108 | public static final long AV_CH_LAYOUT_OCTAGONAL = (AV_CH_LAYOUT_5POINT0 109 | | AV_CH_BACK_LEFT | AV_CH_BACK_CENTER | AV_CH_BACK_RIGHT); 110 | public static final long AV_CH_LAYOUT_STEREO_DOWNMIX = (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT); 111 | 112 | public Bundle mMediaMeta; 113 | 114 | public String mFormat; 115 | public long mDurationUS; 116 | public long mStartUS; 117 | public long mBitrate; 118 | 119 | public final ArrayList mStreams = new ArrayList(); 120 | public IjkStreamMeta mVideoStream; 121 | public IjkStreamMeta mAudioStream; 122 | 123 | public String getString(String key) { 124 | return mMediaMeta.getString(key); 125 | } 126 | 127 | public int getInt(String key) { 128 | return getInt(key, 0); 129 | } 130 | 131 | public int getInt(String key, int defaultValue) { 132 | String value = getString(key); 133 | if (TextUtils.isEmpty(value)) 134 | return defaultValue; 135 | 136 | try { 137 | return Integer.parseInt(value); 138 | } catch (NumberFormatException e) { 139 | return defaultValue; 140 | } 141 | } 142 | 143 | public long getLong(String key) { 144 | return getLong(key, 0); 145 | } 146 | 147 | public long getLong(String key, long defaultValue) { 148 | String value = getString(key); 149 | if (TextUtils.isEmpty(value)) 150 | return defaultValue; 151 | 152 | try { 153 | return Long.parseLong(value); 154 | } catch (NumberFormatException e) { 155 | return defaultValue; 156 | } 157 | } 158 | 159 | public ArrayList getParcelableArrayList(String key) { 160 | return mMediaMeta.getParcelableArrayList(key); 161 | } 162 | 163 | public String getDurationInline() { 164 | long duration = mDurationUS + 5000; 165 | long secs = duration / 1000000; 166 | long mins = secs / 60; 167 | secs %= 60; 168 | long hours = mins / 60; 169 | mins %= 60; 170 | return String.format(Locale.US, "%02d:%02d:%02d", hours, mins, secs); 171 | } 172 | 173 | public static IjkMediaMeta parse(Bundle mediaMeta) { 174 | if (mediaMeta == null) 175 | return null; 176 | 177 | IjkMediaMeta meta = new IjkMediaMeta(); 178 | meta.mMediaMeta = mediaMeta; 179 | 180 | meta.mFormat = meta.getString(IJKM_KEY_FORMAT); 181 | meta.mDurationUS = meta.getLong(IJKM_KEY_DURATION_US); 182 | meta.mStartUS = meta.getLong(IJKM_KEY_START_US); 183 | meta.mBitrate = meta.getLong(IJKM_KEY_BITRATE); 184 | 185 | int videoStreamIndex = meta.getInt(IJKM_KEY_VIDEO_STREAM, -1); 186 | int audioStreamIndex = meta.getInt(IJKM_KEY_AUDIO_STREAM, -1); 187 | 188 | ArrayList streams = meta 189 | .getParcelableArrayList(IJKM_KEY_STREAMS); 190 | if (streams == null) 191 | return meta; 192 | 193 | int index = -1; 194 | for (Bundle streamBundle : streams) { 195 | index++; 196 | 197 | if (streamBundle == null) { 198 | continue; 199 | } 200 | 201 | IjkStreamMeta streamMeta = new IjkStreamMeta(index); 202 | streamMeta.mMeta = streamBundle; 203 | streamMeta.mType = streamMeta.getString(IJKM_KEY_TYPE); 204 | streamMeta.mLanguage = streamMeta.getString(IJKM_KEY_LANGUAGE); 205 | if (TextUtils.isEmpty(streamMeta.mType)) 206 | continue; 207 | 208 | streamMeta.mCodecName = streamMeta.getString(IJKM_KEY_CODEC_NAME); 209 | streamMeta.mCodecProfile = streamMeta 210 | .getString(IJKM_KEY_CODEC_PROFILE); 211 | streamMeta.mCodecLongName = streamMeta 212 | .getString(IJKM_KEY_CODEC_LONG_NAME); 213 | streamMeta.mBitrate = streamMeta.getInt(IJKM_KEY_BITRATE); 214 | 215 | if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__VIDEO)) { 216 | streamMeta.mWidth = streamMeta.getInt(IJKM_KEY_WIDTH); 217 | streamMeta.mHeight = streamMeta.getInt(IJKM_KEY_HEIGHT); 218 | streamMeta.mFpsNum = streamMeta.getInt(IJKM_KEY_FPS_NUM); 219 | streamMeta.mFpsDen = streamMeta.getInt(IJKM_KEY_FPS_DEN); 220 | streamMeta.mTbrNum = streamMeta.getInt(IJKM_KEY_TBR_NUM); 221 | streamMeta.mTbrDen = streamMeta.getInt(IJKM_KEY_TBR_DEN); 222 | streamMeta.mSarNum = streamMeta.getInt(IJKM_KEY_SAR_NUM); 223 | streamMeta.mSarDen = streamMeta.getInt(IJKM_KEY_SAR_DEN); 224 | 225 | if (videoStreamIndex == index) { 226 | meta.mVideoStream = streamMeta; 227 | } 228 | } else if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__AUDIO)) { 229 | streamMeta.mSampleRate = streamMeta 230 | .getInt(IJKM_KEY_SAMPLE_RATE); 231 | streamMeta.mChannelLayout = streamMeta 232 | .getLong(IJKM_KEY_CHANNEL_LAYOUT); 233 | 234 | if (audioStreamIndex == index) { 235 | meta.mAudioStream = streamMeta; 236 | } 237 | } 238 | meta.mStreams.add(streamMeta); 239 | } 240 | 241 | return meta; 242 | } 243 | 244 | public static class IjkStreamMeta { 245 | public Bundle mMeta; 246 | 247 | public final int mIndex; 248 | public String mType; 249 | public String mLanguage; 250 | 251 | // common 252 | public String mCodecName; 253 | public String mCodecProfile; 254 | public String mCodecLongName; 255 | public long mBitrate; 256 | 257 | // video 258 | public int mWidth; 259 | public int mHeight; 260 | public int mFpsNum; 261 | public int mFpsDen; 262 | public int mTbrNum; 263 | public int mTbrDen; 264 | public int mSarNum; 265 | public int mSarDen; 266 | 267 | // audio 268 | public int mSampleRate; 269 | public long mChannelLayout; 270 | 271 | public IjkStreamMeta(int index) { 272 | mIndex = index; 273 | } 274 | 275 | public String getString(String key) { 276 | return mMeta.getString(key); 277 | } 278 | 279 | public int getInt(String key) { 280 | return getInt(key, 0); 281 | } 282 | 283 | public int getInt(String key, int defaultValue) { 284 | String value = getString(key); 285 | if (TextUtils.isEmpty(value)) 286 | return defaultValue; 287 | 288 | try { 289 | return Integer.parseInt(value); 290 | } catch (NumberFormatException e) { 291 | return defaultValue; 292 | } 293 | } 294 | 295 | public long getLong(String key) { 296 | return getLong(key, 0); 297 | } 298 | 299 | public long getLong(String key, long defaultValue) { 300 | String value = getString(key); 301 | if (TextUtils.isEmpty(value)) 302 | return defaultValue; 303 | 304 | try { 305 | return Long.parseLong(value); 306 | } catch (NumberFormatException e) { 307 | return defaultValue; 308 | } 309 | } 310 | 311 | public String getCodecLongNameInline() { 312 | if (!TextUtils.isEmpty(mCodecLongName)) { 313 | return mCodecLongName; 314 | } else if (!TextUtils.isEmpty(mCodecName)) { 315 | return mCodecName; 316 | } else { 317 | return "N/A"; 318 | } 319 | } 320 | 321 | public String getCodecShortNameInline() { 322 | if (!TextUtils.isEmpty(mCodecName)) { 323 | return mCodecName; 324 | } else { 325 | return "N/A"; 326 | } 327 | } 328 | 329 | public String getResolutionInline() { 330 | if (mWidth <= 0 || mHeight <= 0) { 331 | return "N/A"; 332 | } else if (mSarNum <= 0 || mSarDen <= 0) { 333 | return String.format(Locale.US, "%d x %d", mWidth, mHeight); 334 | } else { 335 | return String.format(Locale.US, "%d x %d [SAR %d:%d]", mWidth, 336 | mHeight, mSarNum, mSarDen); 337 | } 338 | } 339 | 340 | public String getFpsInline() { 341 | if (mFpsNum <= 0 || mFpsDen <= 0) { 342 | return "N/A"; 343 | } else { 344 | return String.valueOf(((float) (mFpsNum)) / mFpsDen); 345 | } 346 | } 347 | 348 | public String getBitrateInline() { 349 | if (mBitrate <= 0) { 350 | return "N/A"; 351 | } else if (mBitrate < 1000) { 352 | return String.format(Locale.US, "%d bit/s", mBitrate); 353 | } else { 354 | return String.format(Locale.US, "%d kb/s", mBitrate / 1000); 355 | } 356 | } 357 | 358 | public String getSampleRateInline() { 359 | if (mSampleRate <= 0) { 360 | return "N/A"; 361 | } else { 362 | return String.format(Locale.US, "%d Hz", mSampleRate); 363 | } 364 | } 365 | 366 | public String getChannelLayoutInline() { 367 | if (mChannelLayout <= 0) { 368 | return "N/A"; 369 | } else { 370 | if (mChannelLayout == AV_CH_LAYOUT_MONO) { 371 | return "mono"; 372 | } else if (mChannelLayout == AV_CH_LAYOUT_STEREO) { 373 | return "stereo"; 374 | } else { 375 | return String.format(Locale.US, "%x", mChannelLayout); 376 | } 377 | } 378 | } 379 | } 380 | } 381 | --------------------------------------------------------------------------------