clazz = MediaPlayer.class;
46 | Method method = clazz.getDeclaredMethod("setDataSource", String.class, Map.class);
47 | if (dataSourceObjects.length > 2) {
48 | method.invoke(mediaPlayer, currentDataSource.toString(), dataSourceObjects[2]);
49 | } else {
50 | method.invoke(mediaPlayer, currentDataSource.toString(), null);
51 | }
52 | mediaPlayer.prepareAsync();
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | }
56 | }
57 |
58 | @Override
59 | public void pause() {
60 | mediaPlayer.pause();
61 | }
62 |
63 | @Override
64 | public boolean isPlaying() {
65 | return mediaPlayer != null && mediaPlayer.isPlaying();
66 | }
67 |
68 | @Override
69 | public void seekTo(long time) {
70 | try {
71 | mediaPlayer.seekTo((int) time);
72 | } catch (IllegalStateException e) {
73 | e.printStackTrace();
74 | }
75 | }
76 |
77 | @Override
78 | public void release() {
79 | if (mediaPlayer != null)
80 | mediaPlayer.release();
81 | }
82 |
83 | @Override
84 | public long getCurrentPosition() {
85 | if (mediaPlayer != null) {
86 | return mediaPlayer.getCurrentPosition();
87 | } else {
88 | return 0;
89 | }
90 | }
91 |
92 | @Override
93 | public long getDuration() {
94 | if (mediaPlayer != null) {
95 | return mediaPlayer.getDuration();
96 | } else {
97 | return 0;
98 | }
99 | }
100 |
101 | @Override
102 | public void setSurface(Surface surface) {
103 | mediaPlayer.setSurface(surface);
104 | }
105 |
106 | @Override
107 | public void setVolume(float leftVolume, float rightVolume) {
108 | mediaPlayer.setVolume(leftVolume, rightVolume);
109 | }
110 |
111 | @Override
112 | public void onPrepared(MediaPlayer mediaPlayer) {
113 | mediaPlayer.start();
114 | if (currentDataSource.toString().toLowerCase().contains("mp3") ||
115 | currentDataSource.toString().toLowerCase().contains("wav")) {
116 | JZMediaManager.instance().mainThreadHandler.post(new Runnable() {
117 | @Override
118 | public void run() {
119 | if (JZVideoPlayerManager.getCurrentJzvd() != null) {
120 | JZVideoPlayerManager.getCurrentJzvd().onPrepared();
121 | }
122 | }
123 | });
124 | }
125 | }
126 |
127 | @Override
128 | public void onCompletion(MediaPlayer mediaPlayer) {
129 | JZMediaManager.instance().mainThreadHandler.post(new Runnable() {
130 | @Override
131 | public void run() {
132 | if (JZVideoPlayerManager.getCurrentJzvd() != null) {
133 | JZVideoPlayerManager.getCurrentJzvd().onAutoCompletion();
134 | }
135 | }
136 | });
137 | }
138 |
139 | @Override
140 | public void onBufferingUpdate(MediaPlayer mediaPlayer, final int percent) {
141 | JZMediaManager.instance().mainThreadHandler.post(new Runnable() {
142 | @Override
143 | public void run() {
144 | if (JZVideoPlayerManager.getCurrentJzvd() != null) {
145 | JZVideoPlayerManager.getCurrentJzvd().setBufferProgress(percent);
146 | }
147 | }
148 | });
149 | }
150 |
151 | @Override
152 | public void onSeekComplete(MediaPlayer mediaPlayer) {
153 | JZMediaManager.instance().mainThreadHandler.post(new Runnable() {
154 | @Override
155 | public void run() {
156 | if (JZVideoPlayerManager.getCurrentJzvd() != null) {
157 | JZVideoPlayerManager.getCurrentJzvd().onSeekComplete();
158 | }
159 | }
160 | });
161 | }
162 |
163 | @Override
164 | public boolean onError(MediaPlayer mediaPlayer, final int what, final int extra) {
165 | JZMediaManager.instance().mainThreadHandler.post(new Runnable() {
166 | @Override
167 | public void run() {
168 | if (JZVideoPlayerManager.getCurrentJzvd() != null) {
169 | JZVideoPlayerManager.getCurrentJzvd().onError(what, extra);
170 | }
171 | }
172 | });
173 | return true;
174 | }
175 |
176 | @Override
177 | public boolean onInfo(MediaPlayer mediaPlayer, final int what, final int extra) {
178 | JZMediaManager.instance().mainThreadHandler.post(new Runnable() {
179 | @Override
180 | public void run() {
181 | if (JZVideoPlayerManager.getCurrentJzvd() != null) {
182 | if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
183 | if (JZVideoPlayerManager.getCurrentJzvd().currentState == JZVideoPlayer.CURRENT_STATE_PREPARING
184 | || JZVideoPlayerManager.getCurrentJzvd().currentState == JZVideoPlayer.CURRENT_STATE_PREPARING_CHANGING_URL) {
185 | JZVideoPlayerManager.getCurrentJzvd().onPrepared();
186 | }
187 | } else {
188 | JZVideoPlayerManager.getCurrentJzvd().onInfo(what, extra);
189 | }
190 | }
191 | }
192 | });
193 | return false;
194 | }
195 |
196 | @Override
197 | public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
198 | JZMediaManager.instance().currentVideoWidth = width;
199 | JZMediaManager.instance().currentVideoHeight = height;
200 | if (JZVideoPlayerManager.getCurrentJzvd().currentScreen == SCREEN_WINDOW_FULLSCREEN) {
201 | if (JZMediaManager.instance().currentVideoWidth > JZMediaManager.instance().currentVideoHeight) {
202 | JZUtils.setRequestedOrientation(JZVideoPlayerManager.getCurrentJzvd().getContext(), ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
203 | } else {
204 | JZUtils.setRequestedOrientation(JZVideoPlayerManager.getCurrentJzvd().getContext(), ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
205 | }
206 | }
207 | JZMediaManager.instance().mainThreadHandler.post(new Runnable() {
208 | @Override
209 | public void run() {
210 | if (JZVideoPlayerManager.getCurrentJzvd() != null) {
211 | JZVideoPlayerManager.getCurrentJzvd().onVideoSizeChanged();
212 | }
213 | }
214 | });
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/player/JZResizeTextureView.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.player;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.util.Log;
6 | import android.view.TextureView;
7 | import android.view.View;
8 |
9 |
10 |
11 | /**
12 | * 参照Android系统的VideoView的onMeasure方法
13 | *
注意!relativelayout中无法全屏,要嵌套一个linearlayout
14 | * Referring Android system Video View of onMeasure method
15 | *
NOTE! Can not fullscreen relativelayout, to nest a linearlayout
16 | * Created by Nathen
17 | * On 2016/06/02 00:01
18 | */
19 | public class JZResizeTextureView extends TextureView {
20 | protected static final String TAG = "JZResizeTextureView";
21 |
22 | public int currentVideoWidth = 0;
23 | public int currentVideoHeight = 0;
24 |
25 | public JZResizeTextureView(Context context) {
26 | super(context);
27 | currentVideoWidth = 0;
28 | currentVideoHeight = 0;
29 | }
30 |
31 | public JZResizeTextureView(Context context, AttributeSet attrs) {
32 | super(context, attrs);
33 | currentVideoWidth = 0;
34 | currentVideoHeight = 0;
35 | }
36 |
37 | public void setVideoSize(int currentVideoWidth, int currentVideoHeight) {
38 | if (this.currentVideoWidth != currentVideoWidth || this.currentVideoHeight != currentVideoHeight) {
39 | this.currentVideoWidth = currentVideoWidth;
40 | this.currentVideoHeight = currentVideoHeight;
41 | requestLayout();
42 | }
43 | }
44 |
45 | @Override
46 | public void setRotation(float rotation) {
47 | if (rotation != getRotation()) {
48 | super.setRotation(rotation);
49 | requestLayout();
50 | }
51 | }
52 |
53 | @Override
54 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
55 | Log.i(TAG, "onMeasure " + " [" + this.hashCode() + "] ");
56 | int viewRotation = (int) getRotation();
57 | int videoWidth = currentVideoWidth;
58 | int videoHeight = currentVideoHeight;
59 |
60 |
61 |
62 | int parentHeight = ((View) getParent()).getMeasuredHeight();
63 | int parentWidth = ((View) getParent()).getMeasuredWidth();
64 | if (parentWidth != 0 && parentHeight != 0 && videoWidth != 0 && videoHeight != 0) {
65 | if (JZVideoPlayer.VIDEO_IMAGE_DISPLAY_TYPE == JZVideoPlayer.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT) {
66 | if (viewRotation == 90 || viewRotation == 270) {
67 | int tempSize = parentWidth;
68 | parentWidth = parentHeight;
69 | parentHeight = tempSize;
70 | }
71 | /**强制充满**/
72 | videoHeight = videoWidth * parentHeight / parentWidth;
73 | }
74 | }
75 |
76 | // 如果判断成立,则说明显示的TextureView和本身的位置是有90度的旋转的,所以需要交换宽高参数。
77 | if (viewRotation == 90 || viewRotation == 270) {
78 | int tempMeasureSpec = widthMeasureSpec;
79 | widthMeasureSpec = heightMeasureSpec;
80 | heightMeasureSpec = tempMeasureSpec;
81 | }
82 |
83 | int width = getDefaultSize(videoWidth, widthMeasureSpec);
84 | int height = getDefaultSize(videoHeight, heightMeasureSpec);
85 | if (videoWidth > 0 && videoHeight > 0) {
86 |
87 | int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
88 | int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
89 | int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
90 | int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
91 |
92 | Log.i(TAG, "widthMeasureSpec [" + MeasureSpec.toString(widthMeasureSpec) + "]");
93 | Log.i(TAG, "heightMeasureSpec [" + MeasureSpec.toString(heightMeasureSpec) + "]");
94 |
95 | if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
96 | // the size is fixed
97 | width = widthSpecSize;
98 | height = heightSpecSize;
99 | // for compatibility, we adjust size based on aspect ratio
100 | if (videoWidth * height < width * videoHeight) {
101 | width = height * videoWidth / videoHeight;
102 | } else if (videoWidth * height > width * videoHeight) {
103 | height = width * videoHeight / videoWidth;
104 | }
105 | } else if (widthSpecMode == MeasureSpec.EXACTLY) {
106 | // only the width is fixed, adjust the height to match aspect ratio if possible
107 | width = widthSpecSize;
108 | height = width * videoHeight / videoWidth;
109 | if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
110 | // couldn't match aspect ratio within the constraints
111 | height = heightSpecSize;
112 | width = height * videoWidth / videoHeight;
113 | }
114 | } else if (heightSpecMode == MeasureSpec.EXACTLY) {
115 | // only the height is fixed, adjust the width to match aspect ratio if possible
116 | height = heightSpecSize;
117 | width = height * videoWidth / videoHeight;
118 | if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
119 | // couldn't match aspect ratio within the constraints
120 | width = widthSpecSize;
121 | height = width * videoHeight / videoWidth;
122 | }
123 | } else {
124 | // neither the width nor the height are fixed, try to use actual video size
125 | width = videoWidth;
126 | height = videoHeight;
127 | if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
128 | // too tall, decrease both width and height
129 | height = heightSpecSize;
130 | width = height * videoWidth / videoHeight;
131 | }
132 | if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
133 | // too wide, decrease both width and height
134 | width = widthSpecSize;
135 | height = width * videoHeight / videoWidth;
136 | }
137 | }
138 | } else {
139 | // no size yet, just adopt the given spec sizes
140 | }
141 | if (parentWidth != 0 && parentHeight != 0 && videoWidth != 0 && videoHeight != 0) {
142 | if (JZVideoPlayer.VIDEO_IMAGE_DISPLAY_TYPE == JZVideoPlayer.VIDEO_IMAGE_DISPLAY_TYPE_ORIGINAL) {
143 | /**原图**/
144 | height = videoHeight;
145 | width = videoWidth;
146 | } else if (JZVideoPlayer.VIDEO_IMAGE_DISPLAY_TYPE == JZVideoPlayer.VIDEO_IMAGE_DISPLAY_TYPE_FILL_SCROP) {
147 | if (viewRotation == 90 || viewRotation == 270) {
148 | int tempSize = parentWidth;
149 | parentWidth = parentHeight;
150 | parentHeight = tempSize;
151 | }
152 | /**充满剪切**/
153 | if (((double) videoHeight / videoWidth) > ((double) parentHeight / parentWidth)) {
154 | height = (int) (((double) parentWidth / (double) width * (double) height));
155 | width = parentWidth;
156 | } else if (((double) videoHeight / videoWidth) < ((double) parentHeight / parentWidth)) {
157 | width = (int) (((double) parentHeight / (double) height * (double) width));
158 | height = parentHeight;
159 | }
160 | }
161 | }
162 | setMeasuredDimension(width, height);
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/player/JZUserAction.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.player;
2 |
3 | /**
4 | * Created by Nathen
5 | * On 2016/04/04 22:13
6 | */
7 | public interface JZUserAction {
8 |
9 | int ON_CLICK_START_ICON = 0;
10 | /**
11 | * 视频损坏点击重试
12 | */
13 | int ON_CLICK_START_ERROR = 1;
14 | int ON_CLICK_START_AUTO_COMPLETE = 2;
15 |
16 | int ON_CLICK_PAUSE = 3;
17 | int ON_CLICK_RESUME = 4;
18 | int ON_SEEK_POSITION = 5;
19 | int ON_AUTO_COMPLETE = 6;
20 |
21 | int ON_ENTER_FULLSCREEN = 7;
22 | int ON_QUIT_FULLSCREEN = 8;
23 | int ON_ENTER_TINYSCREEN = 9;
24 | int ON_QUIT_TINYSCREEN = 10;
25 |
26 |
27 | int ON_TOUCH_SCREEN_SEEK_VOLUME = 11;
28 | int ON_TOUCH_SCREEN_SEEK_POSITION = 12;
29 |
30 | void onEvent(int type, Object url, int screen, Object... objects);
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/player/JZUtils.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.player;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.ContextWrapper;
6 | import android.content.SharedPreferences;
7 | import android.graphics.Rect;
8 | import android.net.ConnectivityManager;
9 | import android.net.NetworkInfo;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.support.v7.view.ContextThemeWrapper;
12 | import android.support.v7.widget.RecyclerView;
13 | import android.util.Log;
14 | import android.view.View;
15 | import android.view.Window;
16 | import android.widget.AbsListView;
17 |
18 |
19 | import com.zzh12138.jzvideodemo.R;
20 |
21 | import java.util.Formatter;
22 | import java.util.LinkedHashMap;
23 | import java.util.Locale;
24 |
25 |
26 | /**
27 | * Created by Nathen
28 | * On 2016/02/21 12:25
29 | */
30 | public class JZUtils {
31 | public static final String TAG = "JiaoZiVideoPlayer";
32 |
33 | public static String stringForTime(long timeMs) {
34 | if (timeMs <= 0 || timeMs >= 24 * 60 * 60 * 1000) {
35 | return "00:00";
36 | }
37 | long totalSeconds = timeMs / 1000;
38 | int seconds = (int) (totalSeconds % 60);
39 | int minutes = (int) ((totalSeconds / 60) % 60);
40 | int hours = (int) (totalSeconds / 3600);
41 | StringBuilder stringBuilder = new StringBuilder();
42 | Formatter mFormatter = new Formatter(stringBuilder, Locale.getDefault());
43 | if (hours > 0) {
44 | return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
45 | } else {
46 | return mFormatter.format("%02d:%02d", minutes, seconds).toString();
47 | }
48 | }
49 |
50 | /**
51 | * This method requires the caller to hold the permission ACCESS_NETWORK_STATE.
52 | *
53 | * @param context context
54 | * @return if wifi is connected,return true
55 | */
56 | public static boolean isWifiConnected(Context context) {
57 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
58 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
59 | return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
60 | }
61 |
62 | /**
63 | * Get activity from context object
64 | *
65 | * @param context context
66 | * @return object of Activity or null if it is not Activity
67 | */
68 | public static Activity scanForActivity(Context context) {
69 | if (context == null) return null;
70 |
71 | if (context instanceof Activity) {
72 | return (Activity) context;
73 | } else if (context instanceof ContextWrapper) {
74 | return scanForActivity(((ContextWrapper) context).getBaseContext());
75 | }
76 |
77 | return null;
78 | }
79 |
80 | /**
81 | * Get AppCompatActivity from context
82 | *
83 | * @param context context
84 | * @return AppCompatActivity if it's not null
85 | */
86 | public static AppCompatActivity getAppCompActivity(Context context) {
87 | if (context == null) return null;
88 | if (context instanceof AppCompatActivity) {
89 | return (AppCompatActivity) context;
90 | } else if (context instanceof ContextThemeWrapper) {
91 | return getAppCompActivity(((ContextThemeWrapper) context).getBaseContext());
92 | }
93 | return null;
94 | }
95 |
96 | public static void setRequestedOrientation(Context context, int orientation) {
97 | if (JZUtils.getAppCompActivity(context) != null) {
98 | JZUtils.getAppCompActivity(context).setRequestedOrientation(
99 | orientation);
100 | } else {
101 | JZUtils.scanForActivity(context).setRequestedOrientation(
102 | orientation);
103 | }
104 | }
105 |
106 | public static Window getWindow(Context context) {
107 | if (JZUtils.getAppCompActivity(context) != null) {
108 | return JZUtils.getAppCompActivity(context).getWindow();
109 | } else {
110 | return JZUtils.scanForActivity(context).getWindow();
111 | }
112 | }
113 |
114 | public static int dip2px(Context context, float dpValue) {
115 | final float scale = context.getResources().getDisplayMetrics().density;
116 | return (int) (dpValue * scale + 0.5f);
117 | }
118 |
119 | public static void saveProgress(Context context, Object url, long progress) {
120 | if (!JZVideoPlayer.SAVE_PROGRESS) return;
121 | Log.i(TAG, "saveProgress: " + progress);
122 | if (progress < 500) {
123 | progress = 0;
124 | }
125 | SharedPreferences spn = context.getSharedPreferences("JZVD_PROGRESS",
126 | Context.MODE_PRIVATE);
127 | SharedPreferences.Editor editor = spn.edit();
128 | editor.putLong("newVersion:" + url.toString(), progress).apply();
129 | }
130 |
131 | public static long getSavedProgress(Context context, Object url) {
132 | if (!JZVideoPlayer.SAVE_PROGRESS) return 0;
133 | SharedPreferences spn = context.getSharedPreferences("JZVD_PROGRESS",
134 | Context.MODE_PRIVATE);
135 | return spn.getLong("newVersion:" + url.toString(), 0);
136 | }
137 |
138 | /**
139 | * if url == null, clear all progress
140 | *
141 | * @param context context
142 | * @param url if url!=null clear this url progress
143 | */
144 | public static void clearSavedProgress(Context context, Object url) {
145 | if (url == null) {
146 | SharedPreferences spn = context.getSharedPreferences("JZVD_PROGRESS",
147 | Context.MODE_PRIVATE);
148 | spn.edit().clear().apply();
149 | } else {
150 | SharedPreferences spn = context.getSharedPreferences("JZVD_PROGRESS",
151 | Context.MODE_PRIVATE);
152 | spn.edit().putLong("newVersion:" + url.toString(), 0).apply();
153 | }
154 | }
155 |
156 | public static Object getCurrentFromDataSource(Object[] dataSourceObjects, int index) {
157 | LinkedHashMap map = (LinkedHashMap) dataSourceObjects[0];
158 | if (map != null && map.size() > 0) {
159 | return getValueFromLinkedMap(map, index);
160 | }
161 | return null;
162 | }
163 |
164 | public static Object getValueFromLinkedMap(LinkedHashMap map, int index) {
165 | int currentIndex = 0;
166 | for (String key : map.keySet()) {
167 | if (currentIndex == index) {
168 | return map.get(key);
169 | }
170 | currentIndex++;
171 | }
172 | return null;
173 | }
174 |
175 | public static boolean dataSourceObjectsContainsUri(Object[] dataSourceObjects, Object object) {
176 | LinkedHashMap map = (LinkedHashMap) dataSourceObjects[0];
177 | if (map != null && object != null) {
178 | return map.containsValue(object);
179 | }
180 | return false;
181 | }
182 |
183 | public static String getKeyFromDataSource(Object[] dataSourceObjects, int index) {
184 | LinkedHashMap map = (LinkedHashMap) dataSourceObjects[0];
185 | int currentIndex = 0;
186 | for (String key : map.keySet()) {
187 | if (currentIndex == index) {
188 | return key;
189 | }
190 | currentIndex++;
191 | }
192 | return null;
193 | }
194 |
195 | public static float getViewVisiblePercent(View view) {
196 | if (view == null) {
197 | return 0f;
198 | }
199 | float height = view.getHeight();
200 | Rect rect = new Rect();
201 | if (!view.getLocalVisibleRect(rect)) {
202 | return 0f;
203 | }
204 | float visibleHeight = rect.bottom - rect.top;
205 | Log.d(TAG, "getViewVisiblePercent: emm " + visibleHeight);
206 | return visibleHeight / height;
207 | }
208 |
209 |
210 | public static void onScrollPlayVideo(AbsListView absListView, int firstVisiblePosition, int lastVisiblePosition) {
211 | for (int i = firstVisiblePosition; i <= lastVisiblePosition; i++) {
212 | View ad = absListView.getChildAt(i - firstVisiblePosition);
213 | View view = ad.findViewById(R.id.player);
214 | if (view != null && view instanceof JZVideoPlayerStandard) {
215 | JZVideoPlayerStandard player = (JZVideoPlayerStandard) view;
216 | Log.d(TAG, "onScrollStateChanged: " + JZUtils.getViewVisiblePercent(player));
217 | if (JZMediaManager.instance().positionInList != i && getViewVisiblePercent(player) == 1f) {
218 | player.startButton.performClick();
219 | break;
220 | }
221 | }
222 | }
223 | }
224 |
225 | public static void onScrollPlayVideo(RecyclerView recyclerView, int firstVisiblePosition, int lastVisiblePosition) {
226 | if (JZMediaManager.isWiFi) {
227 | for (int i = 0; i <= lastVisiblePosition - firstVisiblePosition; i++) {
228 | View child = recyclerView.getChildAt(i);
229 | View view = child.findViewById(R.id.player);
230 | if (view != null && view instanceof JZVideoPlayerStandard) {
231 | JZVideoPlayerStandard player = (JZVideoPlayerStandard) view;
232 | if (getViewVisiblePercent(player) == 1f) {
233 | if (JZMediaManager.instance().positionInList != i + firstVisiblePosition) {
234 | player.startButton.performClick();
235 | }
236 | break;
237 | }
238 | }
239 | }
240 | }
241 | }
242 |
243 | public static void onScrollReleaseAllVideos(AbsListView view, int firstVisiblePosition, int visibleItemCount, int totalItemCount) {
244 | onScrollReleaseAllVideos(firstVisiblePosition, firstVisiblePosition + visibleItemCount,0);
245 | }
246 |
247 | public static void onScrollReleaseAllVideos(int firstVisiblePosition, int lastVisiblePosition,float percent) {
248 | int currentPlayPosition = JZMediaManager.instance().positionInList;
249 | if (currentPlayPosition >= 0) {
250 | if ((currentPlayPosition <= firstVisiblePosition || currentPlayPosition >= lastVisiblePosition - 1)) {
251 | if (getViewVisiblePercent(JZVideoPlayerManager.getCurrentJzvd()) < percent) {
252 | JZVideoPlayer.releaseAllVideos();
253 | }
254 | }
255 | }
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/player/JZVideoPlayerManager.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.player;
2 |
3 | /**
4 | * Put JZVideoPlayer into layout
5 | * From a JZVideoPlayer to another JZVideoPlayer
6 | * Created by Nathen on 16/7/26.
7 | */
8 | public class JZVideoPlayerManager {
9 |
10 | public static JZVideoPlayer FIRST_FLOOR_JZVD;
11 | public static JZVideoPlayer SECOND_FLOOR_JZVD;
12 |
13 | public static JZVideoPlayer getFirstFloor() {
14 | return FIRST_FLOOR_JZVD;
15 | }
16 |
17 | public static void setFirstFloor(JZVideoPlayer jzVideoPlayer) {
18 | FIRST_FLOOR_JZVD = jzVideoPlayer;
19 | }
20 |
21 | public static JZVideoPlayer getSecondFloor() {
22 | return SECOND_FLOOR_JZVD;
23 | }
24 |
25 | public static void setSecondFloor(JZVideoPlayer jzVideoPlayer) {
26 | SECOND_FLOOR_JZVD = jzVideoPlayer;
27 | }
28 |
29 | public static JZVideoPlayer getCurrentJzvd() {
30 | if (getSecondFloor() != null) {
31 | return getSecondFloor();
32 | }
33 | return getFirstFloor();
34 | }
35 |
36 | public static void completeAll() {
37 | if (SECOND_FLOOR_JZVD != null) {
38 | SECOND_FLOOR_JZVD.onCompletion();
39 | SECOND_FLOOR_JZVD = null;
40 | }
41 | if (FIRST_FLOOR_JZVD != null) {
42 | FIRST_FLOOR_JZVD.onCompletion();
43 | FIRST_FLOOR_JZVD = null;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/player/SoDownloadIntentService.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.player;
2 |
3 | import android.app.IntentService;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.support.annotation.Nullable;
7 | import android.widget.Toast;
8 |
9 | import com.zzh12138.jzvideodemo.MyApplication;
10 |
11 | import java.io.File;
12 | import java.io.FileOutputStream;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.net.URL;
16 | import java.net.URLConnection;
17 |
18 | /**
19 | * Created by zhangzhihao on 2018/10/10 14:37.
20 | */
21 | public class SoDownloadIntentService extends IntentService {
22 |
23 |
24 | public SoDownloadIntentService() {
25 | super("SoDownloadIntentService");
26 | }
27 |
28 | @Override
29 | protected void onHandleIntent(@Nullable Intent intent) {
30 | File dir = getDir("libs", Context.MODE_PRIVATE);
31 | File soFile = new File(dir, "ijkffmpeg.so");
32 | if (soFile.exists()) {
33 | if (JZVideoPlayerManager.getCurrentJzvd() == null) {
34 | JZVideoPlayer.setMediaInterface(new JZMediaIjkplayer());
35 | }
36 | } else {
37 | String url = "http://bmob-cdn-21848.b0.upaiyun.com/2018/10/12/2296183a4014f71080f878c0818d38b0.so";
38 | try {
39 | URL downUrl = new URL(url);
40 | URLConnection connection = downUrl.openConnection();
41 | InputStream is = connection.getInputStream();
42 | int fileSize = connection.getContentLength();
43 | if (fileSize <= 0) {
44 | throw new RuntimeException("file error");
45 | }
46 | if (is == null) {
47 | throw new RuntimeException("stream is null");
48 | }
49 | if (!dir.exists()) {
50 | dir.mkdirs();
51 | }
52 | FileOutputStream fos = new FileOutputStream(soFile);
53 | byte buf[] = new byte[1024];
54 | do {
55 | int num = is.read(buf);
56 | if (num == -1) {
57 | break;
58 | }
59 | fos.write(buf, 0, num);
60 | } while (true);
61 | is.close();
62 | if (JZVideoPlayerManager.getCurrentJzvd() == null) {
63 | JZVideoPlayer.setMediaInterface(new JZMediaIjkplayer());
64 | }
65 | } catch (Exception e) {
66 | e.printStackTrace();
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/view/MaskView.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.view;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.support.annotation.Nullable;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 |
12 | import com.zzh12138.jzvideodemo.R;
13 |
14 |
15 | /**
16 | * Created by zhangzhihao on 2018/8/14 18:32.
17 | */
18 | public class MaskView extends View {
19 | private static final String TAG = "MaskView";
20 | private int BACKGROUND_COLOR = 0xFF000000;
21 | private int startY;
22 | private int endY;
23 | private Paint mPaint;
24 | private int mBackgroundColor;
25 | private int mWidth;
26 | private int mHeight;
27 |
28 |
29 | public MaskView(Context context) {
30 | this(context, null);
31 | }
32 |
33 | public MaskView(Context context, @Nullable AttributeSet attrs) {
34 | this(context, attrs, 0);
35 | }
36 |
37 | public MaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
38 | super(context, attrs, defStyleAttr);
39 | if (attrs != null) {
40 | TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.MaskView);
41 | mBackgroundColor = arr.getColor(R.styleable.MaskView_backgroundColor, BACKGROUND_COLOR);
42 | arr.recycle();
43 | }
44 | mPaint = new Paint();
45 | mPaint.setStyle(Paint.Style.FILL);
46 | mPaint.setColor(mBackgroundColor);
47 | }
48 |
49 | @Override
50 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
51 | super.onSizeChanged(w, h, oldw, oldh);
52 | mWidth = w;
53 | mHeight = h;
54 | }
55 |
56 | @Override
57 | protected void onDraw(Canvas canvas) {
58 | super.onDraw(canvas);
59 | canvas.drawRect(0, 0, mWidth, startY, mPaint);
60 | mPaint.setColor(Color.TRANSPARENT);
61 | canvas.drawRect(0, startY, mWidth, endY, mPaint);
62 | mPaint.setColor(mBackgroundColor);
63 | canvas.drawRect(0, endY, mWidth, mHeight, mPaint);
64 | }
65 |
66 | public void changeMaskLocation(int startY, int endY) {
67 | this.startY = startY;
68 | this.endY = endY;
69 | invalidate();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/view/PlayerContainer.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.view;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.util.AttributeSet;
7 | import android.widget.FrameLayout;
8 |
9 | /**
10 | * Created by zhangzhihao on 2018/8/30 9:56.
11 | * 播放器容器
12 | * 只有当需要做页面平移的时候才需要使用
13 | */
14 | public class PlayerContainer extends FrameLayout {
15 | private float widthRatio, heightRatio;
16 |
17 | public PlayerContainer(@NonNull Context context) {
18 | super(context);
19 | }
20 |
21 | public PlayerContainer(@NonNull Context context, @Nullable AttributeSet attrs) {
22 | super(context, attrs);
23 | }
24 |
25 | public PlayerContainer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
26 | super(context, attrs, defStyleAttr);
27 | }
28 |
29 | @Override
30 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
31 | if (widthRatio == 0f || heightRatio == 0f) {
32 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
33 | } else {
34 | int specWidth = MeasureSpec.getSize(widthMeasureSpec);
35 | int specHeight = (int) (specWidth * heightRatio / widthRatio);
36 | setMeasuredDimension(specWidth, specHeight);
37 | if(getChildCount()>0) {
38 | int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(specWidth, MeasureSpec.EXACTLY);
39 | int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(specHeight, MeasureSpec.EXACTLY);
40 | getChildAt(0).measure(childWidthMeasureSpec, childHeightMeasureSpec);
41 | }
42 | }
43 | }
44 |
45 | public PlayerContainer setWidthRatio(float widthRatio) {
46 | this.widthRatio = widthRatio;
47 | return this;
48 | }
49 |
50 | public PlayerContainer setHeightRatio(float heightRatio) {
51 | this.heightRatio = heightRatio;
52 | return this;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzh12138/jzvideodemo/view/VoiceAnimationView.java:
--------------------------------------------------------------------------------
1 | package com.zzh12138.jzvideodemo.view;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.support.annotation.Nullable;
8 | import android.util.AttributeSet;
9 | import android.view.View;
10 |
11 | import com.zzh12138.jzvideodemo.R;
12 |
13 |
14 | /**
15 | * Created by zhangzhihao on 2018/7/26 10:10.
16 | */
17 |
18 | public class VoiceAnimationView extends View {
19 | private static final String TAG = "VoiceAnimationView";
20 |
21 | private static final int DEFAULT_COLOR = 0xffffffff;
22 | private static final int DEFAULT_NUM = 3;
23 | private static final int DEFAULT_WIDTH = 5;
24 | private Paint mPaint;
25 | /**
26 | * 矩形个数
27 | */
28 | private int mCount;
29 | /**
30 | * 矩形间距
31 | */
32 | private float mPadding;
33 | /**
34 | * 矩形最大高度,默认为控件高度
35 | */
36 | private float maxRectangleHeight;
37 | /**
38 | * 矩形最小高度
39 | */
40 | private float minRectangleHeight;
41 | private float mRectangleWidth;
42 | /**
43 | * 颜色
44 | */
45 | private int mColor;
46 |
47 | private float percent;
48 |
49 | public VoiceAnimationView(Context context) {
50 | this(context, null);
51 | }
52 |
53 | public VoiceAnimationView(Context context, @Nullable AttributeSet attrs) {
54 | this(context, attrs, 0);
55 | }
56 |
57 | public VoiceAnimationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
58 | super(context, attrs, defStyleAttr);
59 | if (attrs != null) {
60 | TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.VoiceAnimationView);
61 | mColor = arr.getColor(R.styleable.VoiceAnimationView_rectangleColor, DEFAULT_COLOR);
62 | mCount = arr.getInteger(R.styleable.VoiceAnimationView_rectangleNum, DEFAULT_NUM);
63 | mPadding = arr.getDimension(R.styleable.VoiceAnimationView_rectanglePadding, DEFAULT_WIDTH);
64 | }
65 | mPaint = new Paint();
66 | mPaint.setAntiAlias(true);
67 | mPaint.setColor(mColor);
68 | mPaint.setStyle(Paint.Style.FILL);
69 | }
70 |
71 |
72 | @Override
73 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
74 | super.onSizeChanged(w, h, oldw, oldh);
75 | maxRectangleHeight = h-getPaddingBottom()-getPaddingTop();
76 | minRectangleHeight = h / 3f;
77 | mRectangleWidth = (w - getPaddingLeft() - getPaddingRight() - mPadding * (mCount - 1)) / (float) mCount;
78 | }
79 |
80 | @Override
81 | protected void onDraw(Canvas canvas) {
82 | super.onDraw(canvas);
83 | for (int i = 0; i < mCount; i++) {
84 | float top ;
85 | if ((i & 1) != 0) {
86 | top = (maxRectangleHeight - minRectangleHeight) * (1 - percent);
87 | } else {
88 | top = (maxRectangleHeight - minRectangleHeight - 5) * percent + i * 5;
89 | }
90 | if (top > maxRectangleHeight - minRectangleHeight) {
91 | top = maxRectangleHeight - minRectangleHeight;
92 | }
93 | canvas.drawRect(getPaddingLeft() + i * (mRectangleWidth + mPadding), top+getPaddingTop(),
94 | getPaddingLeft() + mRectangleWidth + i * (mRectangleWidth + mPadding), maxRectangleHeight , mPaint);
95 | }
96 | }
97 |
98 | public float getPercent() {
99 | return percent;
100 | }
101 |
102 | public void setPercent(float percent) {
103 | this.percent = percent;
104 | invalidate();
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_mute_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_player_controller_shadow.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/bg_player_controller_shadow.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_player_replay.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_player_standard_seek.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 | -
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | -
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_player_top_shadow.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_player_voice_shadow.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/bg_player_voice_shadow.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/bg_rectangle_red_corner_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_comment.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_left_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_left_back.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_full_screen.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_full_screen.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_loading.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_loading.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_mute.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_mute.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_not_mute.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_not_mute.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_pause.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_pause.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_play.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_play.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_replay.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_replay.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_player_seek_thumb.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_player_seek_thumb.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_praise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_praise.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_share.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/icon_share.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/logo_qq.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/logo_qq.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/logo_sinaweibo.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/logo_sinaweibo.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/logo_wechat.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/logo_wechat.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/logo_wechatmoments.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/drawable-xhdpi/logo_wechatmoments.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/player_loading.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/line.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/adapter_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
29 |
30 |
41 |
42 |
56 |
57 |
68 |
69 |
80 |
81 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/adapter_news_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/adapter_news_video.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
21 |
22 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/adapter_video.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
21 |
22 |
26 |
27 |
28 |
33 |
34 |
42 |
43 |
55 |
56 |
67 |
68 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_video_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
25 |
26 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_video_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
19 |
20 |
27 |
28 |
34 |
35 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_no_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_player_pause.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-xhdpi/icon_player_pause.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zzh12138/JZVideoDemo/e0c114d25e7dbc695e811e3f5fb09aa46497e014/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #ffffff
7 | #000000
8 | #00000000
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | JZVideoDemo
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.1.3'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Sep 12 09:48:12 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/ijk/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/ijk/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 27
5 |
6 |
7 |
8 | defaultConfig {
9 | minSdkVersion 15
10 | targetSdkVersion 27
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 |
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(dir: 'libs', include: ['*.jar'])
29 |
30 | implementation 'com.android.support:appcompat-v7:27.1.1'
31 | testImplementation 'junit:junit:4.12'
32 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
34 | }
35 |
--------------------------------------------------------------------------------
/ijk/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/ijk/src/androidTest/java/tv/danmaku/ijk/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package tv.danmaku.ijk;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("tv.danmaku.ijk.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ijk/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
21 |
22 | @SuppressWarnings("WeakerAccess")
23 | public abstract class AbstractMediaPlayer implements IMediaPlayer {
24 | private OnPreparedListener mOnPreparedListener;
25 | private OnCompletionListener mOnCompletionListener;
26 | private OnBufferingUpdateListener mOnBufferingUpdateListener;
27 | private OnSeekCompleteListener mOnSeekCompleteListener;
28 | private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
29 | private OnErrorListener mOnErrorListener;
30 | private OnInfoListener mOnInfoListener;
31 | private OnTimedTextListener mOnTimedTextListener;
32 |
33 | public final void setOnPreparedListener(OnPreparedListener listener) {
34 | mOnPreparedListener = listener;
35 | }
36 |
37 | public final void setOnCompletionListener(OnCompletionListener listener) {
38 | mOnCompletionListener = listener;
39 | }
40 |
41 | public final void setOnBufferingUpdateListener(
42 | OnBufferingUpdateListener listener) {
43 | mOnBufferingUpdateListener = listener;
44 | }
45 |
46 | public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
47 | mOnSeekCompleteListener = listener;
48 | }
49 |
50 | public final void setOnVideoSizeChangedListener(
51 | OnVideoSizeChangedListener listener) {
52 | mOnVideoSizeChangedListener = listener;
53 | }
54 |
55 | public final void setOnErrorListener(OnErrorListener listener) {
56 | mOnErrorListener = listener;
57 | }
58 |
59 | public final void setOnInfoListener(OnInfoListener listener) {
60 | mOnInfoListener = listener;
61 | }
62 |
63 | public final void setOnTimedTextListener(OnTimedTextListener listener) {
64 | mOnTimedTextListener = listener;
65 | }
66 |
67 | public void resetListeners() {
68 | mOnPreparedListener = null;
69 | mOnBufferingUpdateListener = null;
70 | mOnCompletionListener = null;
71 | mOnSeekCompleteListener = null;
72 | mOnVideoSizeChangedListener = null;
73 | mOnErrorListener = null;
74 | mOnInfoListener = null;
75 | mOnTimedTextListener = null;
76 | }
77 |
78 | protected final void notifyOnPrepared() {
79 | if (mOnPreparedListener != null)
80 | mOnPreparedListener.onPrepared(this);
81 | }
82 |
83 | protected final void notifyOnCompletion() {
84 | if (mOnCompletionListener != null)
85 | mOnCompletionListener.onCompletion(this);
86 | }
87 |
88 | protected final void notifyOnBufferingUpdate(int percent) {
89 | if (mOnBufferingUpdateListener != null)
90 | mOnBufferingUpdateListener.onBufferingUpdate(this, percent);
91 | }
92 |
93 | protected final void notifyOnSeekComplete() {
94 | if (mOnSeekCompleteListener != null)
95 | mOnSeekCompleteListener.onSeekComplete(this);
96 | }
97 |
98 | protected final void notifyOnVideoSizeChanged(int width, int height,
99 | int sarNum, int sarDen) {
100 | if (mOnVideoSizeChangedListener != null)
101 | mOnVideoSizeChangedListener.onVideoSizeChanged(this, width, height,
102 | sarNum, sarDen);
103 | }
104 |
105 | protected final boolean notifyOnError(int what, int extra) {
106 | return mOnErrorListener != null && mOnErrorListener.onError(this, what, extra);
107 | }
108 |
109 | protected final boolean notifyOnInfo(int what, int extra) {
110 | return mOnInfoListener != null && mOnInfoListener.onInfo(this, what, extra);
111 | }
112 |
113 | protected final void notifyOnTimedText(IjkTimedText text) {
114 | if (mOnTimedTextListener != null)
115 | mOnTimedTextListener.onTimedText(this, text);
116 | }
117 |
118 | public void setDataSource(IMediaDataSource mediaDataSource) {
119 | throw new UnsupportedOperationException();
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | import android.annotation.TargetApi;
21 | import android.content.Context;
22 | import android.net.Uri;
23 | import android.os.Build;
24 | import android.view.Surface;
25 | import android.view.SurfaceHolder;
26 |
27 | import java.io.FileDescriptor;
28 | import java.io.IOException;
29 | import java.util.Map;
30 |
31 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
32 | import tv.danmaku.ijk.media.player.misc.ITrackInfo;
33 |
34 | public interface IMediaPlayer {
35 | /*
36 | * Do not change these values without updating their counterparts in native
37 | */
38 | int MEDIA_INFO_UNKNOWN = 1;
39 | int MEDIA_INFO_STARTED_AS_NEXT = 2;
40 | int MEDIA_INFO_VIDEO_RENDERING_START = 3;
41 | int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;
42 | int MEDIA_INFO_BUFFERING_START = 701;
43 | int MEDIA_INFO_BUFFERING_END = 702;
44 | int MEDIA_INFO_NETWORK_BANDWIDTH = 703;
45 | int MEDIA_INFO_BAD_INTERLEAVING = 800;
46 | int MEDIA_INFO_NOT_SEEKABLE = 801;
47 | int MEDIA_INFO_METADATA_UPDATE = 802;
48 | int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
49 | int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;
50 | int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;
51 |
52 | int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;
53 | int MEDIA_INFO_AUDIO_RENDERING_START = 10002;
54 | int MEDIA_INFO_AUDIO_DECODED_START = 10003;
55 | int MEDIA_INFO_VIDEO_DECODED_START = 10004;
56 | int MEDIA_INFO_OPEN_INPUT = 10005;
57 | int MEDIA_INFO_FIND_STREAM_INFO = 10006;
58 | int MEDIA_INFO_COMPONENT_OPEN = 10007;
59 | int MEDIA_INFO_VIDEO_SEEK_RENDERING_START = 10008;
60 | int MEDIA_INFO_AUDIO_SEEK_RENDERING_START = 10009;
61 | int MEDIA_INFO_MEDIA_ACCURATE_SEEK_COMPLETE = 10100;
62 |
63 | int MEDIA_ERROR_UNKNOWN = 1;
64 | int MEDIA_ERROR_SERVER_DIED = 100;
65 | int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;
66 | int MEDIA_ERROR_IO = -1004;
67 | int MEDIA_ERROR_MALFORMED = -1007;
68 | int MEDIA_ERROR_UNSUPPORTED = -1010;
69 | int MEDIA_ERROR_TIMED_OUT = -110;
70 |
71 | void setDisplay(SurfaceHolder sh);
72 |
73 | void setDataSource(Context context, Uri uri)
74 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
75 |
76 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
77 | void setDataSource(Context context, Uri uri, Map headers)
78 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
79 |
80 | void setDataSource(FileDescriptor fd)
81 | throws IOException, IllegalArgumentException, IllegalStateException;
82 |
83 | void setDataSource(String path)
84 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
85 |
86 | String getDataSource();
87 |
88 | void prepareAsync() throws IllegalStateException;
89 |
90 | void start() throws IllegalStateException;
91 |
92 | void stop() throws IllegalStateException;
93 |
94 | void pause() throws IllegalStateException;
95 |
96 | void setScreenOnWhilePlaying(boolean screenOn);
97 |
98 | int getVideoWidth();
99 |
100 | int getVideoHeight();
101 |
102 | boolean isPlaying();
103 |
104 | void seekTo(long msec) throws IllegalStateException;
105 |
106 | long getCurrentPosition();
107 |
108 | long getDuration();
109 |
110 | void release();
111 |
112 | void reset();
113 |
114 | void setVolume(float leftVolume, float rightVolume);
115 |
116 | int getAudioSessionId();
117 |
118 | MediaInfo getMediaInfo();
119 |
120 | @SuppressWarnings("EmptyMethod")
121 | @Deprecated
122 | void setLogEnabled(boolean enable);
123 |
124 | @Deprecated
125 | boolean isPlayable();
126 |
127 | void setOnPreparedListener(OnPreparedListener listener);
128 |
129 | void setOnCompletionListener(OnCompletionListener listener);
130 |
131 | void setOnBufferingUpdateListener(
132 | OnBufferingUpdateListener listener);
133 |
134 | void setOnSeekCompleteListener(
135 | OnSeekCompleteListener listener);
136 |
137 | void setOnVideoSizeChangedListener(
138 | OnVideoSizeChangedListener listener);
139 |
140 | void setOnErrorListener(OnErrorListener listener);
141 |
142 | void setOnInfoListener(OnInfoListener listener);
143 |
144 | void setOnTimedTextListener(OnTimedTextListener listener);
145 |
146 | /*--------------------
147 | * Listeners
148 | */
149 | interface OnPreparedListener {
150 | void onPrepared(IMediaPlayer mp);
151 | }
152 |
153 | interface OnCompletionListener {
154 | void onCompletion(IMediaPlayer mp);
155 | }
156 |
157 | interface OnBufferingUpdateListener {
158 | void onBufferingUpdate(IMediaPlayer mp, int percent);
159 | }
160 |
161 | interface OnSeekCompleteListener {
162 | void onSeekComplete(IMediaPlayer mp);
163 | }
164 |
165 | interface OnVideoSizeChangedListener {
166 | void onVideoSizeChanged(IMediaPlayer mp, int width, int height,
167 | int sar_num, int sar_den);
168 | }
169 |
170 | interface OnErrorListener {
171 | boolean onError(IMediaPlayer mp, int what, int extra);
172 | }
173 |
174 | interface OnInfoListener {
175 | boolean onInfo(IMediaPlayer mp, int what, int extra);
176 | }
177 |
178 | interface OnTimedTextListener {
179 | void onTimedText(IMediaPlayer mp, IjkTimedText text);
180 | }
181 |
182 | /*--------------------
183 | * Optional
184 | */
185 | void setAudioStreamType(int streamtype);
186 |
187 | @Deprecated
188 | void setKeepInBackground(boolean keepInBackground);
189 |
190 | int getVideoSarNum();
191 |
192 | int getVideoSarDen();
193 |
194 | @Deprecated
195 | void setWakeMode(Context context, int mode);
196 |
197 | void setLooping(boolean looping);
198 |
199 | boolean isLooping();
200 |
201 | /*--------------------
202 | * AndroidMediaPlayer: JELLY_BEAN
203 | */
204 | ITrackInfo[] getTrackInfo();
205 |
206 | /*--------------------
207 | * AndroidMediaPlayer: ICE_CREAM_SANDWICH:
208 | */
209 | void setSurface(Surface surface);
210 |
211 | /*--------------------
212 | * AndroidMediaPlayer: M:
213 | */
214 | void setDataSource(IMediaDataSource mediaDataSource);
215 | }
216 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | import android.graphics.SurfaceTexture;
21 |
22 | public interface ISurfaceTextureHolder {
23 | void setSurfaceTexture(SurfaceTexture surfaceTexture);
24 |
25 | SurfaceTexture getSurfaceTexture();
26 |
27 | void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost);
28 | }
29 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | import android.graphics.SurfaceTexture;
21 |
22 | public interface ISurfaceTextureHost {
23 | void releaseSurfaceTexture(SurfaceTexture surfaceTexture);
24 | }
25 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | public interface IjkLibLoader {
21 | void loadLibrary(String libName) throws UnsatisfiedLinkError,
22 | SecurityException;
23 | }
24 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java:
--------------------------------------------------------------------------------
1 | package tv.danmaku.ijk.media.player;
2 |
3 | import android.annotation.TargetApi;
4 | import android.media.MediaCodecInfo;
5 | import android.media.MediaCodecInfo.CodecCapabilities;
6 | import android.media.MediaCodecInfo.CodecProfileLevel;
7 | import android.os.Build;
8 | import android.text.TextUtils;
9 | import android.util.Log;
10 |
11 | import java.util.Locale;
12 | import java.util.Map;
13 | import java.util.TreeMap;
14 |
15 | public class IjkMediaCodecInfo {
16 | private final static String TAG = "IjkMediaCodecInfo";
17 |
18 | public static final int RANK_MAX = 1000;
19 | public static final int RANK_TESTED = 800;
20 | public static final int RANK_ACCEPTABLE = 700;
21 | public static final int RANK_LAST_CHANCE = 600;
22 | public static final int RANK_SECURE = 300;
23 | public static final int RANK_SOFTWARE = 200;
24 | public static final int RANK_NON_STANDARD = 100;
25 | public static final int RANK_NO_SENSE = 0;
26 |
27 | public MediaCodecInfo mCodecInfo;
28 | public int mRank = 0;
29 | public String mMimeType;
30 |
31 | private static Map sKnownCodecList;
32 |
33 | private static synchronized Map getKnownCodecList() {
34 | if (sKnownCodecList != null)
35 | return sKnownCodecList;
36 |
37 | sKnownCodecList = new TreeMap(
38 | String.CASE_INSENSITIVE_ORDER);
39 |
40 | // ----- Nvidia -----
41 | // Tegra3
42 | // Nexus 7 (2012)
43 | // Tegra K1
44 | // Nexus 9
45 | sKnownCodecList.put("OMX.Nvidia.h264.decode", RANK_TESTED);
46 | sKnownCodecList.put("OMX.Nvidia.h264.decode.secure", RANK_SECURE);
47 |
48 | // ----- Intel -----
49 | // Atom Z3735
50 | // Teclast X98 Air
51 | sKnownCodecList.put("OMX.Intel.hw_vd.h264", RANK_TESTED + 1);
52 | // Atom Z2560
53 | // Dell Venue 7 3730
54 | sKnownCodecList.put("OMX.Intel.VideoDecoder.AVC", RANK_TESTED);
55 |
56 | // ----- Qualcomm -----
57 | // MSM8260
58 | // Xiaomi MI 1S
59 | sKnownCodecList.put("OMX.qcom.video.decoder.avc", RANK_TESTED);
60 | sKnownCodecList.put("OMX.ittiam.video.decoder.avc", RANK_NO_SENSE);
61 |
62 | // ----- Samsung -----
63 | // Exynos 3110
64 | // Nexus S
65 | sKnownCodecList.put("OMX.SEC.avc.dec", RANK_TESTED);
66 | sKnownCodecList.put("OMX.SEC.AVC.Decoder", RANK_TESTED - 1);
67 | // OMX.SEC.avcdec doesn't reorder output pictures on GT-9100
68 | sKnownCodecList.put("OMX.SEC.avcdec", RANK_TESTED - 2);
69 | sKnownCodecList.put("OMX.SEC.avc.sw.dec", RANK_SOFTWARE);
70 | // Exynos 5 ?
71 | sKnownCodecList.put("OMX.Exynos.avc.dec", RANK_TESTED);
72 | sKnownCodecList.put("OMX.Exynos.AVC.Decoder", RANK_TESTED - 1);
73 |
74 | // ------ Huawei hisilicon ------
75 | // Kirin 910, Mali 450 MP
76 | // Huawei HONOR 3C (H30-L01)
77 | sKnownCodecList.put("OMX.k3.video.decoder.avc", RANK_TESTED);
78 | // Kirin 920, Mali T624
79 | // Huawei HONOR 6
80 | sKnownCodecList.put("OMX.IMG.MSVDX.Decoder.AVC", RANK_TESTED);
81 |
82 | // ----- TI -----
83 | // TI OMAP4460
84 | // Galaxy Nexus
85 | sKnownCodecList.put("OMX.TI.DUCATI1.VIDEO.DECODER", RANK_TESTED);
86 |
87 | // ------ RockChip ------
88 | // Youku TVBox
89 | sKnownCodecList.put("OMX.rk.video_decoder.avc", RANK_TESTED);
90 |
91 | // ------ AMLogic -----
92 | // MiBox1, 1s, 2
93 | sKnownCodecList.put("OMX.amlogic.avc.decoder.awesome", RANK_TESTED);
94 |
95 | // ------ Marvell ------
96 | // Lenovo A788t
97 | sKnownCodecList.put("OMX.MARVELL.VIDEO.HW.CODA7542DECODER", RANK_TESTED);
98 | sKnownCodecList.put("OMX.MARVELL.VIDEO.H264DECODER", RANK_SOFTWARE);
99 |
100 | // ----- TODO: need test -----
101 | sKnownCodecList.remove("OMX.Action.Video.Decoder");
102 | sKnownCodecList.remove("OMX.allwinner.video.decoder.avc");
103 | sKnownCodecList.remove("OMX.BRCM.vc4.decoder.avc");
104 | sKnownCodecList.remove("OMX.brcm.video.h264.hw.decoder");
105 | sKnownCodecList.remove("OMX.brcm.video.h264.decoder");
106 | sKnownCodecList.remove("OMX.cosmo.video.decoder.avc");
107 | sKnownCodecList.remove("OMX.duos.h264.decoder");
108 | sKnownCodecList.remove("OMX.hantro.81x0.video.decoder");
109 | sKnownCodecList.remove("OMX.hantro.G1.video.decoder");
110 | sKnownCodecList.remove("OMX.hisi.video.decoder");
111 | sKnownCodecList.remove("OMX.LG.decoder.video.avc");
112 | sKnownCodecList.remove("OMX.MS.AVC.Decoder");
113 | sKnownCodecList.remove("OMX.RENESAS.VIDEO.DECODER.H264");
114 | sKnownCodecList.remove("OMX.RTK.video.decoder");
115 | sKnownCodecList.remove("OMX.sprd.h264.decoder");
116 | sKnownCodecList.remove("OMX.ST.VFM.H264Dec");
117 | sKnownCodecList.remove("OMX.vpu.video_decoder.avc");
118 | sKnownCodecList.remove("OMX.WMT.decoder.avc");
119 |
120 | // Really ?
121 | sKnownCodecList.remove("OMX.bluestacks.hw.decoder");
122 |
123 | // ---------------
124 | // Useless codec
125 | // ----- google -----
126 | sKnownCodecList.put("OMX.google.h264.decoder", RANK_SOFTWARE);
127 | sKnownCodecList.put("OMX.google.h264.lc.decoder", RANK_SOFTWARE);
128 | // ----- huawei k920 -----
129 | sKnownCodecList.put("OMX.k3.ffmpeg.decoder", RANK_SOFTWARE);
130 | sKnownCodecList.put("OMX.ffmpeg.video.decoder", RANK_SOFTWARE);
131 | // ----- unknown -----
132 | sKnownCodecList.put("OMX.sprd.soft.h264.decoder", RANK_SOFTWARE);
133 |
134 | return sKnownCodecList;
135 | }
136 |
137 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
138 | public static IjkMediaCodecInfo setupCandidate(MediaCodecInfo codecInfo,
139 | String mimeType) {
140 | if (codecInfo == null
141 | || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
142 | return null;
143 |
144 | String name = codecInfo.getName();
145 | if (TextUtils.isEmpty(name))
146 | return null;
147 |
148 | name = name.toLowerCase(Locale.US);
149 | int rank = RANK_NO_SENSE;
150 | if (!name.startsWith("omx.")) {
151 | rank = RANK_NON_STANDARD;
152 | } else if (name.startsWith("omx.pv")) {
153 | rank = RANK_SOFTWARE;
154 | } else if (name.startsWith("omx.google.")) {
155 | rank = RANK_SOFTWARE;
156 | } else if (name.startsWith("omx.ffmpeg.")) {
157 | rank = RANK_SOFTWARE;
158 | } else if (name.startsWith("omx.k3.ffmpeg.")) {
159 | rank = RANK_SOFTWARE;
160 | } else if (name.startsWith("omx.avcodec.")) {
161 | rank = RANK_SOFTWARE;
162 | } else if (name.startsWith("omx.ittiam.")) {
163 | // unknown codec in qualcomm SoC
164 | rank = RANK_NO_SENSE;
165 | } else if (name.startsWith("omx.mtk.")) {
166 | // 1. MTK only works on 4.3 and above
167 | // 2. MTK works on MIUI 6 (4.2.1)
168 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
169 | rank = RANK_NO_SENSE;
170 | else
171 | rank = RANK_TESTED;
172 | } else {
173 | Integer knownRank = getKnownCodecList().get(name);
174 | if (knownRank != null) {
175 | rank = knownRank;
176 | } else {
177 | try {
178 | CodecCapabilities cap = codecInfo
179 | .getCapabilitiesForType(mimeType);
180 | if (cap != null)
181 | rank = RANK_ACCEPTABLE;
182 | else
183 | rank = RANK_LAST_CHANCE;
184 | } catch (Throwable e) {
185 | rank = RANK_LAST_CHANCE;
186 | }
187 | }
188 | }
189 |
190 | IjkMediaCodecInfo candidate = new IjkMediaCodecInfo();
191 | candidate.mCodecInfo = codecInfo;
192 | candidate.mRank = rank;
193 | candidate.mMimeType = mimeType;
194 | return candidate;
195 | }
196 |
197 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
198 | public void dumpProfileLevels(String mimeType) {
199 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
200 | return;
201 |
202 | try {
203 | CodecCapabilities caps = mCodecInfo
204 | .getCapabilitiesForType(mimeType);
205 | int maxProfile = 0;
206 | int maxLevel = 0;
207 | if (caps != null) {
208 | if (caps.profileLevels != null) {
209 | for (CodecProfileLevel profileLevel : caps.profileLevels) {
210 | if (profileLevel == null)
211 | continue;
212 |
213 | maxProfile = Math.max(maxProfile, profileLevel.profile);
214 | maxLevel = Math.max(maxLevel, profileLevel.level);
215 | }
216 | }
217 | }
218 |
219 | Log.i(TAG,
220 | String.format(Locale.US, "%s",
221 | getProfileLevelName(maxProfile, maxLevel)));
222 | } catch (Throwable e) {
223 | Log.i(TAG, "profile-level: exception");
224 | }
225 | }
226 |
227 | public static String getProfileLevelName(int profile, int level) {
228 | return String.format(Locale.US, " %s Profile Level %s (%d,%d)",
229 | getProfileName(profile), getLevelName(level), profile, level);
230 | }
231 |
232 | public static String getProfileName(int profile) {
233 | switch (profile) {
234 | case CodecProfileLevel.AVCProfileBaseline:
235 | return "Baseline";
236 | case CodecProfileLevel.AVCProfileMain:
237 | return "Main";
238 | case CodecProfileLevel.AVCProfileExtended:
239 | return "Extends";
240 | case CodecProfileLevel.AVCProfileHigh:
241 | return "High";
242 | case CodecProfileLevel.AVCProfileHigh10:
243 | return "High10";
244 | case CodecProfileLevel.AVCProfileHigh422:
245 | return "High422";
246 | case CodecProfileLevel.AVCProfileHigh444:
247 | return "High444";
248 | default:
249 | return "Unknown";
250 | }
251 | }
252 |
253 | public static String getLevelName(int level) {
254 | switch (level) {
255 | case CodecProfileLevel.AVCLevel1:
256 | return "1";
257 | case CodecProfileLevel.AVCLevel1b:
258 | return "1b";
259 | case CodecProfileLevel.AVCLevel11:
260 | return "11";
261 | case CodecProfileLevel.AVCLevel12:
262 | return "12";
263 | case CodecProfileLevel.AVCLevel13:
264 | return "13";
265 | case CodecProfileLevel.AVCLevel2:
266 | return "2";
267 | case CodecProfileLevel.AVCLevel21:
268 | return "21";
269 | case CodecProfileLevel.AVCLevel22:
270 | return "22";
271 | case CodecProfileLevel.AVCLevel3:
272 | return "3";
273 | case CodecProfileLevel.AVCLevel31:
274 | return "31";
275 | case CodecProfileLevel.AVCLevel32:
276 | return "32";
277 | case CodecProfileLevel.AVCLevel4:
278 | return "4";
279 | case CodecProfileLevel.AVCLevel41:
280 | return "41";
281 | case CodecProfileLevel.AVCLevel42:
282 | return "42";
283 | case CodecProfileLevel.AVCLevel5:
284 | return "5";
285 | case CodecProfileLevel.AVCLevel51:
286 | return "51";
287 | case 65536: // CodecProfileLevel.AVCLevel52:
288 | return "52";
289 | default:
290 | return "0";
291 | }
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/IjkTimedText.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Zheng Yuan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package tv.danmaku.ijk.media.player;
18 |
19 | import android.graphics.Rect;
20 | import java.lang.String;
21 |
22 | public final class IjkTimedText {
23 |
24 | private Rect mTextBounds = null;
25 | private String mTextChars = null;
26 |
27 | public IjkTimedText(Rect bounds, String text) {
28 | mTextBounds = bounds;
29 | mTextChars = text;
30 | }
31 |
32 | public Rect getBounds() {
33 | return mTextBounds;
34 | }
35 |
36 | public String getText() {
37 | return mTextChars;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | public class MediaInfo {
21 | public String mMediaPlayerName;
22 |
23 | public String mVideoDecoder;
24 | public String mVideoDecoderImpl;
25 |
26 | public String mAudioDecoder;
27 | public String mAudioDecoderImpl;
28 |
29 | public IjkMediaMeta mMeta;
30 | }
31 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | import android.annotation.TargetApi;
21 | import android.content.Context;
22 | import android.net.Uri;
23 | import android.os.Build;
24 | import android.view.Surface;
25 | import android.view.SurfaceHolder;
26 |
27 | import java.io.FileDescriptor;
28 | import java.io.IOException;
29 | import java.util.Map;
30 |
31 | import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
32 | import tv.danmaku.ijk.media.player.misc.ITrackInfo;
33 |
34 | public class MediaPlayerProxy implements IMediaPlayer {
35 | protected final IMediaPlayer mBackEndMediaPlayer;
36 |
37 | public MediaPlayerProxy(IMediaPlayer backEndMediaPlayer) {
38 | mBackEndMediaPlayer = backEndMediaPlayer;
39 | }
40 |
41 | public IMediaPlayer getInternalMediaPlayer() {
42 | return mBackEndMediaPlayer;
43 | }
44 |
45 | @Override
46 | public void setDisplay(SurfaceHolder sh) {
47 | mBackEndMediaPlayer.setDisplay(sh);
48 | }
49 |
50 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
51 | @Override
52 | public void setSurface(Surface surface) {
53 | mBackEndMediaPlayer.setSurface(surface);
54 | }
55 |
56 | @Override
57 | public void setDataSource(Context context, Uri uri)
58 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
59 | mBackEndMediaPlayer.setDataSource(context, uri);
60 | }
61 |
62 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
63 | @Override
64 | public void setDataSource(Context context, Uri uri, Map headers)
65 | throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
66 | mBackEndMediaPlayer.setDataSource(context, uri, headers);
67 | }
68 |
69 | @Override
70 | public void setDataSource(FileDescriptor fd)
71 | throws IOException, IllegalArgumentException, IllegalStateException {
72 | mBackEndMediaPlayer.setDataSource(fd);
73 | }
74 |
75 | @Override
76 | public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
77 | mBackEndMediaPlayer.setDataSource(path);
78 | }
79 |
80 | @Override
81 | public void setDataSource(IMediaDataSource mediaDataSource) {
82 | mBackEndMediaPlayer.setDataSource(mediaDataSource);
83 | }
84 |
85 | @Override
86 | public String getDataSource() {
87 | return mBackEndMediaPlayer.getDataSource();
88 | }
89 |
90 | @Override
91 | public void prepareAsync() throws IllegalStateException {
92 | mBackEndMediaPlayer.prepareAsync();
93 | }
94 |
95 | @Override
96 | public void start() throws IllegalStateException {
97 | mBackEndMediaPlayer.start();
98 | }
99 |
100 | @Override
101 | public void stop() throws IllegalStateException {
102 | mBackEndMediaPlayer.stop();
103 | }
104 |
105 | @Override
106 | public void pause() throws IllegalStateException {
107 | mBackEndMediaPlayer.pause();
108 | }
109 |
110 | @Override
111 | public void setScreenOnWhilePlaying(boolean screenOn) {
112 | mBackEndMediaPlayer.setScreenOnWhilePlaying(screenOn);
113 | }
114 |
115 | @Override
116 | public int getVideoWidth() {
117 | return mBackEndMediaPlayer.getVideoWidth();
118 | }
119 |
120 | @Override
121 | public int getVideoHeight() {
122 | return mBackEndMediaPlayer.getVideoHeight();
123 | }
124 |
125 | @Override
126 | public boolean isPlaying() {
127 | return mBackEndMediaPlayer.isPlaying();
128 | }
129 |
130 | @Override
131 | public void seekTo(long msec) throws IllegalStateException {
132 | mBackEndMediaPlayer.seekTo(msec);
133 | }
134 |
135 | @Override
136 | public long getCurrentPosition() {
137 | return mBackEndMediaPlayer.getCurrentPosition();
138 | }
139 |
140 | @Override
141 | public long getDuration() {
142 | return mBackEndMediaPlayer.getDuration();
143 | }
144 |
145 | @Override
146 | public void release() {
147 | mBackEndMediaPlayer.release();
148 | }
149 |
150 | @Override
151 | public void reset() {
152 | mBackEndMediaPlayer.reset();
153 | }
154 |
155 | @Override
156 | public void setVolume(float leftVolume, float rightVolume) {
157 | mBackEndMediaPlayer.setVolume(leftVolume, rightVolume);
158 | }
159 |
160 | @Override
161 | public int getAudioSessionId() {
162 | return mBackEndMediaPlayer.getAudioSessionId();
163 | }
164 |
165 | @Override
166 | public MediaInfo getMediaInfo() {
167 | return mBackEndMediaPlayer.getMediaInfo();
168 | }
169 |
170 | @Override
171 | public void setLogEnabled(boolean enable) {
172 |
173 | }
174 |
175 | @Override
176 | public boolean isPlayable() {
177 | return false;
178 | }
179 |
180 | @Override
181 | public void setOnPreparedListener(OnPreparedListener listener) {
182 | if (listener != null) {
183 | final OnPreparedListener finalListener = listener;
184 | mBackEndMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
185 | @Override
186 | public void onPrepared(IMediaPlayer mp) {
187 | finalListener.onPrepared(MediaPlayerProxy.this);
188 | }
189 | });
190 | } else {
191 | mBackEndMediaPlayer.setOnPreparedListener(null);
192 | }
193 | }
194 |
195 | @Override
196 | public void setOnCompletionListener(OnCompletionListener listener) {
197 | if (listener != null) {
198 | final OnCompletionListener finalListener = listener;
199 | mBackEndMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
200 | @Override
201 | public void onCompletion(IMediaPlayer mp) {
202 | finalListener.onCompletion(MediaPlayerProxy.this);
203 | }
204 | });
205 | } else {
206 | mBackEndMediaPlayer.setOnCompletionListener(null);
207 | }
208 | }
209 |
210 | @Override
211 | public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) {
212 | if (listener != null) {
213 | final OnBufferingUpdateListener finalListener = listener;
214 | mBackEndMediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
215 | @Override
216 | public void onBufferingUpdate(IMediaPlayer mp, int percent) {
217 | finalListener.onBufferingUpdate(MediaPlayerProxy.this, percent);
218 | }
219 | });
220 | } else {
221 | mBackEndMediaPlayer.setOnBufferingUpdateListener(null);
222 | }
223 | }
224 |
225 | @Override
226 | public void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
227 | if (listener != null) {
228 | final OnSeekCompleteListener finalListener = listener;
229 | mBackEndMediaPlayer.setOnSeekCompleteListener(new OnSeekCompleteListener() {
230 | @Override
231 | public void onSeekComplete(IMediaPlayer mp) {
232 | finalListener.onSeekComplete(MediaPlayerProxy.this);
233 | }
234 | });
235 | } else {
236 | mBackEndMediaPlayer.setOnSeekCompleteListener(null);
237 | }
238 | }
239 |
240 | @Override
241 | public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) {
242 | if (listener != null) {
243 | final OnVideoSizeChangedListener finalListener = listener;
244 | mBackEndMediaPlayer.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
245 | @Override
246 | public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) {
247 | finalListener.onVideoSizeChanged(MediaPlayerProxy.this, width, height, sar_num, sar_den);
248 | }
249 | });
250 | } else {
251 | mBackEndMediaPlayer.setOnVideoSizeChangedListener(null);
252 | }
253 | }
254 |
255 | @Override
256 | public void setOnErrorListener(OnErrorListener listener) {
257 | if (listener != null) {
258 | final OnErrorListener finalListener = listener;
259 | mBackEndMediaPlayer.setOnErrorListener(new OnErrorListener() {
260 | @Override
261 | public boolean onError(IMediaPlayer mp, int what, int extra) {
262 | return finalListener.onError(MediaPlayerProxy.this, what, extra);
263 | }
264 | });
265 | } else {
266 | mBackEndMediaPlayer.setOnErrorListener(null);
267 | }
268 | }
269 |
270 | @Override
271 | public void setOnInfoListener(OnInfoListener listener) {
272 | if (listener != null) {
273 | final OnInfoListener finalListener = listener;
274 | mBackEndMediaPlayer.setOnInfoListener(new OnInfoListener() {
275 | @Override
276 | public boolean onInfo(IMediaPlayer mp, int what, int extra) {
277 | return finalListener.onInfo(MediaPlayerProxy.this, what, extra);
278 | }
279 | });
280 | } else {
281 | mBackEndMediaPlayer.setOnInfoListener(null);
282 | }
283 | }
284 |
285 | @Override
286 | public void setOnTimedTextListener(OnTimedTextListener listener) {
287 | if (listener != null) {
288 | final OnTimedTextListener finalListener = listener;
289 | mBackEndMediaPlayer.setOnTimedTextListener(new OnTimedTextListener() {
290 | @Override
291 | public void onTimedText(IMediaPlayer mp, IjkTimedText text) {
292 | finalListener.onTimedText(MediaPlayerProxy.this, text);
293 | }
294 | });
295 | } else {
296 | mBackEndMediaPlayer.setOnTimedTextListener(null);
297 | }
298 | }
299 |
300 | @Override
301 | public void setAudioStreamType(int streamtype) {
302 | mBackEndMediaPlayer.setAudioStreamType(streamtype);
303 | }
304 |
305 | @Override
306 | public void setKeepInBackground(boolean keepInBackground) {
307 | mBackEndMediaPlayer.setKeepInBackground(keepInBackground);
308 | }
309 |
310 | @Override
311 | public int getVideoSarNum() {
312 | return mBackEndMediaPlayer.getVideoSarNum();
313 | }
314 |
315 | @Override
316 | public int getVideoSarDen() {
317 | return mBackEndMediaPlayer.getVideoSarDen();
318 | }
319 |
320 | @Override
321 | public void setWakeMode(Context context, int mode) {
322 | mBackEndMediaPlayer.setWakeMode(context, mode);
323 | }
324 |
325 | @Override
326 | public ITrackInfo[] getTrackInfo() {
327 | return mBackEndMediaPlayer.getTrackInfo();
328 | }
329 |
330 | @Override
331 | public void setLooping(boolean looping) {
332 | mBackEndMediaPlayer.setLooping(looping);
333 | }
334 |
335 | @Override
336 | public boolean isLooping() {
337 | return mBackEndMediaPlayer.isLooping();
338 | }
339 | }
340 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player;
19 |
20 | import android.annotation.TargetApi;
21 | import android.graphics.SurfaceTexture;
22 | import android.os.Build;
23 | import android.view.Surface;
24 | import android.view.SurfaceHolder;
25 |
26 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
27 | public class TextureMediaPlayer extends MediaPlayerProxy implements IMediaPlayer, ISurfaceTextureHolder {
28 | private SurfaceTexture mSurfaceTexture;
29 | private ISurfaceTextureHost mSurfaceTextureHost;
30 |
31 | public TextureMediaPlayer(IMediaPlayer backEndMediaPlayer) {
32 | super(backEndMediaPlayer);
33 | }
34 |
35 | public void releaseSurfaceTexture() {
36 | if (mSurfaceTexture != null) {
37 | if (mSurfaceTextureHost != null) {
38 | mSurfaceTextureHost.releaseSurfaceTexture(mSurfaceTexture);
39 | } else {
40 | mSurfaceTexture.release();
41 | }
42 | mSurfaceTexture = null;
43 | }
44 | }
45 |
46 | //--------------------
47 | // IMediaPlayer
48 | //--------------------
49 | @Override
50 | public void reset() {
51 | super.reset();
52 | releaseSurfaceTexture();
53 | }
54 |
55 | @Override
56 | public void release() {
57 | super.release();
58 | releaseSurfaceTexture();
59 | }
60 |
61 | @Override
62 | public void setDisplay(SurfaceHolder sh) {
63 | if (mSurfaceTexture == null)
64 | super.setDisplay(sh);
65 | }
66 |
67 | @Override
68 | public void setSurface(Surface surface) {
69 | if (mSurfaceTexture == null)
70 | super.setSurface(surface);
71 | }
72 |
73 | //--------------------
74 | // ISurfaceTextureHolder
75 | //--------------------
76 |
77 | @Override
78 | public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
79 | if (mSurfaceTexture == surfaceTexture)
80 | return;
81 |
82 | releaseSurfaceTexture();
83 | mSurfaceTexture = surfaceTexture;
84 | if (surfaceTexture == null) {
85 | super.setSurface(null);
86 | } else {
87 | super.setSurface(new Surface(surfaceTexture));
88 | }
89 | }
90 |
91 | @Override
92 | public SurfaceTexture getSurfaceTexture() {
93 | return mSurfaceTexture;
94 | }
95 |
96 | @Override
97 | public void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost) {
98 | mSurfaceTextureHost = surfaceTextureHost;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.annotations;
19 |
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | /**
26 | * is used by the JNI generator to create the necessary JNI
27 | * bindings and expose this method to native code.
28 | */
29 | @Target(ElementType.FIELD)
30 | @Retention(RetentionPolicy.CLASS)
31 | public @interface AccessedByNative {
32 | }
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.annotations;
19 |
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | /**
26 | * is used by the JNI generator to create the necessary JNI
27 | * bindings and expose this method to native code.
28 | */
29 | @Target(ElementType.METHOD)
30 | @Retention(RetentionPolicy.CLASS)
31 | public @interface CalledByNative {
32 | /*
33 | * If present, tells which inner class the method belongs to.
34 | */
35 | String value() default "";
36 | }
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013-2014 Bilibili
3 | * Copyright (C) 2013-2014 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.exceptions;
19 |
20 | public class IjkMediaException extends Exception {
21 | private static final long serialVersionUID = 7234796519009099506L;
22 | }
23 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java:
--------------------------------------------------------------------------------
1 | package tv.danmaku.ijk.media.player.ffmpeg;
2 |
3 | public class FFmpegApi {
4 | public static native String av_base64_encode(byte in[]);
5 | }
6 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | import android.annotation.TargetApi;
21 | import android.media.MediaFormat;
22 | import android.os.Build;
23 |
24 | public class AndroidMediaFormat implements IMediaFormat {
25 | private final MediaFormat mMediaFormat;
26 |
27 | public AndroidMediaFormat(MediaFormat mediaFormat) {
28 | mMediaFormat = mediaFormat;
29 | }
30 |
31 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
32 | @Override
33 | public int getInteger(String name) {
34 | if (mMediaFormat == null)
35 | return 0;
36 |
37 | return mMediaFormat.getInteger(name);
38 | }
39 |
40 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
41 | @Override
42 | public String getString(String name) {
43 | if (mMediaFormat == null)
44 | return null;
45 |
46 | return mMediaFormat.getString(name);
47 | }
48 |
49 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
50 | @Override
51 | public String toString() {
52 | StringBuilder out = new StringBuilder(128);
53 | out.append(getClass().getName());
54 | out.append('{');
55 | if (mMediaFormat != null) {
56 | out.append(mMediaFormat.toString());
57 | } else {
58 | out.append("null");
59 | }
60 | out.append('}');
61 | return out.toString();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | import android.annotation.TargetApi;
21 | import android.media.MediaFormat;
22 | import android.media.MediaPlayer;
23 | import android.os.Build;
24 |
25 | public class AndroidTrackInfo implements ITrackInfo {
26 | private final MediaPlayer.TrackInfo mTrackInfo;
27 |
28 | public static AndroidTrackInfo[] fromMediaPlayer(MediaPlayer mp) {
29 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
30 | return fromTrackInfo(mp.getTrackInfo());
31 |
32 | return null;
33 | }
34 |
35 | private static AndroidTrackInfo[] fromTrackInfo(MediaPlayer.TrackInfo[] trackInfos) {
36 | if (trackInfos == null)
37 | return null;
38 |
39 | AndroidTrackInfo androidTrackInfo[] = new AndroidTrackInfo[trackInfos.length];
40 | for (int i = 0; i < trackInfos.length; ++i) {
41 | androidTrackInfo[i] = new AndroidTrackInfo(trackInfos[i]);
42 | }
43 |
44 | return androidTrackInfo;
45 | }
46 |
47 | private AndroidTrackInfo(MediaPlayer.TrackInfo trackInfo) {
48 | mTrackInfo = trackInfo;
49 | }
50 |
51 | @TargetApi(Build.VERSION_CODES.KITKAT)
52 | @Override
53 | public IMediaFormat getFormat() {
54 | if (mTrackInfo == null)
55 | return null;
56 |
57 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
58 | return null;
59 |
60 | MediaFormat mediaFormat = mTrackInfo.getFormat();
61 | if (mediaFormat == null)
62 | return null;
63 |
64 | return new AndroidMediaFormat(mediaFormat);
65 | }
66 |
67 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
68 | @Override
69 | public String getLanguage() {
70 | if (mTrackInfo == null)
71 | return "und";
72 |
73 | return mTrackInfo.getLanguage();
74 | }
75 |
76 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
77 | @Override
78 | public int getTrackType() {
79 | if (mTrackInfo == null)
80 | return MEDIA_TRACK_TYPE_UNKNOWN;
81 |
82 | return mTrackInfo.getTrackType();
83 | }
84 |
85 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
86 | @Override
87 | public String toString() {
88 | StringBuilder out = new StringBuilder(128);
89 | out.append(getClass().getSimpleName());
90 | out.append('{');
91 | if (mTrackInfo != null) {
92 | out.append(mTrackInfo.toString());
93 | } else {
94 | out.append("null");
95 | }
96 | out.append('}');
97 | return out.toString();
98 | }
99 |
100 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
101 | @Override
102 | public String getInfoInline() {
103 | if (mTrackInfo != null) {
104 | return mTrackInfo.toString();
105 | } else {
106 | return "null";
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/IAndroidIO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bilibili
3 | * Copyright (C) 2016 Raymond Zheng
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | import java.io.IOException;
21 |
22 | @SuppressWarnings("RedundantThrows")
23 | public interface IAndroidIO {
24 | int open(String url) throws IOException;
25 | int read(byte[] buffer, int size) throws IOException;
26 | long seek(long offset, int whence) throws IOException;
27 | int close() throws IOException;
28 | }
29 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | import java.io.IOException;
21 |
22 | @SuppressWarnings("RedundantThrows")
23 | public interface IMediaDataSource {
24 | int readAt(long position, byte[] buffer, int offset, int size) throws IOException;
25 |
26 | long getSize() throws IOException;
27 |
28 | void close() throws IOException;
29 | }
30 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | public interface IMediaFormat {
21 | // Common keys
22 | String KEY_MIME = "mime";
23 |
24 | // Video Keys
25 | String KEY_WIDTH = "width";
26 | String KEY_HEIGHT = "height";
27 |
28 | String getString(String name);
29 |
30 | int getInteger(String name);
31 | }
32 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | public interface ITrackInfo {
21 | int MEDIA_TRACK_TYPE_AUDIO = 2;
22 | int MEDIA_TRACK_TYPE_METADATA = 5;
23 | int MEDIA_TRACK_TYPE_SUBTITLE = 4;
24 | int MEDIA_TRACK_TYPE_TIMEDTEXT = 3;
25 | int MEDIA_TRACK_TYPE_UNKNOWN = 0;
26 | int MEDIA_TRACK_TYPE_VIDEO = 1;
27 |
28 | IMediaFormat getFormat();
29 |
30 | String getLanguage();
31 |
32 | int getTrackType();
33 |
34 | String getInfoInline();
35 | }
36 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | import android.annotation.TargetApi;
21 | import android.os.Build;
22 | import android.text.TextUtils;
23 |
24 | import java.util.HashMap;
25 | import java.util.Locale;
26 | import java.util.Map;
27 |
28 | import tv.danmaku.ijk.media.player.IjkMediaMeta;
29 |
30 | public class IjkMediaFormat implements IMediaFormat {
31 | // Common
32 | public static final String KEY_IJK_CODEC_LONG_NAME_UI = "ijk-codec-long-name-ui";
33 | public static final String KEY_IJK_CODEC_NAME_UI = "ijk-codec-name-ui";
34 | public static final String KEY_IJK_BIT_RATE_UI = "ijk-bit-rate-ui";
35 |
36 | // Video
37 | public static final String KEY_IJK_CODEC_PROFILE_LEVEL_UI = "ijk-profile-level-ui";
38 | public static final String KEY_IJK_CODEC_PIXEL_FORMAT_UI = "ijk-pixel-format-ui";
39 | public static final String KEY_IJK_RESOLUTION_UI = "ijk-resolution-ui";
40 | public static final String KEY_IJK_FRAME_RATE_UI = "ijk-frame-rate-ui";
41 |
42 | // Audio
43 | public static final String KEY_IJK_SAMPLE_RATE_UI = "ijk-sample-rate-ui";
44 | public static final String KEY_IJK_CHANNEL_UI = "ijk-channel-ui";
45 |
46 | // Codec
47 | public static final String CODEC_NAME_H264 = "h264";
48 |
49 | public final IjkMediaMeta.IjkStreamMeta mMediaFormat;
50 |
51 | public IjkMediaFormat(IjkMediaMeta.IjkStreamMeta streamMeta) {
52 | mMediaFormat = streamMeta;
53 | }
54 |
55 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
56 | @Override
57 | public int getInteger(String name) {
58 | if (mMediaFormat == null)
59 | return 0;
60 |
61 | return mMediaFormat.getInt(name);
62 | }
63 |
64 | @Override
65 | public String getString(String name) {
66 | if (mMediaFormat == null)
67 | return null;
68 |
69 | if (sFormatterMap.containsKey(name)) {
70 | Formatter formatter = sFormatterMap.get(name);
71 | return formatter.format(this);
72 | }
73 |
74 | return mMediaFormat.getString(name);
75 | }
76 |
77 | //-------------------------
78 | // Formatter
79 | //-------------------------
80 |
81 | private static abstract class Formatter {
82 | public String format(IjkMediaFormat mediaFormat) {
83 | String value = doFormat(mediaFormat);
84 | if (TextUtils.isEmpty(value))
85 | return getDefaultString();
86 | return value;
87 | }
88 |
89 | protected abstract String doFormat(IjkMediaFormat mediaFormat);
90 |
91 | @SuppressWarnings("SameReturnValue")
92 | protected String getDefaultString() {
93 | return "N/A";
94 | }
95 | }
96 |
97 | private static final Map sFormatterMap = new HashMap();
98 |
99 | {
100 | sFormatterMap.put(KEY_IJK_CODEC_LONG_NAME_UI, new Formatter() {
101 | @Override
102 | public String doFormat(IjkMediaFormat mediaFormat) {
103 | return mMediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_LONG_NAME);
104 | }
105 | });
106 | sFormatterMap.put(KEY_IJK_CODEC_NAME_UI, new Formatter() {
107 | @Override
108 | public String doFormat(IjkMediaFormat mediaFormat) {
109 | return mMediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_NAME);
110 | }
111 | });
112 | sFormatterMap.put(KEY_IJK_BIT_RATE_UI, new Formatter() {
113 | @Override
114 | protected String doFormat(IjkMediaFormat mediaFormat) {
115 | int bitRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_BITRATE);
116 | if (bitRate <= 0) {
117 | return null;
118 | } else if (bitRate < 1000) {
119 | return String.format(Locale.US, "%d bit/s", bitRate);
120 | } else {
121 | return String.format(Locale.US, "%d kb/s", bitRate / 1000);
122 | }
123 | }
124 | });
125 | sFormatterMap.put(KEY_IJK_CODEC_PROFILE_LEVEL_UI, new Formatter() {
126 | @Override
127 | protected String doFormat(IjkMediaFormat mediaFormat) {
128 | int profileIndex = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CODEC_PROFILE_ID);
129 | String profile;
130 | switch (profileIndex) {
131 | case IjkMediaMeta.FF_PROFILE_H264_BASELINE:
132 | profile = "Baseline";
133 | break;
134 | case IjkMediaMeta.FF_PROFILE_H264_CONSTRAINED_BASELINE:
135 | profile = "Constrained Baseline";
136 | break;
137 | case IjkMediaMeta.FF_PROFILE_H264_MAIN:
138 | profile = "Main";
139 | break;
140 | case IjkMediaMeta.FF_PROFILE_H264_EXTENDED:
141 | profile = "Extended";
142 | break;
143 | case IjkMediaMeta.FF_PROFILE_H264_HIGH:
144 | profile = "High";
145 | break;
146 | case IjkMediaMeta.FF_PROFILE_H264_HIGH_10:
147 | profile = "High 10";
148 | break;
149 | case IjkMediaMeta.FF_PROFILE_H264_HIGH_10_INTRA:
150 | profile = "High 10 Intra";
151 | break;
152 | case IjkMediaMeta.FF_PROFILE_H264_HIGH_422:
153 | profile = "High 4:2:2";
154 | break;
155 | case IjkMediaMeta.FF_PROFILE_H264_HIGH_422_INTRA:
156 | profile = "High 4:2:2 Intra";
157 | break;
158 | case IjkMediaMeta.FF_PROFILE_H264_HIGH_444:
159 | profile = "High 4:4:4";
160 | break;
161 | case IjkMediaMeta.FF_PROFILE_H264_HIGH_444_PREDICTIVE:
162 | profile = "High 4:4:4 Predictive";
163 | break;
164 | case IjkMediaMeta.FF_PROFILE_H264_HIGH_444_INTRA:
165 | profile = "High 4:4:4 Intra";
166 | break;
167 | case IjkMediaMeta.FF_PROFILE_H264_CAVLC_444:
168 | profile = "CAVLC 4:4:4";
169 | break;
170 | default:
171 | return null;
172 | }
173 |
174 | StringBuilder sb = new StringBuilder();
175 | sb.append(profile);
176 |
177 | String codecName = mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_NAME);
178 | if (!TextUtils.isEmpty(codecName) && codecName.equalsIgnoreCase(CODEC_NAME_H264)) {
179 | int level = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CODEC_LEVEL);
180 | if (level < 10)
181 | return sb.toString();
182 |
183 | sb.append(" Profile Level ");
184 | sb.append((level / 10) % 10);
185 | if ((level % 10) != 0) {
186 | sb.append(".");
187 | sb.append(level % 10);
188 | }
189 | }
190 |
191 | return sb.toString();
192 | }
193 | });
194 | sFormatterMap.put(KEY_IJK_CODEC_PIXEL_FORMAT_UI, new Formatter() {
195 | @Override
196 | protected String doFormat(IjkMediaFormat mediaFormat) {
197 | return mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_PIXEL_FORMAT);
198 | }
199 | });
200 | sFormatterMap.put(KEY_IJK_RESOLUTION_UI, new Formatter() {
201 | @Override
202 | protected String doFormat(IjkMediaFormat mediaFormat) {
203 | int width = mediaFormat.getInteger(KEY_WIDTH);
204 | int height = mediaFormat.getInteger(KEY_HEIGHT);
205 | int sarNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_NUM);
206 | int sarDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_DEN);
207 |
208 | if (width <= 0 || height <= 0) {
209 | return null;
210 | } else if (sarNum <= 0 || sarDen <= 0) {
211 | return String.format(Locale.US, "%d x %d", width, height);
212 | } else {
213 | return String.format(Locale.US, "%d x %d [SAR %d:%d]", width,
214 | height, sarNum, sarDen);
215 | }
216 | }
217 | });
218 | sFormatterMap.put(KEY_IJK_FRAME_RATE_UI, new Formatter() {
219 | @Override
220 | protected String doFormat(IjkMediaFormat mediaFormat) {
221 | int fpsNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_NUM);
222 | int fpsDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_DEN);
223 | if (fpsNum <= 0 || fpsDen <= 0) {
224 | return null;
225 | } else {
226 | return String.valueOf(((float) (fpsNum)) / fpsDen);
227 | }
228 | }
229 | });
230 | sFormatterMap.put(KEY_IJK_SAMPLE_RATE_UI, new Formatter() {
231 | @Override
232 | protected String doFormat(IjkMediaFormat mediaFormat) {
233 | int sampleRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAMPLE_RATE);
234 | if (sampleRate <= 0) {
235 | return null;
236 | } else {
237 | return String.format(Locale.US, "%d Hz", sampleRate);
238 | }
239 | }
240 | });
241 | sFormatterMap.put(KEY_IJK_CHANNEL_UI, new Formatter() {
242 | @Override
243 | protected String doFormat(IjkMediaFormat mediaFormat) {
244 | int channelLayout = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CHANNEL_LAYOUT);
245 | if (channelLayout <= 0) {
246 | return null;
247 | } else {
248 | if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_MONO) {
249 | return "mono";
250 | } else if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_STEREO) {
251 | return "stereo";
252 | } else {
253 | return String.format(Locale.US, "%x", channelLayout);
254 | }
255 | }
256 | }
257 | });
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Bilibili
3 | * Copyright (C) 2015 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.misc;
19 |
20 | import android.text.TextUtils;
21 |
22 | import tv.danmaku.ijk.media.player.IjkMediaMeta;
23 |
24 | public class IjkTrackInfo implements ITrackInfo {
25 | private int mTrackType = MEDIA_TRACK_TYPE_UNKNOWN;
26 | private IjkMediaMeta.IjkStreamMeta mStreamMeta;
27 |
28 | public IjkTrackInfo(IjkMediaMeta.IjkStreamMeta streamMeta) {
29 | mStreamMeta = streamMeta;
30 | }
31 |
32 | public void setMediaMeta(IjkMediaMeta.IjkStreamMeta streamMeta) {
33 | mStreamMeta = streamMeta;
34 | }
35 |
36 | @Override
37 | public IMediaFormat getFormat() {
38 | return new IjkMediaFormat(mStreamMeta);
39 | }
40 |
41 | @Override
42 | public String getLanguage() {
43 | if (mStreamMeta == null || TextUtils.isEmpty(mStreamMeta.mLanguage))
44 | return "und";
45 |
46 | return mStreamMeta.mLanguage;
47 | }
48 |
49 | @Override
50 | public int getTrackType() {
51 | return mTrackType;
52 | }
53 |
54 | public void setTrackType(int trackType) {
55 | mTrackType = trackType;
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | return getClass().getSimpleName() + '{' + getInfoInline() + "}";
61 | }
62 |
63 | @Override
64 | public String getInfoInline() {
65 | StringBuilder out = new StringBuilder(128);
66 | switch (mTrackType) {
67 | case MEDIA_TRACK_TYPE_VIDEO:
68 | out.append("VIDEO");
69 | out.append(", ");
70 | out.append(mStreamMeta.getCodecShortNameInline());
71 | out.append(", ");
72 | out.append(mStreamMeta.getBitrateInline());
73 | out.append(", ");
74 | out.append(mStreamMeta.getResolutionInline());
75 | break;
76 | case MEDIA_TRACK_TYPE_AUDIO:
77 | out.append("AUDIO");
78 | out.append(", ");
79 | out.append(mStreamMeta.getCodecShortNameInline());
80 | out.append(", ");
81 | out.append(mStreamMeta.getBitrateInline());
82 | out.append(", ");
83 | out.append(mStreamMeta.getSampleRateInline());
84 | break;
85 | case MEDIA_TRACK_TYPE_TIMEDTEXT:
86 | out.append("TIMEDTEXT");
87 | out.append(", ");
88 | out.append(mStreamMeta.mLanguage);
89 | break;
90 | case MEDIA_TRACK_TYPE_SUBTITLE:
91 | out.append("SUBTITLE");
92 | break;
93 | default:
94 | out.append("UNKNOWN");
95 | break;
96 | }
97 | return out.toString();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Bilibili
3 | * Copyright (C) 2013 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package tv.danmaku.ijk.media.player.pragma;
19 |
20 | import java.util.Locale;
21 |
22 |
23 | import android.util.Log;
24 |
25 | @SuppressWarnings({"SameParameterValue", "WeakerAccess"})
26 | public class DebugLog {
27 | public static final boolean ENABLE_ERROR = Pragma.ENABLE_VERBOSE;
28 | public static final boolean ENABLE_INFO = Pragma.ENABLE_VERBOSE;
29 | public static final boolean ENABLE_WARN = Pragma.ENABLE_VERBOSE;
30 | public static final boolean ENABLE_DEBUG = Pragma.ENABLE_VERBOSE;
31 | public static final boolean ENABLE_VERBOSE = Pragma.ENABLE_VERBOSE;
32 |
33 | public static void e(String tag, String msg) {
34 | if (ENABLE_ERROR) {
35 | Log.e(tag, msg);
36 | }
37 | }
38 |
39 | public static void e(String tag, String msg, Throwable tr) {
40 | if (ENABLE_ERROR) {
41 | Log.e(tag, msg, tr);
42 | }
43 | }
44 |
45 | public static void efmt(String tag, String fmt, Object... args) {
46 | if (ENABLE_ERROR) {
47 | String msg = String.format(Locale.US, fmt, args);
48 | Log.e(tag, msg);
49 | }
50 | }
51 |
52 | public static void i(String tag, String msg) {
53 | if (ENABLE_INFO) {
54 | Log.i(tag, msg);
55 | }
56 | }
57 |
58 | public static void i(String tag, String msg, Throwable tr) {
59 | if (ENABLE_INFO) {
60 | Log.i(tag, msg, tr);
61 | }
62 | }
63 |
64 | public static void ifmt(String tag, String fmt, Object... args) {
65 | if (ENABLE_INFO) {
66 | String msg = String.format(Locale.US, fmt, args);
67 | Log.i(tag, msg);
68 | }
69 | }
70 |
71 | public static void w(String tag, String msg) {
72 | if (ENABLE_WARN) {
73 | Log.w(tag, msg);
74 | }
75 | }
76 |
77 | public static void w(String tag, String msg, Throwable tr) {
78 | if (ENABLE_WARN) {
79 | Log.w(tag, msg, tr);
80 | }
81 | }
82 |
83 | public static void wfmt(String tag, String fmt, Object... args) {
84 | if (ENABLE_WARN) {
85 | String msg = String.format(Locale.US, fmt, args);
86 | Log.w(tag, msg);
87 | }
88 | }
89 |
90 | public static void d(String tag, String msg) {
91 | if (ENABLE_DEBUG) {
92 | Log.d(tag, msg);
93 | }
94 | }
95 |
96 | public static void d(String tag, String msg, Throwable tr) {
97 | if (ENABLE_DEBUG) {
98 | Log.d(tag, msg, tr);
99 | }
100 | }
101 |
102 | public static void dfmt(String tag, String fmt, Object... args) {
103 | if (ENABLE_DEBUG) {
104 | String msg = String.format(Locale.US, fmt, args);
105 | Log.d(tag, msg);
106 | }
107 | }
108 |
109 | public static void v(String tag, String msg) {
110 | if (ENABLE_VERBOSE) {
111 | Log.v(tag, msg);
112 | }
113 | }
114 |
115 | public static void v(String tag, String msg, Throwable tr) {
116 | if (ENABLE_VERBOSE) {
117 | Log.v(tag, msg, tr);
118 | }
119 | }
120 |
121 | public static void vfmt(String tag, String fmt, Object... args) {
122 | if (ENABLE_VERBOSE) {
123 | String msg = String.format(Locale.US, fmt, args);
124 | Log.v(tag, msg);
125 | }
126 | }
127 |
128 | public static void printStackTrace(Throwable e) {
129 | if (ENABLE_WARN) {
130 | e.printStackTrace();
131 | }
132 | }
133 |
134 | public static void printCause(Throwable e) {
135 | if (ENABLE_WARN) {
136 | Throwable cause = e.getCause();
137 | if (cause != null)
138 | e = cause;
139 |
140 | printStackTrace(e);
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/ijk/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Bilibili
3 | * Copyright (C) 2013 Zhang Rui
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package tv.danmaku.ijk.media.player.pragma;
18 |
19 | /*-
20 | * configurated by app project
21 | */
22 | public class Pragma {
23 | public static final boolean ENABLE_VERBOSE = true;
24 | }
25 |
--------------------------------------------------------------------------------
/ijk/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ijk
3 |
4 |
--------------------------------------------------------------------------------
/ijk/src/test/java/tv/danmaku/ijk/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package tv.danmaku.ijk;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':ijk'
2 |
--------------------------------------------------------------------------------