环境

1、android 开发环境
2、sdk >= 18


阅读对象

android开发者


音视频合成

根据数据源合成视频文件需要用到MediaMuxer这个类,可以参考这一篇文章(http://www.jianshu.com/p/aeadf260258a)。

MediaMuxer进行音视频合成的步骤

1、创建MediaMuxer,参数为outputPath, videoFormat

1、outputPath:视频文件的输出路径2、videoFormat:视频文件的格式,如 MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4

2、addTrack,参数为dataFormat:声音/图像的格式 MediaFormat

1、声音和图像都要调用一次 2、return: 结果返回一个trackIndex
public synchronized int addTrack(final MediaFormat format) {    if (mIsStarted) {        throw new IllegalStateException("muxer already started");    }    final int trackIx = mMediaMuxer.addTrack(format);    return trackIx;}

3、start

当所有数据都添加track完成后,调用start,之后等待各个track数据的到来   
 public synchronized boolean start() {        mStartedCount++;        if ((mEncoderCount > 0) && (mStartedCount == mEncoderCount)) {            mMediaMuxer.start();            mIsStarted = true;            notifyAll();        }        return mIsStarted;    }

4、writeSampleData,参数为(int trackIndex, final ByteBuffer byteBuf, final MediaCodec.BufferInfo bufferInfo)

1、每个track产生数据时,调用此方法往mp4文件写数据(如何生成源数据?后续会讲到)2、bufferInfo.presentationTimeUs 必须给出正确的时间戳,注意单位是 us (此坑我踩过,而且当时出错还没意识到问题,一直断点...) 注:每次只能添加一帧视频数据或者单个Sample的音频数据,并且BufferInfo对象的值一定要设置正确:bufferInfo.presentationTimeUs 必须给出正确的时间戳,注意单位是 us (此坑我踩过,而且当时出错还没意识到问题,一直断点...)
public synchronized void writeSampleData(final int trackIndex, final ByteBuffer byteBuf, final MediaCodec.BufferInfo bufferInfo) {        if (!mIsStarted) {            return ;        }        if (mStartedCount > 0) {            mMediaMuxer.writeSampleData(trackIndex, byteBuf, bufferInfo);        }    }

5、stop&release

结束录制时,要把所有的track都关闭,再调用stop和release;期间最好加个标志位,方便控制与调试
public synchronized void stop() {        if (!mIsStarted) {            LogTools.d("not started");            return ;        }        mStartedCount--;        if ((mEncoderCount > 0) && (mStartedCount <= 0)) {            mMediaMuxer.stop();            mMediaMuxer.release();            mIsStarted = false;        }    }

音频采集

AudioRecord、MediaCodec

1、准备:

AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)

audioSource : MediaRecorder.AudioSource,详见(http://blog.csdn.net/m0_37039192/article/details/77776844)

sampleRateInHz : 采样率,如44100,取值范围必须在 4000Hz~192000Hz 之间

channelConfig : 通道数,如AudioFormat.CHANNEL_IN_MONO(单通道)、AudioFormat.CHANNEL_IN_STEREO(双通道)等

audioFormat : 配置“数据位宽”,如 ENCODING_PCM_16BIT(16bit)可以保证兼容所有Android手机

bufferSizeInBytes : 配置的是 AudioTrack 内部的音频缓冲区的大小,该缓冲区的值不能低于一帧“音频帧”(Frame)的大小

一帧音频帧的大小:size = 采样率 x 位宽 x 采样时间 x 通道数,可以直接调用int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat);来计算

2、启动,AudioRecord.startRecording()

3、录制:

  • 开启异步线程,读取音频数据
public void run() {    while (isRunning) {        int size = audioRecord.read(audioBuffer, 0, audioBuffer.length);        if (isRunning && audioCore != null && size > 0) {            audioCore.queueAudio(audioBuffer);        }    } }
  • 放到缓冲队列,可以进行声音处理

  • 传送给音频编码器的缓冲队列中(MediaCodec)(异步线程+队列)

dstAudioEncoder.queueInputBuffer(eibIndex, 0, orignAudioBuff.buff.length, nowTimeMs * 1000, 0);
  • 音频编码器循环对队列中的数据进行处理得到ByteBuffer和MediaCodec.BufferInfo,然后分发给其他端,如媒体流或文件合成
 ByteBuffer realData = dstAudioEncoder.getOutputBuffers()[eobIndex]; realData.position(eInfo.offset); realData.limit(eInfo.offset + eInfo.size); if (isMuxerEnable && mMuxerStarted) {     eInfo.presentationTimeUs = getPTSUs();     muxer.writeSampleData(mTrackIndex, realData, eInfo);     prevOutputPTSUs = eInfo.presentationTimeUs; }

4、停止录制,AudioRecord.stop()


视频/图像采集

MediaCodec、TextureView或GLSurfaceView

注:打开摄像头(后续再讲);opengl处理的后续和demo一起讲解
  • 使用TextureView或GLSurfaceView承载摄像头展示画面
  • 视频数据可用时,通知绘制画布(opengl相关),在数据传递给视频编码器之前可以使用opengl做特效,最终到达视频数据处理线程
  • 视频数据处理线程得到ByteBuffer和MediaCodec.BufferInfo,然后分发给其他端,如媒体流或文件合成
  • 停止录制

总结

图片1.png

更多相关文章

  1. 一句话锁定MySQL数据占用元凶
  2. Android(安卓)USB设备通信--读写操作
  3. android sqlite database is locked (code 5): , while compilin
  4. Android(安卓)Application对象必须掌握的七点
  5. Flutter常用数据类型笔记
  6. Android入门:增删改查通讯录
  7. LeakCanary分析,如何判定的内存泄漏说明
  8. Flutter知识点:数据存储之SharedPreferences
  9. Android轮播图-----viewPager

随机推荐

  1. EditText单行显示
  2. Android的四种启动方式
  3. Android中生成xml文件
  4. viewpager实现自动循环轮播图
  5. Android基础知识(二)
  6. Android应用程序与SurfaceFlinger服务之
  7. adb 工具学习
  8. android 相对布局 RelativeLayout
  9. android跳转进市场的代码
  10. Android系统启动流程