Skip to content

Commit 74dbf9b

Browse files
author
Cory Thompson
committed
Allow video with no audio stream present to be transcoded
1 parent 3c3f60c commit 74dbf9b

File tree

6 files changed

+51
-16
lines changed

6 files changed

+51
-16
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,12 @@ private void setupTrackTranscoders(MediaFormatStrategy formatStrategy) {
160160
@Override
161161
public void onDetermineOutputFormat() {
162162
MediaFormatValidator.validateVideoOutputFormat(mVideoTrackTranscoder.getDeterminedFormat());
163-
MediaFormatValidator.validateAudioOutputFormat(mAudioTrackTranscoder.getDeterminedFormat());
163+
164+
// If there is an audio track, validate the output is correct.
165+
MediaFormat audioFormat = mAudioTrackTranscoder.getDeterminedFormat();
166+
if (audioFormat != null) {
167+
MediaFormatValidator.validateAudioOutputFormat(audioFormat);
168+
}
164169
}
165170
});
166171

@@ -170,14 +175,18 @@ public void onDetermineOutputFormat() {
170175
mVideoTrackTranscoder = new VideoTrackTranscoder(mExtractor, trackResult.mVideoTrackIndex, videoOutputFormat, queuedMuxer);
171176
}
172177
mVideoTrackTranscoder.setup();
178+
mExtractor.selectTrack(trackResult.mVideoTrackIndex);
179+
173180
if (audioOutputFormat == null) {
174181
mAudioTrackTranscoder = new PassThroughTrackTranscoder(mExtractor, trackResult.mAudioTrackIndex, queuedMuxer, QueuedMuxer.SampleType.AUDIO);
175182
} else {
176183
mAudioTrackTranscoder = new AudioTrackTranscoder(mExtractor, trackResult.mAudioTrackIndex, audioOutputFormat, queuedMuxer);
177184
}
185+
186+
if (trackResult.mAudioTrackIndex >= 0) {
187+
mExtractor.selectTrack(trackResult.mAudioTrackIndex);
188+
}
178189
mAudioTrackTranscoder.setup();
179-
mExtractor.selectTrack(trackResult.mVideoTrackIndex);
180-
mExtractor.selectTrack(trackResult.mAudioTrackIndex);
181190
}
182191

