Android 音视频开发(七): 音视频录制流程总结
在前面我们学习和使用了AudioRecord、AudioTrack、Camera、MediaExtractor、MediaMuxer API、MediaCodec。 学习和使用了上述的API之后,相信对Android系统的音视频处理有一定的经验和心得了。本文及后面的几篇文章做的事情就是将这些知识串联起来,做一些稍微复杂的事情。
一、流程分析
1.1 需求说明
我们需要做的事情就是:串联整个音视频录制流程,完成音视频的采集、编码、封包成 mp4 输出。
1.2 实现方式
Android音视频采集的方法:预览用SurfaceView,视频采集用Camera类,音频采集用AudioRecord。
1.3 数据处理思路
使用MediaCodec 类进行编码压缩,视频压缩为H.264,音频压缩为aac,使用MediaMuxer 将音视频合成为MP4。
二、 实现过程
2.1 收集Camera数据,并转码为H264存储到文件
在收集数据之前,对Camera设置一些参数,方便收集后进行数据处理:
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewFormat(ImageFormat.NV21);
parameters.setPreviewSize(1280, 720);
然后设置PreviewCallback:
camera.setPreviewCallback(this);
就可以获取到Camera的原始NV21数据:
onPreviewFrame(byte[] bytes, Camera camera)
在创建一个H264Encoder类,在里面进行编码操作,并将编码后的数据存储到文件:
new Thread(new Runnable() { @Override
public void run() {
isRuning = true;
byte[] input = null;
long pts = 0;
long generateIndex = 0; while (isRuning) {
if (yuv420Queue.size() > 0) {
input = yuv420Queue.poll();
byte[] yuv420sp = new byte[width * height * 3 / 2];
// 必须要转格式,否则录制的内容播放出来为绿屏
NV21ToNV12(input, yuv420sp, width, height);
input = yuv420sp;
}
if (input != null) {
try {
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
pts = computePresentationTime(generateIndex);
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(input);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, System.currentTimeMillis(), 0);
generateIndex += 1;
} MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC);
while (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
if (bufferInfo.flags == MediaCodec.BUFFER_FLAG_CODEC_CONFIG) {
configbyte = new byte[bufferInfo.size];
configbyte = outData;
} else if (bufferInfo.flags == MediaCodec.BUFFER_FLAG_SYNC_FRAME) {
byte[] keyframe = new byte[bufferInfo.size + configbyte.length];
System.arraycopy(configbyte, 0, keyframe, 0, configbyte.length);
System.arraycopy(outData, 0, keyframe, configbyte.length, outData.length);
outputStream.write(keyframe, 0, keyframe.length);
} else {
outputStream.write(outData, 0, outData.length);
} mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC);
} } catch (Throwable t) {
t.printStackTrace();
}
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} // 停止编解码器并释放资源
try {
mediaCodec.stop();
mediaCodec.release();
} catch (Exception e) {
e.printStackTrace();
} // 关闭数据流
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
当结束编码的时候,需要将相关的资源释放掉:
// 停止编解码器并释放资源
try {
mediaCodec.stop();
mediaCodec.release();
} catch (Exception e) {
e.printStackTrace();
} // 关闭数据流
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
此时,我们做到了将视频内容采集-->编码-->存储文件。但这个仅仅是对Android 音视频开发(四):使用 Camera API 采集视频数据的延伸,但是很有必要。因为在前面学习了如何采集音频,如何使用MediaCodec去处理音视频,如何使用MediaMuxer去混合音视频。
示例代码:https://github.com/renhui/AndroidRecorder/releases/tag/only_h264_video
下面我们在当前的的基础上继续完善,即将音视频采集并混合为音视频。
2.2 音视频采集+混合,存储到文件
基本完成思路已经在2.1的结尾处坐了说明,下面贴一下demo的链接:
示例代码:https://github.com/renhui/AndroidRecorder/releases/tag/h264_video_audio
想做更多的事情,只有学习了OpenGL之后才能继续了。录制音视频的学习先到此为止了。
Android 音视频开发(七): 音视频录制流程总结的更多相关文章
- Android Camera系列开发 (二)通过Intent录制视频
Android Camera系列开发 (二)通过Intent录制视频 作者:雨水 2013-8-18 CSDN博客:http://blog.csdn.net/gobitan/ 概述 使用Camera ...
- 【Android 直播软件开发:音视频硬解码篇】
开篇 炙手可热,望而生畏的音视频开发 时至今日,短视频App可谓是如日中天,一片兴兴向荣.随着短视频的兴起,音视频开发也越来越受到重视,但是由于音视频开发涉及知识面比较广,入门门槛相对较高,让许许多多 ...
- Android Studio 集成开发工具教学视频
简介 经过2年时间的研发,Google终于正式发布了面向Android开发者的集成开发环境Android Studio 1.2(稳定版).Android Studio是Google开发的一款面向And ...
- Android 音视频开发学习思路
Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...
- 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)
随笔分类 - webrtc Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...
- Android音视频开发(1):H264 基本原理
前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...
- Android WebRTC 音视频开发总结
www.cnblogs.com/lingyunhu/p/3621057.html 前面介绍了WebRTCDemo的基本结构,本节主要介绍WebRTC音视频服务端的处理,,转载请说明出处(博客园RTC. ...
- Android 音视频开发(一):PCM 格式音频的播放与采集
什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...
- Android音视频之MediaRecorder音视频录制
前言: 公司产品有很多地方都需要上传音频视频,今天抽空总结一下音频视频的录制.学习的主角是MediaRecorder类. MediaRecorder类介绍: MediaRecorder类是Androi ...
随机推荐
- Typescript04---模块、命名空间
在Typescript1.5 中,内部模块称作命名空间,外部模块成为模块 一.什么是模块? 模块就是一个或一组功能模块. 模块在其自身的作用域里执行,而不是在全局作用域里.意味着,模块中的变量.函数. ...
- 分割字符串和截取字符串:split 和substring
//按“,”截取字符串 String id="123123,234534,453456"; String[] idArry = id.trim().split(",&qu ...
- git clone pytorch或caffe2速度慢的解决办法
caffe2官方代码,现在已经放在pytorch项目中了. 因此,源码编译pytorch或caffe2,都需要 https://github.com/pytorch/pytorch 下载代码. 由于p ...
- line-gradient 之渐变角度
MDN上对于linear-gradient的定义如下: CSS linear-gradient() 函数用于创建一个表示两种或多种颜色线性渐变的图片.其结果属于<gradient>数据类型 ...
- javafx由浅到深的 认识(一)
javafx是一款比较新兴的语言框架,随着javafx越来越实用,估计许多程序员也会慢慢接触它,故我在这里对它由浅到深进行介绍一下. 首先,要了解javafx,就应该先知道.xml文件的布局软件,以往 ...
- C#实现视频监控客户端onvif协议一
前言 最近做的项目是监控方面的,需要对接各种摄像头,之前的方案是把各个厂家的SDK都集成到系统中,然后让用户进行切换,后来知道了Onvif (自行百度具体概念)这个东西.原来早就有人一统江湖了. on ...
- Docker 学习6 Docker存储卷
一.什么是存储卷 二.为什么要用到数据卷 三.数据卷是怎么被管理的 四.存储卷种类 五.在容器中使用存储卷 1.只声明容器路径 [root@localhost docker]# docker run ...
- vue小技巧之偷懒的文件路径——减少不必要的代码
众所周知,我们写vue项目的时候都会创建很多个文件,尤其是一些中大型项目,会有很深的文件夹,当你去引入的时候,要写很长的路径比如我要引入一个css文件, 必须得 import '../../../s ...
- AutoCAD下载
AutoCAD 2019 64位破解版 附注册机和安装教程 1.71G AutoCAD 2019 64位精简优化版 珊瑚の海简体中文版691.08M
- 数据分析 大数据之路 四 numpy 2
NumPy 数学函数 NumPy 提供了标准的三角函数:sin().cos().tan(import numpy as np a = np.array([0,30,45,60,90])print (' ...