android MediaExtractor分离并播放pcm


//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()
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值