Mediacodec
16lz
2021-01-26
SurfaceView surfaceView; SurfaceHolder holder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceView = findViewById(R.id.surfaceView); holder = surfaceView.getHolder(); /** * 视频输入 */ VideoThread videoThread = new VideoThread(holder); videoThread.start(); /** * 音频输入 */ SecondThread secondThread = new SecondThread(); secondThread.start(); }}class VideoThread extends Thread{ private SurfaceHolder holder; public VideoThread(SurfaceHolder holder){ this.holder = holder; } @Override public void run() { try { final MediaExtractor extractor = new MediaExtractor(); //设置视频地址 String path = Environment.getExternalStorageDirectory().getPath() + "/h265.mp4"; extractor.setDataSource(path); extractor.seekTo(5000, SEEK_TO_NEXT_SYNC); //Count the number of tracks found in the data source.信道总数一般为2 一个视频一个音频 int numTrack = extractor.getTrackCount(); for (int i = 0; i < numTrack; i++) { //Get the track format at the specified index final MediaFormat format = extractor.getTrackFormat(i); //得到数据信息 1.video/avc 2.audio/mp4a-latm String mimetype = format.getString(MediaFormat.KEY_MIME); Log.d("tag", mimetype); if (mimetype.startsWith("video")) { //选择频道 extractor.selectTrack(i); final MediaCodec mediaCodec = MediaCodec.createDecoderByType(mimetype);// mPlayer = new AudioPlayer(format.getInteger(MediaFormat.KEY_SAMPLE_RATE), AudioFormat// .CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);// mPlayer.init(); holder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { mediaCodec.configure(format, holder.getSurface(), null, 0);// outputFormat = format; mediaCodec.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } }); mediaCodec.setCallback(new MediaCodec.Callback() { @Override public void onInputBufferAvailable(MediaCodec codec, int index) { ByteBuffer inputBuffer = codec.getInputBuffer(index); inputBuffer.clear(); int readlen = extractor.readSampleData(inputBuffer, 0); Log.d("tag", "视频输入" + inputBuffer.toString()); codec.queueInputBuffer(index, 0, readlen, 0, 0); extractor.advance();//Advance to the next sample.进入下一帧 刷新 } @Override public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) { Log.d("tag", "onOutputBufferAvailable:" + info.size); ByteBuffer outputBuffer = codec.getOutputBuffer(index); MediaFormat outformat = codec.getOutputFormat(); if (outputBuffer != null && info.size > 0) { byte[] buffer = new byte[outputBuffer.remaining()]; outputBuffer.get(buffer);// mPlayer.play(buffer,0,info.size); Log.d("tag", "Offer to queue failed, queue in full state"); } codec.releaseOutputBuffer(index, true); } @Override public void onError(MediaCodec codec, MediaCodec.CodecException e) { Log.d("tag", "onError:" + e.getDiagnosticInfo()); } @Override public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) { Log.d("tag", "onOutputFormatChanged:");// outputFormat = format; } }); } } } catch (IOException e) { e.printStackTrace(); } }}class SecondThread extends Thread{ AudioPlayer mPlayer; @Override public void run() { try { final MediaExtractor extractor = new MediaExtractor(); //设置视频地址 String path = Environment.getExternalStorageDirectory().getPath() + "/h265.mp4"; extractor.setDataSource(path); extractor.seekTo(5000, SEEK_TO_NEXT_SYNC); //Count the number of tracks found in the data source.信道总数一般为2 一个视频一个音频 int numTrack = extractor.getTrackCount(); for (int i = 0; i < numTrack; i++) { //Get the track format at the specified index final MediaFormat format = extractor.getTrackFormat(i); //得到数据信息 1.video/avc 2.audio/mp4a-latm String mimetype = format.getString(MediaFormat.KEY_MIME); Log.d("tag", mimetype); if (mimetype.startsWith("audio")) { //选择频道 extractor.selectTrack(i); final MediaCodec mediaCodec = MediaCodec.createDecoderByType(mimetype); mPlayer = new AudioPlayer(format.getInteger(MediaFormat.KEY_SAMPLE_RATE), AudioFormat .CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT); mPlayer.init(); mediaCodec.setCallback(new MediaCodec.Callback() { @Override public void onInputBufferAvailable(MediaCodec codec, int index) { ByteBuffer inputBuffer = codec.getInputBuffer(index); inputBuffer.clear(); int readlen = extractor.readSampleData(inputBuffer, 0); Log.d("tag", "音频输入" + inputBuffer.toString()); codec.queueInputBuffer(index, 0, readlen, 0, 0); extractor.advance();//Advance to the next sample.进入下一帧 刷新 } @Override public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) { Log.d("tag", "onOutputBufferAvailable:" + info.size); ByteBuffer outputBuffer = codec.getOutputBuffer(index); MediaFormat outformat = codec.getOutputFormat(); if (outputBuffer != null && info.size > 0) { byte[] buffer = new byte[outputBuffer.remaining()]; outputBuffer.get(buffer); mPlayer.play(buffer, 0, info.size); Log.d("tag", "Offer to queue failed, queue in full state"); } codec.releaseOutputBuffer(index, true); } @Override public void onError(MediaCodec codec, MediaCodec.CodecException e) { Log.d("tag", "onError:" + e.getDiagnosticInfo()); } @Override public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) { Log.d("tag", "onOutputFormatChanged:");// outputFormat = format; } }); mediaCodec.configure(format, null, null, 0);// outputFormat = format; mediaCodec.start(); } } } catch (IOException e) { e.printStackTrace(); } }public class AudioPlayer { private int mFrequency;// 采样率 private int mChannel;// 声道 private int mSampBit;// 采样精度 private AudioTrack mAudioTrack; public AudioPlayer(int frequency, int channel, int sampbit) { this.mFrequency = frequency; this.mChannel = channel; this.mSampBit = sampbit; } /** * 初始化 */ public void init() { if (mAudioTrack != null) { release(); } // 获得构建对象的最小缓冲区大小 int minBufSize = AudioTrack.getMinBufferSize(mFrequency, mChannel, mSampBit); mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mFrequency, mChannel, mSampBit, minBufSize, AudioTrack.MODE_STREAM); mAudioTrack.play(); } /** * 释放资源 */ private void release() { if (mAudioTrack != null) { mAudioTrack.stop(); mAudioTrack.release(); } } /** * 将解码后的pcm数据写入audioTrack播放 * * @param data 数据 * @param offset 偏移 * @param length 需要播放的长度 */ public void play(byte[] data, int offset, int length) { if (data == null || data.length == 0) { return; } try { mAudioTrack.write(data, offset, length); } catch (Exception e) { e.printStackTrace(); } }}
更多相关文章
- 一句话锁定MySQL数据占用元凶
- SharedPreferences保存少量的数据
- 【黑马Android】(03)学生管理系统/动态刷新界面
- android项目中单实例数据库类
- SharedPreferences 数据存储
- Android(安卓)RSA 公钥加密、解密
- Android下建立数据库
- 了解Context
- Android缓存清理