Skip to content

Commit 38a9fe5

Browse files
committed
Merge pull request ypresto#12 from MaiKambayashi/trancode-cancel
Implement cancel support
2 parents 1952254 + 41d68e9 commit 38a9fe5

File tree

4 files changed

+85
-32
lines changed

4 files changed

+85
-32
lines changed

example/src/main/java/net/ypresto/androidtranscoder/example/TranscoderActivity.java

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@
2121
import java.io.FileDescriptor;
2222
import java.io.FileNotFoundException;
2323
import java.io.IOException;
24+
import java.util.concurrent.Future;
2425

2526

2627
public class TranscoderActivity extends Activity {
2728
private static final String TAG = "TranscoderActivity";
2829
private static final int REQUEST_CODE_PICK = 1;
30+
private static final int PROGRESS_BAR_MAX = 1000;
31+
private Future mFuture;
2932

3033
@Override
3134
protected void onCreate(Bundle savedInstanceState) {
@@ -37,6 +40,12 @@ public void onClick(View v) {
3740
startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT).setType("video/*"), REQUEST_CODE_PICK);
3841
}
3942
});
43+
findViewById(R.id.cancel_button).setOnClickListener(new View.OnClickListener() {
44+
@Override
45+
public void onClick(View view) {
46+
mFuture.cancel(true);
47+
}
48+
});
4049
}
4150

4251
@Override
@@ -63,7 +72,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
6372
}
6473
final FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
6574
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
66-
progressBar.setMax(1000);
75+
progressBar.setMax(PROGRESS_BAR_MAX);
6776
final long startTime = SystemClock.uptimeMillis();
6877
MediaTranscoder.Listener listener = new MediaTranscoder.Listener() {
6978
@Override
@@ -72,42 +81,31 @@ public void onTranscodeProgress(double progress) {
7281
progressBar.setIndeterminate(true);
7382
} else {
7483
progressBar.setIndeterminate(false);
75-
progressBar.setProgress((int) Math.round(progress * 1000));
84+
progressBar.setProgress((int) Math.round(progress * PROGRESS_BAR_MAX));
7685
}
7786
}
7887

7988
@Override
8089
public void onTranscodeCompleted() {
8190
Log.d(TAG, "transcoding took " + (SystemClock.uptimeMillis() - startTime) + "ms");
82-
Toast.makeText(TranscoderActivity.this, "transcoded file placed on " + file, Toast.LENGTH_LONG).show();
83-
findViewById(R.id.select_video_button).setEnabled(true);
84-
progressBar.setIndeterminate(false);
85-
progressBar.setProgress(1000);
91+
onTranscodeFinished(true, "transcoded file placed on " + file, parcelFileDescriptor);
8692
startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file), "video/mp4"));
87-
try {
88-
parcelFileDescriptor.close();
89-
} catch (IOException e) {
90-
Log.w("Error while closing", e);
91-
}
93+
}
94+
95+
@Override
96+
public void onTranscodeCanceled() {
97+
onTranscodeFinished(false, "Transcoder canceled.", parcelFileDescriptor);
9298
}
9399

