@@ -6,6 +6,7 @@ import android.media.MediaExtractor
66import android.media.MediaFormat
77import androidx.appcompat.app.AppCompatActivity
88import android.os.Bundle
9+ import android.os.SystemClock
910import android.text.method.ScrollingMovementMethod
1011import android.widget.TextView
1112import java.nio.ByteOrder
@@ -39,12 +40,13 @@ class MainActivity : AppCompatActivity() {
3940
4041 fun audioToPCM (id : Int , textViewText : StringBuilder ) : FloatArray {
4142
43+ val decodingStart = SystemClock .uptimeMillis()
4244 val sampleFD = resources.openRawResourceFd(id)
4345 val mediaExtractor = MediaExtractor ()
4446 mediaExtractor.setDataSource(sampleFD.fileDescriptor, sampleFD.startOffset, sampleFD.length)
4547 val format = mediaExtractor.getTrackFormat(0 )
4648
47- // val mime = format.getString(MediaFormat.KEY_MIME)
49+ val mime = format.getString(MediaFormat .KEY_MIME )
4850 val sampleRate = format.getInteger(MediaFormat .KEY_SAMPLE_RATE )
4951 val duration = format.getLong(MediaFormat .KEY_DURATION )
5052 val channelCount = format.getInteger(MediaFormat .KEY_CHANNEL_COUNT )
@@ -54,7 +56,8 @@ class MainActivity : AppCompatActivity() {
5456 val nFrames = (ceil((duration * sampleRate).toDouble() / 1000000.0 )).toInt()
5557 val nFramesDouble = duration.toDouble() * sampleRate / 1000000.0
5658 textViewText.append(" sample rate = $sampleRate \n " )
57- .append(" duration = $duration \n " )
59+ .append(" mime = $mime \n " )
60+ .append(" duration = $duration us\n " )
5861 .append(" channel count = $channelCount \n " )
5962 .append(" codec name = $mediaCodecName \n " )
6063 .append(" expected frame number = $nFrames , (floating point = $nFramesDouble )\n " )
@@ -69,93 +72,113 @@ class MainActivity : AppCompatActivity() {
6972 // Log.v("AudioMixer", "AudioEncoder.decode: result.size = " + result.size)
7073
7174 val codec = MediaCodec .createByCodecName(mediaCodecName)
75+ // if(mime == null) {
76+ // textViewText.append("no mime\n")
77+ // return floatArrayOf(0f)
78+ // }
79+ // val codec = MediaCodec.createDecoderByType(mime)
7280
7381 codec.configure(format, null , null , 0 )
7482 codec.start()
7583
7684 mediaExtractor.selectTrack(0 )
7785 var numSamples = 0
7886 val bufferInfo = MediaCodec .BufferInfo ()
79-
80- while (true ) {
81-
82- // get input buffer index and then the input buffer itself
83- val inputBufferIndex = codec.dequeueInputBuffer(5000000 )
84- if (inputBufferIndex < 0 ) {
85- textViewText.append(" AudioEncoder.decode: failed to get input buffer index\n " )
86- return floatArrayOf(0f )
87- }
88-
89- val inputBuffer = codec.getInputBuffer(inputBufferIndex)
90- if (inputBuffer == null ) {
91- textViewText.append(" AudioEncoder.decode: failed to acquire input buffer\n " )
92- return floatArrayOf(0f )
93- }
94-
95- // write the next bunch of data from our media file to the input buffer
96- val sampleSize = mediaExtractor.readSampleData(inputBuffer, 0 )
97-
98- // queue the input buffer such that the codec can decode it
99- if (sampleSize < 0 ) {
100- codec.queueInputBuffer(inputBufferIndex, 0 , 0 , 0 , MediaCodec .BUFFER_FLAG_END_OF_STREAM )
101- } else {
102- codec.queueInputBuffer(inputBufferIndex, 0 , sampleSize, mediaExtractor.sampleTime, 0 )
103- mediaExtractor.advance()
87+ val timeOutUs = 5000L
88+ var sawOutputEOS = false
89+ var sawInputEOS = false
90+ var numNoOutput = 0
91+
92+ while (! sawOutputEOS) {
93+
94+ if (! sawInputEOS) {
95+ // get input buffer index and then the input buffer itself
96+ val inputBufferIndex = codec.dequeueInputBuffer(timeOutUs)
97+ if (inputBufferIndex >= 0 ) {
98+
99+ val inputBuffer = codec.getInputBuffer(inputBufferIndex)
100+ if (inputBuffer == null ) {
101+ textViewText.append(" AudioEncoder.decode: failed to acquire input buffer\n " )
102+ return floatArrayOf(0f )
103+ }
104+
105+ // write the next bunch of data from our media file to the input buffer
106+ var sampleSize = mediaExtractor.readSampleData(inputBuffer, 0 )
107+
108+ var presentationTimeUs = 0L
109+ var eosFlag = 0
110+
111+ if (sampleSize < 0 ) {
112+ sawInputEOS = true
113+ eosFlag = MediaCodec .BUFFER_FLAG_END_OF_STREAM
114+ sampleSize = 0
115+ } else {
116+ presentationTimeUs = mediaExtractor.sampleTime
117+ }
118+
119+ // queue the input buffer such that the codec can decode it
120+ codec.queueInputBuffer(
121+ inputBufferIndex,
122+ 0 ,
123+ sampleSize,
124+ presentationTimeUs,
125+ eosFlag
126+ )
127+
128+ if (! sawInputEOS)
129+ mediaExtractor.advance()
130+ }
104131 }
105132
106133 // we are done decoding and can now read our result
107- var outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 5000000 )
108-
109- // sometimes this output format changed appears, then we have to try again to get
110- // the output buffer index again
111- if (outputBufferIndex == MediaCodec .INFO_OUTPUT_FORMAT_CHANGED ) {
112- // Log.v("AudioMixer", "AudioEncoder.decode: output format changed")
113- outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 5000000 )
114- }
134+ val outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, timeOutUs)
135+
136+ if (outputBufferIndex >= 0 ) {
137+ // finally get our output data and create a view to a short buffer which is the
138+ // standard data type for 16bit audio
139+ val outputBuffer = codec.getOutputBuffer(outputBufferIndex)
140+ if (outputBuffer == null ) {
141+ textViewText.append(" Cannot acquire output buffer\n " )
142+ return floatArrayOf(0f )
143+ }
115144
116- // if something fails ....
117- if (outputBufferIndex == MediaCodec .INFO_OUTPUT_FORMAT_CHANGED ) {
118- // Log.v("AudioMixer", "AudioEncoder.decode: output format changed")
119- textViewText.append(" Cannot acquire valid output buffer index\n " )
120- return floatArrayOf(0f )
121- } else if (outputBufferIndex == MediaCodec .INFO_TRY_AGAIN_LATER ) {
122- // Log.v("AudioMixer", "AudioEncoder.decode: try again later")
123- textViewText.append(" Cannot acquire valid output buffer index\n " )
124- return floatArrayOf(0f )
125- }
145+ val shortBuffer = outputBuffer.order(ByteOrder .nativeOrder()).asShortBuffer()
146+
147+ // convert the short data to floats and store it to the result-array which will be
148+ // returned later. We want to have mono output stream, so we add different channel
149+ // to the same index.
150+ while (shortBuffer.position() < shortBuffer.limit()) {
151+ if (numSamples/ channelCount >= result.size) {
152+ textViewText.append(" Too many samples, something is wrong with track duration" )
153+ return result
154+ }
155+ result[numSamples / channelCount] + = shortBuffer.get().toFloat()
156+ ++ numSamples
157+ }
126158
127- // finally get our output data and create a view to a short buffer which is the
128- // standard data type for 16bit audio
129- val outputBuffer = codec.getOutputBuffer(outputBufferIndex)
159+ codec.releaseOutputBuffer(outputBufferIndex, false )
130160
131- if (outputBuffer == null ) {
132- textViewText.append( " Cannot acquire output buffer \n " )
133- return floatArrayOf( 0f )
161+ if ((bufferInfo.flags and MediaCodec . BUFFER_FLAG_END_OF_STREAM ) != 0 )
162+ sawOutputEOS = true
163+ numNoOutput = 0
134164 }
135-
136- val shortBuffer = outputBuffer.order(ByteOrder .nativeOrder()).asShortBuffer()
137-
138- // convert the short data to floats and store it to the result-array which will be
139- // returned later. We want to have mono output stream, so we add different channel
140- // to the same index.
141- while (shortBuffer.position() < shortBuffer.limit()) {
142- if (numSamples/ channelCount >= result.size) {
143- textViewText.append(" Too many samples, something is wrong with track duration" )
144- return result
165+ else {
166+ ++ numNoOutput
167+ if (numNoOutput > 50 ) {
168+ textViewText.append(" it seems as I don't get output data from codec\n " )
169+ break
145170 }
146- result[numSamples / channelCount] + = shortBuffer.get().toFloat()
147- ++ numSamples
148171 }
149-
150- codec.releaseOutputBuffer(outputBufferIndex, false )
151- if ((bufferInfo.flags and MediaCodec .BUFFER_FLAG_END_OF_STREAM ) == MediaCodec .BUFFER_FLAG_END_OF_STREAM )
152- break
153172 }
154173
174+ val decodingEnd = SystemClock .uptimeMillis()
155175 textViewText.append(" decoded frames (total)= $numSamples \n " )
156176 textViewText.append(" decoded frames (per channel)= ${numSamples/ channelCount} \n " )
177+ textViewText.append(" time for decoding = ${decodingEnd- decodingStart} ms\n " )
157178 mediaExtractor.release()
179+ codec.stop()
158180 codec.release()
181+ sampleFD.close()
159182
160183 val channelCountInv = 1.0f / channelCount
161184 for (i in result.indices)
0 commit comments