use of protect.videotranscoder.media.MediaInfo in project video-transcoder by brarcher.
the class MainActivity method setSelectMediaFile.
private void setSelectMediaFile(String path, String overrideBaseName) {
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
final int durationMs = mp.getDuration();
tvLeft.setVisibility(View.VISIBLE);
tvLeft.setText(getTime(0));
tvRight.setVisibility(View.VISIBLE);
tvRight.setText(getTime(durationMs / 1000));
mp.setLooping(true);
rangeSeekBar.setMinValue(0);
rangeSeekBar.setMaxValue(durationMs / 1000f);
rangeSeekBar.setEnabled(true);
rangeSeekBar.setVisibility(View.VISIBLE);
rangeSeekBar.setOnRangeSeekbarChangeListener(new OnRangeSeekbarChangeListener() {
Number prevMinValueSec = 0;
Number prevMaxValueSec = (int) (durationMs / 1000f);
// If the end time slider was moved, resume the playback
// this may seconds before the end
static final int END_PLAYBACK_HEADROOM_SEC = 3;
@Override
public void valueChanged(Number minValue, Number maxValue) {
Integer playStartSec = null;
if (prevMaxValueSec.intValue() != maxValue.intValue()) {
// End time was changed
prevMaxValueSec = maxValue;
playStartSec = prevMaxValueSec.intValue();
// Resume playback a few seconds before the end
int headroom = Math.min(maxValue.intValue() - minValue.intValue(), END_PLAYBACK_HEADROOM_SEC);
playStartSec -= headroom;
}
if (prevMinValueSec.intValue() != minValue.intValue()) {
// Start time was changed
prevMinValueSec = minValue;
playStartSec = prevMinValueSec.intValue();
}
tvLeft.setText(getTime(minValue.intValue()));
tvRight.setText(getTime(maxValue.intValue()));
if (isEncoding() == false && playStartSec != null) {
startVideoPlayback(playStartSec);
}
}
});
class RangeSeekChanger implements View.OnClickListener {
private final int startOffset;
private final int endOffset;
RangeSeekChanger(int startOffset, int endOffset) {
this.startOffset = startOffset;
this.endOffset = endOffset;
}
@Override
public void onClick(View v) {
rangeSeekBar.setMinValue(0);
rangeSeekBar.setMaxValue(durationMs / 1000f);
int selectedStart = rangeSeekBar.getSelectedMinValue().intValue();
int selectedEnd = rangeSeekBar.getSelectedMaxValue().intValue();
rangeSeekBar.setMinStartValue(selectedStart + startOffset);
rangeSeekBar.setMaxStartValue(selectedEnd + endOffset);
rangeSeekBar.apply();
}
}
startJumpForward.setOnClickListener(new RangeSeekChanger(1, 0));
startJumpBack.setOnClickListener(new RangeSeekChanger(-1, 0));
endJumpForward.setOnClickListener(new RangeSeekChanger(0, 1));
endJumpBack.setOnClickListener(new RangeSeekChanger(0, -1));
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(MainActivity.this, R.string.mediaPlaybackFailed, Toast.LENGTH_LONG).show();
stopVideoPlayback();
return true;
}
});
FFmpegUtil.getMediaDetails(new File(path), new ResultCallbackHandler<MediaInfo>() {
@Override
public void onResult(MediaInfo result) {
videoInfo = result;
if (result != null) {
String uri = Uri.fromFile(new File(path)).toString();
videoView.setVideoPath(uri);
videoView.start();
videoInfo.setFileBaseName(overrideBaseName);
populateOptionDefaults();
} else {
Toast.makeText(MainActivity.this, R.string.invalidMediaFile, Toast.LENGTH_LONG).show();
hideAllOptions();
stopVideoPlayback();
}
}
});
}
use of protect.videotranscoder.media.MediaInfo in project video-transcoder by brarcher.
the class FFmpegUtilTest method parseMediaInfo.
@Test
public void parseMediaInfo() throws Exception {
File file = new File("/dev/null");
String string = "{\n" + " \"streams\": [\n" + " {\n" + " \"index\": 0,\n" + " \"codec_name\": \"mp3\",\n" + " \"codec_long_name\": \"MP3 (MPEG audio layer 3)\",\n" + " \"codec_type\": \"audio\",\n" + " \"codec_time_base\": \"1/44100\",\n" + " \"codec_tag_string\": \"[0][0][0][0]\",\n" + " \"codec_tag\": \"0x0000\",\n" + " \"sample_fmt\": \"s16p\",\n" + " \"sample_rate\": \"44100\",\n" + " \"channels\": 2,\n" + " \"channel_layout\": \"stereo\",\n" + " \"bits_per_sample\": 0,\n" + " \"r_frame_rate\": \"0/0\",\n" + " \"avg_frame_rate\": \"0/0\",\n" + " \"time_base\": \"1/14112000\",\n" + " \"start_pts\": 353600,\n" + " \"start_time\": \"0.025057\",\n" + " \"duration_ts\": 63109324800,\n" + " \"duration\": \"4472.032653\",\n" + " \"bit_rate\": \"128000\",\n" + " \"disposition\": {\n" + " \"default\": 0,\n" + " \"dub\": 0,\n" + " \"original\": 0,\n" + " \"comment\": 0,\n" + " \"lyrics\": 0,\n" + " \"karaoke\": 0,\n" + " \"forced\": 0,\n" + " \"hearing_impaired\": 0,\n" + " \"visual_impaired\": 0,\n" + " \"clean_effects\": 0,\n" + " \"attached_pic\": 0\n" + " },\n" + " \"tags\": {\n" + " \"encoder\": \"Lavc57.48\"\n" + " }\n" + " }\n" + " ],\n" + " \"format\": {\n" + " \"filename\": \"/Users/test/Downloads/recording.mp3\",\n" + " \"nb_streams\": 1,\n" + " \"nb_programs\": 0,\n" + " \"format_name\": \"mp3\",\n" + " \"format_long_name\": \"MP2/3 (MPEG audio layer 2/3)\",\n" + " \"start_time\": \"0.025057\",\n" + " \"duration\": \"4472.032653\",\n" + " \"size\": \"71553077\",\n" + " \"bit_rate\": \"128000\",\n" + " \"probe_score\": 51,\n" + " \"tags\": {\n" + " \"major_brand\": \"dash\",\n" + " \"minor_version\": \"0\",\n" + " \"compatible_brands\": \"iso6mp41\",\n" + " \"encoder\": \"Lavf57.41.100\"\n" + " }\n" + " }\n" + "}";
MediaInfo info = FFmpegUtil.parseMediaInfo(file, string);
assertEquals(file, info.file);
assertEquals(4472032, info.durationMs);
assertEquals(MediaContainer.MP3, info.container);
assertEquals(null, info.videoCodec);
assertEquals(null, info.videoResolution);
assertEquals(Integer.valueOf(0), info.videoBitrateK);
assertEquals(null, info.videoFramerate);
assertEquals(AudioCodec.MP3, info.audioCodec);
assertEquals(Integer.valueOf(44100), info.audioSampleRate);
assertEquals(Integer.valueOf(128), info.audioBitrateK);
assertEquals(Integer.valueOf(2), info.audioChannels);
string = "{\n" + " \"streams\": [\n" + " {\n" + " \"index\": 0,\n" + " \"codec_name\": \"h264\",\n" + " \"codec_long_name\": \"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10\",\n" + " \"profile\": \"Constrained Baseline\",\n" + " \"codec_type\": \"video\",\n" + " \"codec_time_base\": \"12864731/489240000\",\n" + " \"codec_tag_string\": \"avc1\",\n" + " \"codec_tag\": \"0x31637661\",\n" + " \"width\": 1080,\n" + " \"height\": 1920,\n" + " \"coded_width\": 1080,\n" + " \"coded_height\": 1920,\n" + " \"has_b_frames\": 0,\n" + " \"sample_aspect_ratio\": \"1:1\",\n" + " \"display_aspect_ratio\": \"9:16\",\n" + " \"pix_fmt\": \"yuv420p\",\n" + " \"level\": 40,\n" + " \"color_range\": \"tv\",\n" + " \"color_space\": \"bt709\",\n" + " \"color_transfer\": \"bt709\",\n" + " \"color_primaries\": \"bt709\",\n" + " \"chroma_location\": \"left\",\n" + " \"refs\": 1,\n" + " \"is_avc\": \"true\",\n" + " \"nal_length_size\": \"4\",\n" + " \"r_frame_rate\": \"180000/2\",\n" + " \"avg_frame_rate\": \"244620000/12864731\",\n" + " \"time_base\": \"1/90000\",\n" + " \"start_pts\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"duration_ts\": 12864731,\n" + " \"duration\": \"142.941456\",\n" + " \"bit_rate\": \"4499166\",\n" + " \"bits_per_raw_sample\": \"8\",\n" + " \"nb_frames\": \"2718\",\n" + " \"disposition\": {\n" + " \"default\": 1,\n" + " \"dub\": 0,\n" + " \"original\": 0,\n" + " \"comment\": 0,\n" + " \"lyrics\": 0,\n" + " \"karaoke\": 0,\n" + " \"forced\": 0,\n" + " \"hearing_impaired\": 0,\n" + " \"visual_impaired\": 0,\n" + " \"clean_effects\": 0,\n" + " \"attached_pic\": 0\n" + " },\n" + " \"tags\": {\n" + " \"creation_time\": \"2018-01-02 00:09:32\",\n" + " \"language\": \"eng\",\n" + " \"handler_name\": \"VideoHandle\"\n" + " }\n" + " },\n" + " {\n" + " \"index\": 1,\n" + " \"codec_name\": \"aac\",\n" + " \"codec_long_name\": \"AAC (Advanced Audio Coding)\",\n" + " \"profile\": \"LC\",\n" + " \"codec_type\": \"audio\",\n" + " \"codec_time_base\": \"1/22050\",\n" + " \"codec_tag_string\": \"mp4a\",\n" + " \"codec_tag\": \"0x6134706d\",\n" + " \"sample_fmt\": \"fltp\",\n" + " \"sample_rate\": \"22050\",\n" + " \"channels\": 1,\n" + " \"channel_layout\": \"mono\",\n" + " \"bits_per_sample\": 0,\n" + " \"r_frame_rate\": \"0/0\",\n" + " \"avg_frame_rate\": \"0/0\",\n" + " \"time_base\": \"1/44100\",\n" + " \"start_pts\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"duration_ts\": 6286221,\n" + " \"duration\": \"142.544694\",\n" + " \"bit_rate\": \"63860\",\n" + " \"nb_frames\": \"3064\",\n" + " \"disposition\": {\n" + " \"default\": 1,\n" + " \"dub\": 0,\n" + " \"original\": 0,\n" + " \"comment\": 0,\n" + " \"lyrics\": 0,\n" + " \"karaoke\": 0,\n" + " \"forced\": 0,\n" + " \"hearing_impaired\": 0,\n" + " \"visual_impaired\": 0,\n" + " \"clean_effects\": 0,\n" + " \"attached_pic\": 0\n" + " },\n" + " \"tags\": {\n" + " \"creation_time\": \"2018-01-02 00:09:32\",\n" + " \"language\": \"eng\",\n" + " \"handler_name\": \"SoundHandle\"\n" + " }\n" + " }\n" + " ],\n" + " \"format\": {\n" + " \"filename\": \"/Users/test/Downloads/ScreenRecord-2018-01-01-19-07-10.mp4\",\n" + " \"nb_streams\": 2,\n" + " \"nb_programs\": 0,\n" + " \"format_name\": \"mov,mp4,m4a,3gp,3g2,mj2\",\n" + " \"format_long_name\": \"QuickTime / MOV\",\n" + " \"start_time\": \"0.000000\",\n" + " \"duration\": \"142.862000\",\n" + " \"size\": \"81603639\",\n" + " \"bit_rate\": \"4569648\",\n" + " \"probe_score\": 100,\n" + " \"tags\": {\n" + " \"major_brand\": \"mp42\",\n" + " \"minor_version\": \"0\",\n" + " \"compatible_brands\": \"isommp42\",\n" + " \"creation_time\": \"2018-01-02 00:09:32\",\n" + " \"com.android.version\": \"7.1.2\"\n" + " }\n" + " }\n" + "}\n";
info = FFmpegUtil.parseMediaInfo(file, string);
assertEquals(file, info.file);
assertEquals(142862, info.durationMs);
assertEquals(MediaContainer.MP4, info.container);
assertEquals(VideoCodec.H264, info.videoCodec);
assertEquals("1080x1920", info.videoResolution);
assertEquals(Integer.valueOf(4499), info.videoBitrateK);
assertEquals("19.01", info.videoFramerate);
assertEquals(AudioCodec.AAC, info.audioCodec);
assertEquals(Integer.valueOf(22050), info.audioSampleRate);
assertEquals(Integer.valueOf(63), info.audioBitrateK);
assertEquals(Integer.valueOf(1), info.audioChannels);
string = "{\n" + " \"streams\": [\n" + " {\n" + " \"index\": 0,\n" + " \"codec_name\": \"h264\",\n" + " \"codec_long_name\": \"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10\",\n" + " \"profile\": \"Main\",\n" + " \"codec_type\": \"video\",\n" + " \"codec_time_base\": \"1/50\",\n" + " \"codec_tag_string\": \"[0][0][0][0]\",\n" + " \"codec_tag\": \"0x0000\",\n" + " \"width\": 640,\n" + " \"height\": 360,\n" + " \"coded_width\": 640,\n" + " \"coded_height\": 360,\n" + " \"has_b_frames\": 0,\n" + " \"sample_aspect_ratio\": \"1:1\",\n" + " \"display_aspect_ratio\": \"16:9\",\n" + " \"pix_fmt\": \"yuv420p\",\n" + " \"level\": 30,\n" + " \"chroma_location\": \"left\",\n" + " \"refs\": 1,\n" + " \"is_avc\": \"true\",\n" + " \"nal_length_size\": \"4\",\n" + " \"r_frame_rate\": \"25/1\",\n" + " \"avg_frame_rate\": \"25/1\",\n" + " \"time_base\": \"1/1000\",\n" + " \"start_pts\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"bits_per_raw_sample\": \"8\",\n" + " \"disposition\": {\n" + " \"default\": 0,\n" + " \"dub\": 0,\n" + " \"original\": 0,\n" + " \"comment\": 0,\n" + " \"lyrics\": 0,\n" + " \"karaoke\": 0,\n" + " \"forced\": 0,\n" + " \"hearing_impaired\": 0,\n" + " \"visual_impaired\": 0,\n" + " \"clean_effects\": 0,\n" + " \"attached_pic\": 0\n" + " }\n" + " },\n" + " {\n" + " \"index\": 1,\n" + " \"codec_name\": \"aac\",\n" + " \"codec_long_name\": \"AAC (Advanced Audio Coding)\",\n" + " \"profile\": \"LC\",\n" + " \"codec_type\": \"audio\",\n" + " \"codec_time_base\": \"1/44100\",\n" + " \"codec_tag_string\": \"[0][0][0][0]\",\n" + " \"codec_tag\": \"0x0000\",\n" + " \"sample_fmt\": \"fltp\",\n" + " \"sample_rate\": \"48000\",\n" + " \"channels\": 6,\n" + " \"channel_layout\": \"5.1\",\n" + " \"bits_per_sample\": 0,\n" + " \"r_frame_rate\": \"0/0\",\n" + " \"avg_frame_rate\": \"0/0\",\n" + " \"time_base\": \"1/1000\",\n" + " \"start_pts\": 3,\n" + " \"start_time\": \"0.003000\",\n" + " \"disposition\": {\n" + " \"default\": 0,\n" + " \"dub\": 0,\n" + " \"original\": 0,\n" + " \"comment\": 0,\n" + " \"lyrics\": 0,\n" + " \"karaoke\": 0,\n" + " \"forced\": 0,\n" + " \"hearing_impaired\": 0,\n" + " \"visual_impaired\": 0,\n" + " \"clean_effects\": 0,\n" + " \"attached_pic\": 0\n" + " }\n" + " }\n" + " ],\n" + " \"format\": {\n" + " \"filename\": \"/Users/test/Downloads/big_buck_bunny_360p_1mb.flv\",\n" + " \"nb_streams\": 2,\n" + " \"nb_programs\": 0,\n" + " \"format_name\": \"flv\",\n" + " \"format_long_name\": \"FLV (Flash Video)\",\n" + " \"start_time\": \"0.000000\",\n" + " \"duration\": \"6.893000\",\n" + " \"size\": \"1048720\",\n" + " \"bit_rate\": \"1217142\",\n" + " \"probe_score\": 100,\n" + " \"tags\": {\n" + " \"encoder\": \"Lavf53.24.2\"\n" + " }\n" + " }\n" + "}";
info = FFmpegUtil.parseMediaInfo(file, string);
assertEquals(file, info.file);
assertEquals(6893, info.durationMs);
assertEquals(MediaContainer.FLV, info.container);
assertEquals(VideoCodec.H264, info.videoCodec);
assertEquals("640x360", info.videoResolution);
// This is guessed from total bitrate
assertEquals(Integer.valueOf(1117), info.videoBitrateK);
assertEquals("25", info.videoFramerate);
assertEquals(AudioCodec.AAC, info.audioCodec);
assertEquals(Integer.valueOf(48000), info.audioSampleRate);
assertEquals(null, info.audioBitrateK);
assertEquals(Integer.valueOf(2), info.audioChannels);
string = "{\n" + " \"streams\": [\n" + " {\n" + " \"index\": 0,\n" + " \"codec_name\": \"h264\",\n" + " \"codec_long_name\": \"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10\",\n" + " \"profile\": \"Main\",\n" + " \"codec_type\": \"video\",\n" + " \"codec_time_base\": \"1/50\",\n" + " \"codec_tag_string\": \"[0][0][0][0]\",\n" + " \"codec_tag\": \"0x0000\",\n" + " \"width\": 640,\n" + " \"height\": 360,\n" + " \"coded_width\": 640,\n" + " \"coded_height\": 360,\n" + " \"has_b_frames\": 0,\n" + " \"sample_aspect_ratio\": \"1:1\",\n" + " \"display_aspect_ratio\": \"16:9\",\n" + " \"pix_fmt\": \"yuv420p\",\n" + " \"level\": 30,\n" + " \"chroma_location\": \"left\",\n" + " \"refs\": 1,\n" + " \"is_avc\": \"true\",\n" + " \"nal_length_size\": \"4\",\n" + " \"r_frame_rate\": \"25/1\",\n" + " \"avg_frame_rate\": \"25/1\",\n" + " \"time_base\": \"1/1000\",\n" + " \"start_pts\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"bits_per_raw_sample\": \"8\",\n" + " \"disposition\": {\n" + " \"default\": 0,\n" + " \"dub\": 0,\n" + " \"original\": 0,\n" + " \"comment\": 0,\n" + " \"lyrics\": 0,\n" + " \"karaoke\": 0,\n" + " \"forced\": 0,\n" + " \"hearing_impaired\": 0,\n" + " \"visual_impaired\": 0,\n" + " \"clean_effects\": 0,\n" + " \"attached_pic\": 0\n" + " }\n" + " },\n" + " {\n" + " \"index\": 1,\n" + " \"codec_name\": \"aac\",\n" + " \"codec_long_name\": \"AAC (Advanced Audio Coding)\",\n" + " \"profile\": \"LC\",\n" + " \"codec_type\": \"audio\",\n" + " \"codec_time_base\": \"1/44100\",\n" + " \"codec_tag_string\": \"[0][0][0][0]\",\n" + " \"codec_tag\": \"0x0000\",\n" + " \"sample_fmt\": \"fltp\",\n" + " \"sample_rate\": \"48000\",\n" + " \"channels\": 6,\n" + " \"channel_layout\": \"5.1\",\n" + " \"bits_per_sample\": 0,\n" + " \"r_frame_rate\": \"0/0\",\n" + " \"avg_frame_rate\": \"0/0\",\n" + " \"time_base\": \"1/1000\",\n" + " \"start_pts\": 3,\n" + " \"start_time\": \"0.003000\",\n" + // Not actually from this file, just added here for the tests
" \"bit_rate\": 517000,\n" + " \"disposition\": {\n" + " \"default\": 0,\n" + " \"dub\": 0,\n" + " \"original\": 0,\n" + " \"comment\": 0,\n" + " \"lyrics\": 0,\n" + " \"karaoke\": 0,\n" + " \"forced\": 0,\n" + " \"hearing_impaired\": 0,\n" + " \"visual_impaired\": 0,\n" + " \"clean_effects\": 0,\n" + " \"attached_pic\": 0\n" + " }\n" + " }\n" + " ],\n" + " \"format\": {\n" + " \"filename\": \"/Users/test/Downloads/big_buck_bunny_360p_1mb.flv\",\n" + " \"nb_streams\": 2,\n" + " \"nb_programs\": 0,\n" + " \"format_name\": \"flv\",\n" + " \"format_long_name\": \"FLV (Flash Video)\",\n" + " \"start_time\": \"0.000000\",\n" + " \"duration\": \"6.893000\",\n" + " \"size\": \"1048720\",\n" + " \"bit_rate\": \"1217142\",\n" + " \"probe_score\": 100,\n" + " \"tags\": {\n" + " \"encoder\": \"Lavf53.24.2\"\n" + " }\n" + " }\n" + "}";
info = FFmpegUtil.parseMediaInfo(file, string);
// This is guessed from total and audio bitrate
assertEquals(Integer.valueOf(700), info.videoBitrateK);
}
use of protect.videotranscoder.media.MediaInfo in project video-transcoder by brarcher.
the class MainActivityTest method openFilePickerFromLoadSelectFile.
private void openFilePickerFromLoadSelectFile(Activity activity, MediaInfo mediaInfo) throws Exception {
shadowOf(activity).grantPermissions(Manifest.permission.READ_EXTERNAL_STORAGE);
shadowOf(activity).grantPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE);
Button selectVideo = activity.findViewById(R.id.selectVideo);
assertNotNull(selectVideo);
selectVideo.performClick();
ShadowActivity.IntentForResult intentForResult = shadowOf(activity).getNextStartedActivityForResult();
assertNotNull(intentForResult);
Intent intent = intentForResult.intent;
assertNotNull(intent);
ComponentName componentName = intent.getComponent();
assertNotNull(componentName);
assertEquals("protect.videotranscoder/.picker.FastScrollerFilePickerActivity", componentName.flattenToShortString());
Intent resultIntent = new Intent();
resultIntent.setData(Uri.fromFile(mediaInfo.file));
final MediaInfo mediaInfoToUse = mediaInfo;
// When the media details are queried for the selected file, capture the call and
// return the passed (or stubbed) MediaInfo instead of calling ffprobe.
PowerMockito.when(FFmpegUtil.class, "getMediaDetails", any(File.class), any(ResultCallbackHandler.class)).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
ResultCallbackHandler<MediaInfo> resultHandler = (ResultCallbackHandler<MediaInfo>) args[1];
resultHandler.onResult(mediaInfoToUse);
return null;
}
});
shadowOf(activity).receiveResult(intent, Activity.RESULT_OK, resultIntent);
}
use of protect.videotranscoder.media.MediaInfo in project video-transcoder by brarcher.
the class FFmpegUtil method mediaInfoFixup.
private static MediaInfo mediaInfoFixup(MediaInfo info) {
if (info.container != null && info.container == MediaContainer.GIF) {
// ffprobe will not report the duration of GIF files. The duration will
// need to be determined another way
Movie gifMovie = Movie.decodeFile(info.file.getAbsolutePath());
int durationMs = gifMovie.duration();
info = new MediaInfo(info.file, durationMs, info.container, info.videoCodec, info.videoResolution, info.videoBitrateK, info.videoFramerate, info.audioCodec, info.audioSampleRate, info.audioBitrateK, info.audioChannels);
}
return info;
}
use of protect.videotranscoder.media.MediaInfo in project video-transcoder by brarcher.
the class FFmpegUtil method parseMediaInfo.
static MediaInfo parseMediaInfo(File mediaFile, String mediaDetailsJsonStr) {
long durationMs = 0;
Integer totalBitrateK = null;
MediaContainer container = null;
VideoCodec videoCodec = null;
String videoResolution = null;
Integer videoBitrateK = null;
String videoFramerate = null;
AudioCodec audioCodec = null;
Integer audioSampleRate = null;
Integer audioBitrateK = null;
int audioChannels = 2;
/*
* Example output:
{
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "Main",
"codec_type": "video",
"codec_time_base": "1/50",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"width": 640,
"height": 360,
"coded_width": 640,
"coded_height": 360,
"has_b_frames": 0,
"sample_aspect_ratio": "1:1",
"display_aspect_ratio": "16:9",
"pix_fmt": "yuv420p",
"level": 30,
"chroma_location": "left",
"refs": 1,
"is_avc": "true",
"nal_length_size": "4",
"r_frame_rate": "25/1",
"avg_frame_rate": "25/1",
"time_base": "1/1000",
"start_pts": 0,
"start_time": "0.000000",
"bits_per_raw_sample": "8",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"profile": "LC",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"sample_fmt": "fltp",
"sample_rate": "48000",
"channels": 6,
"channel_layout": "5.1",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/1000",
"start_pts": 3,
"start_time": "0.003000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0
}
}
],
"format": {
"filename": "/Users/brarcher/Downloads/big_buck_bunny_360p_1mb.flv",
"nb_streams": 2,
"nb_programs": 0,
"format_name": "flv",
"format_long_name": "FLV (Flash Video)",
"start_time": "0.000000",
"duration": "6.893000",
"size": "1048720",
"bit_rate": "1217142",
"probe_score": 100,
"tags": {
"encoder": "Lavf53.24.2"
}
}
}
*/
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode root = mapper.readTree(mediaDetailsJsonStr);
if (root != null) {
JsonNode format = root.get("format");
if (format != null) {
JsonNode duration = format.get("duration");
if (duration != null) {
durationMs = (int) (duration.asDouble() * 1000);
}
JsonNode bitrate = format.get("bit_rate");
if (bitrate != null) {
totalBitrateK = bitrate.asInt() / 1000;
}
JsonNode formatName = format.get("format_name");
if (formatName != null) {
String formatNameStr = formatName.asText();
for (MediaContainer item : MediaContainer.values()) {
if (formatNameStr.contains(item.ffmpegName)) {
container = item;
break;
}
}
}
}
JsonNode streams = root.get("streams");
if (streams != null) {
for (int index = 0; index < streams.size(); index++) {
JsonNode stream = streams.get(index);
JsonNode codecType = stream.get("codec_type");
if (codecType == null) {
continue;
}
if (codecType.asText().equals("video")) {
JsonNode codecName = stream.get("codec_name");
if (codecName == null) {
continue;
}
videoCodec = VideoCodec.fromName(codecName.asText());
JsonNode width = stream.get("width");
JsonNode height = stream.get("height");
if (width == null || height == null) {
continue;
}
videoResolution = width + "x" + height;
// bit_rate may not always be available, so do not require it.
JsonNode bitrate = stream.get("bit_rate");
if (bitrate != null) {
videoBitrateK = bitrate.asInt() / 1000;
}
JsonNode frameRate = stream.get("avg_frame_rate");
if (frameRate == null) {
continue;
}
try {
String frameRateStr = frameRate.asText();
String[] frameRateSplit = frameRateStr.split("/");
int frameRateNum = Integer.parseInt(frameRateSplit[0]);
int frameRateDem = 1;
if (frameRateSplit.length > 1) {
frameRateDem = Integer.parseInt(frameRateSplit[1]);
}
double frameRateValue = frameRateNum / (double) frameRateDem;
videoFramerate = String.format(Locale.US, "%.2f", frameRateValue);
if (videoFramerate.contains(".00")) {
videoFramerate = videoFramerate.replace(".00", "");
}
} catch (NumberFormatException e) {
continue;
}
}
if (codecType.asText().equals("audio")) {
JsonNode codecName = stream.get("codec_name");
if (codecName == null) {
continue;
}
audioCodec = AudioCodec.fromName(codecName.asText());
JsonNode sampleRate = stream.get("sample_rate");
if (sampleRate == null) {
continue;
}
audioSampleRate = sampleRate.asInt();
// bit_rate may not always be available, so do not require it.
JsonNode bitrate = stream.get("bit_rate");
if (bitrate != null) {
audioBitrateK = bitrate.asInt() / 1000;
}
JsonNode channelLaoyout = stream.get("channel_layout");
if (channelLaoyout == null) {
continue;
}
audioChannels = channelLaoyout.asText().equals("mono") ? 1 : 2;
}
}
}
}
} catch (IOException e) {
Log.w(TAG, "Failed to read media details for file : " + mediaFile.getAbsolutePath() + "\n" + mediaDetailsJsonStr, e);
}
if (totalBitrateK != null) {
if (videoBitrateK == null) {
if (audioBitrateK != null) {
// We know the audio bitrate, we can calculate the video bitrate
videoBitrateK = totalBitrateK - audioBitrateK;
}
if (videoBitrateK == null) {
// We do not know any of the separate bitrates. Lets guess 100 kb/s for the audio,
// and subtract that from the total to guess the video bitrate.
// As a guess, subtract 100 kb/s from the bitrate for audio, and
// assume that the video is the rest. This should be a decent-ish
// estimate if the video bitrate cannot be found later.
videoBitrateK = totalBitrateK - 100;
}
}
}
MediaInfo info = null;
if (container != null && (videoCodec != null || audioCodec != null)) {
info = new MediaInfo(mediaFile, durationMs, container, videoCodec, videoResolution, videoBitrateK, videoFramerate, audioCodec, audioSampleRate, audioBitrateK, audioChannels);
}
return info;
}
Aggregations