94100
@Override
95101
public void onTranscodeFailed(Exception exception) {
96-
progressBar.setIndeterminate(false);
97-
progressBar.setProgress(0);
98-
findViewById(R.id.select_video_button).setEnabled(true);
99-
Toast.makeText(TranscoderActivity.this, "Transcoder error occurred.", Toast.LENGTH_LONG).show();
100-
try {
101-
parcelFileDescriptor.close();
102-
} catch (IOException e) {
103-
Log.w("Error while closing", e);
104-
}
102+
onTranscodeFinished(false, "Transcoder error occurred.", parcelFileDescriptor);
105103
}
106104
};
107105
Log.d(TAG, "transcoding into " + file);
108-
MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(),
106+
mFuture = MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(),
109107
MediaFormatStrategyPresets.createAndroid720pStrategy(), listener);
110-
findViewById(R.id.select_video_button).setEnabled(false);
108+
switchButtonEnabled(true);
111109
}
112110
break;
113111
}
@@ -134,4 +132,22 @@ public boolean onOptionsItemSelected(MenuItem item) {
134132
}
135133
return super.onOptionsItemSelected(item);
136134
}
135+
136+
private void onTranscodeFinished(boolean isSuccess, String toastMessage, ParcelFileDescriptor parcelFileDescriptor) {
137+
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
138+
progressBar.setIndeterminate(false);
139+
progressBar.setProgress(isSuccess ? PROGRESS_BAR_MAX : 0);
140+
switchButtonEnabled(false);
141+
Toast.makeText(TranscoderActivity.this, toastMessage, Toast.LENGTH_LONG).show();
142+
try {
143+
parcelFileDescriptor.close();
144+
} catch (IOException e) {
145+
Log.w("Error while closing", e);
146+
}
147+
}
148+
149+
private void switchButtonEnabled(boolean isProgress) {
150+
findViewById(R.id.select_video_button).setEnabled(!isProgress);
151+
findViewById(R.id.cancel_button).setEnabled(isProgress);
152+
}
137153
}

example/src/main/res/layout/activity_transcoder.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,12 @@
3030
android:layout_gravity="center_horizontal"
3131
android:progress="0" />
3232

33+
<Button
34+
android:id="@+id/cancel_button"
35+
android:layout_width="wrap_content"
36+
android:layout_height="wrap_content"
37+
android:layout_gravity="center_horizontal"
38+
android:enabled="false"
39+
android:text="cancel" />
40+
3341
</LinearLayout>

lib/src/main/java/net/ypresto/androidtranscoder/MediaTranscoder.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@
2727
import java.io.FileDescriptor;
2828
import java.io.FileInputStream;
2929
import java.io.IOException;
30+
import java.util.concurrent.Callable;
31+
import java.util.concurrent.Future;
3032
import java.util.concurrent.LinkedBlockingQueue;
3133
import java.util.concurrent.ThreadFactory;
3234
import java.util.concurrent.ThreadPoolExecutor;
3335
import java.util.concurrent.TimeUnit;
36+
import java.util.concurrent.atomic.AtomicReference;
3437

