2121import android .media .MediaMuxer ;
2222import android .util .Log ;
2323
24+ import net .ypresto .androidtranscoder .format .MediaFormatStrategy ;
2425import net .ypresto .androidtranscoder .utils .MediaExtractorUtils ;
2526
2627import java .io .FileDescriptor ;
2728import java .io .IOException ;
2829
30+ /**
31+ * Internal engine, do not use this directly.
32+ */
2933// TODO: treat encrypted data
3034public class MediaTranscoderEngine {
3135 private static final String TAG = "MediaTranscoderEngine" ;
36+ private static final double PROGRESS_UNKNOWN = -1.0 ;
3237 private static final long SLEEP_TO_WAIT_TRACK_TRANSCODERS = 10 ;
3338 private static final long PROGRESS_INTERVAL_STEPS = 10 ;
3439 private FileDescriptor mInputFileDescriptor ;
3540 private TrackTranscoder mVideoTrackTranscoder ;
3641 private TrackTranscoder mAudioTrackTranscoder ;
3742 private MediaExtractor mExtractor ;
3843 private MediaMuxer mMuxer ;
44+ private volatile double mProgress ;
3945 private ProgressCallback mProgressCallback ;
4046 private long mDurationUs ;
4147
48+ /**
49+ * Do not use this constructor unless you know what you are doing.
50+ */
4251 public MediaTranscoderEngine () {
4352 }
4453
@@ -54,15 +63,22 @@ public void setProgressCallback(ProgressCallback progressCallback) {
5463 mProgressCallback = progressCallback ;
5564 }
5665
66+ /**
67+ * NOTE: This method is thread safe.
68+ */
69+ public double getProgress () {
70+ return mProgress ;
71+ }
72+
5773 /**
5874 * Run video transcoding. Blocks current thread.
5975 * Audio data will not be transcoded; original stream will be wrote to output file.
6076 *
61- * @param outputPath File path to output transcoded video file.
62- * @param videoFormat Output video format.
77+ * @param outputPath File path to output transcoded video file.
78+ * @param formatStrategy Output format strategy .
6379 * @throws IOException when input or output file could not be opened.
6480 */
65- public void transcodeVideo (String outputPath , MediaFormat videoFormat ) throws IOException {
81+ public void transcodeVideo (String outputPath , MediaFormatStrategy formatStrategy ) throws IOException {
6682 if (outputPath == null ) {
6783 throw new NullPointerException ("Output path cannot be null." );
6884 }
@@ -75,7 +91,7 @@ public void transcodeVideo(String outputPath, MediaFormat videoFormat) throws IO
7591 mExtractor .setDataSource (mInputFileDescriptor );
7692 mMuxer = new MediaMuxer (outputPath , MediaMuxer .OutputFormat .MUXER_OUTPUT_MPEG_4 );
7793 setupMetadata ();
78- setupTrackTranscoders (videoFormat );
94+ setupTrackTranscoders (formatStrategy );
7995 mMuxer .start ();
8096 runPipelines ();
8197 mMuxer .stop ();
@@ -132,11 +148,21 @@ private void setupMetadata() throws IOException {
132148 Log .d (TAG , "Duration (us): " + mDurationUs );
133149 }
134150
135- private void setupTrackTranscoders (MediaFormat outputFormat ) {
151+ private void setupTrackTranscoders (MediaFormatStrategy formatStrategy ) {
136152 MediaExtractorUtils .TrackResult trackResult = MediaExtractorUtils .getFirstVideoAndAudioTrack (mExtractor );
137- mVideoTrackTranscoder = new VideoTrackTranscoder (mExtractor , trackResult .mVideoTrackIndex , outputFormat , mMuxer );
153+ MediaFormat videoOutputFormat = formatStrategy .createVideoOutputFormat (trackResult .mVideoTrackFormat );
154+ MediaFormat audioOutputFormat = formatStrategy .createAudioOutputFormat (trackResult .mAudioTrackFormat );
155+ if (videoOutputFormat == null ) {
156+ mVideoTrackTranscoder = new PassThroughTrackTranscoder (mExtractor , trackResult .mVideoTrackIndex , mMuxer );
157+ } else {
158+ mVideoTrackTranscoder = new VideoTrackTranscoder (mExtractor , trackResult .mVideoTrackIndex , videoOutputFormat , mMuxer );
159+ }
138160 mVideoTrackTranscoder .setup ();
139- mAudioTrackTranscoder = new PassThroughTrackTranscoder (mExtractor , trackResult .mAudioTrackIndex , mMuxer );
161+ if (audioOutputFormat == null ) {
162+ mAudioTrackTranscoder = new PassThroughTrackTranscoder (mExtractor , trackResult .mAudioTrackIndex , mMuxer );
163+ } else {
164+ throw new UnsupportedOperationException ("Transcoding audio tracks currently not supported." );
165+ }
140166 mAudioTrackTranscoder .setup ();
141167 mVideoTrackTranscoder .determineFormat ();
142168 mAudioTrackTranscoder .determineFormat ();
@@ -148,17 +174,21 @@ private void setupTrackTranscoders(MediaFormat outputFormat) {
148174
149175 private void runPipelines () {
150176 long loopCount = 0 ;
151- if (mDurationUs <= 0 && mProgressCallback != null ) {
152- mProgressCallback .onProgress (-1.0 ); // unknown
177+ if (mDurationUs <= 0 ) {
178+ double progress = PROGRESS_UNKNOWN ;
179+ mProgress = progress ;
180+ if (mProgressCallback != null ) mProgressCallback .onProgress (progress ); // unknown
153181 }
154182 while (!(mVideoTrackTranscoder .isFinished () && mAudioTrackTranscoder .isFinished ())) {
155183 boolean stepped = mVideoTrackTranscoder .stepPipeline ()
156184 || mAudioTrackTranscoder .stepPipeline ();
157185 loopCount ++;
158- if (mDurationUs > 0 && mProgressCallback != null && loopCount % PROGRESS_INTERVAL_STEPS == 0 ) {
186+ if (mDurationUs > 0 && loopCount % PROGRESS_INTERVAL_STEPS == 0 ) {
159187 double videoProgress = mVideoTrackTranscoder .isFinished () ? 1.0 : Math .min (1.0 , (double ) mVideoTrackTranscoder .getWrittenPresentationTimeUs () / mDurationUs );
160188 double audioProgress = mAudioTrackTranscoder .isFinished () ? 1.0 : Math .min (1.0 , (double ) mAudioTrackTranscoder .getWrittenPresentationTimeUs () / mDurationUs );
161- mProgressCallback .onProgress ((videoProgress + audioProgress ) / 2.0 );
189+ double progress = (videoProgress + audioProgress ) / 2.0 ;
190+ mProgress = progress ;
191+ if (mProgressCallback != null ) mProgressCallback .onProgress (progress );
162192 }
163193 if (!stepped ) {
164194 try {
0 commit comments