//activity 1
class Video2PcmActivity : Activity() {
val TAG: String = "Video2PcmActivity"
val filePath: String = "/sdcard/test/test.mp4"
val pcmPath: String = "/sdcard/test/test.pcm"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pcm)
Thread {
try {
initExtractor(filePath)
} catch (e: Exception) {
e.printStackTrace()
}
}.start()
}
private fun initExtractor(fileStr: String) {
try {
val mediaExtractor = MediaExtractor()
mediaExtractor.setDataSource(fileStr)
var audioIndex = -1
var hasAudio = false
for (i in 0 until mediaExtractor.trackCount) {
var format: MediaFormat = mediaExtractor.getTrackFormat(i)
var mine: String = format.getString(MediaFormat.KEY_MIME)
if (mine.startsWith("audio")) {
audioIndex = i
hasAudio = true
break
}
}
if (hasAudio) {
mediaExtractor.selectTrack(audioIndex)
Thread {
getPCMfromMp4(mediaExtractor, audioIndex)
Log.e(TAG,"finish")
}.start()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 单纯得到PCM文件
*/
private fun getPCMfromMp4(extractor: MediaExtractor, index: Int) {
try {
val mediaFormat: MediaFormat = extractor.getTrackFormat(index)
val audioCodec = MediaCodec.createDecoderByType(mediaFormat.getString(MediaFormat.KEY_MIME))
audioCodec.configure(mediaFormat, null, null, 0)
audioCodec.start()
val inputBuff = audioCodec.inputBuffers
val outputBuff = audioCodec.outputBuffers
val inputInfo = MediaCodec.BufferInfo()
val outputInfo = MediaCodec.BufferInfo()
val fileOutPutStream = FileOutputStream(pcmPath)
var inputDone = false
var isOverCode = false
while (!isOverCode) {
if (!inputDone) {
for (i in 0 until inputBuff.size) {
val inputIndex = audioCodec.dequeueInputBuffer(0)
if (inputIndex >= 0) {
val byteBuffer = inputBuff[inputIndex]
byteBuffer.clear()
val sampleSize = extractor.readSampleData(byteBuffer, 0)
if (sampleSize <= 0) {
audioCodec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
inputDone = true
} else {
inputInfo.offset = 0
inputInfo.size = sampleSize
inputInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME
inputInfo.presentationTimeUs = extractor.sampleTime
audioCodec.queueInputBuffer(
inputIndex,
inputInfo.offset,
inputInfo.size,
inputInfo.presentationTimeUs,
0
)
extractor.advance()
}
}
}
}
var decodeOutPutDone = false
while (!decodeOutPutDone) {
val outPutIndex = audioCodec.dequeueOutputBuffer(outputInfo, 0)
if (outPutIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
decodeOutPutDone = true
} else if (outPutIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED || outPutIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
} else if (outPutIndex < 0) {
} else {
val dataBuff: ByteBuffer = outputBuff[outPutIndex]
val chumkPcm = ByteArray(outputInfo.size)
dataBuff.get(chumkPcm)
dataBuff.clear()
fileOutPutStream.write(chumkPcm)
fileOutPutStream.flush()
audioCodec.releaseOutputBuffer(outPutIndex, false)
if ((outputInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
extractor.release()
audioCodec.stop()
audioCodec.release()
decodeOutPutDone = true
isOverCode = true
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onDestroy() {
super.onDestroy()
}
}
//activity 2
class PlayPcmActivity : Activity() {
val pcmPath: String = "/sdcard/test/test.pcm"
val streamType: Int = AudioManager.STREAM_MUSIC
val streamRate: Int = 44100
val channelConfig: Int = AudioFormat.CHANNEL_CONFIGURATION_MONO
val audioFormat: Int = AudioFormat.ENCODING_PCM_16BIT
val model: Int = AudioTrack.MODE_STREAM
var buffSize: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pcm)
playPcm()
}
private fun playPcm() {
try {
buffSize = AudioTrack.getMinBufferSize(streamRate, channelConfig, audioFormat)
val track: AudioTrack = AudioTrack(streamType, streamRate, channelConfig, audioFormat, buffSize, model)
Thread {
track.play()
val filtInputStream: FileInputStream = FileInputStream(pcmPath)
var resultArray: ByteArray = ByteArray(buffSize)
while (filtInputStream.read(resultArray) != -1) {
track.write(resultArray, 0, resultArray.size)
}
filtInputStream.close()
track.stop()
track.release()
}.start()
} catch (e: Exception) {
e.printStackTrace()
}
}
}