11package net .ypresto .androidtranscoder .engine ;
22
3- import android .media .MediaCodecInfo ;
43import android .media .MediaExtractor ;
54import android .media .MediaFormat ;
65import android .media .MediaMetadataRetriever ;
76import android .media .MediaMuxer ;
7+ import android .util .Log ;
88
99import net .ypresto .androidtranscoder .utils .MediaExtractorUtils ;
1010
1313
1414// TODO: treat encrypted data
1515public class MediaTranscoderEngine {
16- private static final MediaFormat OUTPUT_VIDEO_FORMAT ;
17- private static final long SLEEP_TO_WAIT_TRACK_TRANSCODERS = 100 ;
16+ private static final String TAG = "MediaTranscoderEngine" ;
17+ private static final long SLEEP_TO_WAIT_TRACK_TRANSCODERS = 10 ;
1818
1919 static {
20- // Refer: https://gist.github.com/wobbals/3990442
21- // Refer: https://developer.apple.com/library/ios/documentation/networkinginternet/conceptual/streamingmediaguide/UsingHTTPLiveStreaming/UsingHTTPLiveStreaming.html#//apple_ref/doc/uid/TP40008332-CH102-SW8
22- // Refer: (ANDROID ROOT)/media/libstagefright/ACodec.cpp
23- /*
24- OUTPUT_VIDEO_FORMAT = MediaFormat.createVideoFormat("video/avc", 640, 480); // TODO
25- OUTPUT_VIDEO_FORMAT.setInteger(MediaFormat.KEY_BIT_RATE, 5375 * 1000); // TODO
26- OUTPUT_VIDEO_FORMAT.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
27- OUTPUT_VIDEO_FORMAT.setFloat(MediaFormat.KEY_FRAME_RATE, 29.97f); // NTSC, recommended by apple
28- OUTPUT_VIDEO_FORMAT.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5); // FIXME
29- */
30- OUTPUT_VIDEO_FORMAT = MediaFormat .createVideoFormat ("video/avc" , 320 , 240 ); // TODO
31- OUTPUT_VIDEO_FORMAT .setInteger (MediaFormat .KEY_BIT_RATE , 2000000 ); // TODO
32- OUTPUT_VIDEO_FORMAT .setInteger (MediaFormat .KEY_COLOR_FORMAT , MediaCodecInfo .CodecCapabilities .COLOR_FormatSurface );
33- OUTPUT_VIDEO_FORMAT .setInteger (MediaFormat .KEY_FRAME_RATE , 15 ); // NTSC, recommended by apple
34- OUTPUT_VIDEO_FORMAT .setInteger (MediaFormat .KEY_I_FRAME_INTERVAL , 10 ); // FIXME
3520 }
3621
3722 private FileDescriptor mInputFileDescriptor ;
3823 private TrackTranscoder mVideoTrackTranscoder ;
3924 private TrackTranscoder mAudioTrackTranscoder ;
4025 private MediaExtractor mExtractor ;
41- private MediaExtractor mExtractor2 ;
4226 private MediaMuxer mMuxer ;
4327
4428 public MediaTranscoderEngine () {
@@ -52,7 +36,7 @@ public void setDataSource(FileDescriptor fileDescriptor) {
5236 * Run transcoding. Blocks current thread.
5337 * @throws IOException when extractor or muxer cannot open file.
5438 */
55- public void transcode (String outputPath ) throws IOException {
39+ public void transcode (String outputPath , MediaFormat outputFormat ) throws IOException {
5640 if (outputPath == null ) {
5741 throw new NullPointerException ("Output path cannot be null." );
5842 }
@@ -62,10 +46,8 @@ public void transcode(String outputPath) throws IOException {
6246 try {
6347 mExtractor = new MediaExtractor ();
6448 mExtractor .setDataSource (mInputFileDescriptor );
65- mExtractor2 = new MediaExtractor ();
66- mExtractor2 .setDataSource (mInputFileDescriptor );
6749 mMuxer = new MediaMuxer (outputPath , MediaMuxer .OutputFormat .MUXER_OUTPUT_MPEG_4 );
68- setupTrackTranscoders ();
50+ setupTrackTranscoders (outputFormat );
6951 mMuxer .start ();
7052 runPipelines ();
7153 mMuxer .stop ();
@@ -82,10 +64,6 @@ public void transcode(String outputPath) throws IOException {
8264 mExtractor .release ();
8365 mExtractor = null ;
8466 }
85- if (mExtractor2 != null ) {
86- mExtractor2 .release ();
87- mExtractor2 = null ;
88- }
8967 if (mMuxer != null ) {
9068 mMuxer .release ();
9169 mMuxer = null ;
@@ -99,31 +77,37 @@ private void setupProgressCalculation() throws IOException {
9977 // TODO
10078 }
10179
102- private void setupTrackTranscoders () {
80+ private void setupTrackTranscoders (MediaFormat outputFormat ) {
10381 MediaExtractorUtils .TrackResult trackResult = MediaExtractorUtils .getFirstVideoAndAudioTrack (mExtractor );
104- mVideoTrackTranscoder = new VideoTrackTranscoder (mExtractor , trackResult .mVideoTrackIndex , OUTPUT_VIDEO_FORMAT , mMuxer );
82+ mVideoTrackTranscoder = new VideoTrackTranscoder (mExtractor , trackResult .mVideoTrackIndex , outputFormat , mMuxer );
10583 mVideoTrackTranscoder .setup ();
106- mAudioTrackTranscoder = new PassThroughTrackTranscoder (mExtractor2 , trackResult .mAudioTrackIndex , mMuxer );
84+ mAudioTrackTranscoder = new PassThroughTrackTranscoder (mExtractor , trackResult .mAudioTrackIndex , mMuxer );
10785 mAudioTrackTranscoder .setup ();
10886 mVideoTrackTranscoder .determineFormat ();
10987 mAudioTrackTranscoder .determineFormat ();
11088 mVideoTrackTranscoder .addTrackToMuxer ();
11189 mAudioTrackTranscoder .addTrackToMuxer ();
11290 mExtractor .selectTrack (trackResult .mVideoTrackIndex );
113- mExtractor2 .selectTrack (trackResult .mAudioTrackIndex );
91+ mExtractor .selectTrack (trackResult .mAudioTrackIndex );
11492 }
11593
11694 private void runPipelines () {
95+ int stepCount = 0 ;
11796 while (!(mVideoTrackTranscoder .isFinished () && mAudioTrackTranscoder .isFinished ())) {
118- boolean stepped = mVideoTrackTranscoder .stepPipeline ();
119- stepped |= mAudioTrackTranscoder .stepPipeline ();
97+ boolean stepped = mVideoTrackTranscoder .stepPipeline ()
98+ || mAudioTrackTranscoder .stepPipeline ();
99+ if (true ) continue ;
120100 if (!stepped ) {
121101 try {
102+ Log .v (TAG , "Sleeping " + SLEEP_TO_WAIT_TRACK_TRANSCODERS + "msec, " + stepCount + " steps run after last sleep." );
122103 Thread .sleep (SLEEP_TO_WAIT_TRACK_TRANSCODERS );
123104 } catch (InterruptedException e ) {
124105 // nothing to do
125106 }
107+ stepCount = 0 ;
108+ continue ;
126109 }
110+ stepCount ++;
127111 }
128112 }
129113}
0 commit comments