Skip to content

Commit d87536b

Browse files
committed
Changed decoding algorithm
1 parent f40994e commit d87536b

2 files changed

Lines changed: 92 additions & 69 deletions

File tree

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ android {
1010
applicationId "de.moekadu.decodertest"
1111
minSdkVersion 23
1212
targetSdkVersion 29
13-
versionCode 2
14-
versionName "2.0"
13+
versionCode 3
14+
versionName "3.0"
1515

1616
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1717
}

app/src/main/java/de/moekadu/decodertest/MainActivity.kt

Lines changed: 90 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.media.MediaExtractor
66
import android.media.MediaFormat
77
import androidx.appcompat.app.AppCompatActivity
88
import android.os.Bundle
9+
import android.os.SystemClock
910
import android.text.method.ScrollingMovementMethod
1011
import android.widget.TextView
1112
import 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

Comments
 (0)