├── .gitignore
├── .gitmodules
├── .idea
├── gradle.xml
└── runConfigurations.xml
├── LICENSE
├── README.md
├── VPlayerExample
├── AndroidManifest.xml
├── build.gradle
├── res
│ ├── drawable
│ │ ├── ic_folder_light.png
│ │ ├── ic_folder_up_light.png
│ │ ├── ic_launcher.png
│ │ └── ic_video_file_light.png
│ ├── layout
│ │ └── file_system_layout.xml
│ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
└── src
│ └── com
│ └── vplayer
│ └── example
│ ├── FileSystemAdapter.java
│ ├── MainActivity.java
│ ├── VideoActivity.java
│ └── ViewAdapterBase.java
├── VPlayer_library
├── AndroidManifest.xml
├── build.gradle
├── jni
│ ├── .gitignore
│ ├── Android-tropicssl.mk
│ ├── Android.mk
│ ├── Application.mk
│ ├── android-ndk-profiler-3.1
│ │ ├── android-ndk-profiler.mk
│ │ ├── armeabi-v7a
│ │ │ └── libandprof.a
│ │ ├── armeabi
│ │ │ └── libandprof.a
│ │ └── prof.h
│ ├── application
│ │ ├── aes-protocol.c
│ │ ├── aes-protocol.h
│ │ ├── blend.c
│ │ ├── blend.h
│ │ ├── convert.cpp
│ │ ├── convert.h
│ │ ├── ffmpeg-jni.c
│ │ ├── helpers.c
│ │ ├── helpers.h
│ │ ├── jni-protocol.c
│ │ ├── jni-protocol.h
│ │ ├── jni_helper.h
│ │ ├── nativetester-jni.c
│ │ ├── nativetester.c
│ │ ├── nativetester.h
│ │ ├── player.c
│ │ ├── player.h
│ │ ├── queue.c
│ │ ├── queue.h
│ │ └── sync.h
│ └── setup.sh
├── lint.xml
├── proguard-rules.pro
├── res
│ └── values
│ │ ├── attrs.xml
│ │ └── styles.xml
└── src
│ └── com
│ └── vplayer
│ ├── FpsCounter.java
│ ├── JniReader.java
│ ├── MediaStreamInfo.java
│ ├── NativeTester.java
│ ├── SeekerView.java
│ ├── VPlayerController.java
│ ├── VPlayerListener.java
│ ├── VPlayerSurfaceView.java
│ ├── VPlayerView.java
│ ├── ViewCompat.java
│ └── exception
│ ├── NotPlayingException.java
│ └── VPlayerException.java
├── build.gradle
├── ffmpeg_build
├── README.md
├── build_android.sh
└── config_and_build.sh
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project specific
2 | /VPlayer_library/libs/
3 | /VPlayer_library/jni/ffmpeg-build/
4 | /VPlayer_library/jni/ffmpeg/
5 |
6 | # Built application files
7 | build/
8 | obj/
9 | .externalNativeBuild/
10 |
11 | # Crashlytics configuations
12 | com_crashlytics_export_strings.xml
13 |
14 | # Local configuration file (sdk path, etc)
15 | local.properties
16 |
17 | # Gradle generated files
18 | .gradle/
19 |
20 | # Signing files
21 | .signing/
22 |
23 | # User-specific configurations
24 | .idea/libraries/
25 | .idea/workspace.xml
26 | .idea/tasks.xml
27 | .idea/.name
28 | .idea/compiler.xml
29 | .idea/copyright/profiles_settings.xml
30 | .idea/encodings.xml
31 | .idea/misc.xml
32 | .idea/modules.xml
33 | .idea/scopes/scope_settings.xml
34 | .idea/vcs.xml
35 | *.iml
36 |
37 | # OS-specific files
38 | .DS_Store
39 | .DS_Store?
40 | ._*
41 | .Spotlight-V100
42 | .Trashes
43 | ehthumbs.db
44 | Thumbs.db
45 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "FFmpegLibrary/jni/ffmpeg"]
2 | path = ffmpeg_build/ffmpeg
3 | url = git://source.ffmpeg.org/ffmpeg.git
4 | [submodule "FFmpegLibrary/jni/vo-aacenc"]
5 | path = ffmpeg_build/vo-aacenc
6 | url = https://github.com/mstorsjo/vo-aacenc.git
7 | [submodule "FFmpegLibrary/jni/vo-amrwbenc"]
8 | path = ffmpeg_build/vo-amrwbenc
9 | url = https://github.com/mstorsjo/vo-amrwbenc.git
10 | [submodule "FFmpegLibrary/jni/libass"]
11 | path = ffmpeg_build/libass
12 | url = https://github.com/libass/libass.git
13 | [submodule "FFmpegLibrary/jni/fribidi"]
14 | path = ffmpeg_build/fribidi
15 | url = https://github.com/matthewn4444/fribidi.git
16 | [submodule "ffmpeg_build/freetype2"]
17 | path = ffmpeg_build/freetype2
18 | url = git://git.sv.gnu.org/freetype/freetype2.git
19 | [submodule "ffmpeg_build/x264"]
20 | path = ffmpeg_build/x264
21 | url = git://git.videolan.org/x264.git
22 | [submodule "VPlayer_library/jni/tropicssl"]
23 | path = VPlayer_library/jni/tropicssl
24 | url = git://repo.or.cz/tropicssl.git
25 | [submodule "ffmpeg_build/libpng"]
26 | path = ffmpeg_build/libpng
27 | url = git://git.code.sf.net/p/libpng/code
28 | [submodule "ffmpeg_build/fdk-aac"]
29 | path = ffmpeg_build/fdk-aac
30 | url = https://github.com/mstorsjo/fdk-aac.git
31 | [submodule "VPlayer_library/jni/libyuv"]
32 | path = VPlayer_library/jni/libyuv
33 | url = https://chromium.googlesource.com/libyuv/libyuv
34 | [submodule "ffmpeg_build/libjpeg-turbo"]
35 | path = ffmpeg_build/libjpeg-turbo
36 | url = https://github.com/libjpeg-turbo/libjpeg-turbo.git
37 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VPlayer Library (0.3.2)
2 | This project provides the easiest way to include FFmpeg into any Android project with almost no NDK building and tweaking.
3 | Of course if you want to customize FFmpeg, you will have to build the project from scratch.
4 |
5 | Forked from [appunite/AndroidFFmpeg](https://github.com/appunite/AndroidFFmpeg), this project has a few enhancements to make it
6 | easier to develop and embed videos to your app. I have added some more functionality and a new simple project for
7 | developers to get started with. This project follows AndroidFFmpeg closely.
8 |
9 | Read the wikis for this work. Even if you are a beginner to NDK, this project should be comprehensable enough to include
10 | VPlayer into your project. I provide prebuilt binaries for the project.
11 |
12 | ## Changes/Fixes from AndroidFFmpeg
13 |
14 | - Able to compile with gcc 4.9+ toolchain and NDK r16b (64bit)
15 | - Updated with the newest versions of each library
16 | - Super easy way to compile FFmpeg from scratch without hassles
17 | - Fixes crashing issue when using the same video player for multiple videos (with or without subs)
18 | - Added a single build file to compile all dependencies without any need of commandline
19 | - Changed the Java library to easily integrate a video into a project
20 | - Added looping functionality
21 |
22 | ## Sample integration
23 |
24 | This is a very simple example that plays a video after starting the activity.
25 | You can view more integration tutorials [here](https://github.com/matthewn4444/VPlayer_lib/wiki/Integration-Tutorial).
26 |
27 | public class VideoActivity extends Activity {
28 | private VPlayerView mPlayerView;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 |
34 | // Attach the player
35 | mPlayerView = new VPlayerView(this);
36 | setContentView(mPlayerView);
37 |
38 | // Set the content and play the video
39 | mPlayerView.setDataSource(path);
40 | mPlayerView.play();
41 | }
42 |
43 | @Override
44 | protected void onPause() {
45 | super.onPause();
46 | mPlayerView.onPause();
47 | }
48 |
49 | @Override
50 | protected void onResume() {
51 | super.onResume();
52 | mPlayerView.onResume();
53 | }
54 |
55 | @Override
56 | public void finish() {
57 | super.finish();
58 | mPlayerView.finish();
59 | }
60 | }
61 |
62 | ## Cloning and Building
63 |
64 | You can clone the project here:
65 |
66 | `` git clone https://github.com/matthewn4444/VPlayer_lib.git``
67 |
68 | For building the project, please refer [here](https://github.com/matthewn4444/VPlayer_lib/wiki/Compiling-VPlayer).
69 |
70 | ## License
71 | Copyright (C) 2015 Matthew Ng
72 | Licensed under the Apache License, Verision 2.0
73 |
74 | AndroidFFmpeg, FFmpeg, libpng, fdk-aac, fribidi, libvo-aacenc, vo-amrwbenc, tropicssl, and libyuv are distributed on theirs own license.
75 |
76 | ## Patent disclaimer
77 | We do not grant of patent rights.
78 | Some codecs use patented techniques and before use those parts of library you have to buy thrid-party patents.
79 |
80 | ## Credits
81 | This library was modified by Matthew Ng from the original author Jacek Marchwicki
82 | from Appunite.com and other libraries he used. Also thanks to his issues page that
83 | fixed a bunch of issues.
84 |
--------------------------------------------------------------------------------
/VPlayerExample/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
9 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/VPlayerExample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | dependencies {
4 | implementation fileTree(dir: 'libs', include: '*.jar')
5 | implementation project(':VPlayer_library')
6 | }
7 |
8 | android {
9 | compileSdkVersion 17
10 | buildToolsVersion '26.0.2'
11 |
12 | sourceSets {
13 | main {
14 | manifest.srcFile 'AndroidManifest.xml'
15 | java.srcDirs = ['src']
16 | resources.srcDirs = ['src']
17 | aidl.srcDirs = ['src']
18 | renderscript.srcDirs = ['src']
19 | res.srcDirs = ['res']
20 | assets.srcDirs = ['assets']
21 | }
22 |
23 | // Move the build types to build-types/
24 | // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
25 | // This moves them out of them default location under src//... which would
26 | // conflict with src/ being used by the main source set.
27 | // Adding new build types or product flavors should be accompanied
28 | // by a similar customization.
29 | debug.setRoot('build-types/debug')
30 | release.setRoot('build-types/release')
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/VPlayerExample/res/drawable/ic_folder_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/VPlayer_lib/06d20ba3c24e3c01e8025ff26687d4afa8e017c4/VPlayerExample/res/drawable/ic_folder_light.png
--------------------------------------------------------------------------------
/VPlayerExample/res/drawable/ic_folder_up_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/VPlayer_lib/06d20ba3c24e3c01e8025ff26687d4afa8e017c4/VPlayerExample/res/drawable/ic_folder_up_light.png
--------------------------------------------------------------------------------
/VPlayerExample/res/drawable/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/VPlayer_lib/06d20ba3c24e3c01e8025ff26687d4afa8e017c4/VPlayerExample/res/drawable/ic_launcher.png
--------------------------------------------------------------------------------
/VPlayerExample/res/drawable/ic_video_file_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/VPlayer_lib/06d20ba3c24e3c01e8025ff26687d4afa8e017c4/VPlayerExample/res/drawable/ic_video_file_light.png
--------------------------------------------------------------------------------
/VPlayerExample/res/layout/file_system_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
21 |
22 |
--------------------------------------------------------------------------------
/VPlayerExample/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | VPlayer Example
4 |
5 |
6 | Back
7 |
8 |
9 |
--------------------------------------------------------------------------------
/VPlayerExample/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/VPlayerExample/src/com/vplayer/example/FileSystemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.vplayer.example;
2 |
3 | import java.io.File;
4 | import java.io.FileFilter;
5 | import java.io.FileNotFoundException;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.Comparator;
9 |
10 | import android.app.Activity;
11 | import android.content.Context;
12 | import android.graphics.drawable.Drawable;
13 | import android.view.View;
14 | import android.widget.ImageView;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | import com.vplayer.example.FileSystemAdapter.FileListItem;
19 |
20 | public class FileSystemAdapter extends ViewAdapterBase {
21 |
22 | private File mCurrentDirectory;
23 | private boolean mShowHidden;
24 | private boolean mOnlyShowFolders;
25 | private boolean mShowBackItem;
26 | private File[] mFileList;
27 | private final FileSort mFileSorter = new FileSort();
28 | private TextView mBindedPath;
29 | private CustomFileTypeParser mTypeParser;
30 | private final ArrayList mLowerBoundFiles;
31 | private FileFilter mFilter;
32 |
33 | private static String BackString;
34 | private static FileListItem BackFileListItem;
35 | private static Drawable IconBackDrawable;
36 | private static Drawable IconFileDrawable;
37 | private static Drawable IconFolderDrawable;
38 |
39 | static final public int[] LAYOUT_IDS = {
40 | R.id.icon,
41 | R.id.filename
42 | };
43 |
44 | public static enum LIST_ITEM_TYPE {
45 | FILE, FOLDER, BACK
46 | };
47 |
48 | interface CustomFileTypeParser {
49 | public LIST_ITEM_TYPE onFileTypeParse(File file);
50 | }
51 |
52 | static class FileListItem {
53 | private final LIST_ITEM_TYPE mType;
54 | private final String mName;
55 |
56 | public FileListItem(LIST_ITEM_TYPE type, String name) {
57 | mType = type;
58 | mName = name;
59 | }
60 |
61 | public boolean isFile() {
62 | return mType == LIST_ITEM_TYPE.FILE;
63 | }
64 | public boolean isFolder() {
65 | return mType == LIST_ITEM_TYPE.FOLDER;
66 | }
67 | public boolean isBackItem() {
68 | return mType == LIST_ITEM_TYPE.BACK;
69 | }
70 | public LIST_ITEM_TYPE getType() {
71 | return mType;
72 | }
73 | public String getName() {
74 | return mName;
75 | }
76 | }
77 |
78 | static class FileSort implements Comparator{
79 | @Override
80 | public int compare(File src, File target){
81 | if (src.isDirectory() && target.isFile()) {
82 | return -1;
83 | } else if (src.isFile() && target.isDirectory()) {
84 | return 1;
85 | }
86 | return src.getName().compareTo(target.getName());
87 | }
88 | }
89 |
90 | public FileSystemAdapter(Context context, File startDirectory) throws FileNotFoundException {
91 | this(context, startDirectory, false);
92 | }
93 |
94 | public FileSystemAdapter(Context context, File startDirectory, boolean showBackButton)
95 | throws FileNotFoundException {
96 | this(context, startDirectory, showBackButton, false);
97 | }
98 |
99 | public FileSystemAdapter(Context context, File startDirectory, boolean showBackButton,
100 | boolean onlyShowFolders) throws FileNotFoundException {
101 | this(context, startDirectory, showBackButton, onlyShowFolders, false);
102 | }
103 |
104 | public FileSystemAdapter(Context context, File startDirectory, boolean showBackButton,
105 | boolean onlyShowFolders, boolean showHiddenFolders) throws FileNotFoundException {
106 | this(context, startDirectory, showBackButton, onlyShowFolders, false, null);
107 | }
108 | public FileSystemAdapter(Context context, File startDirectory, boolean showBackButton,
109 | boolean onlyShowFolders, boolean showHiddenFolders, CustomFileTypeParser parser) throws FileNotFoundException {
110 | super((Activity)context, R.layout.file_system_layout, LAYOUT_IDS, new ArrayList());
111 | if (!startDirectory.exists() || !startDirectory.isDirectory()) {
112 | throw new FileNotFoundException("Cannot find directory.");
113 | }
114 | mLowerBoundFiles = new ArrayList();
115 | mShowHidden = showHiddenFolders;
116 | mOnlyShowFolders = onlyShowFolders;
117 | mShowBackItem = showBackButton;
118 | mCurrentDirectory = startDirectory;
119 | if (BackString == null) {
120 | BackString = context.getString(R.string.directory_back);
121 | BackFileListItem = new FileListItem(LIST_ITEM_TYPE.BACK, BackString);
122 | }
123 |
124 | IconBackDrawable = context.getResources().getDrawable(R.drawable.ic_folder_up_light);
125 | IconFileDrawable = context.getResources().getDrawable(R.drawable.ic_video_file_light);
126 | IconFolderDrawable = context.getResources().getDrawable(R.drawable.ic_folder_light);
127 |
128 | mTypeParser = parser;
129 | refresh();
130 | }
131 |
132 | public void bindPathToTextView(TextView textView) {
133 | mBindedPath = textView;
134 | if (mBindedPath != null) {
135 | mBindedPath.setText(mCurrentDirectory.getPath());
136 | }
137 | }
138 |
139 | public String getCurrentDirectoryPath() {
140 | return mCurrentDirectory.getPath();
141 | }
142 |
143 | public void setCustomFileTypeParser(CustomFileTypeParser parser) {
144 | mTypeParser = parser;
145 | }
146 |
147 | public File getCurrentDirectory() {
148 | return mCurrentDirectory;
149 | }
150 |
151 | public void onlyShowFolders(boolean flag) {
152 | if (mOnlyShowFolders != flag) {
153 | mOnlyShowFolders = flag;
154 | refresh();
155 | }
156 | }
157 |
158 | public boolean isOnlyShowingFolders() {
159 | return mOnlyShowFolders;
160 | }
161 |
162 | public void showHiddenFiles(boolean flag) {
163 | if (mShowHidden != flag) {
164 | mShowHidden = flag;
165 | refresh();
166 | }
167 | }
168 |
169 | public boolean isShowingHiddenFiles() {
170 | return mShowHidden;
171 | }
172 |
173 | public void showBackListItem(boolean flag) {
174 | if (mShowBackItem != flag) {
175 | mShowBackItem = flag;
176 | if (mShowBackItem) {
177 | insert(BackFileListItem, 0);
178 | } else {
179 | remove(BackFileListItem);
180 | }
181 | }
182 | }
183 |
184 | public boolean isBackListItemVisible() {
185 | return mShowBackItem;
186 | }
187 |
188 | public File getFile(int index) {
189 | if (isBackButtonShown()) {
190 | if (index == 0) { // Back button
191 | return null;
192 | }
193 | index--;
194 | }
195 | return mFileList[index];
196 | }
197 |
198 | public boolean refresh() {
199 | File[] files = mCurrentDirectory.listFiles(new FileFilter() { // TODO split this into file and folder
200 | @Override
201 | public boolean accept(File file) {
202 | boolean accept = (!mOnlyShowFolders && (!file.isHidden() || file.isHidden()
203 | && mShowHidden)) || file.isDirectory();
204 | if (accept && mFilter != null) {
205 | accept = mFilter.accept(file);
206 | }
207 | return accept;
208 | }
209 | });
210 | if (files == null) {
211 | Toast.makeText(getContext(), "Unable to open folder because of permissions", Toast.LENGTH_SHORT).show();
212 | return false;
213 | }
214 | clear();
215 | mFileList = files;
216 | if (mShowBackItem && !isDirectoryAtLowerBound()) {
217 | add(BackFileListItem);
218 | }
219 | Arrays.sort(mFileList, mFileSorter);
220 | for (int i = 0; i < mFileList.length; i++) {
221 | if (mTypeParser != null) {
222 | LIST_ITEM_TYPE type = mTypeParser.onFileTypeParse(mFileList[i]);
223 | add(new FileListItem(type, mFileList[i].getName()));
224 | } else {
225 | if (mFileList[i].isDirectory()) {
226 | add(new FileListItem(LIST_ITEM_TYPE.FOLDER, mFileList[i].getName()));
227 | } else {
228 | add(new FileListItem(LIST_ITEM_TYPE.FILE, mFileList[i].getName()));
229 | }
230 | }
231 | }
232 | if (mBindedPath != null) {
233 | mBindedPath.setText(mCurrentDirectory.getPath());
234 | }
235 | notifyDataSetChanged();
236 | return true;
237 | }
238 |
239 | public void setFileFilter(FileFilter filter) {
240 | mFilter = filter;
241 | refresh();
242 | }
243 |
244 | public void setChildAsCurrent(int index) {
245 | if (isBackButtonShown()) {
246 | if (index == 0) {
247 | moveUp();
248 | return;
249 | }
250 | index--;
251 | }
252 | if (index < mFileList.length) {
253 | setCurrentDirectory(mFileList[index]);
254 | }
255 | }
256 |
257 | public boolean setCurrentDirectory(File currentDirectory) {
258 | if (currentDirectory.exists() && currentDirectory.isDirectory()) {
259 | File old = mCurrentDirectory;
260 | mCurrentDirectory = currentDirectory;
261 | if (refresh()) {
262 | return true;
263 | } else {
264 | mCurrentDirectory = old;
265 | }
266 | }
267 | return false;
268 | }
269 |
270 | public boolean moveUp() {
271 | if (mCurrentDirectory.getParent() == null) {
272 | return false;
273 | }
274 | File old = mCurrentDirectory;
275 | mCurrentDirectory = mCurrentDirectory.getParentFile();
276 | if (refresh()) {
277 | return true;
278 | }
279 | mCurrentDirectory = old;
280 | return false;
281 | }
282 |
283 | public void addLowerBoundFile(File path) {
284 | if (path != null && path.exists()) {
285 | mLowerBoundFiles.add(path);
286 | refresh();
287 | }
288 | }
289 |
290 | public boolean isDirectoryAtLowerBound() {
291 | if (mLowerBoundFiles != null) {
292 | for (int i = 0; i < mLowerBoundFiles.size(); i++) {
293 | if (mLowerBoundFiles.get(i).getPath().equals(mCurrentDirectory.getPath())) {
294 | return true;
295 | }
296 | }
297 | }
298 | return false;
299 | }
300 |
301 | protected boolean isBackButtonShown() {
302 | return mShowBackItem && !isDirectoryAtLowerBound();
303 | }
304 |
305 | @Override
306 | protected void setWidgetValues(int position, FileListItem item, View[] elements,
307 | View layout) {
308 | Drawable drawable = null;
309 | switch(item.getType()) {
310 | case FILE:
311 | drawable = IconFileDrawable;
312 | break;
313 | case BACK:
314 | drawable = IconBackDrawable;
315 | break;
316 | case FOLDER:
317 | drawable = IconFolderDrawable;
318 | break;
319 | }
320 | ((ImageView)elements[0]).setImageDrawable(drawable);
321 | ((TextView)elements[1]).setText(item.getName());
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/VPlayerExample/src/com/vplayer/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.vplayer.example;
2 |
3 | import java.io.File;
4 | import java.io.FileFilter;
5 | import java.io.FileNotFoundException;
6 |
7 | import android.app.Activity;
8 | import android.content.Intent;
9 | import android.graphics.Color;
10 | import android.os.Bundle;
11 | import android.os.Environment;
12 | import android.view.View;
13 | import android.widget.AdapterView;
14 | import android.widget.AdapterView.OnItemClickListener;
15 | import android.widget.ListView;
16 | import android.widget.Toast;
17 |
18 | public class MainActivity extends Activity implements OnItemClickListener {
19 |
20 | public static String[] VIDEO_FORMATS = {
21 | ".avi", ".mpeg", ".mpg", ".m1v", ".m2v", ".mkv", ".mjpeg", ".mjpg", ".webm", ".mp4", ".mov", ".m4v", ".mp4v", ".3gp", ".wmv"
22 | };
23 |
24 | private FileSystemAdapter mAdapter;
25 | private boolean mShowedToastBeforeBackExit = false;
26 |
27 | private final FileFilter mVideoFilter = new FileFilter() {
28 | @Override
29 | public boolean accept(File pathname) {
30 | return pathname.isDirectory() || pathname.isFile() && isVideoFile(pathname);
31 | }
32 | };
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 |
38 | final File storage = Environment.getExternalStorageDirectory();
39 | try {
40 | mAdapter = new FileSystemAdapter(this, storage, true);
41 | mAdapter.addLowerBoundFile(storage);
42 | mAdapter.setFileFilter(mVideoFilter);
43 | } catch (FileNotFoundException e) {
44 | e.printStackTrace();
45 | Toast.makeText(this, "Failed to find external storage!", Toast.LENGTH_LONG).show();
46 | return;
47 | }
48 |
49 | final ListView listView = new ListView(this);
50 | listView.setBackgroundColor(Color.WHITE);
51 | listView.setAdapter(mAdapter);
52 | listView.setOnItemClickListener(this);
53 | setContentView(listView);
54 | }
55 |
56 | private boolean isVideoFile(File file) {
57 | String name = file.getName();
58 | for (int i = 0; i < VIDEO_FORMATS.length; i++) {
59 | if (name.endsWith(VIDEO_FORMATS[i])) {
60 | return true;
61 | }
62 | }
63 | return false;
64 | }
65 |
66 | @Override
67 | public void onItemClick(AdapterView> parent, View view, int position,
68 | long id) {
69 | File selectedFile = mAdapter.getFile(position);
70 |
71 | // Detect back button press
72 | if (selectedFile == null) {
73 | mAdapter.moveUp();
74 | return;
75 | }
76 |
77 | // Check permissions of this folder
78 | if (!selectedFile.canRead()) {
79 | Toast.makeText(this, "Unable to open this folder due to lack of permissions.", Toast.LENGTH_SHORT).show();
80 | return;
81 | }
82 |
83 | if (selectedFile.isDirectory()) {
84 | mAdapter.setChildAsCurrent(position);
85 | } else { // is a file
86 | Intent in = new Intent(this, VideoActivity.class);
87 | in.putExtra(VideoActivity.VideoPath, selectedFile.getPath());
88 | startActivity(in);
89 | }
90 | }
91 |
92 | @Override
93 | public void onBackPressed() {
94 | if (mAdapter != null) {
95 | // Back button will exit
96 | if (mAdapter.isDirectoryAtLowerBound()) {
97 | if (mShowedToastBeforeBackExit) {
98 | super.onBackPressed();
99 | } else {
100 | mShowedToastBeforeBackExit = true;
101 | Toast.makeText(this, "Press back again to exit", Toast.LENGTH_SHORT).show();
102 | }
103 | } else {
104 | mShowedToastBeforeBackExit = false;
105 | mAdapter.showBackListItem(true);
106 | mAdapter.moveUp();
107 | }
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/VPlayerExample/src/com/vplayer/example/VideoActivity.java:
--------------------------------------------------------------------------------
1 | package com.vplayer.example;
2 |
3 | import java.io.File;
4 |
5 | import android.app.Activity;
6 | import android.app.AlertDialog;
7 | import android.content.DialogInterface;
8 | import android.content.Intent;
9 | import android.graphics.Color;
10 | import android.graphics.PixelFormat;
11 | import android.graphics.Point;
12 | import android.os.Bundle;
13 | import android.view.Display;
14 | import android.view.Gravity;
15 | import android.view.View;
16 | import android.view.View.OnClickListener;
17 | import android.view.Window;
18 | import android.widget.FrameLayout;
19 | import android.widget.Toast;
20 |
21 | import com.vplayer.MediaStreamInfo;
22 | import com.vplayer.VPlayerListener;
23 | import com.vplayer.VPlayerView;
24 | import com.vplayer.exception.NotPlayingException;
25 | import com.vplayer.exception.VPlayerException;
26 |
27 | public class VideoActivity extends Activity {
28 | public static final String VideoPath = "video_path_key";
29 |
30 | public static final String SystemFontPath = "/system/fonts/";
31 | public static final String[] PossibleSubtitleFonts = {
32 | "Roboto-Regular.ttf", "Roboto-Light.ttf", "AndroidClock.ttf", "DroidSans.ttf"
33 | };
34 |
35 | private VPlayerView mPlayerView;
36 | private AlertDialog mDialog;
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | this.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
41 | getWindow().setFormat(PixelFormat.RGBA_8888);
42 | super.onCreate(savedInstanceState);
43 | findViewById(android.R.id.content).setBackgroundColor(Color.BLACK);
44 |
45 | Intent in = getIntent();
46 | if (in != null) {
47 | String path = in.getStringExtra(VideoPath);
48 | if (path != null && new File(path).exists()) {
49 | attachPlayer(path);
50 | return;
51 | }
52 | }
53 |
54 | // No video was passed when starting this activity
55 | alert(null, "There was no video found, going back.");
56 | }
57 |
58 | private void attachPlayer(String path) {
59 | mPlayerView = new VPlayerView(this);
60 | mPlayerView.setVideoListener(new VPlayerListener() {
61 | @Override
62 | public void onMediaSourceLoaded(VPlayerException err, MediaStreamInfo[] streams) {
63 | if (err != null) {
64 | alert("Decode Error", "Unable to read the video!");
65 | err.printStackTrace();
66 | } else {
67 | // Get the display dimensions
68 | Display display = getWindowManager().getDefaultDisplay();
69 | Point size = new Point();
70 | display.getSize(size);
71 |
72 | // Fill the screen with the video with correct aspect ratio
73 | FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mPlayerView.getLayoutParams();
74 | params.height = size.y;
75 | params.width = (int) (size.y * mPlayerView.getVideoWidth() * 1.0 / mPlayerView.getVideoHeight());
76 | params.gravity = Gravity.CENTER;
77 | mPlayerView.setLayoutParams(params);
78 |
79 | // Play the video
80 | mPlayerView.play();
81 | }
82 | }
83 | @Override
84 | public void onMediaPause(NotPlayingException err) {
85 | Toast.makeText(VideoActivity.this, "Pause", Toast.LENGTH_SHORT).show();
86 | }
87 | @Override
88 | public void onMediaResume(NotPlayingException result) {
89 | Toast.makeText(VideoActivity.this, "Play", Toast.LENGTH_SHORT).show();
90 | }
91 | @Override
92 | public void onMediaUpdateTime(long mCurrentTimeUs,
93 | long mVideoDurationUs, boolean isFinished) {
94 | if (isFinished) {
95 | Toast.makeText(VideoActivity.this, "Video is finished", Toast.LENGTH_SHORT).show();
96 | }
97 | }
98 | });
99 | setContentView(mPlayerView);
100 |
101 | // Toggle pause when you click the video
102 | mPlayerView.setOnClickListener(new OnClickListener() {
103 | @Override
104 | public void onClick(View v) {
105 | if (mPlayerView.isPlaying()) {
106 | mPlayerView.pause();
107 | } else {
108 | mPlayerView.play();
109 | }
110 | }
111 | });
112 |
113 | mPlayerView.setWindowFullscreen();
114 |
115 | // Choose existing font
116 | String fontPath = null;
117 | for (String font : PossibleSubtitleFonts) {
118 | File file = new File(SystemFontPath + font);
119 | if (file.exists() && file.canRead()) {
120 | fontPath = file.getAbsolutePath();
121 | break;
122 | }
123 | }
124 |
125 | // Set the video path
126 | mPlayerView.setDataSource(path, fontPath);
127 | }
128 |
129 | private void alert(String title, String message) {
130 | if (mDialog == null) {
131 | mDialog = new AlertDialog.Builder(this)
132 | .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
133 | @Override
134 | public void onClick(DialogInterface dialog, int which) {
135 | finish();
136 | }
137 | }).create();
138 | }
139 | mDialog.setMessage(message);
140 | mDialog.setTitle(title);
141 | mDialog.show();
142 | }
143 |
144 | @Override
145 | protected void onPause() {
146 | super.onPause();
147 | mPlayerView.onPause();
148 | }
149 |
150 | @Override
151 | protected void onResume() {
152 | super.onResume();
153 | mPlayerView.onResume();
154 | }
155 |
156 | @Override
157 | public void finish() {
158 | super.finish();
159 | mPlayerView.finish();
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/VPlayerExample/src/com/vplayer/example/ViewAdapterBase.java:
--------------------------------------------------------------------------------
1 | package com.vplayer.example;
2 |
3 | import java.util.ArrayList;
4 |
5 | import android.app.Activity;
6 | import android.content.Context;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ArrayAdapter;
11 |
12 |
13 | public abstract class ViewAdapterBase extends ArrayAdapter{
14 | protected ArrayList entries;
15 | private final Activity activity;
16 | private final int widgetLayout;
17 | private final int[] resources;
18 |
19 | public ViewAdapterBase(Activity a, int widgetResourceLayout, int[] viewResourceIdListInWidget, ArrayList list) {
20 | super(a, 0, list);
21 | entries = list;
22 | activity = a;
23 | resources = viewResourceIdListInWidget;
24 | widgetLayout = widgetResourceLayout;
25 | }
26 |
27 | protected abstract void setWidgetValues(int position, TItem item, View[] elements, View layout);
28 |
29 | protected Activity getActivity() {
30 | return activity;
31 | }
32 |
33 | public ArrayList getList() {
34 | return entries;
35 | }
36 |
37 | protected void onCreateListItem(int position, View item, ViewGroup parent) {
38 | }
39 |
40 | @Override
41 | public View getView(int position, View convertView, ViewGroup parent) {
42 | View viewObj = convertView;
43 | View[] elements = null;
44 | if (viewObj == null) {
45 | LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
46 | viewObj = inflator.inflate(widgetLayout, null);
47 | int size = resources.length;
48 | elements = new View[size];
49 | for (int i = 0; i < size; i++) {
50 | elements[i] = viewObj.findViewById(resources[i]);
51 | }
52 | viewObj.setTag(elements);
53 | onCreateListItem(position, viewObj, parent);
54 | } else {
55 | elements = (View[]) viewObj.getTag();
56 | }
57 | final TItem item = entries.get(position);
58 | for (View v: elements) {
59 | v.setVisibility(View.VISIBLE);
60 | }
61 | setWidgetValues(position, item, elements, viewObj);
62 | return viewObj;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/VPlayer_library/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
--------------------------------------------------------------------------------
/VPlayer_library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | dependencies {
4 | implementation fileTree(dir: 'libs', include: '*.jar')
5 | }
6 |
7 | android {
8 | compileSdkVersion 22
9 | buildToolsVersion '26.0.2'
10 | defaultConfig {
11 | minSdkVersion 8
12 | targetSdkVersion 22
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | externalNativeBuild {
17 | ndkBuild {
18 | targets "nativetester-jni", "ffmpeg-jni", "cpufeatures", "yuv_static", "ffmpeg-jni-neon"
19 | arguments "-Wno-invalid-source-encoding -j4"
20 | }
21 | }
22 | ndk {
23 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'//, 'mips', 'armeabi'
24 | }
25 | }
26 | sourceSets {
27 | main {
28 | manifest.srcFile 'AndroidManifest.xml'
29 | jniLibs.srcDir 'jni/dist'
30 | java.srcDirs = ['src']
31 | resources.srcDirs = ['src']
32 | aidl.srcDirs = ['src']
33 | renderscript.srcDirs = ['src']
34 | res.srcDirs = ['res']
35 | assets.srcDirs = ['assets']
36 | }
37 |
38 | // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
39 | // This moves them out of them default location under src//... which would
40 | // conflict with src/ being used by the main source set.
41 | // Adding new build types or product flavors should be accompanied
42 | // by a similar customization.
43 | debug.setRoot('build-types/debug')
44 | release.setRoot('build-types/release')
45 | }
46 | externalNativeBuild {
47 | ndkBuild {
48 | path 'jni/Android.mk'
49 | }
50 | }
51 | }
52 |
53 | def copyFileIfNotExists(src, dstFolder) {
54 | def srcFile = new File(src)
55 | if (!srcFile.exists()) {
56 | return false
57 | }
58 | def file = new File(dstFolder + '/' + srcFile.name)
59 | if (!file.exists()) {
60 | copy {
61 | from src
62 | into dstFolder
63 | }
64 | return true
65 | }
66 | return false
67 | }
68 |
69 | def deleteOtherArchFromFolder(config, path) {
70 | new File(path).listFiles().each { folder ->
71 | if (!config.ndk.abiFilters.contains(folder.name)) {
72 | delete {
73 | delete folder
74 | }
75 | }
76 | }
77 | }
78 |
79 | task prebuildTask() {
80 | doLast {
81 | // TODO support multiple flavors if used in the future
82 | def config = android.defaultConfig
83 |
84 | def here = project.buildscript.sourceFile.parentFile.absolutePath
85 | def destRoot = here + '/jni/dist'
86 |
87 | // Delete the arch that are not in this build from the dist folder
88 | deleteOtherArchFromFolder(config, destRoot)
89 |
90 | // Also delete the obj files in build directory
91 | android.buildTypes.all { type ->
92 | deleteOtherArchFromFolder(config, project.buildDir.absolutePath
93 | + '/intermediates/ndkBuild/' + type.name + '/obj/local')
94 | }
95 |
96 | // Copy all the binaries that are not already there
97 | config.ndk.abiFilters.each { abi ->
98 | def destFolder = destRoot + '/' + abi + '/'
99 | def folder = new File(destFolder)
100 | if (!folder.exists()) {
101 | folder.mkdirs()
102 | }
103 | def dir = here + '/jni/ffmpeg-build/' + abi
104 | if (copyFileIfNotExists(dir + '/libffmpeg.so', destFolder)) {
105 | println 'Copied libffmpeg.so (FFMPEG binary) for ' + abi
106 | }
107 |
108 | // Neon support only for arm v7
109 | if (abi == "armeabi-v7a" && copyFileIfNotExists(dir + '/libffmpeg-neon.so', destFolder)) {
110 | println 'Copied libffmpeg-neon.so (FFMPEG binary) for ' + abi
111 | }
112 | }
113 | }
114 | }
115 | preBuild.dependsOn(prebuildTask)
116 |
117 | task deleteDummySharedLibraries {
118 | doLast {
119 | def config = android.defaultConfig
120 |
121 | // Loop through each build type and abi and delete neon if not needed or not armv7
122 | android.buildTypes.all { type ->
123 | def dir = project.buildDir.absolutePath + '/intermediates/ndkBuild/' + type.name + '/obj/local/'
124 | config.ndk.abiFilters.each { abi ->
125 | if (abi != "armeabi-v7a") {
126 | delete {
127 | delete dir + abi + "/libffmpeg-jni-neon.so"
128 | }
129 | }
130 | }
131 | }
132 | }
133 | }
134 | tasks.whenTaskAdded { task ->
135 | if (task.name == "mergeDebugJniLibFolders") {
136 | task.dependsOn deleteDummySharedLibraries
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/.gitignore:
--------------------------------------------------------------------------------
1 | # Header files copied
2 | dist/
3 | libjpeg-turbo/
--------------------------------------------------------------------------------
/VPlayer_library/jni/Android-tropicssl.mk:
--------------------------------------------------------------------------------
1 | #the tropicssl library
2 | include $(CLEAR_VARS)
3 |
4 | LOCAL_CFLAGS := -std=gnu99
5 |
6 | SRC_FILES := \
7 | aes.c arc4.c base64.c \
8 | bignum.c certs.c debug.c \
9 | des.c dhm.c havege.c \
10 | md2.c md4.c md5.c \
11 | net.c padlock.c rsa.c \
12 | sha1.c sha2.c sha4.c \
13 | ssl_cli.c ssl_srv.c ssl_tls.c \
14 | timing.c x509parse.c xtea.c \
15 | camellia.c
16 | SRC_DIR=tropicssl/library
17 |
18 | #disable thumb
19 | LOCAL_ARM_MODE := arm
20 | LOCAL_CFLAGS := -O3
21 |
22 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/tropicssl/include/
23 | LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
24 | LOCAL_MODULE := tropicssl
25 | LOCAL_SRC_FILES := $(addprefix $(SRC_DIR)/,$(SRC_FILES))
26 |
27 | LOCAL_LDLIBS := -ldl -llog
28 |
29 | include $(BUILD_STATIC_LIBRARY)
30 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/Android.mk:
--------------------------------------------------------------------------------
1 | # Android.mk
2 | # Copyright (c) 2012 Jacek Marchwicki
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 | LOCAL_PATH := $(call my-dir)
17 |
18 | include $(CLEAR_VARS)
19 |
20 | #
21 | # Presets - comment out what you don't need
22 | #
23 | # If you comment out FEATURE_NEON, you need to remove System.LoadLibrary
24 | # from the java code in VPlayerController.java. Also you may want to remove
25 | # libffmpeg-neon.so copying code in build.gradle, sorry gradle makes it too
26 | # complicated to merge settings
27 | FEATURE_NEON:=yes
28 | #LIBRARY_PROFILER:=yes
29 | SUBTITLES:=yes
30 |
31 | # add support for encryption
32 | MODULE_ENCRYPT:=yes
33 |
34 |
35 |
36 | #if armeabi-v7a
37 | ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
38 | ifdef FEATURE_NEON
39 | # add neon optimization code (only armeabi-v7a)
40 | FEATURE_NEON:=yes
41 | LOCAL_ARM_NEON := true
42 | endif
43 | else
44 | FEATURE_NEON:=
45 | endif
46 |
47 | #if armeabi or armeabi-v7a
48 | ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI),armeabi armeabi-v7a arm64-v8a))
49 | ifdef LIBRARY_PROFILER
50 | # add profiler (only arm)
51 | LIBRARY_PROFILER:=yes
52 | endif
53 | else
54 | LIBRARY_PROFILER:=
55 | endif
56 |
57 | include $(CLEAR_VARS)
58 | LOCAL_MODULE := ffmpeg-prebuilt
59 | LOCAL_SRC_FILES := ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg.so
60 | LOCAL_EXPORT_C_INCLUDES := ffmpeg-build/$(TARGET_ARCH_ABI)/include
61 | LOCAL_EXPORT_LDLIBS := ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg.so
62 | LOCAL_PRELINK_MODULE := true
63 | include $(PREBUILT_SHARED_LIBRARY)
64 |
65 | include $(CLEAR_VARS)
66 | LOCAL_MODULE := libjpeg
67 | LOCAL_SRC_FILES := $(LOCAL_PATH)/ffmpeg-build/$(TARGET_ARCH_ABI)/lib/libjpeg.a
68 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/libjpeg-turbo
69 | LOCAL_EXPORT_LDLIBS := $(LOCAL_SRC_FILES)
70 | LOCAL_PRELINK_MODULE := true
71 | include $(PREBUILT_STATIC_LIBRARY)
72 |
73 | #../../ffmpeg_build/ffmpeg
74 |
75 | ifdef FEATURE_NEON
76 | include $(CLEAR_VARS)
77 | LOCAL_MODULE := ffmpeg-prebuilt-neon
78 | LOCAL_SRC_FILES := ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg-neon.so
79 | LOCAL_EXPORT_C_INCLUDES := ffmpeg-build/$(TARGET_ARCH_ABI)-neon/include
80 | LOCAL_EXPORT_LDLIBS := ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg-neon.so
81 | LOCAL_PRELINK_MODULE := true
82 | include $(PREBUILT_SHARED_LIBRARY)
83 | endif
84 |
85 | #ffmpeg-jni library
86 | include $(CLEAR_VARS)
87 | LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
88 |
89 | LOCAL_MODULE := ffmpeg-jni
90 | LOCAL_SRC_FILES := application/ffmpeg-jni.c application/player.c application/queue.c \
91 | application/helpers.c application/jni-protocol.c application/blend.c \
92 | application/convert.cpp
93 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/ffmpeg-build/$(TARGET_ARCH_ABI)/include \
94 | $(LOCAL_PATH)/application
95 | LOCAL_SHARED_LIBRARY := ffmpeg-prebuilt
96 |
97 | ifdef SUBTITLES
98 | LOCAL_CFLAGS += -DSUBTITLES
99 | endif
100 |
101 | #if enabled profiler add it
102 | ifdef LIBRARY_PROFILER
103 | LOCAL_CFLAGS += -pg -g -DPROFILER
104 | LOCAL_STATIC_LIBRARIES += andprof
105 | LOCAL_REQUIRED_MODULES += andprof
106 | endif
107 |
108 | LOCAL_CFLAGS += -DLIBYUV
109 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/libyuv/include
110 | LOCAL_CPP_INCLUDES += $(LOCAL_PATH)/libyuv/include
111 | LOCAL_STATIC_LIBRARIES += libyuv_static
112 | LOCAL_REQUIRED_MODULES += libyuv_static
113 |
114 | ifdef MODULE_ENCRYPT
115 | LOCAL_CFLAGS += -DMODULE_ENCRYPT
116 | LOCAL_SRC_FILES += application/aes-protocol.c
117 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/tropicssl/include
118 | LOCAL_STATIC_LIBRARIES += tropicssl
119 | LOCAL_REQUIRED_MODULES += tropicssl
120 | endif
121 |
122 | LOCAL_LDLIBS += -landroid
123 | LOCAL_LDLIBS += -llog -ljnigraphics -lz -lm -g $(LOCAL_PATH)/ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg.so
124 | include $(BUILD_SHARED_LIBRARY)
125 |
126 |
127 | ifdef FEATURE_NEON
128 | include $(CLEAR_VARS)
129 | LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
130 | LOCAL_MODULE := ffmpeg-jni-neon
131 | LOCAL_SRC_FILES := application/ffmpeg-jni.c application/player.c application/queue.c \
132 | application/helpers.c application/jni-protocol.c application/blend.c \
133 | application/convert.cpp
134 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/ffmpeg-build/$(TARGET_ARCH_ABI)/include \
135 | $(LOCAL_PATH)/application
136 | LOCAL_SHARED_LIBRARY := ffmpeg-prebuilt-neon
137 |
138 | ifdef SUBTITLES
139 | LOCAL_CFLAGS += -DSUBTITLES
140 | endif
141 |
142 | #if enabled profiler add it
143 | ifdef LIBRARY_PROFILER
144 | LOCAL_CFLAGS += -pg -g -DPROFILER
145 | LOCAL_STATIC_LIBRARIES += andprof
146 | LOCAL_REQUIRED_MODULES += andprof
147 | endif
148 |
149 | LOCAL_CFLAGS += -DLIBYUV
150 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/libyuv/include
151 | LOCAL_CPP_INCLUDES += $(LOCAL_PATH)/libyuv/include
152 | LOCAL_STATIC_LIBRARIES += libyuv_static
153 | LOCAL_REQUIRED_MODULES += libyuv_static
154 |
155 | ifdef MODULE_ENCRYPT
156 | LOCAL_CFLAGS += -DMODULE_ENCRYPT
157 | LOCAL_SRC_FILES += application/aes-protocol.c
158 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/tropicssl/include
159 | LOCAL_STATIC_LIBRARIES += tropicssl
160 | LOCAL_REQUIRED_MODULES += tropicssl
161 | endif
162 |
163 | LOCAL_LDLIBS += -landroid
164 | LOCAL_LDLIBS += -llog -ljnigraphics -lz -lm -g $(LOCAL_PATH)/ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg-neon.so
165 | include $(BUILD_SHARED_LIBRARY)
166 | else
167 | include $(CLEAR_VARS)
168 | LOCAL_MODULE := ffmpeg-jni-neon
169 | LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
170 | include $(BUILD_SHARED_LIBRARY)
171 | endif
172 |
173 | #nativetester-jni library
174 | include $(CLEAR_VARS)
175 |
176 | ifdef FEATURE_VFPV3
177 | LOCAL_CFLAGS += -DFEATURE_VFPV3
178 | endif
179 |
180 | ifdef FEATURE_NEON
181 | LOCAL_CFLAGS += -DFEATURE_NEON
182 | endif
183 |
184 | LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
185 | LOCAL_MODULE := nativetester-jni
186 | LOCAL_SRC_FILES := application/nativetester-jni.c application/nativetester.c
187 | LOCAL_STATIC_LIBRARIES := cpufeatures
188 | LOCAL_LDLIBS := -llog
189 | include $(BUILD_SHARED_LIBRARY)
190 |
191 | #includes
192 | ifdef MODULE_ENCRYPT
193 | include $(LOCAL_PATH)/Android-tropicssl.mk
194 | endif
195 |
196 | ifdef LIBRARY_PROFILER
197 | include $(LOCAL_PATH)/android-ndk-profiler-3.1/android-ndk-profiler.mk
198 | endif
199 |
200 | include $(call all-makefiles-under,$(LOCAL_PATH))
201 | $(call import-module,android/cpufeatures)
202 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/Application.mk:
--------------------------------------------------------------------------------
1 | # Application.mk
2 | # Copyright (c) 2018 Matthew Ng
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 | APP_OPTIM := release
17 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/android-ndk-profiler-3.1/android-ndk-profiler.mk:
--------------------------------------------------------------------------------
1 | TARGET_thumb_release_CFLAGS := $(filter-out -ffunction-sections,$(TARGET_thumb_release_CFLAGS))
2 | TARGET_thumb_release_CFLAGS := $(filter-out -fomit-frame-pointer,$(TARGET_thumb_release_CFLAGS))
3 | TARGET_arm_release_CFLAGS := $(filter-out -ffunction-sections,$(TARGET_arm_release_CFLAGS))
4 | TARGET_arm_release_CFLAGS := $(filter-out -fomit-frame-pointer,$(TARGET_arm_release_CFLAGS))
5 | TARGET_CFLAGS := $(filter-out -ffunction-sections,$(TARGET_CFLAGS))
6 |
7 | # include libandprof.a in the build
8 | include $(CLEAR_VARS)
9 | LOCAL_MODULE := andprof
10 | LOCAL_SRC_FILES := android-ndk-profiler-3.1/$(TARGET_ARCH_ABI)/libandprof.a
11 | include $(PREBUILT_STATIC_LIBRARY)
12 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/android-ndk-profiler-3.1/armeabi-v7a/libandprof.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/VPlayer_lib/06d20ba3c24e3c01e8025ff26687d4afa8e017c4/VPlayer_library/jni/android-ndk-profiler-3.1/armeabi-v7a/libandprof.a
--------------------------------------------------------------------------------
/VPlayer_library/jni/android-ndk-profiler-3.1/armeabi/libandprof.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matthewn4444/VPlayer_lib/06d20ba3c24e3c01e8025ff26687d4afa8e017c4/VPlayer_library/jni/android-ndk-profiler-3.1/armeabi/libandprof.a
--------------------------------------------------------------------------------
/VPlayer_library/jni/android-ndk-profiler-3.1/prof.h:
--------------------------------------------------------------------------------
1 | #ifndef prof_h_seen
2 | #define prof_h_seen
3 | #ifdef __cplusplus
4 | extern "C" {
5 | #endif
6 |
7 | void monstartup(const char *libname);
8 | void moncleanup(void);
9 |
10 | #ifdef __cplusplus
11 | }
12 | #endif
13 | #endif
14 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/aes-protocol.c:
--------------------------------------------------------------------------------
1 | /*
2 | * aes-protocol.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "ffmpeg/libavformat/url.h"
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "aes-protocol.h"
31 |
32 | #define FALSE (0)
33 | #define TRUE (!FALSE)
34 |
35 | #include
36 | #define LOG_LEVEL 2
37 | #define LOG_TAG "aes-protocol.c"
38 | #define LOGI(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}
39 | #define LOGE(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);}
40 |
41 | #define RAW_KEY_SIZE 24
42 | #define BASE64_KEY_SIZE ((4 * RAW_KEY_SIZE) / 3)
43 | #define SHA256_KEY_SIZE 32
44 | #define AES_KEY_SIZE 16
45 | #define BUFFER_SIZE 512
46 |
47 | typedef struct {
48 | const AVClass *class;
49 | URLContext *hd;
50 | uint8_t *key;
51 | aes_context aes;
52 | unsigned char iv[AES_KEY_SIZE];
53 | unsigned char read_buff[BUFFER_SIZE];
54 | unsigned char decoded_buff[BUFFER_SIZE];
55 | int64_t reading_position;
56 | int64_t read_start_point;
57 | int64_t read_end_point;
58 | int64_t stream_end;
59 | } AesContext;
60 |
61 | #define OFFSET(x) offsetof(AesContext, x)
62 |
63 | static const AVOption options[] = { { "aeskey", "AES decryption key",
64 | OFFSET(key), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_DECODING_PARAM },
65 | { NULL } };
66 |
67 | static const AVClass aes_class = { .class_name = "aes", .item_name =
68 | av_default_item_name, .option = options, .version =
69 | LIBAVUTIL_VERSION_INT, };
70 |
71 | #define MAX_PRINT_LEN 2048
72 |
73 | #if LOG_LEVEL >= 10
74 | static char print_buff[MAX_PRINT_LEN * 2 + 1];
75 | #endif
76 |
77 | static void log_hex(char *log, char *data, int len) {
78 | #if LOG_LEVEL >= 10
79 | int i;
80 | if (len > MAX_PRINT_LEN) {
81 | LOGI(1,
82 | "log_hex: oversized log requested: %d, max size: %d", len, MAX_PRINT_LEN);
83 | len = MAX_PRINT_LEN;
84 | }
85 | for (i = 0; i < len; ++i)
86 | sprintf(&print_buff[i * 2], "%02X", (unsigned char) data[i]);
87 | LOGI(10, log, len, print_buff);
88 | #endif
89 | }
90 |
91 | static int aes_open(URLContext *h, const char *uri, int flags) {
92 | const char *nested_url;
93 | int ret = 0;
94 | AesContext *c = h->priv_data;
95 | LOGI(3, "aes_open: opening data");
96 |
97 | if (!av_strstart(uri, "aes+", &nested_url)
98 | && !av_strstart(uri, "aes:", &nested_url)) {
99 | av_log(h, AV_LOG_ERROR, "Unsupported url %s", uri);
100 | LOGE(1, "Unsupported url %s", uri);
101 | ret = AVERROR(EINVAL);
102 | goto err;
103 | }
104 |
105 | if (c->key == NULL) {
106 | av_log(h, AV_LOG_ERROR, "Key is not set\n");
107 | LOGE(1, "Key is not set");
108 | ret = AVERROR(EINVAL);
109 | goto err;
110 | }
111 | if (strlen(c->key) != BASE64_KEY_SIZE) {
112 | av_log(h, AV_LOG_ERROR, "Wrong size of key\n");
113 | LOGE(1, "Wrong size of key");
114 | ret = AVERROR(EINVAL);
115 | goto err;
116 | }
117 | if (flags & AVIO_FLAG_WRITE) {
118 | av_log(h, AV_LOG_ERROR, "Only decryption is supported currently\n");
119 | LOGE(1, "Only decryption is supported currently");
120 | ret = AVERROR(ENOSYS);
121 | goto err;
122 | }
123 | if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ,
124 | &h->interrupt_callback, NULL)) < 0) {
125 | av_log(h, AV_LOG_ERROR, "Unable to open input\n");
126 | LOGE(1, "Unable to open input");
127 | goto err;
128 | }
129 | LOGI(3, "aes_open: opened data with key: %s", c->key);
130 | log_hex("aes_open: raw_key[%d]: %s", c->key, RAW_KEY_SIZE);
131 |
132 | memset(c->iv, 0, AES_KEY_SIZE);
133 | memset(c->read_buff, 0, BUFFER_SIZE);
134 | memset(c->decoded_buff, 0, BUFFER_SIZE);
135 | c->reading_position = 0;
136 | c->read_start_point = 0;
137 | c->read_end_point = 0;
138 | c->stream_end = -1;
139 |
140 | unsigned char sha256_key[SHA256_KEY_SIZE];
141 | sha2_context ctx;
142 | sha2_starts(&ctx, 0);
143 | sha2_update(&ctx, c->key, BASE64_KEY_SIZE);
144 | sha2_finish(&ctx, sha256_key);
145 | log_hex("aes_open: sha256_key[%d]: %s", sha256_key, SHA256_KEY_SIZE);
146 |
147 | unsigned char aes_key[AES_KEY_SIZE];
148 | memcpy(aes_key, sha256_key, AES_KEY_SIZE);
149 |
150 | log_hex("aes_open: aes_key[%d]: %s", aes_key, AES_KEY_SIZE);
151 |
152 | aes_setkey_dec(&c->aes, aes_key, AES_KEY_SIZE << 3);
153 |
154 | // h->is_streamed = 1; // disable seek
155 | LOGI(3, "aes_open: finished opening");
156 | err: return ret;
157 | }
158 |
159 | static int64_t aes_seek(URLContext *h, int64_t pos, int whence) {
160 | AesContext *c = h->priv_data;
161 | LOGI(3, "aes_seek: trying to seek");
162 | switch (whence) {
163 | case SEEK_SET:
164 | LOGI(3, "aes_seek: pos: %"PRId64", SEEK_SET", pos);
165 | // The offset is set to offset bytes.
166 | c->reading_position = pos;
167 | break;
168 |
169 | case SEEK_CUR:
170 | LOGI(3, "aes_seek: pos: %"PRId64", SEEK_CUR", pos);
171 | // The offset is set to its current location plus offset bytes.
172 | c->reading_position += pos;
173 | break;
174 |
175 | case AVSEEK_SIZE:
176 | // Measuring file size
177 | LOGI(3, "aes_seek: AVSEEK_SIZE");
178 | if (c->stream_end >= 0) {
179 | LOGI(3, "aes_seek: already_measured_size: %"PRId64, c->stream_end);
180 | return c->stream_end;
181 | }
182 | c->stream_end = ffurl_seek(c->hd, 0, AVSEEK_SIZE);
183 | LOGI(3, "aes_seek: measured_size: %"PRId64, c->stream_end);
184 | return c->stream_end;
185 |
186 | case SEEK_END:
187 | LOGI(3, "aes_seek: pos: %d, SEEK_END", pos);
188 | // The offset is set to the size of the file plus offset bytes.
189 | if (c->stream_end < 0) {
190 | c->stream_end = ffurl_seek(c->hd, 0, AVSEEK_SIZE);
191 | if (c->stream_end < 0) {
192 | LOGE(2,
193 | "aes_seek: could not measure size, error: %"PRId64, c->stream_end);
194 | return c->stream_end;
195 | }
196 | }
197 | LOGI(3, "aes_seek: measured_size: %"PRId64, c->stream_end);
198 | c->reading_position = c->stream_end - pos;
199 | break;
200 | default:
201 | LOGE(1, "aes_seek: unknown whence: %d", whence);
202 | return -1;
203 | }
204 | LOGI(3, "aes_seek: reading_position: %" PRId64, c->reading_position);
205 |
206 | c->read_start_point = (c->reading_position / (int64_t) BUFFER_SIZE)
207 | * (int64_t) BUFFER_SIZE;
208 | c->read_end_point = c->read_start_point;
209 | LOGI(3, "aes_seek: read_start_point: %" PRId64, c->read_start_point);
210 |
211 | int64_t ret = ffurl_seek(c->hd, c->read_start_point, whence);
212 | LOGI(3, "aes_seek: return: %"PRId64, ret);
213 | if (ret < 0) {
214 | LOGE(1,
215 | "aes_seek: seeking error: %"PRId64", trying to seek: %"PRId64", whence: %d", ret, c->read_start_point, whence);
216 | return ret;
217 | }
218 | if (ret != c->read_start_point) {
219 | LOGE(1, "aes_seek: seeking fatal error: unknown state");
220 | return -2;
221 | }
222 | return c->reading_position;
223 | }
224 |
225 | static int aes_read(URLContext *h, uint8_t *buf, int size) {
226 | AesContext *c = h->priv_data;
227 |
228 | int buf_position = 0;
229 | int buf_left = size;
230 | int end = FALSE;
231 | LOGI(3, "aes_read started");
232 |
233 | while (buf_left > 0 && !end) {
234 | LOGI(3,
235 | "aes_read loop, read_position: %"PRId64", buf_left: %d", c->reading_position, buf_left);
236 | if (c->reading_position < c->read_start_point) {
237 | LOGE(1, "aes_read reading error");
238 | return -1;
239 | }
240 |
241 | while (c->reading_position >= c->read_end_point && !end) {
242 | LOGI(3,
243 | "aes_read read loop: current read_end_point %"PRId64, c->read_end_point);
244 | int64_t position = c->read_end_point;
245 |
246 | int decode_buf_left = BUFFER_SIZE;
247 | int encrypted_buffer_size = 0;
248 | while (decode_buf_left > 0 && !end) {
249 | int n = ffurl_read(c->hd,
250 | &(c->read_buff[encrypted_buffer_size]),
251 | decode_buf_left);
252 |
253 | if (n < 0)
254 | return n;
255 |
256 | if (n == 0)
257 | end = TRUE;
258 |
259 | decode_buf_left -= n;
260 | encrypted_buffer_size += n;
261 | }
262 | c->read_start_point = c->read_end_point;
263 | c->read_end_point += encrypted_buffer_size;
264 |
265 | // Inflight magic trick - LOL
266 | *(int *) &c->iv[0] = (int) (c->read_start_point >> 9);
267 | memset(&c->iv[4], 0, sizeof(c->iv) - 4);
268 | aes_crypt_cbc(&c->aes, AES_DECRYPT, encrypted_buffer_size, c->iv,
269 | c->read_buff, c->decoded_buff);
270 | LOGI(3, "aes_read enc: position: %"PRId64, position);
271 | log_hex("aes_read enc: encoded[%d]: %s", c->read_buff,
272 | encrypted_buffer_size);
273 | log_hex("aes_read enc: decoded[%d]: %s", c->decoded_buff,
274 | encrypted_buffer_size);
275 | }
276 | int delta = c->reading_position - c->read_start_point;
277 | int copy_size = c->read_end_point - c->reading_position;
278 | if (copy_size > buf_left)
279 | copy_size = buf_left;
280 |
281 | LOGI(10, "aes_read delta: %d, copy_size: %d", delta, copy_size);
282 | memcpy(&buf[buf_position], &c->decoded_buff[delta], copy_size);
283 | c->reading_position += copy_size;
284 | buf_left -= copy_size;
285 | buf_position += copy_size;
286 | }
287 | LOGI(3, "aes_read read bytes: %d", buf_position);
288 | log_hex("eas_read wrote to buffer[%d]: %s", buf, buf_position);
289 | LOGI(3, "aes_read write success");
290 | return buf_position;
291 | }
292 |
293 | static int aes_close(URLContext *h) {
294 | AesContext *c = h->priv_data;
295 | if (c->hd)
296 | ffurl_close(c->hd);
297 | return 0;
298 | }
299 |
300 | URLProtocol aes_protocol = { .name = "aes", .url_open = aes_open, .url_read =
301 | aes_read, .url_close = aes_close, .url_seek = aes_seek,
302 | .priv_data_size = sizeof(AesContext), .priv_data_class = &aes_class,
303 | .flags = URL_PROTOCOL_FLAG_NESTED_SCHEME, };
304 |
305 | void register_aes_protocol() {
306 | ffurl_register_protocol(&aes_protocol);
307 | }
308 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/aes-protocol.h:
--------------------------------------------------------------------------------
1 | /*
2 | * aes-protocol.h
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #ifndef AES_PROTOCOL_H
20 | #define AES_PROTOCOL_H
21 |
22 | void register_aes_protocol();
23 |
24 | #endif /* H_AES_PROTOCOL */
25 |
26 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/blend.c:
--------------------------------------------------------------------------------
1 | /*
2 | * blend.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #ifdef SUBTITLES
20 |
21 | #include "blend.h"
22 | #include
23 |
24 | #define RGBA_IN(r, g, b, a, s)\
25 | {\
26 | unsigned int v = ((const uint32_t *)(s))[0];\
27 | a = (v >> 24) & 0xff;\
28 | r = (v >> 16) & 0xff;\
29 | g = (v >> 8) & 0xff;\
30 | b = v & 0xff;\
31 | }
32 |
33 | #define RGB565_IN(r, g, b, s)\
34 | {\
35 | unsigned int v = ((const uint16_t *)(s))[0];\
36 | r = (v >> 11) & 0x1f;\
37 | g = (v >> 5) & 0x3f;\
38 | b = v & 0x1f;\
39 | }
40 |
41 | #define RGB565_OUT(d, r, g, b)\
42 | {\
43 | ((uint16_t *)(d))[0] = (r << 11) | (g << 5) | b;\
44 | }
45 |
46 | #define RGBA_OUT(d, r, g, b, a)\
47 | {\
48 | ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
49 | }
50 |
51 | #define ALPHA_BLEND_RGB(color1, color2, alpha)\
52 | (((color1 * (0xff - alpha)) + (color2 * alpha))/0xff)
53 |
54 | #define AR(c) ( (c)>>24)
55 | #define AG(c) (((c)>>16)&0xFF)
56 | #define AB(c) (((c)>>8) &0xFF)
57 | #define AA(c) ((0xFF-c) &0xFF)
58 |
59 | void blend_ass_image(AVPicture *dest, const ASS_Image *image, int imgw,
60 | int imgh, enum PixelFormat pixel_format) {
61 | uint8_t rgba_color[] = { AR(image->color), AG(image->color), AB(
62 | image->color), AA(image->color) };
63 | uint8_t rect_r, rect_g, rect_b, rect_a;
64 | int dest_r, dest_g, dest_b, dest_a;
65 | int x, y;
66 | uint32_t *dst2;
67 | uint8_t *src, *src2;
68 | uint8_t *dst = dest->data[0];
69 |
70 | if (pixel_format != PIX_FMT_RGBA)
71 | return;
72 |
73 | dst += image->dst_y * dest->linesize[0] + image->dst_x * 4;
74 | src = image->bitmap;
75 | for (y = 0; y < image->h; y++) {
76 | dst2 = (uint32_t *) dst;
77 | src2 = src;
78 | for (x = 0; x < image->w; x++) {
79 | uint8_t image_pixel = *(src2++);
80 | uint32_t *pixel = (dst2++);
81 |
82 | rect_r = image_pixel & rgba_color[0];
83 | rect_g = image_pixel & rgba_color[1];
84 | rect_b = image_pixel & rgba_color[2];
85 | rect_a = image_pixel & rgba_color[3];
86 |
87 | RGBA_IN(dest_r, dest_g, dest_b, dest_a, pixel);
88 |
89 | // write subtitle on the image
90 | dest_r = ALPHA_BLEND_RGB(dest_r, rect_r, rect_a);
91 | dest_g = ALPHA_BLEND_RGB(dest_g, rect_g, rect_a);
92 | dest_b = ALPHA_BLEND_RGB(dest_b, rect_b, rect_a);
93 |
94 | RGBA_OUT(pixel, dest_r, dest_g, dest_b, dest_a);
95 | }
96 | dst += dest->linesize[0];
97 | src += image->stride;
98 | }
99 | }
100 |
101 | void blend_subrect_rgba(AVPicture *dest, const AVSubtitleRect *rect, int imgw,
102 | int imgh, enum PixelFormat pixel_format) {
103 | int rect_r, rect_g, rect_b, rect_a;
104 | int dest_r, dest_g, dest_b, dest_a;
105 | uint32_t *pal;
106 | uint32_t *dst2;
107 | uint8_t *src, *src2;
108 | int x, y;
109 | uint8_t *dst = dest->data[0];
110 |
111 | if (pixel_format != PIX_FMT_RGBA)
112 | return;
113 |
114 | dst += rect->y * dest->linesize[0] + rect->x * 4;
115 | src = rect->pict.data[0];
116 | pal = (uint32_t *) rect->pict.data[1];
117 |
118 | for (y = 0; y < rect->h; y++) {
119 | dst2 = (uint32_t *) dst;
120 | src2 = src;
121 | for (x = 0; x < rect->w; x++) {
122 | uint32_t *rect_pixel = &pal[*(src2++)];
123 | uint32_t *pixel = (dst2++);
124 |
125 | // read subtitle rgba8888
126 | RGBA_IN(rect_r, rect_g, rect_b, rect_a, rect_pixel);
127 |
128 | RGBA_IN(dest_r, dest_g, dest_b, dest_a, pixel);
129 |
130 | // write subtitle on the image
131 | dest_r = ALPHA_BLEND_RGB(dest_r, rect_r, rect_a);
132 | dest_g = ALPHA_BLEND_RGB(dest_g, rect_g, rect_a);
133 | dest_b = ALPHA_BLEND_RGB(dest_b, rect_b, rect_a);
134 |
135 | RGBA_OUT(pixel, dest_r, dest_g, dest_b, dest_a);
136 | }
137 | dst += dest->linesize[0];
138 | src += rect->pict.linesize[0];
139 | }
140 | }
141 |
142 | #endif /* SUBTITLES */
143 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/blend.h:
--------------------------------------------------------------------------------
1 | /*
2 | * blend.h
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | // Comment to ignore subtitles
20 | #ifdef SUBTITLES
21 | #ifndef BLEND_H_
22 | #define BLEND_H_
23 |
24 | #include
25 |
26 | #include
27 |
28 | void blend_ass_image(AVPicture *dest, const ASS_Image *image, int imgw,
29 | int imgh, enum PixelFormat pixel_format);
30 | void blend_subrect_rgba(AVPicture *dest, const AVSubtitleRect *rect, int imgw,
31 | int imgh, enum PixelFormat pixel_format);
32 |
33 | #endif /* BLEND_H_ */
34 | #endif /* SUBTITLES */
35 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/convert.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | extern "C" {
7 | int __I420ToARGB(const uint8* src_y, int src_stride_y,
8 | const uint8* src_u, int src_stride_u,
9 | const uint8* src_v, int src_stride_v,
10 | uint8* dst_argb, int dst_stride_argb,
11 | int width, int height) {
12 | return libyuv::I420ToARGB(src_y,src_stride_y,
13 | src_u, src_stride_u,
14 | src_v, src_stride_v,
15 | dst_argb, dst_stride_argb,
16 | width, height);
17 | }
18 |
19 | int __NV12ToARGB(const uint8* src_y, int src_stride_y,
20 | const uint8* src_uv, int src_stride_uv,
21 | uint8* dst_argb, int dst_stride_argb,
22 | int width, int height) {
23 | return libyuv::NV12ToARGB(src_y, src_stride_y,
24 | src_uv, src_stride_uv,
25 | dst_argb, dst_stride_argb,
26 | width, height);
27 | }
28 |
29 | int __NV21ToARGB(const uint8* src_y, int src_stride_y,
30 | const uint8* src_uv, int src_stride_uv,
31 | uint8* dst_argb, int dst_stride_argb,
32 | int width, int height) {
33 | return libyuv::NV21ToARGB(src_y, src_stride_y,
34 | src_uv, src_stride_uv,
35 | dst_argb, dst_stride_argb,
36 | width, height);
37 | }
38 |
39 | int __BGRAToARGB(const uint8* src_frame, int src_stride_frame,
40 | uint8* dst_argb, int dst_stride_argb,
41 | int width, int height) {
42 | return libyuv::BGRAToARGB(src_frame, src_stride_frame,
43 | dst_argb, dst_stride_argb,
44 | width, height);
45 | }
46 |
47 | int __ARGBCopy(const uint8* src_argb, int src_stride_argb,
48 | uint8* dst_argb, int dst_stride_argb,
49 | int width, int height) {
50 | return libyuv::ARGBCopy(src_argb, src_stride_argb,
51 | dst_argb, dst_stride_argb,
52 | width, height);
53 | }
54 |
55 | int __ARGBScale(const uint8* src_argb, int src_stride_argb,
56 | int src_width, int src_height,
57 | uint8* dst_argb, int dst_stride_argb,
58 | int dst_width, int dst_height,
59 | enum __FilterMode filtering) {
60 | libyuv::FilterMode filterMode = static_cast(filtering);
61 | return libyuv::ARGBScale(src_argb, src_stride_argb,
62 | src_width, src_height,
63 | dst_argb, dst_stride_argb,
64 | dst_width, dst_height,
65 | filterMode);
66 | }
67 |
68 | int __ARGBToRGBA(const uint8* src_frame, int src_stride_frame,
69 | uint8* dst_argb, int dst_stride_argb,
70 | int width, int height) {
71 | return libyuv::ARGBToRGBA(src_frame, src_stride_frame,
72 | dst_argb, dst_stride_argb,
73 | width, height);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/convert.h:
--------------------------------------------------------------------------------
1 | #ifndef CONVERT_H_
2 | #define CONVERT_H_
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | #include
9 |
10 | enum __FilterMode {
11 | __kFilterNone = 0, // Point sample; Fastest.
12 | __kFilterBilinear = 1, // Faster than box, but lower quality scaling down.
13 | __kFilterBox = 2 // Highest quality.
14 | };
15 |
16 | int __I420ToARGB(const uint8* src_y, int src_stride_y,
17 | const uint8* src_u, int src_stride_u,
18 | const uint8* src_v, int src_stride_v,
19 | uint8* dst_argb, int dst_stride_argb,
20 | int width, int height);
21 |
22 | int __NV12ToARGB(const uint8* src_y, int src_stride_y,
23 | const uint8* src_uv, int src_stride_uv,
24 | uint8* dst_argb, int dst_stride_argb,
25 | int width, int height);
26 | int __NV21ToARGB(const uint8* src_y, int src_stride_y,
27 | const uint8* src_uv, int src_stride_uv,
28 | uint8* dst_argb, int dst_stride_argb,
29 | int width, int height);
30 | int __BGRAToARGB(const uint8* src_frame, int src_stride_frame,
31 | uint8* dst_argb, int dst_stride_argb,
32 | int width, int height);
33 | int __ARGBCopy(const uint8* src_argb, int src_stride_argb,
34 | uint8* dst_argb, int dst_stride_argb,
35 | int width, int height);
36 |
37 | int __ARGBScale(const uint8* src_argb, int src_stride_argb,
38 | int src_width, int src_height,
39 | uint8* dst_argb, int dst_stride_argb,
40 | int dst_width, int dst_height,
41 | enum __FilterMode filtering);
42 |
43 | int __ARGBToRGBA(const uint8* src_frame, int src_stride_frame,
44 | uint8* dst_argb, int dst_stride_argb,
45 | int width, int height);
46 | #ifdef __cplusplus
47 | }
48 | #endif
49 |
50 | #endif /* CONVERT_H_ */
51 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/ffmpeg-jni.c:
--------------------------------------------------------------------------------
1 | /*
2 | * ffmpeg-jni.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | /*android specific headers*/
20 | #include
21 | #include
22 | /*standard library*/
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 |
33 | #include "helpers.h"
34 | #include "player.h"
35 |
36 | /*for android logs*/
37 | #define LOG_TAG "FFmpegTest"
38 | #define LOG_LEVEL 10
39 | #define LOGI(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}
40 | #define LOGE(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);}
41 |
42 | #ifndef NELEM
43 | #define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0])))
44 | #endif
45 |
46 | static int register_native_methods(JNIEnv* env,
47 | const char* class_name,
48 | JNINativeMethod* methods,
49 | int num_methods)
50 | {
51 | jclass clazz;
52 |
53 | clazz = (*env)->FindClass(env, class_name);
54 | if (clazz == NULL) {
55 | fprintf(stderr, "Native registration unable to find class '%s'\n",
56 | class_name);
57 | return JNI_FALSE;
58 | }
59 | if ((*env)->RegisterNatives(env, clazz, methods, num_methods) < 0) {
60 | fprintf(stderr, "RegisterNatives failed for '%s'\n", class_name);
61 | return JNI_FALSE;
62 | }
63 |
64 | return JNI_TRUE;
65 | }
66 |
67 | jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
68 | {
69 | JNIEnv* env = NULL;
70 | jint result = -1;
71 |
72 | if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
73 | fprintf(stderr, "ERROR: GetEnv failed\n");
74 | goto bail;
75 | }
76 | assert(env != NULL);
77 |
78 | if (register_native_methods(env,
79 | player_class_path_name,
80 | player_methods,
81 | NELEM(player_methods)) < 0) {
82 | fprintf(stderr, "ERROR: Exif native registration failed\n");
83 | goto bail;
84 | }
85 |
86 | /* success -- return valid version number */
87 | result = JNI_VERSION_1_6;
88 |
89 | bail:
90 | return result;
91 | }
92 |
93 | void JNI_OnUnload(JavaVM *vm, void *reserved)
94 | {
95 | }
96 |
97 |
98 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/helpers.c:
--------------------------------------------------------------------------------
1 | /*
2 | * helpers.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #include
20 |
21 | #include "helpers.h"
22 |
23 | jfieldID java_get_field(JNIEnv *env, char * class_name, JavaField field) {
24 | jclass clazz = (*env)->FindClass(env, class_name);
25 | jfieldID jField = (*env)->GetFieldID(env, clazz, field.name, field.signature);
26 | (*env)->DeleteLocalRef(env, clazz);
27 | return jField;
28 | }
29 |
30 | jmethodID java_get_method(JNIEnv *env, jclass class, JavaMethod method) {
31 | return (*env)->GetMethodID(env, class, method.name, method.signature);
32 | }
33 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/helpers.h:
--------------------------------------------------------------------------------
1 | /*
2 | * helpers.h
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #ifndef HELPERS_H_
20 | #define HELPERS_H_
21 |
22 | typedef struct {
23 | const char* name;
24 | const char* signature;
25 | } JavaMethod;
26 |
27 | typedef struct {
28 | char* name;
29 | char* signature;
30 | } JavaField;
31 |
32 | jfieldID java_get_field(JNIEnv *env, char * class_name, JavaField field);
33 | jmethodID java_get_method(JNIEnv *env, jclass class, JavaMethod method);
34 |
35 |
36 | #endif /* HELPERS_H_ */
37 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/jni-protocol.c:
--------------------------------------------------------------------------------
1 | /*
2 | * jni-protocol.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "ffmpeg/libavformat/url.h"
24 |
25 | #include "jni-protocol.h"
26 |
27 | static const char *jni_reader_class_name = JAVA_PACKAGE_PATH"/JniReader";
28 | static JavaVM *global_jvm;
29 |
30 | static int jni_read(URLContext *h, unsigned char *buf, int size) {
31 | int err = 0;
32 | JNIEnv* env;
33 | jclass jni_reader_class;
34 | jmethodID jni_reader_read;
35 | jobject jni_reader;
36 | jbyteArray byte_array;
37 | jbyte *jni_samples;
38 | if ((*global_jvm)->GetEnv(global_jvm, (void**) &env, JNI_VERSION_1_6)) {
39 | err = -1;
40 | goto end;
41 | }
42 | if (env == NULL) {
43 | err = -1;
44 | goto end;
45 | }
46 |
47 | jni_reader_class = (*env)->FindClass(env, jni_reader_class_name);
48 | if (jni_reader_class == NULL) {
49 | err = -1;
50 | goto end;
51 | }
52 |
53 | jni_reader_read = (*env)->GetMethodID(env, jni_reader_class, "read",
54 | "([B)I");
55 | if (jni_reader_read == NULL) {
56 | err = -1;
57 | goto end;
58 | }
59 |
60 | jni_reader = (jobject) h->priv_data;
61 |
62 | byte_array = (*env)->NewByteArray(env, size);
63 |
64 | err = (*env)->CallIntMethod(env, jni_reader, jni_reader_read, byte_array);
65 |
66 | jni_samples = (*env)->GetByteArrayElements(env, byte_array, NULL);
67 | memcpy(buf, jni_samples, size);
68 | (*env)->ReleaseByteArrayElements(env, byte_array, jni_samples, 0);
69 |
70 | (*env)->DeleteLocalRef(env, byte_array);
71 |
72 | end: return err >= 0 ? err : AVERROR(err);
73 | }
74 |
75 | static int jni_write(URLContext *h, const unsigned char *buf, int size) {
76 | int err = 0;
77 | JNIEnv* env;
78 | jclass jni_reader_class;
79 | jmethodID jni_reader_write;
80 | jobject jni_reader;
81 | jbyteArray byte_array;
82 | jbyte *jni_samples;
83 | if ((*global_jvm)->GetEnv(global_jvm, (void**) &env, JNI_VERSION_1_6)) {
84 | err = -1;
85 | goto end;
86 | }
87 | if (env == NULL) {
88 | err = -1;
89 | goto end;
90 | }
91 |
92 | jni_reader_class = (*env)->FindClass(env, jni_reader_class_name);
93 | if (jni_reader_class == NULL) {
94 | err = -1;
95 | goto end;
96 | }
97 |
98 | jni_reader_write = (*env)->GetMethodID(env, jni_reader_class, "write",
99 | "([B)I");
100 | if (jni_reader_write == NULL) {
101 | err = -1;
102 | goto end;
103 | }
104 |
105 | jni_reader = (jobject) h->priv_data;
106 |
107 | byte_array = (*env)->NewByteArray(env, size);
108 |
109 | jni_samples = (*env)->GetByteArrayElements(env, byte_array, NULL);
110 | memcpy(jni_samples, buf, size);
111 | (*env)->ReleaseByteArrayElements(env, byte_array, jni_samples, 0);
112 |
113 | err = (*env)->CallIntMethod(env, jni_reader, jni_reader_write, byte_array);
114 |
115 | (*env)->DeleteLocalRef(env, byte_array);
116 |
117 | end: return err >= 0 ? err : AVERROR(err);
118 | }
119 |
120 | static int jni_get_handle(URLContext *h) {
121 | return (intptr_t) h->priv_data;
122 | }
123 |
124 | static int jni_check(URLContext *h, int mask) {
125 | int err = 0;
126 | JNIEnv* env;
127 | jclass jni_reader_class;
128 | jmethodID jni_reader_check;
129 | jobject jni_reader;
130 |
131 | if ((*global_jvm)->GetEnv(global_jvm, (void**) &env, JNI_VERSION_1_6)) {
132 | err = -1;
133 | goto end;
134 | }
135 | if (env == NULL) {
136 | err = -1;
137 | goto end;
138 | }
139 |
140 | jni_reader_class = (*env)->FindClass(env, jni_reader_class_name);
141 | if (jni_reader_class == NULL) {
142 | err = -1;
143 | goto end;
144 | }
145 |
146 | jni_reader_check = (*env)->GetMethodID(env, jni_reader_class, "check",
147 | "(I)I");
148 | if (jni_reader_check == NULL) {
149 | err = -1;
150 | goto end;
151 | }
152 |
153 | jni_reader = (jobject) h->priv_data;
154 |
155 | err = (*env)->CallIntMethod(env, jni_reader, jni_reader_check, mask);
156 |
157 | end: return err >= 0 ? err : AVERROR(err);
158 | }
159 |
160 | static int jni_open2(URLContext *h, const char *url, int flags,
161 | AVDictionary **options) {
162 | int err = 0;
163 | JNIEnv* env;
164 | jclass jni_reader_class;
165 | jmethodID jni_reader_constructor;
166 | jstring url_java_string;
167 | jobject jni_reader;
168 |
169 | if ((*global_jvm)->GetEnv(global_jvm, (void**) &env, JNI_VERSION_1_6)) {
170 | err = -1;
171 | goto end;
172 | }
173 | if (env == NULL) {
174 | err = -1;
175 | goto end;
176 | }
177 |
178 | jni_reader_class = (*env)->FindClass(env, jni_reader_class_name);
179 | if (jni_reader_class == NULL) {
180 | err = -1;
181 | goto end;
182 | }
183 |
184 | jni_reader_constructor = (*env)->GetMethodID(env, jni_reader_class,
185 | "", "(Ljava/lang/String;I)V");
186 | if (jni_reader_constructor == NULL) {
187 | err = -1;
188 | goto end;
189 | }
190 |
191 | url_java_string = (*env)->NewStringUTF(env, url);
192 |
193 | if (url_java_string == NULL) {
194 | err = -1;
195 | goto end;
196 | }
197 |
198 | jni_reader = (*env)->NewObject(env, jni_reader_class,
199 | jni_reader_constructor, url_java_string, flags);
200 | if (jni_reader == NULL) {
201 | err = -1;
202 | goto free_url_java_string;
203 | }
204 |
205 | h->priv_data = (void *) (*env)->NewGlobalRef(env, jni_reader);
206 | if (h->priv_data == NULL) {
207 | err = -1;
208 | goto free_jni_reader;
209 | }
210 |
211 | free_jni_reader:
212 |
213 | (*env)->DeleteLocalRef(env, jni_reader);
214 |
215 | free_url_java_string:
216 |
217 | (*env)->DeleteLocalRef(env, url_java_string);
218 |
219 | end: return err >= 0 ? err : AVERROR(err);
220 | }
221 |
222 | static int jni_open(URLContext *h, const char *filename, int flags) {
223 | return jni_open2(h, filename, flags, NULL);
224 | }
225 |
226 | static int64_t jni_seek(URLContext *h, int64_t pos, int whence) {
227 | int64_t err = 0;
228 | JNIEnv* env;
229 | jclass jni_reader_class;
230 | jmethodID jni_reader_seek;
231 | jobject jni_reader;
232 |
233 | if ((*global_jvm)->GetEnv(global_jvm, (void**) &env, JNI_VERSION_1_6)) {
234 | err = -1;
235 | goto end;
236 | }
237 | if (env == NULL) {
238 | err = -1;
239 | goto end;
240 | }
241 |
242 | jni_reader_class = (*env)->FindClass(env, jni_reader_class_name);
243 | if (jni_reader_class == NULL) {
244 | err = -1;
245 | goto end;
246 | }
247 |
248 | jni_reader_seek = (*env)->GetMethodID(env, jni_reader_class, "seek",
249 | "(JI)J");
250 | if (jni_reader_seek == NULL) {
251 | err = -1;
252 | goto end;
253 | }
254 |
255 | jni_reader = (jobject) h->priv_data;
256 |
257 | err = (*env)->CallIntMethod(env, jni_reader, jni_reader_seek, pos, whence);
258 |
259 | end: return err >= 0 ? err : AVERROR(err);
260 | }
261 |
262 | static int jni_close(URLContext *h) {
263 | int err = 0;
264 | JNIEnv* env;
265 | jobject jni_reader;
266 |
267 | if ((*global_jvm)->GetEnv(global_jvm, (void**) &env, JNI_VERSION_1_6)) {
268 | err = -1;
269 | goto end;
270 | }
271 | if (env == NULL) {
272 | err = -1;
273 | goto end;
274 | }
275 |
276 | jni_reader = (jobject) h->priv_data;
277 |
278 | (*env)->DeleteGlobalRef(env, jni_reader);
279 |
280 | end: return err >= 0 ? err : AVERROR(err);
281 | }
282 |
283 | URLProtocol jni_protocol = { .name = "jni", .url_open2 = jni_open2,
284 | .url_open = jni_open, .url_read = jni_read, .url_write = jni_write,
285 | .url_seek = jni_seek, .url_close = jni_close, .url_get_file_handle =
286 | jni_get_handle, .url_check = jni_check, };
287 |
288 | void register_jni_protocol(JavaVM *jvm) {
289 | global_jvm = jvm;
290 | ffurl_register_protocol(&jni_protocol);
291 | }
292 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/jni-protocol.h:
--------------------------------------------------------------------------------
1 | /*
2 | * jni-protocol.h
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #ifndef JNI_PROTOCOL_H
20 | #define JNI_PROTOCOL_H
21 |
22 | void register_jni_protocol(JavaVM *jvm);
23 |
24 | #endif /* H_JNI_PROTOCOL */
25 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/jni_helper.h:
--------------------------------------------------------------------------------
1 | #ifndef JNI_HELPER_H_
2 | #define JNI_HELPER_H_
3 |
4 | #include
5 |
6 | // Change package name here
7 | #define JAVA_PACKAGE_PATH "com/vplayer"
8 |
9 | #endif /* JNI_HELPER_H_ */
10 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/nativetester-jni.c:
--------------------------------------------------------------------------------
1 | /*
2 | * nativetester-jni.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | /*android specific headers*/
20 | #include
21 | #include
22 |
23 | #include
24 | #include
25 |
26 | #include "nativetester.h"
27 |
28 | #ifndef NELEM
29 | #define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0])))
30 | #endif
31 |
32 |
33 | #define LOG_TAG "NativeTester-jni"
34 | #define LOG_LEVEL 10
35 | #define LOGI(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}
36 | #define LOGE(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);}
37 |
38 | static int register_native_methods(JNIEnv* env,
39 | const char* class_name,
40 | JNINativeMethod* methods,
41 | int num_methods)
42 | {
43 | jclass clazz;
44 |
45 | clazz = (*env)->FindClass(env, class_name);
46 | if (clazz == NULL) {
47 | LOGE(1, "Native registration unable to find class '%s'\n",
48 | class_name);
49 | return JNI_FALSE;
50 | }
51 | if ((*env)->RegisterNatives(env, clazz, methods, num_methods) < 0) {
52 | LOGE(1, "RegisterNatives failed for '%s'\n", class_name);
53 | return JNI_FALSE;
54 | }
55 |
56 | return JNI_TRUE;
57 | }
58 |
59 | jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
60 | {
61 | JNIEnv* env = NULL;
62 | jint result = -1;
63 |
64 | if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) {
65 | LOGE(1, "ERROR: GetEnv failed\n");
66 | goto bail;
67 | }
68 | assert(env != NULL);
69 |
70 | if (register_native_methods(env,
71 | nativetester_class_path_name,
72 | nativetester_methods,
73 | NELEM(nativetester_methods)) < 0) {
74 | LOGE(1, "ERROR: Exif native registration failed\n");
75 | goto bail;
76 | }
77 |
78 | /* success -- return valid version number */
79 | result = JNI_VERSION_1_6;
80 |
81 | bail:
82 | return result;
83 | }
84 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/nativetester.c:
--------------------------------------------------------------------------------
1 | /*
2 | * nativetester.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | /*android specific headers*/
20 | #include
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | #include "nativetester.h"
27 |
28 |
29 | #define LOG_TAG "NativeTester"
30 | #define LOG_LEVEL 10
31 | #define LOGI(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}
32 | #define LOGE(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);}
33 |
34 | jboolean jni_nativetester_is_neon(JNIEnv *env, jobject thiz) {
35 | uint64_t features;
36 | #ifdef FEATURE_NEON
37 |
38 | if (android_getCpuFamily() != ANDROID_CPU_FAMILY_ARM) {
39 | LOGI(5, "Not an ARM CPU\n");
40 | return JNI_FALSE;
41 | }
42 |
43 | features = android_getCpuFeatures();
44 |
45 | if ((features & ANDROID_CPU_ARM_FEATURE_ARMv7) == 0) {
46 | LOGI(5, "Not an ARMv7 CPU\n");
47 | return JNI_FALSE;
48 | }
49 |
50 | if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) {
51 | LOGI(5, "CPU doesn't support NEON\n");
52 | return JNI_FALSE;
53 | }
54 |
55 | return JNI_TRUE;
56 | #else
57 | return JNI_FALSE;
58 | #endif
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/nativetester.h:
--------------------------------------------------------------------------------
1 | /*
2 | * nativetester.h
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #ifndef NATIVETESTER_H_
20 | #define NATIVETESTER_H_
21 |
22 | #include "jni_helper.h"
23 |
24 | static const char *nativetester_class_path_name = JAVA_PACKAGE_PATH"/NativeTester";
25 |
26 | jboolean jni_nativetester_is_neon(JNIEnv *env, jobject thiz);
27 |
28 |
29 | static JNINativeMethod nativetester_methods[] = {
30 | {"isNeon", "()Z", (void*) jni_nativetester_is_neon},
31 | };
32 |
33 | #endif /* NATIVETESTER_H_ */
34 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/player.h:
--------------------------------------------------------------------------------
1 | /*
2 | * player.h
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #ifndef H_PLAYER
20 | #define H_PLAYER
21 |
22 | #include
23 | #include
24 |
25 | static JavaMethod empty_constructor = {"", "()V"};
26 |
27 | // InterruptedException
28 | static char *interrupted_exception_class_path_name = "java/lang/InterruptedException";
29 |
30 | // RuntimeException
31 | static char *runtime_exception_class_path_name = "java/lang/RuntimeException";
32 |
33 | // NotPlayingException
34 | static char *not_playing_exception_class_path_name = JAVA_PACKAGE_PATH"/exception/NotPlayingException";
35 |
36 | // Object
37 | static char *object_class_path_name = "java/lang/Object";
38 |
39 | // HashMap
40 | static char *hash_map_class_path_name = "java/util/HashMap";
41 | static char *map_class_path_name = "java/util/Map";
42 | static JavaMethod map_key_set = {"keySet", "()Ljava/util/Set;"};
43 | static JavaMethod map_get = {"get", "(Ljava/lang/Object;)Ljava/lang/Object;"};
44 | static JavaMethod map_put = {"put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"};
45 |
46 | // MediaStreamInfo.CodeType
47 | enum CodecType {
48 | CODEC_TYPE_UNKNOWN = 0,
49 | CODEC_TYPE_AUDIO = 1,
50 | CODEC_TYPE_VIDEO = 2,
51 | CODEC_TYPE_SUBTITLE = 3,
52 | CODEC_TYPE_ATTACHMENT = 4,
53 | CODEC_TYPE_NB = 5,
54 | CODEC_TYPE_DATA = 6
55 | };
56 |
57 | enum StreamNumber {
58 | NO_STREAM = -2,
59 | UNKNOWN_STREAM = -1,
60 | };
61 |
62 | // MediaStreamInfo
63 | static char *stream_info_class_path_name = JAVA_PACKAGE_PATH"/MediaStreamInfo";
64 | static JavaMethod steram_info_set_metadata = {"setMetadata", "(Ljava/util/Map;)V"};
65 | static JavaMethod steram_info_set_media_type_internal = {"setMediaTypeInternal", "(I)V"};
66 | static JavaMethod stream_info_set_stream_number = {"setStreamNumber", "(I)V"};
67 |
68 |
69 | // Set
70 | static char *set_class_path_name = "java/util/Set";
71 | static JavaMethod set_iterator = {"iterator", "()Ljava/util/Iterator;"};
72 |
73 | // Iterator
74 | static char *iterator_class_path_name = "java/util/Iterator";
75 | static JavaMethod iterator_next = {"next", "()Ljava/lang/Object;"};
76 | static JavaMethod iterator_has_next = {"hasNext", "()Z"};
77 |
78 | static const struct {
79 | const char *name;
80 | int nb_channels;
81 | uint64_t layout;
82 | } channel_android_layout_map[] = {
83 | { "mono", 1, AV_CH_LAYOUT_MONO },
84 | { "stereo", 2, AV_CH_LAYOUT_STEREO },
85 | { "2.1", 3, AV_CH_LAYOUT_2POINT1 },
86 | { "4.0", 4, AV_CH_LAYOUT_4POINT0 },
87 | { "4.1", 5, AV_CH_LAYOUT_4POINT1 },
88 | { "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK },
89 | { "6.0", 6, AV_CH_LAYOUT_6POINT0 },
90 | { "7.0(front)", 7, AV_CH_LAYOUT_7POINT0_FRONT },
91 | { "7.1", 8, AV_CH_LAYOUT_7POINT1 },
92 | };
93 |
94 | // VPlayerController
95 | static char *player_class_path_name = JAVA_PACKAGE_PATH"/VPlayerController";
96 | static JavaField player_m_native_player = {"mNativePlayer", "J"};
97 | static JavaMethod player_on_update_time = {"onUpdateTime","(JJZ)V"};
98 | static JavaMethod player_prepare_audio_track = {"prepareAudioTrack", "(II)Landroid/media/AudioTrack;"};
99 | static JavaMethod player_prepare_frame = {"prepareFrame", "(II)Landroid/graphics/Bitmap;"};
100 | static JavaMethod player_set_stream_info = {"setStreamsInfo", "([L"JAVA_PACKAGE_PATH"/MediaStreamInfo;)V"};
101 | static JavaMethod player_video_dimensions_ready = {"videoDimensionsReady", "(II)V"};
102 |
103 | // AudioTrack
104 | static char *android_track_class_path_name = "android/media/AudioTrack";
105 | static JavaMethod audio_track_write = {"write", "([BII)I"};
106 | static JavaMethod audio_track_pause = {"pause", "()V"};
107 | static JavaMethod audio_track_play = {"play", "()V"};
108 | static JavaMethod audio_track_flush = {"flush", "()V"};
109 | static JavaMethod audio_track_stop = {"stop", "()V"};
110 | static JavaMethod audio_track_get_channel_count = {"getChannelCount", "()I"};
111 | static JavaMethod audio_track_get_sample_rate = {"getSampleRate", "()I"};
112 |
113 |
114 | // Player
115 |
116 | int jni_player_init(JNIEnv *env, jobject thiz);
117 | void jni_player_dealloc(JNIEnv *env, jobject thiz);
118 |
119 | void jni_player_seek(JNIEnv *env, jobject thiz, jlong positionUs);
120 |
121 | void jni_player_pause(JNIEnv *env, jobject thiz);
122 | void jni_player_resume(JNIEnv *env, jobject thiz);
123 |
124 | int jni_player_set_data_source(JNIEnv *env, jobject thiz, jstring string,
125 | jobject dictionary, int video_stream_no, int audio_stream_no,
126 | int subtitle_stream_no);
127 | void jni_player_stop(JNIEnv *env, jobject thiz);
128 |
129 | void jni_player_render_frame_start(JNIEnv *env, jobject thiz);
130 | void jni_player_render_frame_stop(JNIEnv *env, jobject thiz);
131 | void jni_player_render_frame_pause(JNIEnv *env, jobject thiz);
132 |
133 | void jni_player_render_last_frame(JNIEnv *env, jobject thiz);
134 |
135 | jlong jni_player_get_video_duration(JNIEnv *env, jobject thiz);
136 | void jni_player_render(JNIEnv *env, jobject thiz, jobject surface);
137 |
138 | static JNINativeMethod player_methods[] = {
139 |
140 | {"initNative", "()I", (void*) jni_player_init},
141 | {"deallocNative", "()V", (void*) jni_player_dealloc},
142 |
143 | {"seekNative", "(J)V", (void*) jni_player_seek},
144 |
145 | {"pauseNative", "()V", (void*) jni_player_pause},
146 | {"resumeNative", "()V", (void*) jni_player_resume},
147 |
148 | {"setDataSourceNative", "(Ljava/lang/String;Ljava/util/Map;III)I", (void*) jni_player_set_data_source},
149 | {"stopNative", "()V", (void*) jni_player_stop},
150 |
151 | {"renderFrameStart", "()V", (void*) jni_player_render_frame_start},
152 | {"renderFrameStop", "()V", (void*) jni_player_render_frame_stop},
153 | {"renderFramePause", "()V", (void*) jni_player_render_frame_pause},
154 |
155 | {"renderLastNativeFrame", "()V", (void*) jni_player_render_last_frame},
156 |
157 | {"getVideoDurationNative", "()J", (void*) jni_player_get_video_duration},
158 | {"render", "(Landroid/view/Surface;)V", (void*) jni_player_render},
159 | };
160 |
161 | #endif
162 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/queue.c:
--------------------------------------------------------------------------------
1 | /*
2 | * queue.c
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #include "queue.h"
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #define FALSE 0
27 | #define TRUE (!(FALSE))
28 |
29 | struct _Queue {
30 | int next_to_write;
31 | int next_to_read;
32 | int *ready;
33 |
34 | int in_read;
35 |
36 | queue_free_func free_func;
37 |
38 | int is_custom_lock;
39 | int size;
40 | void ** tab;
41 | };
42 |
43 | int queue_get_next(Queue *queue, int value) {
44 | return (value + 1) % queue->size;
45 | }
46 |
47 | Queue *queue_init_with_custom_lock(int size, queue_fill_func fill_func,
48 | queue_free_func free_func, void *obj, void *free_obj, pthread_mutex_t *custom_lock,
49 | pthread_cond_t *custom_cond) {
50 | Queue *queue = malloc(sizeof(Queue));
51 | if (queue == NULL)
52 | return NULL;
53 |
54 | queue->next_to_write = 0;
55 | queue->next_to_read = 0;
56 | queue->ready = malloc(sizeof(*queue->ready) * size);
57 | if (queue->ready == NULL)
58 | goto free_queue;
59 |
60 | queue->in_read = FALSE;
61 |
62 | queue->free_func = free_func;
63 |
64 | queue->is_custom_lock = TRUE;
65 |
66 | queue->size = size;
67 |
68 | queue->tab = malloc(sizeof(*queue->tab) * size);
69 | if (queue->tab == NULL)
70 | goto free_ready;
71 | memset(queue->tab, 0, sizeof(*queue->tab) * size);
72 | int i;
73 | for (i = queue->size - 1; i >= 0; --i) {
74 | void * elem = fill_func(obj);
75 | if (elem == NULL)
76 | goto free_tabs;
77 | queue->tab[i] = elem;
78 | }
79 |
80 | goto end;
81 | free_tabs: for (i = queue->size - 1; i >= 0; --i) {
82 | void *elem = queue->tab[i];
83 | if (elem == NULL)
84 | continue;
85 | queue->free_func(free_obj, elem);
86 | }
87 |
88 | free_tab: free(queue->tab);
89 |
90 | free_ready: free(queue->ready);
91 |
92 | free_queue: free(queue);
93 | queue = NULL;
94 |
95 | end: return queue;
96 | }
97 |
98 | void queue_free(Queue *queue, pthread_mutex_t * mutex, pthread_cond_t *cond, void *free_obj) {
99 | pthread_mutex_lock(mutex);
100 | while (queue->in_read)
101 | pthread_cond_wait(cond, mutex);
102 |
103 | int i;
104 | for (i = queue->size - 1; i >= 0; --i) {
105 | void *elem = queue->tab[i];
106 | queue->free_func(free_obj, elem);
107 | }
108 | pthread_mutex_unlock(mutex);
109 |
110 | free(queue->tab);
111 |
112 | free(queue->ready);
113 |
114 | free(queue);
115 | }
116 |
117 | void *queue_push_start_already_locked(Queue *queue, pthread_mutex_t * mutex,
118 | pthread_cond_t *cond, int *to_write, QueueCheckFunc func,
119 | void *check_data, void *check_ret_data) {
120 | int next_next_to_write;
121 | while (1) {
122 | if (func == NULL)
123 | goto test;
124 | QueueCheckFuncRet check = func(queue, check_data, check_ret_data);
125 | if (check == QUEUE_CHECK_FUNC_RET_SKIP)
126 | return NULL;
127 | else if (check == QUEUE_CHECK_FUNC_RET_WAIT)
128 | goto wait;
129 | else if (check == QUEUE_CHECK_FUNC_RET_TEST)
130 | goto test;
131 | else
132 | assert(FALSE);
133 |
134 | test: next_next_to_write = queue_get_next(queue, queue->next_to_write);
135 | if (next_next_to_write != queue->next_to_read) {
136 | break;
137 | }
138 |
139 | wait: pthread_cond_wait(cond, mutex);
140 | }
141 | *to_write = queue->next_to_write;
142 | queue->ready[*to_write] = FALSE;
143 |
144 | queue->next_to_write = next_next_to_write;
145 |
146 | pthread_cond_broadcast(cond);
147 |
148 | end: return queue->tab[*to_write];
149 | }
150 |
151 | void *queue_push_start(Queue *queue, pthread_mutex_t * mutex,
152 | pthread_cond_t *cond, int *to_write, QueueCheckFunc func,
153 | void *check_data, void *check_ret_data) {
154 | void *ret;
155 | pthread_mutex_lock(mutex);
156 | ret = queue_push_start_already_locked(queue, mutex, cond, to_write, func,
157 | check_data, check_ret_data);
158 | pthread_mutex_unlock(mutex);
159 | return ret;
160 | }
161 |
162 | void queue_push_finish_already_locked(Queue *queue, pthread_mutex_t * mutex,
163 | pthread_cond_t *cond, int to_write) {
164 | queue->ready[to_write] = TRUE;
165 | pthread_cond_broadcast(cond);
166 | }
167 |
168 | void queue_push_finish(Queue *queue, pthread_mutex_t * mutex,
169 | pthread_cond_t *cond, int to_write) {
170 | pthread_mutex_lock(mutex);
171 | queue_push_finish_already_locked(queue, mutex, cond, to_write);
172 | pthread_mutex_unlock(mutex);
173 | }
174 |
175 | void *queue_pop_start_already_locked_non_block(Queue *queue) {
176 | assert(!queue->in_read);
177 | int to_read = queue->next_to_read;
178 | if (to_read == queue->next_to_write)
179 | return NULL;
180 | if (!queue->ready[to_read])
181 | return NULL;
182 |
183 | queue->in_read = TRUE;
184 | return queue->tab[to_read];
185 | }
186 |
187 | void *queue_pop_start_already_locked(Queue **queue, pthread_mutex_t * mutex,
188 | pthread_cond_t *cond, QueueCheckFunc func, void *check_data,
189 | void *check_ret_data) {
190 | int to_read;
191 | Queue *q;
192 | while (1) {
193 | if (func == NULL)
194 | goto test;
195 | QueueCheckFuncRet check = func(*queue, check_data, check_ret_data);
196 | if (check == QUEUE_CHECK_FUNC_RET_SKIP)
197 | goto skip;
198 | else if (check == QUEUE_CHECK_FUNC_RET_WAIT)
199 | goto wait;
200 | else if (check == QUEUE_CHECK_FUNC_RET_TEST)
201 | goto test;
202 | else
203 | assert(FALSE);
204 | test:
205 | q = *queue;
206 | assert(!q->in_read);
207 | if (q->next_to_read != q->next_to_write
208 | && q->ready[q->next_to_read])
209 | break;
210 | wait: pthread_cond_wait(cond, mutex);
211 | }
212 | q=*queue;
213 | to_read = q->next_to_read;
214 | q->in_read = TRUE;
215 |
216 | end:
217 |
218 | return q->tab[to_read];
219 |
220 | skip: return NULL;
221 | }
222 |
223 | void *queue_pop_start(Queue **queue, pthread_mutex_t * mutex,
224 | pthread_cond_t *cond, QueueCheckFunc func, void *check_data,
225 | void *check_ret_data) {
226 | void *ret;
227 | pthread_mutex_lock(mutex);
228 | ret = queue_pop_start_already_locked(queue, mutex, cond, func, check_data,
229 | check_ret_data);
230 | pthread_mutex_unlock(mutex);
231 | return ret;
232 | }
233 |
234 | void queue_pop_roll_back_already_locked(Queue *queue, pthread_mutex_t * mutex,
235 | pthread_cond_t *cond) {
236 | assert(queue->in_read);
237 | queue->in_read = FALSE;
238 |
239 | pthread_cond_broadcast(cond);
240 | }
241 |
242 | void queue_pop_roll_back(Queue *queue, pthread_mutex_t * mutex,
243 | pthread_cond_t *cond) {
244 | pthread_mutex_lock(mutex);
245 | queue_pop_roll_back_already_locked(queue, mutex, cond);
246 | pthread_mutex_unlock(mutex);
247 | }
248 |
249 | void queue_pop_finish_already_locked(Queue *queue, pthread_mutex_t * mutex,
250 | pthread_cond_t *cond) {
251 | assert(queue->in_read);
252 | queue->in_read = FALSE;
253 | queue->next_to_read = queue_get_next(queue, queue->next_to_read);
254 |
255 | pthread_cond_broadcast(cond);
256 | }
257 |
258 | void queue_pop_finish(Queue *queue, pthread_mutex_t * mutex,
259 | pthread_cond_t *cond) {
260 | pthread_mutex_lock(mutex);
261 | queue_pop_finish_already_locked(queue, mutex, cond);
262 | pthread_mutex_unlock(mutex);
263 | }
264 |
265 | int queue_get_size(Queue *queue) {
266 | return queue->size;
267 | }
268 |
269 | void queue_wait_for(Queue *queue, int size, pthread_mutex_t * mutex,
270 | pthread_cond_t *cond) {
271 | assert(queue->size >= size);
272 |
273 | pthread_mutex_lock(mutex);
274 | while (1) {
275 | int next = queue->next_to_read;
276 | int i;
277 | int all_ok = TRUE;
278 | for (i = 0; i < size; ++i) {
279 | if (next == queue->next_to_write
280 | || !queue->ready[queue->next_to_read]) {
281 | all_ok = FALSE;
282 | break;
283 | }
284 |
285 | next = queue_get_next(queue, next);
286 | }
287 |
288 | if (all_ok)
289 | break;
290 |
291 | pthread_cond_wait(cond, mutex);
292 | }
293 | pthread_mutex_unlock(mutex);
294 | }
295 |
296 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/queue.h:
--------------------------------------------------------------------------------
1 | /*
2 | * queue.h
3 | * Copyright (c) 2012 Jacek Marchwicki
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 |
19 | #ifndef QUEUE_H_
20 | #define QUEUE_H_
21 |
22 | #include
23 |
24 | typedef struct _Queue Queue;
25 |
26 | typedef void * (*queue_fill_func)(void * obj);
27 | typedef void (*queue_free_func)(void * obj, void *elem);
28 |
29 | typedef enum {
30 | QUEUE_CHECK_FUNC_RET_WAIT = -1,
31 | QUEUE_CHECK_FUNC_RET_TEST = 0,
32 | QUEUE_CHECK_FUNC_RET_SKIP = 1
33 | } QueueCheckFuncRet;
34 |
35 | typedef QueueCheckFuncRet (*QueueCheckFunc)(Queue *queue, void* check_data,
36 | void *check_ret_data);
37 |
38 | Queue *queue_init_with_custom_lock(int size, queue_fill_func fill_func,
39 | queue_free_func free_func, void *obj, void *free_obj,
40 | pthread_mutex_t *custom_lock, pthread_cond_t *custom_cond);
41 | void queue_free(Queue *queue, pthread_mutex_t * mutex, pthread_cond_t *cond,
42 | void *free_obj);
43 |
44 | void *queue_push_start_already_locked(Queue *queue, pthread_mutex_t * mutex,
45 | pthread_cond_t *cond, int *to_write, QueueCheckFunc func,
46 | void *check_data, void *check_ret_data);
47 | void *queue_push_start(Queue *queue, pthread_mutex_t * mutex,
48 | pthread_cond_t *cond, int *to_write, QueueCheckFunc func,
49 | void *check_data, void *check_ret_data);
50 | void queue_push_finish_already_locked(Queue *queue, pthread_mutex_t * mutex,
51 | pthread_cond_t *cond, int to_write);
52 | void queue_push_finish(Queue *queue, pthread_mutex_t * mutex,
53 | pthread_cond_t *cond, int to_write);
54 |
55 | void *queue_pop_start_already_locked_non_block(Queue *queue);
56 | void *queue_pop_start_already_locked(Queue **queue, pthread_mutex_t * mutex,
57 | pthread_cond_t *cond, QueueCheckFunc func, void *check_data,
58 | void *check_ret_data);
59 | void *queue_pop_start(Queue **queue, pthread_mutex_t * mutex,
60 | pthread_cond_t *cond, QueueCheckFunc func, void *check_data,
61 | void *check_ret_data);
62 | void queue_pop_roll_back_already_locked(Queue *queue, pthread_mutex_t * mutex,
63 | pthread_cond_t *cond);
64 | void queue_pop_roll_back(Queue *queue, pthread_mutex_t * mutex,
65 | pthread_cond_t *cond);
66 | void queue_pop_finish_already_locked(Queue *queue, pthread_mutex_t * mutex,
67 | pthread_cond_t *cond);
68 | void queue_pop_finish(Queue *queue, pthread_mutex_t * mutex,
69 | pthread_cond_t *cond);
70 |
71 | int queue_get_size(Queue *queue);
72 |
73 | void queue_wait_for(Queue *queue, int size, pthread_mutex_t * mutex,
74 | pthread_cond_t *cond);
75 |
76 | #endif /* QUEUE_H_ */
77 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/application/sync.h:
--------------------------------------------------------------------------------
1 | /*
2 | * sync.h
3 | * Copyright (c) 2013 Jacek Marchwicki
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 |
19 | #ifndef SYNC_H_
20 | #define SYNC_H_
21 |
22 | enum WaitFuncRet {
23 | WAIT_FUNC_RET_OK = 0,
24 | WAIT_FUNC_RET_SKIP = 1,
25 | };
26 |
27 | typedef enum WaitFuncRet (WaitFunc) (void *data , int64_t time, int stream_no);
28 |
29 |
30 | #endif /* SYNC_H_ */
31 |
--------------------------------------------------------------------------------
/VPlayer_library/jni/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Do it twice incase some repos are not cloned!
4 | # You only need ffmpeg repo if you are not building it, but we have to update all submodules
5 | git submodule update --init --recursive
6 | git submodule update --init --recursive
7 |
8 | # Copy all the header files into ffmpeg folder under the project
9 | SRC_FOLDER=../../ffmpeg_build/ffmpeg
10 | DST_FOLDER=ffmpeg
11 | mkdir -p $DST_FOLDER
12 | (cd $SRC_FOLDER && find . -name '*.h' -print | tar --create --files-from -) | (cd $DST_FOLDER && tar xvfp -)
13 |
14 | # Copy all the header files into ffmpeg folder under the project
15 | SRC_FOLDER=../../ffmpeg_build/
16 | DST_FOLDER=libjpeg-turbo
17 | mkdir -p $DST_FOLDER
18 | (cd $SRC_FOLDER/$DST_FOLDER && find . -name '*.h' -print | tar --create --files-from -) | (cd $DST_FOLDER && tar xvfp -)
--------------------------------------------------------------------------------
/VPlayer_library/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/VPlayer_library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/gfan/dev/sdk_current/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 | #}
--------------------------------------------------------------------------------
/VPlayer_library/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/VPlayer_library/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/VPlayer_library/src/com/vplayer/FpsCounter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * FpsCounter.java
3 | * Copyright (c) 2012 Jacek Marchwicki, modified by Matthew Ng
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 |
19 | package com.vplayer;
20 |
21 | public class FpsCounter {
22 | private final int frameCount;
23 | private int counter = 0;
24 | boolean start = true;
25 |
26 | private long startTime = 0;
27 |
28 | private String tick = "- fps";
29 |
30 | public FpsCounter(int frameCount) {
31 | this.frameCount = frameCount;
32 | }
33 |
34 | public String tick() {
35 | if (this.start) {
36 | this.start = false;
37 | this.startTime = System.nanoTime();
38 | }
39 | if (this.counter++ < this.frameCount) {
40 | return this.tick;
41 | }
42 |
43 | long stopTime = System.nanoTime();
44 | double fps = this.frameCount * (1000.0 * 1000.0 * 1000.0)
45 | / (stopTime - this.startTime);
46 | this.startTime = stopTime;
47 | this.counter = 0;
48 |
49 | this.tick = String.format("%.2f fps", fps);
50 | return this.tick;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/VPlayer_library/src/com/vplayer/JniReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * JniReader.java
3 | * Copyright (c) 2012 Jacek Marchwicki, modified by Matthew Ng
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 |
19 | package com.vplayer;
20 |
21 | import java.io.UnsupportedEncodingException;
22 | import java.security.MessageDigest;
23 | import java.security.NoSuchAlgorithmException;
24 |
25 | import android.util.Log;
26 |
27 | class JniReader {
28 |
29 | private static final String TAG = JniReader.class.getCanonicalName();
30 |
31 | private final byte[] value = new byte[16];
32 | private int position;
33 |
34 | public JniReader(String url, int flags) {
35 | Log.d(TAG, String.format("Reading: %s", url));
36 | try {
37 | byte[] key = "dupadupadupadupa".getBytes("UTF-8");
38 |
39 | MessageDigest m = MessageDigest.getInstance("MD5");
40 | m.update(key);
41 | System.arraycopy(m.digest(), 0, value, 0, 16);
42 |
43 | } catch (UnsupportedEncodingException e) {
44 | throw new RuntimeException(e);
45 | } catch (NoSuchAlgorithmException e) {
46 | throw new RuntimeException(e);
47 | }
48 | position = 0;
49 | }
50 |
51 | public int read(byte[] buffer) {
52 | int end = position + buffer.length;
53 | if (end >= value.length) {
54 | end = value.length;
55 | }
56 |
57 | int length = end - position;
58 | System.arraycopy(value, position, buffer, 0, length);
59 | position += length;
60 |
61 | return length;
62 | }
63 |
64 | public int write(byte[] buffer) {
65 | return 0;
66 | }
67 |
68 | public int check(int mask) {
69 | return 0;
70 | }
71 |
72 | public long seek(long pos, int whence) {
73 | return -1;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/VPlayer_library/src/com/vplayer/MediaStreamInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediaStreamInfo.java
3 | * Copyright (c) 2012 Jacek Marchwicki, Modified by Matthew Ng
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 |
19 | package com.vplayer;
20 |
21 | import java.util.HashMap;
22 | import java.util.Locale;
23 | import java.util.Map;
24 |
25 | public class MediaStreamInfo {
26 | public enum CodecType {
27 | UNKNOWN, AUDIO, VIDEO, SUBTITLE, ATTACHMENT, NB, DATA;
28 | }
29 |
30 | private static Map sLocaleMap;
31 | static {
32 | String[] languages = Locale.getISOLanguages();
33 | sLocaleMap = new HashMap(languages.length);
34 | for (String language : languages) {
35 | Locale locale = new Locale(language);
36 | sLocaleMap.put(locale.getISO3Language(), locale);
37 | }
38 | }
39 |
40 | private Map mMetadata;
41 | private CodecType mMediaType;
42 | private int mStreamNumber;
43 |
44 | public void setMetadata(Map metadata) {
45 | this.mMetadata = metadata;
46 | }
47 |
48 | void setMediaTypeInternal(int mediaTypeInternal) {
49 | mMediaType = CodecType.values()[mediaTypeInternal];
50 | }
51 |
52 | void setStreamNumber(int streamNumber) {
53 | this.mStreamNumber = streamNumber;
54 | }
55 |
56 | public int getStreamNumber() {
57 | return this.mStreamNumber;
58 | }
59 |
60 | /**
61 | * Return stream language locale
62 | * @return locale or null if not known
63 | */
64 | public Locale getLanguage() {
65 | if (mMetadata == null) {
66 | return null;
67 | }
68 | String iso3Langugae = mMetadata.get("language");
69 | if (iso3Langugae == null) {
70 | return null;
71 | }
72 | return sLocaleMap.get(iso3Langugae);
73 | }
74 |
75 | public CodecType getMediaType() {
76 | return mMediaType;
77 | }
78 |
79 | public Map getMetadata() {
80 | return mMetadata;
81 | }
82 |
83 | @Override
84 | public String toString() {
85 | Locale language = getLanguage();
86 | String languageName = language == null ? "unknown" : language.getDisplayName();
87 | return new StringBuilder().
88 | append("{\n")
89 | .append("\tmediaType: ")
90 | .append(mMediaType)
91 | .append("\n")
92 | .append("\tlanguage: ")
93 | .append(languageName)
94 | .append("\n")
95 | .append("\tmetadata ")
96 | .append(mMetadata)
97 | .append("\n")
98 | .append("}")
99 | .toString();
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/VPlayer_library/src/com/vplayer/NativeTester.java:
--------------------------------------------------------------------------------
1 | /*
2 | * NativeTester.java
3 | * Copyright (c) 2012 Jacek Marchwicki, modified by Matthew Ng
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 |
19 | package com.vplayer;
20 |
21 | class NativeTester {
22 | static {
23 | System.loadLibrary("nativetester-jni");
24 | }
25 |
26 | native boolean isNeon();
27 | }
28 |
--------------------------------------------------------------------------------
/VPlayer_library/src/com/vplayer/SeekerView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * SeekerView.java
3 | * Copyright (c) 2012 Jacek Marchwicki, modified by Matthew Ng
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 |
19 | package com.vplayer;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.graphics.Canvas;
24 | import android.graphics.Color;
25 | import android.graphics.Paint;
26 | import android.graphics.Rect;
27 | import android.util.AttributeSet;
28 | import android.view.MotionEvent;
29 | import android.view.View;
30 |
31 | public class SeekerView extends View {
32 |
33 | public static interface OnProgressChangeListener {
34 | void onProgressChange(boolean finished, int currentValue, int maxValue);
35 | }
36 |
37 | private final int mBorderWidth;
38 | private final int mBorderColor;
39 | private final int mBorderPadding;
40 |
41 | private final int mBarMinHeight;
42 | private final int mBarMinWidth;
43 | private final int mBarColor;
44 |
45 | private final Paint mBorderPaint = new Paint();
46 | private final Paint mBarPaint = new Paint();
47 |
48 | private final Rect mBorderRect = new Rect();
49 | private final Rect mBarRect = new Rect();
50 | private OnProgressChangeListener mOnProgressChangeListener = null;
51 |
52 | private int mMaxValue = 100;
53 | private int mCurrentValue = 10;
54 |
55 | public void setOnProgressChangeListener(OnProgressChangeListener onProgressChangeListener) {
56 | this.mOnProgressChangeListener = onProgressChangeListener;
57 | }
58 |
59 | public SeekerView(Context context, AttributeSet attrs, int defStyle) {
60 | super(context, attrs, defStyle);
61 | TypedArray a = this.getContext().obtainStyledAttributes(attrs,
62 | R.styleable.SeekerView, defStyle, 0);
63 |
64 | final float scale = getResources().getDisplayMetrics().density;
65 |
66 | mBorderWidth = a.getDimensionPixelSize(
67 | R.styleable.SeekerView_borderWidth, (int) (1 * scale + 0.5f));
68 | mBorderColor = a.getColor(R.styleable.SeekerView_barColor, Color.CYAN);
69 | mBorderPadding = a.getColor(R.styleable.SeekerView_borderPadding,
70 | (int) (1 * scale + 0.5f));
71 |
72 | mBarMinHeight = a.getDimensionPixelSize(
73 | R.styleable.SeekerView_barMinHeight, (int) (10 * scale + 0.5f));
74 | mBarMinWidth = a.getDimensionPixelSize(
75 | R.styleable.SeekerView_barMinWidth, (int) (50 * scale + 0.5f));
76 | mBarColor = a.getColor(R.styleable.SeekerView_barColor, Color.BLUE);
77 |
78 | mBorderPaint.setDither(true);
79 | mBorderPaint.setColor(mBorderColor);
80 | mBorderPaint.setStyle(Paint.Style.STROKE);
81 | mBorderPaint.setStrokeJoin(Paint.Join.ROUND);
82 | mBorderPaint.setStrokeCap(Paint.Cap.ROUND);
83 | mBorderPaint.setStrokeWidth(mBorderWidth);
84 |
85 | mBarPaint.setDither(true);
86 | mBarPaint.setColor(mBarColor);
87 | mBarPaint.setStyle(Paint.Style.FILL);
88 | mBarPaint.setStrokeJoin(Paint.Join.ROUND);
89 | mBarPaint.setStrokeCap(Paint.Cap.ROUND);
90 |
91 | mMaxValue = a.getInt(R.styleable.SeekerView_maxValue, mMaxValue);
92 | mCurrentValue = a.getInt(R.styleable.SeekerView_currentValue, mCurrentValue);
93 | }
94 |
95 | public SeekerView(Context context, AttributeSet attrs) {
96 | this(context, attrs, 0);
97 | }
98 |
99 | public SeekerView(Context context) {
100 | this(context, null);
101 | }
102 |
103 | public void setMaxValue(int maxValue) {
104 | this.mMaxValue = maxValue;
105 | this.invalidate();
106 | }
107 |
108 | public int maxValue() {
109 | return mMaxValue;
110 | }
111 |
112 | public void setCurrentValue(int currentValue) {
113 | this.mCurrentValue = currentValue;
114 | this.invalidate();
115 | }
116 |
117 | public int currentValue() {
118 | return this.mCurrentValue;
119 | }
120 |
121 | @Override
122 | protected void onDraw(Canvas canvas) {
123 | super.onDraw(canvas);
124 | canvas.drawRect(mBorderRect, mBorderPaint);
125 | canvas.drawRect(mBarRect, mBarPaint);
126 | }
127 |
128 | @Override
129 | public boolean onTouchEvent(MotionEvent event) {
130 | int action = event.getActionMasked();
131 |
132 | boolean superResult = super.onTouchEvent(event);
133 | boolean grab = false;
134 | boolean finished = false;
135 |
136 | if (action == MotionEvent.ACTION_DOWN) {
137 | grab = true;
138 | } else if (action == MotionEvent.ACTION_MOVE) {
139 | grab = true;
140 | } else if (action == MotionEvent.ACTION_UP) {
141 | grab = true;
142 | finished = true;
143 | }
144 | if (grab) {
145 |
146 | float eventX = event.getX();
147 | int padding = mBorderWidth + mBorderPadding;
148 | int barLeft = padding;
149 | int barWidth = getWidth() - 2*padding;
150 | float x = eventX - barLeft;
151 | if (x < 0.0f) {
152 | x = 0.0f;
153 | }
154 | if (x > barWidth) {
155 | x = barWidth;
156 | }
157 | x /= barWidth;
158 | mCurrentValue = (int) (mMaxValue * x);
159 |
160 | if (mOnProgressChangeListener != null) {
161 | mOnProgressChangeListener.onProgressChange(finished, mCurrentValue, mMaxValue);
162 | }
163 | calculateBarRect();
164 | this.invalidate();
165 | return true;
166 | } else {
167 | return superResult;
168 | }
169 | }
170 |
171 | @Override
172 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
173 | int dw = 0;
174 | int dh = 0;
175 |
176 | dw = (mBorderWidth + mBorderPadding) * 2 + mBarMinWidth;
177 | dh = (mBorderWidth + mBorderPadding) * 2 + mBarMinHeight;
178 | this.setMeasuredDimension(
179 | ViewCompat.resolveSizeAndState(dw, widthMeasureSpec, 0),
180 | ViewCompat.resolveSizeAndState(dh, heightMeasureSpec, 0));
181 | }
182 |
183 | private void calculateBarRect() {
184 | int width = getWidth();
185 | int height = getHeight();
186 | int barPadding = mBorderWidth + mBorderPadding;
187 |
188 | int maxBarWidth = width - barPadding;
189 | float pos = (float) mCurrentValue / mMaxValue;
190 | int barWidth = (int) (maxBarWidth * pos);
191 | mBarRect.set(
192 | barPadding,
193 | barPadding,
194 | barWidth,
195 | height - barPadding);
196 | }
197 |
198 | @Override
199 | protected void onLayout(boolean changed, int left, int top, int right,
200 | int bottom) {
201 | super.onLayout(changed, left, top, right, bottom);
202 |
203 | if (changed) {
204 | int width = right-left;
205 | int height = bottom-top;
206 | mBorderRect.set(0, 0, width, height);
207 | calculateBarRect();
208 | }
209 | }
210 |
211 | }
212 |
--------------------------------------------------------------------------------
/VPlayer_library/src/com/vplayer/VPlayerController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * VPlayerController.java
3 | * Copyright (c) 2012 Jacek Marchwicki, Modified by Matthew Ng
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 |
19 | package com.vplayer;
20 |
21 | import android.app.Activity;
22 | import android.graphics.Bitmap;
23 | import android.media.AudioFormat;
24 | import android.media.AudioManager;
25 | import android.media.AudioTrack;
26 | import android.os.AsyncTask;
27 | import android.view.Surface;
28 |
29 | import com.vplayer.exception.NotPlayingException;
30 | import com.vplayer.exception.VPlayerException;
31 |
32 | import java.util.Map;
33 |
34 | class VPlayerController {
35 | private static class StopTask extends AsyncTask {
36 |
37 | private final VPlayerController player;
38 |
39 | public StopTask(VPlayerController player) {
40 | this.player = player;
41 | }
42 |
43 | @Override
44 | protected Void doInBackground(Void... params) {
45 | player.stopNative();
46 | return null;
47 | }
48 |
49 | @Override
50 | protected void onPostExecute(Void result) {
51 | if (player.mpegListener != null) {
52 | player.mpegListener.onMediaStop();
53 | }
54 | }
55 |
56 | }
57 |
58 | private static class SetDataSourceTaskResult {
59 | VPlayerException error;
60 | MediaStreamInfo[] streams;
61 | }
62 |
63 | private static class SetDataSourceTask extends
64 | AsyncTask