1
1
package net .ypresto .androidtranscoder .engine ;
2
2
3
- import android .media .MediaCodecInfo ;
4
3
import android .media .MediaExtractor ;
5
4
import android .media .MediaFormat ;
6
5
import android .media .MediaMetadataRetriever ;
7
6
import android .media .MediaMuxer ;
7
+ import android .util .Log ;
8
8
9
9
import net .ypresto .androidtranscoder .utils .MediaExtractorUtils ;
10
10
13
13
14
14
// TODO: treat encrypted data
15
15
public 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 ;
18
18
19
19
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
35
20
}
36
21
37
22
private FileDescriptor mInputFileDescriptor ;
38
23
private TrackTranscoder mVideoTrackTranscoder ;
39
24
private TrackTranscoder mAudioTrackTranscoder ;
40
25
private MediaExtractor mExtractor ;
41
- private MediaExtractor mExtractor2 ;
42
26
private MediaMuxer mMuxer ;
43
27
44
28
public MediaTranscoderEngine () {
@@ -52,7 +36,7 @@ public void setDataSource(FileDescriptor fileDescriptor) {
52
36
* Run transcoding. Blocks current thread.
53
37
* @throws IOException when extractor or muxer cannot open file.
54
38
*/
55
- public void transcode (String outputPath ) throws IOException {
39
+ public void transcode (String outputPath , MediaFormat outputFormat ) throws IOException {
56
40
if (outputPath == null ) {
57
41
throw new NullPointerException ("Output path cannot be null." );
58
42
}
@@ -62,10 +46,8 @@ public void transcode(String outputPath) throws IOException {
62
46
try {
63
47
mExtractor = new MediaExtractor ();
64
48
mExtractor .setDataSource (mInputFileDescriptor );
65
- mExtractor2 = new MediaExtractor ();
66
- mExtractor2 .setDataSource (mInputFileDescriptor );
67
49
mMuxer = new MediaMuxer (outputPath , MediaMuxer .OutputFormat .MUXER_OUTPUT_MPEG_4 );
68
- setupTrackTranscoders ();
50
+ setupTrackTranscoders (outputFormat );
69
51
mMuxer .start ();
70
52
runPipelines ();
71
53
mMuxer .stop ();
@@ -82,10 +64,6 @@ public void transcode(String outputPath) throws IOException {
82
64
mExtractor .release ();
83
65
mExtractor = null ;
84
66
}
85
- if (mExtractor2 != null ) {
86
- mExtractor2 .release ();
87
- mExtractor2 = null ;
88
- }
89
67
if (mMuxer != null ) {
90
68
mMuxer .release ();
91
69
mMuxer = null ;
@@ -99,31 +77,37 @@ private void setupProgressCalculation() throws IOException {
99
77
// TODO
100
78
}
101
79
102
- private void setupTrackTranscoders () {
80
+ private void setupTrackTranscoders (MediaFormat outputFormat ) {
103
81
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 );
105
83
mVideoTrackTranscoder .setup ();
106
- mAudioTrackTranscoder = new PassThroughTrackTranscoder (mExtractor2 , trackResult .mAudioTrackIndex , mMuxer );
84
+ mAudioTrackTranscoder = new PassThroughTrackTranscoder (mExtractor , trackResult .mAudioTrackIndex , mMuxer );
107
85
mAudioTrackTranscoder .setup ();
108
86
mVideoTrackTranscoder .determineFormat ();
109
87
mAudioTrackTranscoder .determineFormat ();
110
88
mVideoTrackTranscoder .addTrackToMuxer ();
111
89
mAudioTrackTranscoder .addTrackToMuxer ();
112
90
mExtractor .selectTrack (trackResult .mVideoTrackIndex );
113
- mExtractor2 .selectTrack (trackResult .mAudioTrackIndex );
91
+ mExtractor .selectTrack (trackResult .mAudioTrackIndex );
114
92
}
115
93
116
94
private void runPipelines () {
95
+ int stepCount = 0 ;
117
96
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 ;
120
100
if (!stepped ) {
121
101
try {
102
+ Log .v (TAG , "Sleeping " + SLEEP_TO_WAIT_TRACK_TRANSCODERS + "msec, " + stepCount + " steps run after last sleep." );
122
103
Thread .sleep (SLEEP_TO_WAIT_TRACK_TRANSCODERS );
123
104
} catch (InterruptedException e ) {
124
105
// nothing to do
125
106
}
107
+ stepCount = 0 ;
108
+ continue ;
126
109
}
110
+ stepCount ++;
127
111
}
128
112
}
129
113
}
0 commit comments