-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVideoSurfaceView.java
More file actions
186 lines (157 loc) · 6.43 KB
/
Copy pathVideoSurfaceView.java
File metadata and controls
186 lines (157 loc) · 6.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
* Created by Kastr
* https://github.com/Kastr/VideoSurfaceView
*/
public class VideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener {
private static final int MODE_CENTER = 1;
private static final int MODE_FIT_HORIZONTAL = 2;
private static final int MODE_FIT_VERTICAL = 3;
private static final int MODE_FIT_ALL = 4;
private MediaPlayer mp;
private int mVideoWidth;
private int mVideoHeight;
private @RawRes int videoResource;
private int videoScaleType;
public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupAttrs(context, attrs, defStyleAttr);
init();
}
public VideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setupAttrs(context, attrs, 0);
init();
}
private void setupAttrs(Context context, AttributeSet attrs, int defStyle) {
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.VideoSurfaceView,
defStyle, 0
);
try {
videoResource = a.getResourceId(R.styleable.VideoSurfaceView_videoRawResource, 0);
videoScaleType = a.getInteger(R.styleable.VideoSurfaceView_videoScaleType, 0);
} finally {
a.recycle();
}
}
private void init() {
mp = new MediaPlayer();
getHolder().addCallback(this);
}
synchronized public void releaseMediaPlayer() {
if(mp == null) {
return;
}
mp.release();
mp = null;
}
private void startMediaPlayer(SurfaceHolder holder) {
if(mp == null) {
mp = new MediaPlayer();
}
try {
AssetFileDescriptor afd = getResources().openRawResourceFd(videoResource);
mp.setDisplay(holder);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
mp.setLooping(true);
mp.setOnPreparedListener(this);
mp.setOnErrorListener(this);
mp.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
/* SURFACE
* ------------------------------------------------------------------------------------------------*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
startMediaPlayer(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseMediaPlayer();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureVideo(widthMeasureSpec, heightMeasureSpec);
}
/* MEDIA PLAYER
* ------------------------------------------------------------------------------------------------*/
@Override
public void onPrepared(MediaPlayer mp) {
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
this.mp.start();
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e(VideoSurfaceView.class.getSimpleName(), "Error occurred with MediaPlayer.\n(int)What: " + String.valueOf(what));
return false;
}
/* Utils
* ------------------------------------------------------------------------------------------------*/
private void measureVideo(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth == 0 && mVideoHeight == 0) {
setMeasuredDimension(width, height);
return;
}
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
switch (videoScaleType) {
case MODE_CENTER:
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
break;
case MODE_FIT_HORIZONTAL:
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
break;
case MODE_FIT_VERTICAL:
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
break;
case MODE_FIT_ALL:
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if (mVideoWidth * height < width * mVideoHeight) {
//image too wide, correcting
width = height * mVideoWidth / mVideoHeight;
} else if (mVideoWidth * height > width * mVideoHeight) {
//image too tall, correcting
height = width * mVideoHeight / mVideoWidth;
}
break;
}
setMeasuredDimension(width, height);
}
}