11package cc .openframeworks ;
22
33import android .annotation .TargetApi ;
4+ import android .content .Context ;
45import android .graphics .SurfaceTexture ;
56import android .graphics .SurfaceTexture .OnFrameAvailableListener ;
67import android .media .MediaPlayer ;
78import android .media .MediaPlayer .OnPreparedListener ;
89import android .media .MediaPlayer .OnVideoSizeChangedListener ;
910import android .media .MediaPlayer .OnCompletionListener ;
11+ import android .net .Uri ;
1012import android .os .Build ;
1113import android .util .FloatMath ;
1214import android .util .Log ;
1315import android .view .Surface ;
1416import androidx .annotation .Keep ;
1517
18+ import java .io .FileNotFoundException ;
19+
20+ import android .content .res .AssetFileDescriptor ;
21+
1622@ Keep
1723@ TargetApi (Build .VERSION_CODES .ICE_CREAM_SANDWICH )
1824public class OFAndroidVideoPlayer extends OFAndroidObject implements OnFrameAvailableListener {
19-
25+
2026 public OFAndroidVideoPlayer (){
21-
27+
2228 bIsLoaded = false ;
2329 bIsPlaying = false ;
2430 bIsPaused = true ;
2531 bIsFrameNew = false ;
2632 bAutoResume = false ;
2733 bIsMoviedone = false ;
2834 bIsLooping = false ;
29-
35+
3036 // TODO Get movie FPS to implement Frame methods
3137 // movieFPS = 16;
3238 // nFrames = 0;
33-
39+
3440 pan = 0.f ;
3541 volume = leftVolume = rightVolume = 1 ;
36-
42+
3743 }
38-
44+
3945 public void setTexture (int texName ) {
4046 surfaceTexture = new SurfaceTexture (texName );
4147 surfaceTexture .setOnFrameAvailableListener (this );
4248 surface = new Surface (surfaceTexture );
4349 mediaPlayer .setSurface (surface );
4450 }
45-
51+
4652 public void clearTextures () {
4753 if (surface != null ) {
4854 surface .release ();
@@ -54,7 +60,7 @@ public void clearTextures() {
5460 surfaceTexture = null ;
5561 }
5662 }
57-
63+
5864 public boolean update () {
5965 synchronized (this ){
6066 if (bIsFrameNew ) {
@@ -67,11 +73,11 @@ public boolean update() {
6773 }
6874 }
6975 }
70-
76+
7177 public void getTextureMatrix (float [] mtx ) {
7278 if (surfaceTexture != null ) surfaceTexture .getTransformMatrix (mtx );
7379 }
74-
80+
7581 public void loadMovie (String fileName ){
7682 try {
7783 if (mediaPlayer == null ) {
@@ -102,38 +108,52 @@ public void onCompletion(MediaPlayer mp) {
102108 } else {
103109 mediaPlayer .reset ();
104110 }
105- mediaPlayer .setDataSource (fileName );
106- mediaPlayer .prepare ();
107- bIsLoaded = true ;
108- //setVolume(volume);
109111 this .fileName = fileName ;
112+ boolean hasLoaded = false ;
113+
114+ try {
115+ if (fileName .startsWith ("/" )) {
116+ // Physical path (external storage)
117+ mediaPlayer .setDataSource (fileName );
118+ } else {
119+ // Asset-based fallback
120+ AssetFileDescriptor afd = OFAndroid .getContext ().getAssets ().openFd (fileName );
121+ mediaPlayer .setDataSource (afd .getFileDescriptor (), afd .getStartOffset (), afd .getLength ());
122+ }
123+ } catch (FileNotFoundException e ) {
124+ Log .e ("OF" ,"couldn't load " + fileName ,e );
125+ bIsLoaded = false ;
126+ mediaPlayer .reset ();
127+ hasLoaded = false ;
128+ }
129+
130+ if (mediaPlayer != null && hasLoaded ) {
131+ mediaPlayer .prepareAsync ();
132+ }
133+ //setVolume(volume);
110134 } catch (Exception e ) {
111135 Log .e ("OF" ,"couldn't load " + fileName ,e );
112- }
136+ }
113137 }
114-
115- public void play (){
116138
139+ public void play (){
117140 if (mediaPlayer ==null ) return ;
118-
119141 if (!bIsLoaded ){
120142 Log .e ("OF" ,"ofxAndroidVideo::play - movie not loaded!" );
121143 return ;
122144 }
123-
124145 mediaPlayer .start ();
125-
126146 bIsPlaying = true ;
127147 bIsPaused = false ;
128-
148+
129149 }
130-
150+
131151 public void stop (){
132152 if (mediaPlayer ==null ) return ;
133153 mediaPlayer .stop ();
134154 bIsPlaying = false ;
135155 }
136-
156+
137157 void unloadMovie (){
138158 if (mediaPlayer !=null ){
139159 mediaPlayer .setSurface (null );
@@ -142,75 +162,77 @@ void unloadMovie(){
142162 mediaPlayer = null ;
143163 }
144164 clearTextures ();
145-
165+
146166 fileName = null ;
147167 bIsLoaded = false ;
148168 bIsMoviedone = false ;
149169 bIsPlaying = false ;
150170 bIsPaused = true ;
151-
171+
152172 //nFrames = 0;
153-
173+
154174 }
155-
175+
156176 void setVolume (float vol ){
157177 volume = vol ;
158- // calculates left/right volumes from pan-value (constant panning law)
178+ // calculates left/right volumes from pan-value (constant panning law)
159179 // see: Curtis Roads: Computer Music Tutorial p 460
160180 // thanks to jasch
161181 float angle = pan * 0.7853981633974483f ; // in radians from -45. to +45.
162182 float cosAngle = (float ) Math .cos (angle );
163183 float sinAngle = (float ) Math .sin (angle );
164184 leftVolume = (float )((cosAngle - sinAngle ) * 0.7071067811865475 ) * vol ; // multiplied by sqrt(2)/2
165185 rightVolume = (float )((cosAngle + sinAngle ) * 0.7071067811865475 ) * vol ; // multiplied by sqrt(2)/2
166- if (mediaPlayer !=null )mediaPlayer .setVolume (leftVolume , rightVolume );
186+ if (mediaPlayer !=null ) mediaPlayer .setVolume (leftVolume , rightVolume );
167187 }
168-
188+
169189 float getVolume (){
170190 return volume ;
171191 }
172-
192+
173193 void setPaused (boolean bP ){
174- if ( mediaPlayer == null ) return ;
194+
175195 if (bP ) {
176196 if (bIsPlaying ) {
177- mediaPlayer .pause ();
197+ if (mediaPlayer !=null )
198+ mediaPlayer .pause ();
178199 bIsPlaying = !bP ;
179200 bIsPaused = bP ;
180201 }
181202 } else {
182203 if (bIsPaused ) {
183- mediaPlayer .start ();
204+ if (mediaPlayer !=null )
205+ mediaPlayer .start ();
184206 bIsPlaying = !bP ;
185207 bIsPaused = bP ;
186208 }
187209 }
188210 }
189-
211+
190212 void setLoopState (boolean bL ){
213+ bIsLooping = bL ;
191214 if (mediaPlayer ==null ) return ;
192215 mediaPlayer .setLooping (bL );
193- bIsLooping = bL ;
194216 }
195-
217+
196218 boolean getLoopState (){
197- if ( mediaPlayer == null ) return false ;
219+ if (! bIsLoaded || mediaPlayer == null ) return false ;
198220 return mediaPlayer .isLooping ();
199221 }
200-
222+
201223 int getWidth (){
202- if ( mediaPlayer == null ) return 0 ;
224+ if (! bIsLoaded || mediaPlayer == null ) return 0 ;
203225 return mediaPlayer .getVideoWidth ();
204226 }
205-
227+
206228 int getHeight (){
207- if ( mediaPlayer == null ) return 0 ;
229+ if (! bIsLoaded || mediaPlayer == null ) return 0 ;
208230 return mediaPlayer .getVideoHeight ();
209231 }
210-
232+
211233 /* Needs movie frameRate to work
212234 int getCurrentFrame(){
213-
235+
214236 float framePosInFloat = ((float)getTotalNumFrames() * (float)getPosition());
215237 int framePosInInt = (int)framePosInFloat;
216238 float floatRemainder = (framePosInFloat - framePosInInt);
@@ -220,83 +242,83 @@ int getCurrentFrame(){
220242
221243 }
222244 */
223-
245+
224246 /* Needs movie frameRate to work
225247 int getTotalNumFrames(){
226248 return nFrames;
227249 }
228250 */
229-
251+
230252 public boolean isLoaded (){
231253 return bIsLoaded ;
232254 }
233-
255+
234256 public boolean isPaused (){
235257 return bIsPaused ;
236258 }
237-
259+
238260 public boolean isPlaying (){
239261 return bIsPlaying ;
240262 }
241-
263+
242264 boolean isMovieDone (){
243265 return bIsMoviedone ;
244266 }
245-
246-
267+
268+
247269 void setPosition (float pct ){
248270 if (mediaPlayer !=null ) mediaPlayer .seekTo ((int ) (mediaPlayer .getDuration ()*pct )); // 0 = start, 1 = end;
249271 }
250-
272+
251273 void setPositionMS (int ms ){
252274 if (mediaPlayer !=null ) mediaPlayer .seekTo (ms ); // 0 = start, 1 = end;
253275 }
254-
276+
255277 float getPosition (){
256278 if (mediaPlayer !=null )
257279 return ((float )mediaPlayer .getCurrentPosition ())/(float )mediaPlayer .getDuration ();
258280 else
259281 return 0 ;
260282 }
261-
283+
262284 int getPositionMS (){
263285 if (mediaPlayer !=null )
264286 return mediaPlayer .getCurrentPosition ();
265287 else
266288 return 0 ;
267289 }
268-
290+
269291 float getDuration (){
270292 if (mediaPlayer !=null )
271293 return (float )mediaPlayer .getDuration ();
272294 else
273295 return 0 ;
274296 }
275-
297+
276298 int getDurationMS (){
277299 if (mediaPlayer !=null )
278300 return mediaPlayer .getDuration ();
279301 else
280302 return 0 ;
281303 }
282-
283304
284-
305+
306+
285307 @ Override
286308 protected void appPause () {
287309 int currMovieTime = getPositionMS ();
288310 stop ();
289311 String currFileName = fileName ;
290- boolean currIsLoaded = bIsLoaded ;
312+ boolean currIsLoaded = bIsLoaded ;
291313 boolean currIsPlaying = bIsPlaying ;
292314 unloadMovie ();
293315 fileName = currFileName ;
294- bIsLoaded = currIsLoaded ;
316+ bIsLoaded = currIsLoaded ;
295317 bIsPlaying = currIsPlaying ;
296-
318+
297319 bAutoResume = true ;
298320 movieResumeTime = currMovieTime ;
299-
321+
300322 }
301323
302324 @ Override
@@ -310,18 +332,18 @@ protected void appResume() {
310332 protected void appStop () {
311333 appPause ();
312334 }
313-
335+
314336 @ Override
315337 public void onFrameAvailable (SurfaceTexture arg0 ) {
316338 synchronized (this ){
317339 bIsFrameNew = true ;
318340 }
319341 }
320-
321-
322-
342+
343+
344+
323345 private MediaPlayer mediaPlayer ;
324-
346+
325347 private SurfaceTexture surfaceTexture ;
326348 private Surface surface ;
327349 private String fileName ;
@@ -334,12 +356,12 @@ public void onFrameAvailable(SurfaceTexture arg0) {
334356 private boolean bIsMoviedone ;
335357 private boolean bIsFrameNew ;
336358 private boolean bIsLooping ;
337-
359+
338360 //private int movieFPS;
339361 //private int nFrames;
340-
362+
341363 private boolean bAutoResume ;
342364 private int movieResumeTime ;
343-
344-
365+
366+
345367}
0 commit comments