├── 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 | [](https://travis-ci.org/xdtianyu/LibMediaPlayer)
5 | [](http://central.maven.org/maven2/org/xdty/media/mediaplayer/)
6 | [  ](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 |
--------------------------------------------------------------------------------