Fix Seeking: Disable scrubbing seek for remote files, remember playing state after seek. Use media from gstreamer.com instead of freedesktop.org (weird buffering from the later)

This commit is contained in:
Xavi Artigas 2012-10-01 12:37:07 +02:00
parent cf083414f6
commit ceaab451f2

View file

@ -46,13 +46,15 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
private native void nativeSurfaceFinalize(); private native void nativeSurfaceFinalize();
private long native_custom_data; private long native_custom_data;
private boolean playing; private boolean is_playing_desired;
private int position; private int position;
private int duration; private int duration;
private boolean is_local_media;
private int desired_position;
private Bundle initialization_data; private Bundle initialization_data;
private final String mediaUri = "http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv"; private final String mediaUri = "http://docs.gstreamer.com/media/sintel_trailer-480p.ogv";
/* Called when the activity is first created. /* Called when the activity is first created.
@Override */ @Override */
@ -73,6 +75,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
ImageButton play = (ImageButton) this.findViewById(R.id.button_play); ImageButton play = (ImageButton) this.findViewById(R.id.button_play);
play.setOnClickListener(new OnClickListener() { play.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
is_playing_desired = true;
nativePlay(); nativePlay();
} }
}); });
@ -80,6 +83,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
ImageButton pause = (ImageButton) this.findViewById(R.id.button_stop); ImageButton pause = (ImageButton) this.findViewById(R.id.button_stop);
pause.setOnClickListener(new OnClickListener() { pause.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
is_playing_desired = false;
nativePause(); nativePause();
} }
}); });
@ -93,12 +97,15 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
initialization_data = savedInstanceState; initialization_data = savedInstanceState;
is_local_media = false;
is_playing_desired = false;
nativeInit(); nativeInit();
} }
protected void onSaveInstanceState (Bundle outState) { protected void onSaveInstanceState (Bundle outState) {
Log.d ("GStreamer", "Saving state, playing:" + playing + " position:" + position); Log.d ("GStreamer", "Saving state, playing:" + is_playing_desired + " position:" + position);
outState.putBoolean("playing", playing); outState.putBoolean("playing", is_playing_desired);
outState.putInt("position", position); outState.putInt("position", position);
outState.putInt("duration", duration); outState.putInt("duration", duration);
} }
@ -121,6 +128,8 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
/* Called from native code */ /* Called from native code */
private void onGStreamerInitialized () { private void onGStreamerInitialized () {
nativeSetUri (mediaUri); nativeSetUri (mediaUri);
if (mediaUri.startsWith("file://")) is_local_media = true;
if (initialization_data != null) { if (initialization_data != null) {
boolean should_play = initialization_data.getBoolean("playing"); boolean should_play = initialization_data.getBoolean("playing");
int milliseconds = initialization_data.getInt("position"); int milliseconds = initialization_data.getInt("position");
@ -128,7 +137,8 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
/* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the /* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the
* milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind * milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind
* where we were before. This, combined with seeking to keyframe positions, would skip one keyframe * where we were before. This, combined with seeking to keyframe positions, would skip one keyframe
* backwards on each iteration. */ * backwards on each iteration.
*/
nativeSetPosition(milliseconds + 1); nativeSetPosition(milliseconds + 1);
if (should_play) { if (should_play) {
nativePlay(); nativePlay();
@ -140,18 +150,32 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
} }
} }
/* Called from native code */ /* The text widget acts as an slave for the seek bar, so it reflects what the seek bar shows, whether
private void setCurrentPosition(final int position, final int duration) { * it is an actual pipeline position or the position the user is currently dragging to.
*/
private void updateTimeWidget () {
final TextView tv = (TextView) this.findViewById(R.id.textview_time); final TextView tv = (TextView) this.findViewById(R.id.textview_time);
final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar);
final int pos = sb.getProgress();
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC")); df.setTimeZone(TimeZone.getTimeZone("UTC"));
final String message = df.format(new Date (position)) + " / " + df.format(new Date (duration)); final String message = df.format(new Date (pos)) + " / " + df.format(new Date (duration));
tv.setText(message);
}
/* Called from native code */
private void setCurrentPosition(final int position, final int duration) {
final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar);
/* Ignore position messages from the pipeline if the seek bar is being dragged */
if (sb.isPressed()) return;
runOnUiThread (new Runnable() { runOnUiThread (new Runnable() {
public void run() { public void run() {
tv.setText(message);
sb.setMax(duration); sb.setMax(duration);
sb.setProgress(position); sb.setProgress(position);
updateTimeWidget();
} }
}); });
this.position = position; this.position = position;
@ -175,7 +199,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
setMessage ("PLAYING"); setMessage ("PLAYING");
break; break;
} }
playing = (state == 4);
} }
static { static {
@ -202,7 +225,12 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) { public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) {
if (fromUser == false) return; if (fromUser == false) return;
nativeSetPosition(progress); desired_position = progress;
/* If this is a local file, allow scrub seeking, this is, seek soon as the slider
* is moved.
*/
if (is_local_media) nativeSetPosition(desired_position);
updateTimeWidget();
} }
public void onStartTrackingTouch(SeekBar sb) { public void onStartTrackingTouch(SeekBar sb) {
@ -210,6 +238,10 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee
} }
public void onStopTrackingTouch(SeekBar sb) { public void onStopTrackingTouch(SeekBar sb) {
if (playing) nativePlay(); /* If this is a remote file, scrub seeking is probably not going to work smoothly enough.
* Therefore, perform only the seek when the slider is released.
*/
if (!is_local_media) nativeSetPosition(desired_position);
if (is_playing_desired) nativePlay();
} }
} }