3538
public class MediaTranscoder {
3639
private static final String TAG = "MediaTranscoder";
@@ -71,8 +74,8 @@ public static MediaTranscoder getInstance() {
7174
* @deprecated Use {@link #transcodeVideo(FileDescriptor, String, MediaFormatStrategy, MediaTranscoder.Listener)} which accepts output video format.
7275
*/
7376
@Deprecated
74-
public void transcodeVideo(final FileDescriptor inFileDescriptor, final String outPath, final Listener listener) {
75-
transcodeVideo(inFileDescriptor, outPath, new MediaFormatStrategy() {
77+
public Future transcodeVideo(final FileDescriptor inFileDescriptor, final String outPath, final Listener listener) {
78+
return transcodeVideo(inFileDescriptor, outPath, new MediaFormatStrategy() {
7679
@Override
7780
public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
7881
return MediaFormatPresets.getExportPreset960x540();
@@ -95,7 +98,7 @@ public MediaFormat createAudioOutputFormat(MediaFormat inputFormat) {
9598
* @param listener Listener instance for callback.
9699
* @throws IOException if input file could not be read.
97100
*/
98-
public void transcodeVideo(final String inPath, final String outPath, final MediaFormatStrategy outFormatStrategy, final Listener listener) throws IOException {
101+
public Future transcodeVideo(final String inPath, final String outPath, final MediaFormatStrategy outFormatStrategy, final Listener listener) throws IOException {
99102
FileInputStream fileInputStream = null;
100103
FileDescriptor inFileDescriptor;
101104
try {
@@ -112,7 +115,7 @@ public void transcodeVideo(final String inPath, final String outPath, final Medi
112115
throw e;
113116
}
114117
final FileInputStream finalFileInputStream = fileInputStream;
115-
transcodeVideo(inFileDescriptor, outPath, outFormatStrategy, new Listener() {
118+
return transcodeVideo(inFileDescriptor, outPath, outFormatStrategy, new Listener() {
116119
@Override
117120
public void onTranscodeProgress(double progress) {
118121
listener.onTranscodeProgress(progress);
@@ -124,6 +127,12 @@ public void onTranscodeCompleted() {
124127
closeStream();
125128
}
126129

130+
@Override
131+
public void onTranscodeCanceled() {
132+
listener.onTranscodeCanceled();
133+
closeStream();
134+
}
135+
127136
@Override
128137
public void onTranscodeFailed(Exception exception) {
129138
listener.onTranscodeFailed(exception);
@@ -149,13 +158,14 @@ private void closeStream() {
149158
* @param outFormatStrategy Strategy for output video format.
150159
* @param listener Listener instance for callback.
151160
*/
152-
public void transcodeVideo(final FileDescriptor inFileDescriptor, final String outPath, final MediaFormatStrategy outFormatStrategy, final Listener listener) {
161+
public Future transcodeVideo(final FileDescriptor inFileDescriptor, final String outPath, final MediaFormatStrategy outFormatStrategy, final Listener listener) {
153162
Looper looper = Looper.myLooper();
154163
if (looper == null) looper = Looper.getMainLooper();
155164
final Handler handler = new Handler(looper);
156-
mExecutor.execute(new Runnable() {
165+
final AtomicReference<Future> futureReference = new AtomicReference<>();
166+
final Future<Void> createdFuture = mExecutor.submit(new Callable<Void>() {
157167
@Override
158-
public void run() {
168+
public Void call() throws Exception {
159169
Exception caughtException = null;
160170
try {
161171
MediaTranscoderEngine engine = new MediaTranscoderEngine();
@@ -176,6 +186,9 @@ public void run() {
176186
Log.w(TAG, "Transcode failed: input file (fd: " + inFileDescriptor.toString() + ") not found"
177187
+ " or could not open output file ('" + outPath + "') .", e);
178188
caughtException = e;
189+
} catch (InterruptedException e) {
190+
Log.i(TAG, "Cancel transcode video file.", e);
191+
caughtException = e;
179192
} catch (RuntimeException e) {
180193
Log.e(TAG, "Fatal error while transcoding, this might be invalid format or bug in engine or Android.", e);
181194
caughtException = e;
@@ -188,12 +201,22 @@ public void run() {
188201
if (exception == null) {
189202
listener.onTranscodeCompleted();
190203
} else {
191-
listener.onTranscodeFailed(exception);
204+
Future future = futureReference.get();
205+
if (future != null && future.isCancelled()) {
206+
listener.onTranscodeCanceled();
207+
} else {
208+
listener.onTranscodeFailed(exception);
209+
}
192210
}
193211
}
194212
});
213+
214+
if (exception != null) throw exception;
215+
return null;
195216
}
196217
});
218+
futureReference.set(createdFuture);
219+
return createdFuture;
197220
}
198221

199222
public interface Listener {
@@ -209,6 +232,11 @@ public interface Listener {
209232
*/
210233
void onTranscodeCompleted();
211234

235+
/**
236+
* Called when transcode canceled.
237+
*/
238+
void onTranscodeCanceled();
239+
212240
/**
213241
* Called when transcode failed.
214242
*

lib/src/main/java/net/ypresto/androidtranscoder/engine/MediaTranscoderEngine.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,11 @@ public double getProgress() {
7676
*
7777
* @param outputPath File path to output transcoded video file.
7878
* @param formatStrategy Output format strategy.
79-
* @throws IOException when input or output file could not be opened.
79+
* @throws IOException when input or output file could not be opened.
8080
* @throws InvalidOutputFormatException when output format is not supported.
81+
* @throws InterruptedException when cancel to transcode.
8182
*/
82-
public void transcodeVideo(String outputPath, MediaFormatStrategy formatStrategy) throws IOException {
83+
public void transcodeVideo(String outputPath, MediaFormatStrategy formatStrategy) throws IOException, InterruptedException {
8384
if (outputPath == null) {
8485
throw new NullPointerException("Output path cannot be null.");
8586
}

0 commit comments

Comments
 (0)