GVKun编程网logo

Android音视频【六】视频数据存储方式YUV(安卓视频存储位置)

30

在本文中,我们将为您详细介绍Android音视频【六】视频数据存储方式YUV的相关知识,并且为您解答关于安卓视频存储位置的疑问,此外,我们还会提供一些关于2021了,为什么说音视频技术是技术风口?An

在本文中,我们将为您详细介绍Android音视频【六】视频数据存储方式YUV的相关知识,并且为您解答关于安卓视频存储位置的疑问,此外,我们还会提供一些关于2021了,为什么说音视频技术是技术风口?Android音视频开发这么吃香?、5G时代风口浪尖上的音视频开发技术,你还在观望吗?保姆级Android音视频开发学习一篇就够、5种Android数据存储方式汇总、android – 如何向MediaMux提供音频数据和视频数据的有用信息。

本文目录一览:

Android音视频【六】视频数据存储方式YUV(安卓视频存储位置)

Android音视频【六】视频数据存储方式YUV(安卓视频存储位置)

人间观察

这个社会很浮躁,千万不要考验人性

在视频中的数据保存和传输都是YUV数据格式。主要是为了降低数据大小,如果用argb格式的数据,1px可能需要4个字节,而用YUV可能就需要1.5个字节。

YUV简介

与RGB类似,YUV也是一种颜色编码方法,主要用于视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,比如这样的设计解决了彩色电视机与黑白电视的兼容问题。

