在前面我们学习和使用了AudioRecordAudioTrackCameraMediaExtractorMediaMuxer APIMediaCodec。 学习和使用了上述的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 音视频开发(七): 音视频录制流程总结的更多相关文章

  1. Android Camera系列开发 (二)通过Intent录制视频

    Android Camera系列开发 (二)通过Intent录制视频 作者:雨水  2013-8-18 CSDN博客:http://blog.csdn.net/gobitan/ 概述 使用Camera ...

  2. 【Android 直播软件开发:音视频硬解码篇】

    开篇 炙手可热,望而生畏的音视频开发 时至今日,短视频App可谓是如日中天,一片兴兴向荣.随着短视频的兴起,音视频开发也越来越受到重视,但是由于音视频开发涉及知识面比较广,入门门槛相对较高,让许许多多 ...

  3. Android Studio 集成开发工具教学视频

    简介 经过2年时间的研发,Google终于正式发布了面向Android开发者的集成开发环境Android Studio 1.2(稳定版).Android Studio是Google开发的一款面向And ...

  4. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  5. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

  6. Android音视频开发(1):H264 基本原理

    前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...

  7. Android WebRTC 音视频开发总结

    www.cnblogs.com/lingyunhu/p/3621057.html 前面介绍了WebRTCDemo的基本结构,本节主要介绍WebRTC音视频服务端的处理,,转载请说明出处(博客园RTC. ...

  8. Android 音视频开发(一):PCM 格式音频的播放与采集

    什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...

  9. Android音视频之MediaRecorder音视频录制

    前言: 公司产品有很多地方都需要上传音频视频,今天抽空总结一下音频视频的录制.学习的主角是MediaRecorder类. MediaRecorder类介绍: MediaRecorder类是Androi ...

随机推荐

  1. IntelliJ IDEA设置svn.exe的路径

    安装TortoiseSVN客户端时,必须选中command line client tools这个选项

  2. linux安装lamp环境(linux+apache+mysql+php)

    源码安装 本次使用 Centos7.2 MySQL5.7.22 Apache2.4.37 PHP5.6.38 安装Apache 安装httpd和所需依赖:gcc, apr, apr-util,apr- ...

  3. python3与mysql交互

    1.安装pymysql模块 pip3 install pymysql3 2.pymysql的简单使用: # /usr/bin/env python3 import pymysql class Mysq ...

  4. 2018-2019-2 20165323《网络攻防技术》Exp5 MSF基础应用

    一.知识点总结 1.MSF攻击方法 主动攻击:扫描主机漏洞,进行攻击 攻击浏览器 攻击其他客户端 2.MSF的六种模块 渗透攻击模块Exploit Modules:攻击漏洞,把shellcode&qu ...

  5. C#学习-类型转换

    类型转换的方式主要有以下几种: 隐式类型转换,由低级别类型向高级类型的转换过程.例如派生类可以隐式地转换为它的父类,装箱过程就属于这种隐式类型转换. 显式类型转换,也叫强制类型转换, 通过is和as运 ...

  6. Scrapy 隐含 bug: 强制关闭爬虫后从 requests.queue 读取的已保存 request 数量可能有误

    问题描述和解决方案已提交至 Scrapy issues: The size of requests.queue may be wrong when resuming crawl from unclea ...

  7. 阿里云+WordPress搭建个人博客

    搭建过程: 第一步:首先你需要一台阿里云服务器ECS,如果你是学生,可以享受学生价9.5元/月 (阿里云翼计划:https://promotion.aliyun.com/ntms/act/campus ...

  8. c/c++再学习:C与Python相互调用

    c/c++再学习:Python调用C函数 Python 调用C函数比较简单 这里两个例子,一个是直接调用参数,另一个是调用结构体 C代码 typedef struct { int i1; int i2 ...

  9. SQLSERVER的递归

    实际项目如遇到按照如地区这样树状结构的条件递归查询数据的场景中,可以使用. CREATE FUNCTION [dbo].[GetAllChildrenTypeById] ( ) ) RETURNS T ...

  10. 实现upnp ssdp来查找局域网内的其他节点

    upnp协议常用于一些智能家居产品中,这些产品连上家里局域网后,用同样连入家中局域网的手机就能很快检测到此产品了.在区块链技术中,upnp也被应用于寻找同一局域网内的其他节点. 关于upnp的具体描述 ...