183192
private void runPipelines() {

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,19 @@ public PassThroughTrackTranscoder(MediaExtractor extractor, int trackIndex,
4242
mMuxer = muxer;
4343
mSampleType = sampleType;
4444

45-
mActualOutputFormat = mExtractor.getTrackFormat(mTrackIndex);
46-
mMuxer.setOutputFormat(mSampleType, mActualOutputFormat);
47-
mBufferSize = mActualOutputFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
48-
mBuffer = ByteBuffer.allocateDirect(mBufferSize).order(ByteOrder.nativeOrder());
45+
if (trackIndex >= 0) {
46+
mActualOutputFormat = mExtractor.getTrackFormat(mTrackIndex);
47+
mMuxer.setOutputFormat(mSampleType, mActualOutputFormat);
48+
mBufferSize = mActualOutputFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
49+
mBuffer = ByteBuffer.allocateDirect(mBufferSize).order(ByteOrder.nativeOrder());
50+
} else {
51+
// track has no audio. Passthrough should also exclude the track.
52+
mMuxer.setOutputFormat(mSampleType, null);
53+
54+
// Nothing to do. EOS and report it took us 0 ms.
55+
mIsEOS = true;
56+
mWrittenPresentationTimeUs = 0;
57+
}
4958
}
5059

5160
@Override

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
*/
3131
public class QueuedMuxer {
3232
private static final String TAG = "QueuedMuxer";
33+
private static final int EXCLUDE_TRACK_INDEX = -1;
3334
private static final int BUFFER_SIZE = 64 * 1024; // I have no idea whether this value is appropriate or not...
3435
private final MediaMuxer mMuxer;
3536
private final Listener mListener;
@@ -54,6 +55,11 @@ public void setOutputFormat(SampleType sampleType, MediaFormat format) {
5455
break;
5556
case AUDIO:
5657
mAudioFormat = format;
58+
59+
if(format == null) {
60+
// Tell the muxer we do not require audio.
61+
mAudioTrackIndex = EXCLUDE_TRACK_INDEX;
62+
}
5763
break;
5864
default:
5965
throw new AssertionError();
@@ -62,13 +68,17 @@ public void setOutputFormat(SampleType sampleType, MediaFormat format) {
6268
}
6369

6470
private void onSetOutputFormat() {
65-
if (mVideoFormat == null || mAudioFormat == null) return;
71+
if (mVideoFormat == null || (mAudioFormat == null && mAudioTrackIndex != EXCLUDE_TRACK_INDEX)) return;
6672
mListener.onDetermineOutputFormat();
6773

6874
mVideoTrackIndex = mMuxer.addTrack(mVideoFormat);
6975
Log.v(TAG, "Added track #" + mVideoTrackIndex + " with " + mVideoFormat.getString(MediaFormat.KEY_MIME) + " to muxer");
70-
mAudioTrackIndex = mMuxer.addTrack(mAudioFormat);
71-
Log.v(TAG, "Added track #" + mAudioTrackIndex + " with " + mAudioFormat.getString(MediaFormat.KEY_MIME) + " to muxer");
76+
77+
if(mAudioFormat != null) {
78+
mAudioTrackIndex = mMuxer.addTrack(mAudioFormat);
79+
Log.v(TAG, "Added track #" + mAudioTrackIndex + " with " + mAudioFormat.getString(MediaFormat.KEY_MIME) + " to muxer");
80+
}
81+
7282
mMuxer.start();
7383
mStarted = true;
7484

lib/src/main/java/net/ypresto/androidtranscoder/format/Android16By9FormatStrategy.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,14 @@ public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
6161
if (longer * 9 != shorter * 16) {
6262
throw new OutputFormatUnavailableException("This video is not 16:9, and is not able to transcode. (" + width + "x" + height + ")");
6363
}
64+
65+
/*
66+
I've commented this out because its unsafe to assume the user wants to bypass compression if resolution is equal.
6467
if (shorter <= targetShorter) {
6568
Log.d(TAG, "This video's height is less or equal to " + targetShorter + ", pass-through. (" + width + "x" + height + ")");
6669
return null;
67-
}
70+
}*/
71+
6872
MediaFormat format = MediaFormat.createVideoFormat("video/avc", outWidth, outHeight);
6973
// From Nexus 4 Camera in 720p
7074
format.setInteger(MediaFormat.KEY_BIT_RATE, mVideoBitrate);
@@ -76,7 +80,7 @@ public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
7680

7781
@Override
7882
public MediaFormat createAudioOutputFormat(MediaFormat inputFormat) {
79-
if (mAudioBitrate == AUDIO_BITRATE_AS_IS || mAudioChannels == AUDIO_CHANNELS_AS_IS) return null;
83+
if (inputFormat == null || mAudioBitrate == AUDIO_BITRATE_AS_IS || mAudioChannels == AUDIO_CHANNELS_AS_IS) return null;
8084

8185
// Use original sample rate, as resampling is not supported yet.
8286
final MediaFormat format = MediaFormat.createAudioFormat(MediaFormatExtraConstants.MIMETYPE_AUDIO_AAC,

lib/src/main/java/net/ypresto/androidtranscoder/format/Android720pFormatStrategy.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,13 @@ public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
6363
if (longer * 9 != shorter * 16) {
6464
throw new OutputFormatUnavailableException("This video is not 16:9, and is not able to transcode. (" + width + "x" + height + ")");
6565
}
66+
67+
/*
68+
I've commented this out because its unsafe to assume the user wants to bypass compression if resolution is equal.
6669
if (shorter <= SHORTER_LENGTH) {
6770
Log.d(TAG, "This video is less or equal to 720p, pass-through. (" + width + "x" + height + ")");
6871
return null;
69-
}
72+
}*/
7073
MediaFormat format = MediaFormat.createVideoFormat("video/avc", outWidth, outHeight);
7174
// From Nexus 4 Camera in 720p
7275
format.setInteger(MediaFormat.KEY_BIT_RATE, mVideoBitrate);
@@ -78,7 +81,7 @@ public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
7881

7982
@Override
8083
public MediaFormat createAudioOutputFormat(MediaFormat inputFormat) {
81-
if (mAudioBitrate == AUDIO_BITRATE_AS_IS || mAudioChannels == AUDIO_CHANNELS_AS_IS) return null;
84+
if (inputFormat == null || mAudioBitrate == AUDIO_BITRATE_AS_IS || mAudioChannels == AUDIO_CHANNELS_AS_IS) return null;
8285

8386
// Use original sample rate, as resampling is not supported yet.
8487
final MediaFormat format = MediaFormat.createAudioFormat(MediaFormatExtraConstants.MIMETYPE_AUDIO_AAC,

lib/src/main/java/net/ypresto/androidtranscoder/utils/MediaExtractorUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ public static TrackResult getFirstVideoAndAudioTrack(MediaExtractor extractor) {
5555
}
5656
if (trackResult.mVideoTrackIndex >= 0 && trackResult.mAudioTrackIndex >= 0) break;
5757
}
58-
if (trackResult.mVideoTrackIndex < 0 || trackResult.mAudioTrackIndex < 0) {
59-
throw new IllegalArgumentException("extractor does not contain video and/or audio tracks.");
58+
if (trackResult.mVideoTrackIndex < 0) {
59+
throw new IllegalArgumentException("extractor does not contain video tracks.");
6060
}
6161
return trackResult;
6262
}

0 commit comments

Comments
 (0)