YUV,分为三个分量,“Y”表示的是明亮度(luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是用于指定像素的颜色。

UV 即CbCr(C代表颜色,b代表蓝色,r代表红色)

分类

YUV格式有两大类:平面(planar)和紧凑(packed)。

对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是存储所有像素点的V,或者是先v后u

对于packed的YUV格式,每个像素点的Y,U,V是连续交替存储的。比如YUV420P 其中的P表示“紧凑”,YUV420SP 其中的SP表示“半紧凑”。

采样

主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0

YUV 4:4:4采样,每一个Y对应一组UV分量,一个YUV占8+8+8 = 24bits 3个字节。

YUV 4:2:2采样,每两个Y共用一组UV分量,一个YUV占8+4+4 = 16bits 2个字节。

YUV 4:2:0采样,每四个Y共用一组UV分量,一个YUV占8+2+2 = 12bits 1.5个字节。

最常见的YUV420P和YUV420SP都是基于4:2:0采样的,所以如果图片的宽为width,高为heigth,在内存中占的空间为width * height * 3 / 2,其中前width * height的空间存放Y分量,接着width * height / 4存放U分量,最后width * height / 4存放V分量。

YUV格式

常见的YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420等,Android中比较常见是YUV420分为两种:YUV420PYUV420SP。所以就先了解下YUV420PYUV420SP.

YUV420P

YUV420P是平面模式,Y , U , V分别在不同平面,也就是有三个平面,它是YUV标准格式4:2:0

为了更方便的看如下表示:

YUV420SP-NV21格式

为了说明存储方式,每一组用不同的颜色表示。每一种颜色是一组,每四个Y共用一组UV分量,比如Y1 Y2 Y7 Y8 U1V1 Y3 Y4 Y8 Y10 U2V2

那么真实的在字节流中就是按照行从左到右一行一行的拼起来的:

yuv-stream

YUV420P分为:YU12和YV12

YU12格式

在Android中也叫作I420格式,首先是所有Y值,然后是所有U值,最后是所有V值。比如6x6的图片,内存大小就是6x6x3/2=54个字节。为了更清晰的查看,我们换行看,真实的是一行byte[]数据流。

YYYYYY
YYYYYY
YYYYYY
YYYYYY
UUUUUU
VVVVVV

YV12格式

YV12格式与YU12基本相同,首先是所有Y值,然后是所有V值,最后是所有U值。比如6x6的图片,内存大小就是6x6x3/2=54个字节

YYYYYY
YYYYYY
YYYYYY
YYYYYY
VVVVVV
UUUUUU

YUV420SP

YUV420SP 也是是平面模式。分为NV21和NV12两种格式。Y是一个平面,UV是一个平面,UV/VU为交替存储,而不是分为三个平面。

在Android Camera中文档中强烈推荐使用NV21YV12,因为这两种格式支持所有的相机设备。Camera默认输出YUV的数据格式为NV21。但是在Camera2中,推荐使用的格式则是YUV_420_888

ImageFormat.NV21 注释

YCrCb format used for images, which uses the NV21 encoding format.
This is the default format for android.hardware.Camera preview images, when not otherwise set with android.hardware.Camera.Parameters.setPreviewFormat(int).
For the android.hardware.camera2 API, the YUV_420_888 format is recommended for YUV output instead.

Camera.Parameters预览参数设置setPreviewFormat 注释

Sets the image format for preview pictures.
If this is never called, the default format will be ImageFormat.NV21, which uses the NV21 encoding format.
Use getSupportedPreviewFormats to get a list of the available preview formats.
It is strongly recommended that either ImageFormat.NV21 or ImageFormat.YV12 is used, since they are supported by all camera devices.

为了更方便的看如下表示,真实的在字节流中就是按照行从左到右一行一行的拼起来的。

YUV420SP-NV21格式

NV21格式

在Android Camera中手机从摄像头采集的预览数据默认值是NV21。

NV21存储顺序是先存Y值,再VU交替存储:YYYYVUVUVU,比如6x6的图片,内存大小就是6x6x3/2=54个字节

YYYYYY
YYYYYY
YYYYYY
YYYYYY
VUVUVU
VUVUVU

NV12格式

NV12存储顺序是先存Y值,再UV交替存储:YYYYUVUVUV,比如6x6的图片,内存大小就是6x6x3/2=54个字节

YYYYYY
YYYYYY
YYYYYY
YYYYYY
UVUVUV
UVUVUV

这里先熟悉下Android中常见的YUV420PYUV420SP。一般我们在使用yuv数据的时候,会对yuv数据进行变换,比如:摄像头数据旋转,从一种格式转为另一种数据等。

2021了,为什么说音视频技术是技术风口?Android音视频开发这么吃香?

2021了,为什么说音视频技术是技术风口?Android音视频开发这么吃香?

互联网发展日新月异的今天,人们的社交需求也在不断升级。一直以来,社交平台持续探索新的互动方式,以满足人们不断更迭的社交需求。从2018年火爆的直播,再到越来越被大众依赖的实时音视频,高速发展的通信技术为社交平台的探索提供了更多可能。

随着**5G的普及,将会改变人与人、人与物、物与物之间的沟通方式。**以后图文沟通的方式会越来越少,而音视频则将成为主流

这也催生出大量的音视频相关需求。但目前具备音视频开发技术的开发者,可谓是少之又少。

而且,现在音视频工程师的薪资比纯Android应用层开发高出40%。

图片

音视频开发单从薪资的角度考虑是没问题的,要记住薪资水平是市场决定的,市场对音视频需求其实非常大,而且逐年上升直播、点播、视频会议等等都是这些年起来的项目。而相比较起来,音视频从业者少得可怕我了解到的行情就是几个公司互相挖角,对人才的竞争属于存量搏杀


另外,5G时代下的万物互联,体现在设备互相访问、读取、调用,还可以在将屏幕直接拖动到另外一个屏幕中,也是华为鸿蒙系统的一个卖点,交互式投屏技术
**交互式投屏:**我们可以将任意的设备通过快速链接投屏到另外一台设备,并且还可以在任意一台设备中操作,这是非常方便的。值得一提的是,以往智能电视投屏时常常容易出现花屏、卡顿、延迟等现象,荣耀智慧屏却把这个使用痛点改善得肉眼察觉不到。

他是怎么做到的呢?

秘密就在编码,编码中采用了H265编码,实现高效编码的同时,保证不失真、不卡顿、不延迟

图片

交互式投屏,如果采用H265编码的话,压缩更出众,与 H.264 相比压缩效率提升 1 倍

H.265 全新的编码方式有效提升了视频压缩率,仅需原先的一半带宽即可播放相同质量的视频。以相同的视频质量为基准,H.265 编码技术相比 H.264 编码技术能够在视频容量减少大约 39~74%,并且还能获得比 H.264 视频更好清晰的效果,使得 H.265 在相同体积、码率下,H.265 画质细腻度提升 1 倍。


此外,H265交互式投屏技术在互动上更是丝滑到了极致

图片

那么,我们该如何学习交互式投屏技术呢?

而如今音视频的知识纷繁复杂,自己学习非常困难,既需要非常扎实的基础知识,又需要有很多的工程经验;

而音视频从业者基本上有两个层面:一个层面是搞音视频算法,这类人非常少,需要有深的数学能力和算法背景,这类人一般都会选择去大公司,薪水百万是最low 的。

另一个层面是搞工程,这类人相对较多,他们有扎实的理论基础,很强的技术功底,对音频、视频都非常熟悉。这些人工资要比一般开发者高20%左右;随着5G时代的到来,音视频慢慢变成人们日常生活中的必须品。所以,现在有大量的公司开始寻找音视频人才,一个稍好点的音视频人才现在可能会有3-4家公司抢着要。因此,对音视频人才的需求也从小众变成了大众,这更多的是大家对未来市场的预期导致的结果。

可在目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的,在此小编花费大量时间收集和整理,终于将音视频方面的知识点整理成了一个专题,今天借此文章分享给对音视频感兴趣的小伙伴。

我们先来看看一个方向性的学习指南:

1. 在 Android 平台绘制一张图片,使用至少 3 种不同的 API,ImageView,SurfaceView,自定义 View
2. 在 Android 平台使用 AudioRecord 和 AudioTrack API 完成音频 PCM 数据的采集和播放,并实现读写音频 wav 文件
3. 在 Android 平台使用 Camera API 进行视频的采集,分别使用 SurfaceView、TextureView 来预览 Camera 数据,取到 NV21 的数据回调
4. 学习 Android 平台的 MediaExtractor 和 Mediamuxer API,知道如何解析和封装 mp4 文件
5. 学习 Android 平台 OpenGL ES API,了解 OpenGL 开发的基本流程,使用 OpenGL 绘制一个三角形
6. 学习 Android 平台 OpenGL ES API,学习纹理绘制,能够使用 OpenGL 显示一张图片
7. 学习 MediaCodec API,完成音频 AAC 硬编、硬解
8. 学习 MediaCodec API,完成视频 H.264 的硬编、硬解
9. 串联整个音视频录制流程,完成音视频的采集、编码、封包成 mp4 输出
10. 串联整个音视频播放流程,完成 mp4 的解析、音视频的解码、播放和渲染
11. 进一步学习 OpenGL,了解如何实现视频的剪裁、旋转、水印、滤镜,并学习 OpenGL 高级特性,如:VBO,VAO,FBO 等等
12. 学习 Android 图形图像架构,能够使用 GLSurfaceviw 绘制 Camera 预览画面
13. 深入研究音视频相关的网络协议,如 rtmp,hls,以及封包格式,如:flv,mp4
14. 深入学习一些音视频领域的开源项目,如 webrtc,ffmpeg,ijkplayer,librtmp 等等
15. 将 ffmpeg 库移植到 Android 平台,结合上面积累的经验,编写一款简易的音视频播放器
16. 将 x264 库移植到 Android 平台,结合上面积累的经验,完成视频数据 H264 软编功能
17. 将 librtmp 库移植到 Android 平台,结合上面积累的经验,完成 Android RTMP 推流功能
18. 上面积累的经验,做一款短视频 APP,完成如:断点拍摄、添加水印、本地转码、视频剪辑、视频拼接、MV 特效等功能

相信我,如果你认真把所有任务都完成了,你一定会成为音视频人才招聘市场的香饽饽~~如何才能更好地学好以上知识呢?下面正是要给大家分享小编花费86天整理的关于音视频开发入门到进阶,已整理成PDF文档:有需要完整版的可以点此处免费获取。

一,初级入门篇:

一 绘制图片

1. ImageView 绘制图片

2. SurfaceView 绘制图片

3. 自定义 View 绘制图片

二、AudioRecord API详解

三、使用 AudioRecord 实现录音,并生成wav

  • 创建一个AudioRecord对象
  • 初始化一个buffer
  • 开始录音
  • 创建一个数据流,一边从AudioRecord中读取声音数据到初始化的buffer,一边将buffer中数据导入数据流。
  • 关闭数据流
  • 停止录音

四、用 AudioTrack 播放PCM音频

1.AudioTrack 基本使用

  • MODE_STATIC模式
  • MODE_STREAM模式

2.AudioTrack 详解

  • 音频流的类型
  • Buffer分配和Frame的概念
  • AudioTrack构造过程

3. AudioTrack 与 MediaPlayer 的对比

  • 区别
  • 联系
  • SoundPool

五、使用 Camera API 采集视频数据

1.预览 Camera 数据

2.取到 NV21 的数据回调

六、使用 MediaExtractor 和 Mediamuxer API 解析和封装 mp4 文件

1.MediaExtractor API介绍

2.Mediamuxer API介绍

3.使用情境

七. MediaCodec API 详解

1.MediaCodec 介绍

2.MediaCodec API 说明

3.MediaCodec 流控

  • 流控基本概念
  • Android 硬编码流控
  • Android 流控策略选择

由于文章篇幅受限,剩余内容过多,文中插图有限,下文只能截图目录展示:

二,中级进阶篇:

  • Android OpenGL ES 开发(一): OpenGL ES 介绍
  • Android OpenGL ES 开发(二): OpenGL ES 环境搭建
  • Android OpenGL ES 开发(三): OpenGL ES 定义形状
  • Android OpenGL ES 开发(四): OpenGL ES 绘制形状
  • Android OpenGL ES 开发(五): OpenGL ES 使用投影和相机视图
  • Android OpenGL ES 开发(六): OpenGL ES 添加运动效果
  • Android OpenGL ES 开发(七): OpenGL ES 响应触摸事件
  • Android OpenGL ES 开发(八): OpenGL ES 着色器语言GLSL
  • Android OpenGL ES 开发(九): OpenGL ES 纹理贴图
  • Android OpenGL ES 开发(十): 通过GLES20与着色器交互
  • 使用 OpenGL 显示一张图片
  • GLSurfaceviw 绘制 Camera 预览画面及实现拍照
  • 使用OpenGL ES 完成视频的录制,并实现视频水印效果

高级探究篇:

  • 深入学习音视频编码,如H.264,AAC,研究使用开源编解码库,如x.264,JM 等
  • 深入研究音视频相关的网络协议,如 rtmp,hls,以及封包格式,如:flv,mp4
  • 深入学习一些音视频领域的开源项目,如 webrtc,ffmpeg,ijkplayer,librtmp 等等
  • 将 ffmpeg 库移植到 Android 平台,结合上面积累的经验,编写一款简易的音视频播放器
  • 将 x264 库移植到 Android 平台,结合上面积累的经验,完成视频数据 H264 软编功能
  • 将 librtmp 库移植到 Android 平台,结合上面积累的经验,完成 Android RTMP 推流功能

音视频编解码技术

  • 音视频编解码技术(一):MPEG-4/H.264 AVC 编解码标准
  • 音视频编解码技术(二):AAC 音频编码技术

流媒体协议

  • 流媒体协议(一):HLS 协议
  • 流媒体协议(二):RTMP协议

多媒体文件格式

  • 多媒体文件格式(一):MP4 格式
  • 多媒体文件格式(二):FLV 格式
  • 多媒体文件格式(三):M3U8 格式
  • 多媒体文件格式(四):TS 格式
  • 多媒体文件格式(五):PCM / WAV 格式

FFmpeg 学习记录

  • FFmpeg命令行工具学习(一):查看媒体文件头信息工具ffprobe
  • FFmpeg命令行工具学习(二):播放媒体文件的工具ffplay
  • FFmpeg命令行工具学习(三):媒体文件转换工具ffmpeg
  • FFmpeg命令行工具学习(四):FFmpeg 采集设备
  • FFmpeg命令行工具学习(五):FFmpeg 调整音视频播放速度

  • FFmpeg 学习(一):FFmpeg 简介
  • FFmpeg 学习(二):Mac下安装FFmpeg
  • FFmpeg 学习(三):将 FFmpeg 移植到 Android平台
  • FFmpeg 学习(四):FFmpeg API 介绍与通用 API 分析
  • FFmpeg 学习(五):FFmpeg 编解码 API 分析
  • FFmpeg 学习(六):FFmpeg 核心模块 libavformat 与 libavcodec 分析

  • FFmpeg 结构体学习(一): AVFormatContext 分析
  • FFmpeg 结构体学习(二): AVStream 分析
  • FFmpeg 结构体学习(三): AVPacket 分析
  • FFmpeg 结构体学习(四): AVFrame 分析
  • FFmpeg 结构体学习(五): AVCodec 分析
  • FFmpeg 结构体学习(六): AVCodecContext 分析
  • FFmpeg 结构体学习(七): AVIOContext 分析
  • FFmpeg 结构体学习(八):FFMPEG中重要结构体之间的关系

更多目录截图:

**总结:**以上就是关于音视频的资料最强整理和概括了(还有部分内容没有截图出来),相信应该是全网最全了,所有资料都是免费分享给大家的,也省去了对音视频感兴趣的小伙伴们四处找资料的时间,如果你正好需要可以点此处免费获取

音视频开发的前景,相信大家从相关的招聘网站上就可以看到,不管是流媒体开发还是音视频处理开发,都是大量招人的,并且由于入门门槛相对较高,学习周期长,薪资也是居高不下。

另外:小编还收集整理一些音视频相关配套视频,相信能使大家学习起来更加快速有效:

文中所有资料都是免费分享给大家的,只需你动动手指点击此处就可直达免费领取方式了。

Android架构师之路很漫长, 一起共勉吧!学习之路犹如逆水行舟,不进则退,如果你松懈了, 那么你就退步了,而在Android开发工作中没有一门吃香独特的技术,想拿高薪也只能是望尘莫及的。做个勤奋向上的人,加紧学习,抓住中心,宁精勿杂,宁专勿多。

如果你正好需要这份完整版Android音视频开发,只需你多多支持我这篇文章。

快速入手通道:(点这里)下载!诚意满满!!!

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!!!

5G时代风口浪尖上的音视频开发技术,你还在观望吗?保姆级Android音视频开发学习一篇就够

5G时代风口浪尖上的音视频开发技术,你还在观望吗?保姆级Android音视频开发学习一篇就够

从技术上来讲,需要从如下两个大类知识点上去积累:

  1. C/C++通用开发知识

音视频开发的主要编程语言就是C和C++。

这块的专业知识积累是通用的,并不局限于某个特定的行业,属于程序员的技术功底。

可以重点关注如下几个方面:

  • 计算机系统的底层工作原理

  • 操作系统原理

  • 程序的编译、链接和加载机制

  • C/C++语言特性背后蕴含的思想,底层工作原理,适用场景,存在什么样的问题

  • 软件设计原则和设计模式

  • 数据结构和算法

  • 多线程并发编程原理

  • 网络编程

  • 跨平台

  • 操作系统API

  • 软件调试

2. 音视频领域专业知识

这块属于从事音视频行业的专业知识。

这块的专业知识是非常多的,每个功能模块背后涉及很多专业的知识。

音视频的开发可以分为两大块,涉及的内容大致如下:

  • 音视频客户端开发

  • 客户端应用开发

  • 音视频引擎开发

  • 音视频引擎SDK

  • 音视频引擎框架

  • 音视频引擎功能模块

  • 音/视频采集

  • 音/视频渲染

  • 音/视频数据处理

  • 音/视频编/解码

  • 录制

  • 串流

  • 音视频同步

  • 流媒体服务器开发

  • 通用服务器开发知识,需要关注如下几个点

  • 高稳定性

  • 高性能

  • 高并发

  • 高可用

  • 流媒体服务器开发

  • SFU vs MCU

  • 流媒体协议转换

  • 弱网下的音视频传输协议

  • 录制 & 转码

上述内容中,客户端应用开发、音视频引擎SDK、音视频引擎框架、通用服务器开发等主要涉及C/C++通用开发知识,但要设计好这些部分必须对音视频相关的知识和产品业务有比较深刻的理解才能做到。通常,音视频架构师比较关注这些部分。

而音视频引擎底层功能模块和SFU/MCU流媒体服务器的开发,则和音视频的专业知识密切相关。

  • 音视频的采集模块

  • 视频数据可以通过如下方式获得:

  • USB摄像头

  • 专业的硬件视频采集卡(有软压卡和硬压卡之分)

  • 网络摄像机(支持RTSP协议)

  • 操作系统提供的屏幕录制API

  • 读取音视频文件并解码

  • 订阅流媒体服务器上的流

  • 音频数据可以通过如下方式获得:

  • 声卡

  • 扬声器播放声音的回环采集(依赖操作系统的API)

  • 读取音视频文件并解码

  • 订阅流媒体服务器上的流

  • 支持音频输入的网络摄像机(支持RTSP协议)

  • 支持音频输入的视频采集卡

  • 在手机上,操作系统的SDK会提供相关的音视频采集接口

  • 音/视频渲染

  • 视频渲染一般需要了解OpenGL,而音频渲染需要了解OpenAL

  • 可以通过开源库SDL来快速实现渲染模块

  • 在Windows下使用DirectShow框架,操作系统提供了对应的视频和音频渲染模块(通过GraphEdit可以看到)

  • 在DirectShow中渲染器会涉及到音视频同步的策略,当然,也完全可以自己去实现音视频同步模块

  • 音/视频数据处理

  • 这些模块基本是在编码前或解码后,对视频或音频的原始数据进行某种算法上的处理

  • 视频处理主要包括分辨率转换、色彩空间转换、帧率转换、图像增强、多路视频拼接、添加字幕、添加logo图片等,这块对整体的性能影响比较大,往往需要使用SIMD指令进行汇编优化或使用GPU算法进行加速

  • 音频处理主要包括回声消除、噪声抑制、自动增益、混音等,这块往往会涉及比较多的信号处理和数学知识,是音频中比较复杂的一块

  • 音/视频编/解码

  • 视频编/解码

  • 要理解视频的基本编码原理,熟悉视频编码的关键参数和码流格式

  • 目前


    使用比较多的是H.264,H.265开始逐步在使用,其他的视频编码也有很多,如AVS、VP8、VP9等

  • 视频编码对音视频引擎的性能影响比较大,这块基本都是需要使用GPU加速的,目前的Intel集显对H.264和H.265支持还是比较好的,NVIDIA的独立显卡在编码上存在路数的限制;手机上一般都有对应的硬件加速模块;在性能较好的硬件上,可以考虑开源的X264

  • 音频编/解码

  • 要理解音频的基本编码原理,熟悉音频的关键参数和码流格式

  • 目前使用比较多的是AAC,其他的音频编码也有很多,如G7.11、G.722、OPUS等

  • 在PC上,一般音频的相关模块对性能的影响不明显,但在海思嵌入式系统上,音频模块对性能的影响就不能忽略,因为海思基本没有提供音频的硬件加速模块,而ARM cpu性能也有点弱

  • 录制

  • 需要理解FLV、MP4、TS等容器格式

  • 对于特殊的录制方式要注意软件的处理方式,例如,加片头和片尾的录制功能,追加录制

  • MP4录制要注意moov Box放在文件开始或结束对录制文件的写入和点播的影响

  • 录制时音视频均匀混合的策略

  • 串流

  • 理解视频互动、直播和点播的工作原理

  • 关键评价指标

  • 延迟

  • 首屏时间

  • 同步

  • 流畅性

  • 画质/音质

  • 理解下述的几种音视频传输协议

  • RTMP

  • HTTP + FLV / Websocket + FLV

  • HLS

  • RTP & RTCP

  • RTSP

  • SIP

  • WebRTC

  • H.323

  • 弱网下的音视频传输协议

  • 理解TCP协议栈原理

  • 可靠的UDP传输协议

  • KCP

  • SRT

  • QUIC

  • FEC + 丢包重传机制(如NACK)

音视频的开发并不是完全从零开始,而是有许多可以依赖的开源库,但要用好这些库,需要对上述的音视频专业知识有深刻的理解。

比较常见的音视频开源库,如下:

  • ffmpeg

  • 可以直接使用ffmpeg的命令行实现转码、切片等常见功能

  • 可以基于FFmpeg API封装开发自己的音视频模块

  • live555

  • 比较完善的RTSP库

  • x264

  • 比较常用的H.264编码库

  • fdkaac

  • 比较常用的AAC编解码库

  • librtmp

  • 支持rtmp协议,产品化时需要自己进一步完善

  • pjsip

  • 支持sip协议

  • webrtc

  • google开源的webrtc库,有比较好的音/视频引擎,对网络状态的实时评估可以借鉴,回声消除模块也是比较有名的

  • SDL

  • 比较有名的音视频渲染库

  • SRS

  • 国内比较知名的RTMP流媒体服务器,支持HLS、HTTP+FLV,4.0版本开始支持WebRTC

  • OWT

  • Intel开源的WebRTC套件,支持了WebRTC客户端SDK和分布式的WebRTC MCU服务器

  • OpenCV

  • 著名的视频算法库

另外,视频的编码和解码可以基于Intel Media SDK和NVIDIA的NVENC来实现。

在海思嵌入式上,海思芯片(如Hi3531D等)提供了硬件的音视频采集、音视频渲染、视频编/解码、视频图像处理等核心功能,这就需要借助于海思提供的SDK进行开发了。

音视频这块,目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的,希望我后面能挤出时间整一个专题详细讲一讲~~目前的话,我先给出一个大的方向性的学习指南,希望对初学者有所帮助。

我一直相信带着 “任务” 去学习和实践,效率会高很多,因此我列出了一系列音视频相关的 “开发任务”,从简单到困难(当然,不一定非常严格和完美,部分任务先后可调整),大家在完成任务的过程中,遇到任何不懂的地方都要及时去 google,或者去请教身边的大牛,不放过任何一个疑点,相信大家会很快就能把音视频周边相关知识积累起来。

这里整理和概括了(还有部分内容没有截图出来)关于音视频的资料,相信应该是全网最全了,所有资料都是免费分享给大家的,也省去了对音视频感兴趣的小伙伴们四处找资料的时间,如果你正好需要可以扫一扫下方二维码免费获取。

Android 音视频从入门到精通——学习目标

1. 在 Android 平台绘制一张图片,使用至少 3 种不同的 API,ImageView,SurfaceView,自定义 View

2. 在 Android 平台使用 AudioRecord 和 AudioTrack API 完成音频 PCM 数据的采集和播放,并实现读写音频 wav 文件

3. 在 Android 平台使用 Camera API 进行视频的采集,分别使用 SurfaceView、TextureView 来预览 Camera 数据,取到 NV21 的数据回调

4. 学习 Android 平台的 MediaExtractor 和 Mediamuxer API,知道如何解析和封装 mp4 文件

5. 学习 Android 平台 OpenGL ES API,了解 OpenGL 开发的基本流程,使用 OpenGL 绘制一个三角形

6. 学习 Android 平台 OpenGL ES API,学习纹理绘制,能够使用 OpenGL 显示一张图片

7. 学习 MediaCodec API,完成音频 AAC 硬编、硬解

8. 学习 MediaCodec API,完成视频 H.264 的硬编、硬解

9. 串联整个音视频录制流程,完成音视频的采集、编码、封包成 mp4 输出

10. 串联整个音视频播放流程,完成 mp4 的解析、音视频的解码、播放和渲染

11. 进一步学习 OpenGL,了解如何实现视频的剪裁、旋转、水印、滤镜,并学习 OpenGL 高级特性,如:VBO,VAO,FBO 等等

12. 学习 Android 图形图像架构,能够使用 GLSurfaceviw 绘制 Camera 预览画面

13. 深入研究音视频相关的网络协议,如 rtmp,hls,以及封包格式,如:flv,mp4

14. 深入学习一些音视频领域的开源项目,如 webrtc,ffmpeg,ijkplayer,librtmp 等等

15. 将 ffmpeg 库移植到 Android 平台,结合上面积累的经验,编写一款简易的音视频播放器

16. 将 x264 库移植到 Android 平台,结合上面积累的经验,完成视频数据 H264 软编功能

17. 将 librtmp 库移植到 Android 平台,结合上面积累的经验,完成 Android RTMP 推流功能

18. 上面积累的经验,做一款短视频 APP,完成如:断点拍摄、添加水印、本地转码、视频剪辑、视频拼接、MV 特效等功能

相信我,如果你认真把所有任务都完成了,你一定会成为音视频人才招聘市场的香饽饽~~

一,初级入门篇:

一 绘制图片

  1. ImageView 绘制图片

习 OpenGL,了解如何实现视频的剪裁、旋转、水印、滤镜,并学习 OpenGL 高级特性,如:VBO,VAO,FBO 等等

12. 学习 Android 图形图像架构,能够使用 GLSurfaceviw 绘制 Camera 预览画面

13. 深入研究音视频相关的网络协议,如 rtmp,hls,以及封包格式,如:flv,mp4

14. 深入学习一些音视频领域的开源项目,如 webrtc,ffmpeg,ijkplayer,librtmp 等等

15. 将 ffmpeg 库移植到 Android 平台,结合上面积累的经验,编写一款简易的音视频播放器

16. 将 x264 库移植到 Android 平台,结合上面积累的经验,完成视频数据 H264 软编功能

17. 将 librtmp 库移植到 Android 平台,结合上面积累的经验,完成 Android RTMP 推流功能

18. 上面积累的经验,做一款短视频 APP,完成如:断点拍摄、添加水印、本地转码、视频剪辑、视频拼接、MV 特效等功能

相信我,如果你认真把所有任务都完成了,你一定会成为音视频人才招聘市场的香饽饽~~

一,初级入门篇:

一 绘制图片

  1. ImageView 绘制图片

5种Android数据存储方式汇总

5种Android数据存储方式汇总

本文介绍Android中的5种数据存储方式。

数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是:

1 使用SharedPreferences存储数据
2 文件存储数据
3 sqlite数据库存储数据
4 使用ContentProvider存储数据
5 网络存储数据

下面将为大家一一详细介绍。

第一种:使用SharedPreferences存储数据
SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android平台常规的Long长 整形、Int整形、String字符串型的保存。

它是什么样的处理方式呢? SharedPreferences类似过去Windows系统上的ini配置文件,但是它分为多种权限,可以全局共享访问,android123提示最终是以xml方式来保存,整体效率来看不是特别的高,对于常规的轻量级而言比sqlite要好不少,如果真的存储量不大可以考虑自己定义文件格式。xml 处理时Dalvik会通过自带底层的本地XML Parser解析,比如XMLpull方式,这样对于内存资源占用比较好。

它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。
其存储位置在/data/data/< >/shared_prefs目录下。
SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。

实现SharedPreferences存储的步骤如下:
step1、根据Context获取SharedPreferences对象
step2、利用edit()方法获取Editor对象。
step3、通过Editor对象存储key-value键值对数据。
step4、通过commit()方法提交数据。

下面是示例代码:

public class MainActivity extends Activity {  
 @Override
   public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //获取SharedPreferences对象
    Context ctx = MainActivity.this;    
    SharedPreferences sp = ctx.getSharedPreferences("SP",MODE_PRIVATE);
    //存入数据
    Editor editor = sp.edit();
    editor.putString("STRING_KEY","string");
    editor.putInt("INT_KEY",0);
    editor.putBoolean("BOOLEAN_KEY",true);
    editor.commit();

    //返回STRING_KEY的值
    Log.d("SP",sp.getString("STRING_KEY","none"));
    //如果NOT_EXIST不存在,则返回值为"none"
    Log.d("SP",sp.getString("NOT_EXIST","none"));
   }

} 

