Skip to content

Commit 3f1ea63

Browse files
authored
Merge pull request #9 from brarcher/settings
Settings
2 parents 1593586 + 7b3251b commit 3f1ea63

File tree

6 files changed

+202
-69
lines changed

6 files changed

+202
-69
lines changed

app/src/main/java/protect/videotranscoder/FFmpegUtil.java

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ public void onSuccess()
7676
*/
7777
public static void call(final String[] command, @NonNull final ExecuteBinaryResponseHandler handler)
7878
{
79-
if(ffmpeg == null)
79+
if(ffmpeg == null || ffmpeg.isFFmpegCommandRunning())
8080
{
81-
String message = "Command failed, FFmpeg not initialized";
81+
String message = "Command failed, FFmpeg " + (ffmpeg == null ? "not initialized" : "still running");
8282
Log.d(TAG, message);
8383

8484
handler.onFailure(message);
@@ -182,7 +182,7 @@ public static Long timestampToMs(String timestamp)
182182

183183
public static void getMediaDetails(final File mediaFile, final ResultCallbackHandler<MediaInfo> resultHandler)
184184
{
185-
if(ffmpeg == null)
185+
if(ffmpeg == null || ffmpeg.isFFmpegCommandRunning())
186186
{
187187
resultHandler.onResult(null);
188188
return;
@@ -208,14 +208,15 @@ public void onResult(String mediaDetailsStr)
208208
static MediaInfo parseMediaInfo(File mediaFile, String string)
209209
{
210210
long durationMs = 0;
211+
Integer totalBitrate = null;
211212
MediaContainer container = null;
212213
VideoCodec videoCodec = null;
213214
String videoResolution = null;
214-
String videoBitrate = null;
215+
Integer videoBitrate = null;
215216
String videoFramerate = null;
216217
AudioCodec audioCodec = null;
217-
String audioSampleRate = null;
218-
String audioBitrate = null;
218+
Integer audioSampleRate = null;
219+
Integer audioBitrate = null;
219220
int audioChannels = 2;
220221

221222
/*
@@ -263,6 +264,24 @@ static MediaInfo parseMediaInfo(File mediaFile, String string)
263264
}
264265

265266
durationMs = time;
267+
268+
split = line.split(",");
269+
for(String item : split)
270+
{
271+
if(item.contains("bitrate:"))
272+
{
273+
item = item.replace("bitrate:", "").replace("kb/s", "").trim();
274+
try
275+
{
276+
// This may be used later if the video bitrate cannot be determined.
277+
totalBitrate = Integer.parseInt(item);
278+
}
279+
catch(NumberFormatException e)
280+
{
281+
continue;
282+
}
283+
}
284+
}
266285
}
267286

268287
if(line.startsWith("Input"))
@@ -311,7 +330,15 @@ static MediaInfo parseMediaInfo(File mediaFile, String string)
311330

312331
if(piece.contains("kb/s"))
313332
{
314-
videoBitrate = piece.replace("kb/s", "").trim();
333+
try
334+
{
335+
String videoBitrateStr = piece.replace("kb/s", "").trim();
336+
videoBitrate = Integer.parseInt(videoBitrateStr);
337+
}
338+
catch(NumberFormatException e)
339+
{
340+
// Nothing to do
341+
}
315342
}
316343

317344
if(piece.contains("fps"))
@@ -342,16 +369,33 @@ static MediaInfo parseMediaInfo(File mediaFile, String string)
342369

343370
if(piece.contains("Hz"))
344371
{
345-
audioSampleRate = piece.replace("Hz", "").trim();
372+
try
373+
{
374+
String audioSampeRateStr = piece.replace("Hz", "").trim();
375+
audioSampleRate = Integer.parseInt(audioSampeRateStr);
376+
}
377+
catch(NumberFormatException e)
378+
{
379+
// Nothing to do
380+
}
346381
}
347382

348383
if(piece.contains("kb/s"))
349384
{
350-
audioBitrate = piece.replace("kb/s", "").trim();
385+
String audioBitrateStr = piece.replace("kb/s", "").trim();
351386

352-
if(audioBitrate.contains("(default)"))
387+
if(audioBitrateStr.contains("(default)"))
353388
{
354-
audioBitrate = audioBitrate.replace("(default)", "").trim();
389+
audioBitrateStr = audioBitrateStr.replace("(default)", "").trim();
390+
}
391+
392+
try
393+
{
394+
audioBitrate = Integer.parseInt(audioBitrateStr);
395+
}
396+
catch(NumberFormatException e)
397+
{
398+
// Nothing to do
355399
}
356400
}
357401

@@ -363,14 +407,37 @@ static MediaInfo parseMediaInfo(File mediaFile, String string)
363407
}
364408
}
365409

410+
if(totalBitrate != null)
411+
{
412+
if(videoBitrate == null)
413+
{
414+
if(audioBitrate != null)
415+
{
416+
// We know the audio bitrate, we can calculate the video bitrate
417+
videoBitrate = totalBitrate - audioBitrate;
418+
}
419+
420+
if(videoBitrate == null)
421+
{
422+
// We do not know any of the separate bitrates. Lets guess 100 kb/s for the audio,
423+
// and subtract that from the total to guess the video bitrate.
424+
425+
// As a guess, subtract 100 kb/s from the bitrate for audio, and
426+
// assume that the video is the rest. This should be a decent-ish
427+
// estimate if the video bitrate cannot be found later.
428+
videoBitrate = totalBitrate - 100;
429+
}
430+
}
431+
}
432+
366433
MediaInfo info = new MediaInfo(mediaFile, durationMs, container, videoCodec, videoResolution,
367434
videoBitrate, videoFramerate, audioCodec, audioSampleRate, audioBitrate, audioChannels);
368435
return info;
369436
}
370437

371438
public static void getSupportedContainers(final ResultCallbackHandler<List<MediaContainer>> resultHandler)
372439
{
373-
if(ffmpeg == null)
440+
if(ffmpeg == null || ffmpeg.isFFmpegCommandRunning())
374441
{
375442
resultHandler.onResult(null);
376443
return;

app/src/main/java/protect/videotranscoder/activity/MainActivity.java

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import android.widget.AdapterView;
2727
import android.widget.ArrayAdapter;
2828
import android.widget.Button;
29+
import android.widget.EditText;
2930
import android.widget.ProgressBar;
3031
import android.widget.Spinner;
3132
import android.widget.TextView;
@@ -102,7 +103,7 @@ public class MainActivity extends AppCompatActivity
102103
private Spinner videoCodecSpinner;
103104
private Spinner fpsSpinner;
104105
private Spinner resolutionSpinner;
105-
private Spinner videoBitrateSpinner;
106+
private EditText videoBitrateValue;
106107
private Spinner audioCodecSpinner;
107108
private Spinner audioBitrateSpinner;
108109
private Spinner audioSampleRateSpinner;
@@ -136,7 +137,7 @@ protected void onCreate(Bundle savedInstanceState)
136137
videoCodecSpinner = findViewById(R.id.videoCodecSpinner);
137138
fpsSpinner = findViewById(R.id.fpsSpinner);
138139
resolutionSpinner = findViewById(R.id.resolutionSpinner);
139-
videoBitrateSpinner = findViewById(R.id.videoBitrateSpinner);
140+
videoBitrateValue = findViewById(R.id.videoBitrateValue);
140141
audioCodecSpinner = findViewById(R.id.audioCodecSpinner);
141142
audioBitrateSpinner = findViewById(R.id.audioBitrateSpinner);
142143
audioSampleRateSpinner = findViewById(R.id.audioSampleRateSpinner);
@@ -282,11 +283,22 @@ private void startEncode()
282283
VideoCodec videoCodec = (VideoCodec)videoCodecSpinner.getSelectedItem();
283284
String fps = (String)fpsSpinner.getSelectedItem();
284285
String resolution = (String)resolutionSpinner.getSelectedItem();
285-
String videoBitrate = (String)videoBitrateSpinner.getSelectedItem();
286286
AudioCodec audioCodec = (AudioCodec) audioCodecSpinner.getSelectedItem();
287-
String audioBitrate = (String) audioBitrateSpinner.getSelectedItem();
288-
String audioSampleRate = (String) audioSampleRateSpinner.getSelectedItem();
287+
Integer audioBitrate = (Integer) audioBitrateSpinner.getSelectedItem();
288+
Integer audioSampleRate = (Integer) audioSampleRateSpinner.getSelectedItem();
289289
String audioChannel = (String) audioChannelSpinner.getSelectedItem();
290+
int videoBitrate;
291+
292+
try
293+
{
294+
String videoBitrateStr = videoBitrateValue.getText().toString();
295+
videoBitrate = Integer.parseInt(videoBitrateStr);
296+
}
297+
catch(NumberFormatException e)
298+
{
299+
Toast.makeText(this, R.string.videoBitrateValueInvalid, Toast.LENGTH_LONG).show();
300+
return;
301+
}
290302

291303
File outputDir;
292304

@@ -377,7 +389,7 @@ private void startEncode()
377389

378390
// Sample rate
379391
command.add("-ar");
380-
command.add(audioSampleRate);
392+
command.add(Integer.toString(audioSampleRate));
381393

382394
// Channels
383395
command.add("-ac");
@@ -414,6 +426,11 @@ private void cancelEncode()
414426
}
415427
}
416428

429+
private boolean isEncoding()
430+
{
431+
return cancelButton.getVisibility() == View.VISIBLE;
432+
}
433+
417434
private void stopVideoPlayback()
418435
{
419436
videoView.pause();
@@ -457,15 +474,19 @@ protected void onPause()
457474
protected void onResume()
458475
{
459476
super.onResume();
460-
startVideoPlayback();
477+
478+
if(isEncoding() == false)
479+
{
480+
startVideoPlayback();
481+
}
461482
}
462483

463-
private void setSpinnerSelection(Spinner spinner, String value)
484+
private void setSpinnerSelection(Spinner spinner, Object value)
464485
{
465486
for(int index = 0; index < spinner.getCount(); index++)
466487
{
467488
String item = spinner.getItemAtPosition(index).toString();
468-
if(item.equals(value))
489+
if(item.equals(value.toString()))
469490
{
470491
spinner.setSelection(index);
471492
break;
@@ -528,16 +549,20 @@ public void onNothingSelected(AdapterView<?> parentView)
528549
}
529550
});
530551

531-
String [] fps = new String [] {"24", "23.98", "25", "29.97", "30", "50"};
552+
LinkedList<String> fps = new LinkedList<>(Arrays.asList("24", "23.98", "25", "29.97", "30", "50"));
553+
if(videoInfo.videoFramerate != null && fps.contains(videoInfo.videoFramerate) == false)
554+
{
555+
fps.addFirst(videoInfo.videoFramerate);
556+
}
532557
fpsSpinner.setAdapter(new ArrayAdapter<>(this, R.layout.spinner_textview, fps));
533558

534-
String [] resolution = new String[] {"176x144", "320x240", "480x360", "640x360", "640x480", "800x600", "960x720", "1024x768", "1280x720", "1920x1080", "2048x1080", "2048x858", "2560x1440", "2560x1600", "4096x2160"};
559+
LinkedList<String> resolution = new LinkedList<>(Arrays.asList("176x144", "320x240", "480x360", "640x360", "640x480", "800x600", "960x720", "1024x768", "1280x720", "1920x1080", "2048x1080", "2048x858", "2560x1440", "2560x1600", "4096x2160"));
560+
if(videoInfo.videoResolution != null && resolution.contains(videoInfo.videoResolution) == false)
561+
{
562+
resolution.addFirst(videoInfo.videoResolution);
563+
}
535564
resolutionSpinner.setAdapter(new ArrayAdapter<>(this, R.layout.spinner_textview, resolution));
536565

537-
// TODO: Should be a text field, not a spinner
538-
String [] videoBitrate = new String[] {"500"};
539-
videoBitrateSpinner.setAdapter(new ArrayAdapter<>(this, R.layout.spinner_textview, videoBitrate));
540-
541566
audioCodecSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
542567
{
543568
@Override
@@ -559,10 +584,20 @@ public void onNothingSelected(AdapterView<?> parentView)
559584
}
560585
});
561586

562-
String [] audioBitrate = new String[] {"15", "24", "32", "64", "96", "128", "192", "256", "320", "384", "448", "512"};
587+
List<Integer> audioBitrate = new ArrayList<>(Arrays.asList(15, 24, 32, 64, 96, 128, 192, 256, 320, 384, 448, 512));
588+
if(videoInfo.audioBitrate != null && audioBitrate.contains(videoInfo.audioBitrate) == false)
589+
{
590+
audioBitrate.add(videoInfo.audioBitrate);
591+
Collections.sort(audioBitrate);
592+
}
563593
audioBitrateSpinner.setAdapter(new ArrayAdapter<>(this, R.layout.spinner_textview, audioBitrate));
564594

565-
String [] sampleRate = new String[] {"8000", "11025", "16000", "22050", "24000", "32000", "44100", "48000"};
595+
List<Integer> sampleRate = new ArrayList<>(Arrays.asList(8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000));
596+
if(videoInfo.audioSampleRate != null && audioBitrate.contains(videoInfo.audioSampleRate) == false)
597+
{
598+
sampleRate.add(videoInfo.audioSampleRate);
599+
Collections.sort(sampleRate);
600+
}
566601
audioSampleRateSpinner.setAdapter(new ArrayAdapter<>(this, R.layout.spinner_textview, sampleRate));
567602

568603
String [] channels = new String[] {"1", "2"};
@@ -590,19 +625,23 @@ public void onNothingSelected(AdapterView<?> parentView)
590625

591626
if(videoInfo.videoBitrate != null)
592627
{
593-
setSpinnerSelection(videoBitrateSpinner, videoInfo.videoBitrate);
628+
videoBitrateValue.setText(Integer.toString(videoInfo.videoBitrate));
594629
}
595630

596631
if(videoInfo.audioCodec != null)
597632
{
598633
setSpinnerSelection(audioCodecSpinner, videoInfo.audioCodec.toString());
599634
}
600635

601-
if(videoInfo.audioBitrate != null)
636+
Integer defaultAudioBitrate = videoInfo.audioBitrate;
637+
if(defaultAudioBitrate == null)
602638
{
603-
setSpinnerSelection(audioBitrateSpinner, videoInfo.audioBitrate);
639+
// Set some default if none is detected
640+
defaultAudioBitrate = 128;
604641
}
605642

643+
setSpinnerSelection(audioBitrateSpinner, defaultAudioBitrate);
644+
606645
if(videoInfo.audioSampleRate != null)
607646
{
608647
setSpinnerSelection(audioSampleRateSpinner, videoInfo.audioSampleRate);
@@ -656,7 +695,10 @@ public void valueChanged(Number minValue, Number maxValue)
656695
tvLeft.setText(getTime(minValue.intValue()));
657696
tvRight.setText(getTime(maxValue.intValue()));
658697

659-
startVideoPlayback();
698+
if(isEncoding() == false)
699+
{
700+
startVideoPlayback();
701+
}
660702
}
661703
});
662704
}
@@ -673,8 +715,8 @@ public void onResult(MediaInfo result)
673715
{
674716
// Could not query the file, fill in what we know.
675717
result = new MediaInfo(videoFile, 0, MediaContainer.MP4, VideoCodec.MPEG4, "640x480",
676-
"800", "25", AudioCodec.MP3,
677-
"44100", "128", 2);
718+
800, "25", AudioCodec.MP3,
719+
44100, 128, 2);
678720
}
679721

680722
videoInfo = result;

app/src/main/java/protect/videotranscoder/media/MediaInfo.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ public class MediaInfo
1212
public final MediaContainer container;
1313
public final VideoCodec videoCodec;
1414
public final String videoResolution;
15-
public final String videoBitrate;
15+
public final Integer videoBitrate;
1616
public final String videoFramerate;
1717
public final AudioCodec audioCodec;
18-
public final String audioSampleRate;
19-
public final String audioBitrate;
20-
public final int audioChannels;
18+
public final Integer audioSampleRate;
19+
public final Integer audioBitrate;
20+
public final Integer audioChannels;
2121

2222

2323
public MediaInfo(File file, long durationMs, MediaContainer container, VideoCodec videoCodec,
24-
String videoResolution, String videoBitrate, String videoFramerate,
25-
AudioCodec audioCodec, String audioSampleRate, String audioBitrate,
26-
int audioChannels)
24+
String videoResolution, Integer videoBitrate, String videoFramerate,
25+
AudioCodec audioCodec, Integer audioSampleRate, Integer audioBitrate,
26+
Integer audioChannels)
2727
{
2828
this.file = file;
2929
this.durationMs = durationMs;

0 commit comments

Comments
 (0)