这段代码执行过后,即在/data/data/com.test/shared_prefs目录下生成了一个SP.xml文件,一个应用可以创建多个这样的xml文件。

SharedPreferences对象与sqlite数据库相比,免去了创建数据库,创建表,写sql语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如sqlite数据库这样的其他数据存储方式。

第二种:文件存储数据
关于文件存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的。
文件可用来存放大量数据,如文本、图片、音频等。
默认位置:/data/data/< >/files/.。

代码示例:

public void save()
 {

    try {
      FileOutputStream outStream=this.openFileOutput("a.txt",Context.MODE_WORLD_READABLE);
      outStream.write(text.getText().toString().getBytes());
      outStream.close();
      Toast.makeText(MyActivity.this,"Saved",Toast.LENGTH_LONG).show();
    } catch (FileNotFoundException e) {
      return;
    }
    catch (IOException e){
      return ;
    }

 } 

openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。
创建的文件保存在/data/data//files目录,如: /data/data/cn.itcast.action/files/itcast.txt ,通过点击Eclipse菜单“Window”-“Show View”-“Other”,在对话窗口中展开android文件夹,选择下面的File Explorer视图,然后在File Explorer视图中展开/data/data//files目录就可以看到该文件。

openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为:

Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2

Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;
MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。

如果希望文件被其他应用读和写,可以传入: openFileOutput(“itcast.txt”,Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源比如文件的时候,就需要userid匹配。默认情况下,任何应用创建的文件,sharedpreferences,数据库都应该是私有的(位于/data/data//files),其他程序无法访问。
除非在创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,只有这样其他程序才能正确访问。

读取文件示例:

public void load()
{
  try {
    FileInputStream inStream=this.openFileInput("a.txt");
    ByteArrayOutputStream stream=new ByteArrayOutputStream();
    byte[] buffer=new byte[1024];
    int length=-1;
while((length=inStream.read(buffer))!=-1)  {
      stream.write(buffer,length);
    }

    stream.close();
    inStream.close();
    text.setText(stream.toString());
    Toast.makeText(MyActivity.this,"Loaded",Toast.LENGTH_LONG).show();
  } catch (FileNotFoundException e) {
    e.printstacktrace();
  }
  catch (IOException e){
    return ;
  }

} 

对于私有文件只能被创建该文件的应用访问,如果希望文件能被其他应用读和写,可以在创建文件时,指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE权限。

Activity还提供了getCacheDir()和getFilesDir()方法: getCacheDir()方法用于获取/data/data//cache目录 getFilesDir()方法用于获取/data/data//files目录。

把文件存入SDCard:
使用Activity的openFileOutput()方法保存文件,文件是存放在手机空间上,一般手机的存储空间不是很大,存放些小文件还行,如果要存放像视频这样的大文件,是不可行的。对于像视频这样的大文件,我们可以把它存放在SDCard。
SDCard是干什么的?你可以把它看作是移动硬盘或U盘。 在模拟器中使用SDCard,你需要先创建一张SDCard卡(当然不是真的SDCard,只是镜像文件)。

创建SDCard可以在Eclipse创建模拟器时随同创建,也可以使用DOS命令进行创建,如下: 在Dos窗口中进入android SDK安装路径的tools目录,输入以下命令创建一张容量为2G的SDCard,文件后缀可以随便取,建议使用.img: mksdcard 2048M D:\AndroidTool\sdcard.img 在程序中访问SDCard,你需要申请访问SDCard的权限。

在AndroidManifest.xml中加入访问SDCard的权限如下:

 <!-- 在SDCard中创建与删除文件权限 -->
  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYstemS"/>

  <!-- 往SDCard写入数据权限 -->
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

要往SDCard存放文件,程序必须先判断手机是否装有SDCard,并且可以进行读写。
注意:访问SDCard必须在AndroidManifest.xml中加入访问SDCard的权限。

 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ 
File sdCardDir = Environment.getExternalStorageDirectory();//获取SDCard目录     

File saveFile = new File(sdCardDir,“a.txt”);
    FileOutputStream outStream = new FileOutputStream(saveFile);
    outStream.write("test".getBytes());
    outStream.close();
}

​Environment.getExternalStorageState()方法用于获取SDCard的状态,如果手机装有SDCard,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED。
Environment.getExternalStorageDirectory()方法用于获取SDCard的目录,当然要获取SDCard的目录,你也可以这样写:

File sdCardDir = new File("/sdcard"); //获取SDCard目录
File saveFile = new File(sdCardDir,"itcast.txt");
//上面两句代码可以合成一句:
File saveFile = new File("/sdcard/a.txt");
FileOutputStream outStream = new FileOutputStream(saveFile);
outStream.write("test".getBytes());
outStream.close();

第三种:sqlite数据库存储数据

sqlite是轻量级嵌入式数据库引擎,它支持 sql 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((Mozilla,PHP,Python)都使用了 sqlite.sqlite 由以下几个组件组成:sql 编译器、内核、后端以及附件。sqlite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 sqlite 的内核变得更加方便。

特点:

面向资源有限的设备,

没有服务器进程,

所有数据存放在同一文件中跨平台,

可自由复制。

sqlite 内部结构:

​ sqlite 基本上符合 sql-92 标准,和其他的主要 sql 数据库没什么区别。它的优点就是高效,Android 运行时环境包含了完整的 sqlite。

sqlite 和其他数据库最大的不同就是对数据类型的支持,创建一个表时,可以在 CREATE TABLE 语句中指定某列的数据类型,但是你可以把任何数据类型放入任何列中。当某个值插入数据库时,sqlite 将检查它的类型。如果该类型与关联的列不匹配,则 sqlite 会尝试将该值转换成该列的类型。如果不能转换,则该值将作为其本身具有的类型存储。比如可以把一个字符串(String)放入 INTEGER 列。sqlite 称这为“弱类型”(manifest typing.)。 此外,sqlite 不支持一些标准的 sql 功能,特别是外键约束(FOREIGN KEY constrains),嵌套 transcaction 和 RIGHT OUTER JOIN 和 FULL OUTER JOIN,还有一些 ALTER TABLE 功能。 除了上述功能外,sqlite 是一个完整的 sql 系统,拥有完整的触发器,交易等等。

Android 集成了 sqlite 数据库 Android 在运行时(run-time)集成了 sqlite,所以每个 Android 应用程序都可以使用 sqlite 数据库。

对于熟悉 sql 的开发人员来时,在 Android 开发中使用 sqlite 相当简单。但是,由于 JDBC 会消耗太多的系统资源,所以 JDBC 对于手机这种内存受限设备来说并不合适。因此,Android 提供了一些新的 API 来使用 sqlite 数据库,Android 开发中,程序员需要学使用这些 API。

数据库存储在 data/< 项目文件夹 >/databases/ 下。 Android 开发中使用 sqlite 数据库 Activites 可以通过 Content Provider 或者 Service 访问一个数据库。

下面会详细讲解如果创建数据库,添加数据和查询数据库。 创建数据库 Android 不自动提供数据库。在 Android 应用程序中使用 sqlite,必须自己创建数据库,然后创建表、索引,填充数据。

Android 提供了 sqliteOpenHelper 帮助你创建一个数据库,你只要继承 sqliteOpenHelper 类,就可以轻松的创建数据库。sqliteOpenHelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。

sqliteOpenHelper 的子类,至少需要实现三个方法:

1 构造函数调用父类 sqliteOpenHelper 的构造函数。这个方法需要四个参数:上下文环境(例如,一个 Activity),数据库名字,一个可选的游标工厂(通常是 Null),一个代表你正在使用的数据库模型版本的整数。

2 onCreate()方法它需要一个 sqliteDatabase 对象作为参数,根据需要对这个对象填充表和初始化数据。

3 onUpgrage() 方法,它需要三个参数,一个 sqliteDatabase 对象,一个旧的版本号和一个新的版本号,这样你就可以清楚如何把一个数据库从旧的模型转变到新的模型。

下面示例代码展示了如何继承 sqliteOpenHelper 创建数据库:

public class DatabaseHelper extends sqliteOpenHelper {  
 DatabaseHelper(Context context,String name,CursorFactory cursorFactory,int version) 
 {   
  super(context,name,cursorFactory,version);   
   }   

   @Override  
   public void onCreate(sqliteDatabase db) {   
     // Todo 创建数据库后,对数据库的操作   
   }   

   @Override  
 public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) {   
     // Todo 更改数据库版本的操作   
   }   

 @Override  
 public void onopen(sqliteDatabase db) {   
     super.onopen(db);    
     // Todo 每次成功打开数据库后首先被执行   
   }   
 }  

接下来讨论具体如何创建表、插入数据、删除表等等。调用 getReadableDatabase() 或 getWriteableDatabase() 方法,你可以得到 sqliteDatabase 实例,具体调用那个方法,取决于你是否需要改变数据库的内容:

 db=(new DatabaseHelper(getContext())).getWritableDatabase();
    return (db == null) ? false : true; 

上面这段代码会返回一个 sqliteDatabase 类的实例,使用这个对象,你就可以查询或者修改数据库。 当你完成了对数据库的操作(例如你的 Activity 已经关闭),需要调用 sqliteDatabase 的 Close() 方法来释放掉数据库连接。 创建表和索引 为了创建表和索引,需要调用 sqliteDatabase 的 execsql() 方法来执行 DDL 语句。如果没有异常,这个方法没有返回值。

例如,你可以执行如下代码:

db.execsql("CREATE TABLE mytable (_id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT,value REAL);"); 

这条语句会创建一个名为 mytable 的表,表有一个列名为 _id,并且是主键,这列的值是会自动增长的整数(例如,当你插入一行时,sqlite 会给这列自动赋值),另外还有两列:title( 字符 ) 和 value( 浮点数 )。 sqlite 会自动为主键列创建索引。 通常情况下,第一次创建数据库时创建了表和索引。

如果你不需要改变表的 schema,不需要删除表和索引 . 删除表和索引,需要使用 execsql() 方法调用 DROP INDEX 和 DROP TABLE 语句。 给表添加数据 上面的代码,已经创建了数据库和表,现在需要给表添加数据。有两种方法可以给表添加数据。

像上面创建表一样,你可以使用 execsql() 方法执行 INSERT,UPDATE,DELETE 等语句来更新表的数据。execsql() 方法适用于所有不返回结果的 sql 语句。

例如: db.execsql(“INSERT INTO widgets (name,inventory)”+ “VALUES (‘Sprocket',5)”);

另一种方法是使用 sqliteDatabase 对象的 insert(),update(),delete() 方法。这些方法把 sql 语句的一部分作为参数。

示例如下:

ContentValues cv=new ContentValues();
cv.put(Constants.TITLE,"example title");
cv.put(Constants.VALUE,SensorManager.GraviTY_DEATH_STAR_I);
db.insert("mytable",getNullColumnHack(),cv);

update()方法有四个参数,分别是表名,表示列名和值的 ContentValues 对象,可选的 WHERE 条件和可选的填充 WHERE 语句的字符串,这些字符串会替换 WHERE 条件中的“?”标记。

update() 根据条件,更新指定列的值,所以用 execsql() 方法可以达到同样的目的。 WHERE 条件和其参数和用过的其他 sql APIs 类似。

例如:

String[] parms=new String[] {“this is a string”};
db.update(“widgets”,replacements,“name=?”,parms); 

delete() 方法的使用和 update() 类似,使用表名,可选的 WHERE 条件和相应的填充 WHERE 条件的字符串。 查询数据库 类似 INSERT,DELETE,有两种方法使用 SELECT 从 sqlite 数据库检索数据。

1.使用 rawQuery() 直接调用 SELECT 语句; 使用 query() 方法构建一个查询。

Raw Queries 正如 API 名字,rawQuery() 是最简单的解决方法。通过这个方法你就可以调用 sql SELECT 语句。

例如: Cursor c=db.rawQuery( “SELECT name FROM sqlite_master WHERE type='table' AND name='mytable'”,null);

在上面例子中,我们查询 sqlite 系统表(sqlite_master)检查 table 表是否存在。返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。 如果查询是动态的,使用这个方法就会非常复杂。

例如,当你需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。

Regular Queries query() 方法用 SELECT 语句段构建查询。SELECT 语句内容作为 query() 方法的参数,比如:要查询的表名,要获取的字段名,WHERE 条件,包含可选的位置参数,去替代 WHERE 条件中位置参数的值,GROUP BY 条件,HAVING 条件。 除了表名,其他参数可以是 null。所以,以前的代码段可以可写成:

String[] columns={“ID”,“inventory”};

String[] parms={“snicklefritz”}; 
Cursor result=db.query(“widgets”,columns,parms,null,null);

使用游标

不管你如何执行查询,都会返回一个 Cursor,这是 Android 的 sqlite 数据库游标,

使用游标,你可以:

通过使用 getCount() 方法得到结果集中有多少记录;

通过 movetoFirst(),movetoNext(),和 isAfterLast() 方法遍历所有记录;

通过 getColumnNames() 得到字段名;

通过 getColumnIndex() 转换成字段号;

通过 getString(),getInt() 等方法得到给定字段当前记录的值;

通过 requery() 方法重新执行查询得到游标;

通过 close() 方法释放游标资源;

例如,下面代码遍历 mytable 表:

Cursor result=db.rawQuery(“SELECT ID,inventory FROM mytable”); 
result.movetoFirst(); 
while (!result.isAfterLast()) { 
int id=result.getInt(0); 
String name=result.getString(1); 
int inventory=result.getInt(2); 
// do something useful with these 
result.movetoNext(); 
}

result.close();

在Android 中使用 sqlite 数据库管理工具 在其他数据库上作开发,一般都使用工具来检查和处理数据库的内容,而不是仅仅使用数据库的 API。

使用 Android 模拟器,有两种可供选择的方法来管理数据库。

首先,模拟器绑定了 sqlite3 控制台程序,可以使用 adb shell 命令来调用他。只要你进入了模拟器的 shell,在数据库的路径执行 sqlite3 命令就可以了。

数据库文件一般存放在: /data/data/your.app.package/databases/your-db-name 如果你喜欢使用更友好的工具,你可以把数据库拷贝到你的开发机上,使用 sqlite-aware 客户端来操作它。这样的话,你在一个数据库的拷贝上操作,如果你想要你的修改能反映到设备上,你需要把数据库备份回去。

把数据库从设备上考出来,你可以使用 adb pull 命令(或者在 IDE 上做相应操作)。

存储一个修改过的数据库到设备上,使用 adb push 命令。 一个最方便的 sqlite 客户端是 FireFox sqlite Manager 扩展,它可以跨所有平台使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

android – 如何向MediaMux提供音频数据和视频数据

android – 如何向MediaMux提供音频数据和视频数据

我正在尝试通过预览获取视频原始数据,通过AudioRecord获取音频原始数据.然后我将它们发送到MediaCodec(我将设置两个Codec实例).之后,我将视频数据和音频数据发送到MediaMux以获得mp4文件.我有两个问题:

1)之前我曾使用MediaMux处理视频数据.对于视频数据,MediaMux按帧处理,但视频记录是连续的. MediaMux如何同步处理视频和音频.

2)我在函数writeSampleData中只找到了inputbuffer的变量.StackOverflow上的一个好人也提供了MediaMux的演示.但是这个演示只有一个源数据变量.这个变量怎么能同时代表视频数据和音频数据呢?

谢谢!

解决方法:

我已经成功将同步的音频和视频传递给Mediamuxer.我计算了每帧视频应播放的音频样本数:基于音频采样率和视频帧率.然后我有一个循环,在每次迭代中写入一个视频帧和一个音频块.使用演示时间确保它们在播放时同步.在调用writeSampleData时使用addTrack中的track index,以允许将视频和音频写入两个单独的轨道.

今天关于Android音视频【六】视频数据存储方式YUV安卓视频存储位置的介绍到此结束,谢谢您的阅读,有关2021了,为什么说音视频技术是技术风口?Android音视频开发这么吃香?、5G时代风口浪尖上的音视频开发技术,你还在观望吗?保姆级Android音视频开发学习一篇就够、5种Android数据存储方式汇总、android – 如何向MediaMux提供音频数据和视频数据等更多相关知识的信息可以在本站进行查询。

本文标签: