Android视频开发基础(二)

https://blog.csdn.net/goodlixueyong/article/details/62447452

前一篇文章详细介绍了视频的一些基本概念,这些内容与Android系统本身没有密切关系,只是作为熟悉视频领域的一个基础,便于介绍接下来关于Android上视频处理的其他内容。继续来看Android上视频相关的内容。

      Android支持的格式

先来看一下Android官网上给出的Android系统支持的文件格式。

从图中我们可以看到

1、Android支持mp4、3gp、mkv和webm四种视频封装格式。前三种都是比较常见的,最后一种要特别讲一下。

WebM由Google提出,一个用于网页的开放、免费的媒体文件格式,目前在Youtube上使用最多的格式。WebM 影片格式其实是以 mkv容器格式为基础开发的新容器格式,里面包括了VP8/VP9视轨和 Ogg Vorbis音轨。

2、Android支持多种的视频编码格式。如H.264 AVC、H.263、VP8、VP9等。每种封装格式可以对应于不同的编码格式。比如mp4格式视频文件可能对应于H.263、H.264、H.265三种格式。

3、Android对于视频编解码的支持有版本的差异。比如对于VP9的编码是不支持的,而VP9的解码是在4.4版本之后才支持。

从上面几点看,在Android上做视频处理功能,不仅需要考虑各种视频格式的兼容,还要考虑Android版本的兼容问题,另外,还需要考虑不同Rom厂商对系统做的定制。

 Android实现视频编辑

音视频的编码可以使用硬编码和软编码两种,硬编码就是直接调用GPU进行编码处理,而软编码是使用CPU进行运算。两种编码方式都有各自的优缺点,硬编码的效率更高,对CPU的消耗较少,但是兼容性较差,硬编码就会涉及到硬件,所以当机器不同,可能会有的机器能编码,有的会失败。而软编码的兼容性更好,但是效率较低,会加重CPU的负载。在Android的视频处理中,这两种编码方式分别对应于不同的两种实现。

 MediaCodec

从API 16开始,Android提供了Mediacodec类以便开发者更加灵活的处理音视频的编解码。MediaCodec就属于硬编码。MediaCodec类可用于访问Android底层的媒体编解码器。它是Android底层多媒体支持基本架构的一部分(通常与MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, 以及AudioTrack一起使用)。

从广义上讲,一个编解码器通过处理输入数据来产生输出数据。MediaCodec采用异步方式处理数据,并且使用了一组输入输出缓存(buffer)。在简单的层面,你请求或接收到一个空的输入缓存(buffer),向其中填充满数据并将它传递给编解码器处理。编解码器处理完这些数据并将处理结果输出至一个空的输出缓存(buffer)中。最终,你请求或接收到一个填充了数据的输出缓存(buffer),使用完其中的数据,并将其释放回编解码器。

优点:功耗低,硬件编解码速度快

缺点:扩展性不强,不同芯片厂商提供的支持方案不同,导致程序移植性差,实测发现很多手机的YUV码流不一致,还会出现硬编码后偏色的问题

适用场景:有固定的硬件方案,无需移植(如智能家具产品);需要长时间摄像的场景,如手机摄像头实时取景,这种场景软解码的处理速度跟不上。

FFmpeg

FFmpeg是一套用来记录、转换数字音频、视频,并能将其转化为流的开源程序。FFmpeg有非常强大的功能,包括视频采集功能、视频格式转换、视频抓图、视频加水印等。FFmpeg在Linux平台下开发,但它也可以在其它操作系统中编译运行,包括Windows、OS X等。

FFmpeg堪称自由软件中最完备的一套多媒体支持库,它几乎实现了所有当下常见的数据封装格式、多媒体传输协议以及音视频编解码器。可以直接通过命令行使用FFmpeg,它提供了三个命令行工具,ffmpeg用于转码,ffplay用于播放,ffprobe用于查看文件格式。

实际上,除去部分具备系统软件开发能力的大型公司(Microsoft、Apple等)以及某些著名的音视频技术提供商(Divx、Real等)提供的自有播放器之外,绝大部分第三方开发的播放器都离不开FFmpeg的支持,像Linux桌面环境中的开源播放器VLC、MPlayer,Windows下的KMPlayer、暴风影音以及Android下几乎全部第三方播放器都是基于FFMpeg的。可以这么说,只要做视频音频开发都离不开FFmpeg。

优点:(1)封装了很多的格式,使用起来比较灵活,兼容性好;(2)命令行的方式使用非常方便,比如视频裁剪的步骤:ffmpeg -ss 10 -t 20 -i INPUT -acodec copy -vcodec copy OUTPUT,相对来说比写函数的方式要简单很多。(3)功能十分强大

缺点:(1)学习成本有点高(2)软编解码功耗大,占用CPU较多,效率偏低

适用场景:跨平台使用(如不同芯片厂商的手机);短时间拍摄。

因此,从整个行业来看,由于Android平台的碎片化,以及各个厂商硬件的差异化,直接使用MediaCodec进行视频硬编码的实现会遇到各种兼容性问题,因此大部分都是直接使用ffmpeg进行视频处理,或多或少进行一些性能和功能上的优化。

获取视频帧

Android系统提供了统一的MediaMetadataRetriever类,用于从一个输入媒体文件中取得帧和元数据(时间、名字、长度等等)。如果是视频文件,还可以通过getFrameAtTime方法取得指定time位置的Bitmap。

先看方法原型:public Bitmap getFrameAtTime(long timeUs, int option) ,第一个参数是传入时间,单位是us。

第二个参数可以设置为下面四个值:

OPTION_CLOSEST    在给定的时间,检索最近一个帧,这个帧不一定是关键帧

OPTION_CLOSEST_SYNC    在给定的时间,检索与当前时间最近的关键帧

OPTION_NEXT_SYNC  在给定时间之后检索一个关键帧

OPTION_PREVIOUS_SYNC   在给定时间之前检索一个关键帧

MediaMetadataRetriever有几个问题导致使用并不是很方便。

1、获取的Bitmap是与原视频尺寸相同的,图片会比较大,并没有提供获取压缩的图片的接口。

2、获取的帧的速度较慢,测试下来获取一帧的时间为250ms左右。

3、即使使用OPTION_CLOSEST获得的也是有一定偏差的,并不能保证获取指定时间点的帧。

因此,实际实现中,通常使用ffmpeg来获取视频帧,不仅可以获取任意大小的图片,速度也有比较大的提升,使用ffmpeg通常可以精确获得指定时间的帧。

    MediaPlayer seek误差问题

Android使用VideoView播放视频的时候,常常会调用seek方法去移动视频播放位置,但是有时候却不能准确的定位到我们想要的位置。通常会比我们指定的位置回退几秒(在有的手机上可能会前进几秒)。

这是由于seek操作跳转的位置其实并不是参数所带的position,而是离position最近的关键帧。为了提高seek的速度,MediaPlayer在seek到指定postion位置时,会去找最近的关键帧,然后从关键帧的位置开始播放。由于不同的手机实现的差别,可能向前也可能向后寻找关键帧,因此就出现了指定seek位置后,播放位置前进或者后退的情况。

如果要解决seek不准的问题,需要修改播放器seek的策略,seek到关键帧后,然后循环读帧,直到你需要的位置,然后输出这一帧的完整图像信息。但是,这样处理seek的速度相对就会慢一点。

Android视频开发基础(二)相关推荐

  1. Android视频开发基础

    Android视频开发基础 版权声明:本文为[viclee]原创,如需转载请注明出处~ https://blog.csdn.net/goodlixueyong/article/details/6205 ...

  2. 音视频开发(19)---Android视频开发基础(一)

    Android视频开发基础(一) 版权声明:本文为[viclee]原创,如需转载请注明出处~ https://blog.csdn.net/goodlixueyong/article/details/6 ...

  3. Android视频开发基础(一)

    基本概念 码率        码率就是数据传输时单位时间传送的数据位数,单位一般是kbps即千位每秒.码率影响体积,与体积成正比:码率越大,体积越大:码率越小,体积越小.码率还影响清晰度,码率越高清晰 ...

  4. Android音视频开发基础(七):视频采集-系统API基础

    前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了<Android 音视频从入门到提高 - 任务列表>.本文是Android音视 ...

  5. Android音视频开发基础(六):学习MediaCodec API,完成视频H.264的解码

    前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了<Android 音视频从入门到提高 - 任务列表>.本文是Android音视 ...

  6. android界面数据存储,Android应用开发基础之数据存储和界面展现(二)

    Android应用开发基础之数据存储和界面展现(二) 常见布局 相对布局 RelativeLayout 组件默认左对齐.顶部对齐 设置组件在指定组件的右边 android:layout_toRight ...

  7. 蓝鸥Unity开发基础二——课时20 接口

    蓝鸥Unity开发基础二--课时20 接口 一.接口 使用interface关键字定义接口 接口定义一组成员单不直接实现它们 二.实现接口 实现接口的任何类都必须实现其所有的成员方法 接口不能直接实例 ...

  8. Android App开发基础

    Android App开发基础 App的开发特点 (1)App的运行环境 1.使用数据线把手机连到电脑上 2.在电脑上安装手机的驱动程序 3.打开手机的开发者选项并启用USB调试 4.将连接的手机设为 ...

  9. 音视频开发基础知识(转载)

    音视频入门前,需要了解下一些基础概念,不必死记硬背,可之后再补再翻阅. 一. 颜色模式 RGB RGB颜色模型的主要目的是在电子系统中检测,表示和显示图像,比如电视和计算机,但是在传统摄影中也有应用. ...

最新文章

  1. 最新!字节跳动再次扩招1000人,招聘要求令人窒息
  2. mysql pma用户_MYSQL用户权限管理学习笔记
  3. 重读图灵经典之作,九条反驳意见引人深思
  4. scrapy 分布式爬虫- RedisSpider
  5. [WP8.1UI控件编程]Windows Phone自定义布局规则
  6. OPenGL模板缓冲区示例程序
  7. linux内核的I2C子系统详解5——i2c_driver的注册、i2c_client的来源
  8. FreeModbus TCP传输初始化
  9. 超级详细的手写webpack4配置来启动vue2项目(附配置作用)
  10. 第四十三篇 面向对象进阶2
  11. 倾斜模型精细化处理_基于倾斜摄影和近景摄影技术的实景三维模型结合(CC与 DPModeler结合)...
  12. 特斯拉两高管被爆离职,股价狂跌超过10%,马斯克宣布高层大换血
  13. PHP架设网页微端,GeeM2引擎20180425版本搭建微端方法
  14. 如何花式计算20的阶乘?
  15. load data infile into table 的使用例子
  16. 使用MySQLWorkBench绘制ER图详解
  17. linux proftpd mysql_虚拟主机与Proftpd和MySQL(包括配额)在Ubuntu 14.04LTS
  18. curl CURLE_COULDNT_CONNECT
  19. InfluxDB导入导出数据
  20. 让ckplayer支持m3u8格式的播放

热门文章

  1. python牛顿法解非线性方程组_萌新请教牛顿法求解三元非线性方程组
  2. python3.6sysos_python3.6实现学生信息管理系统
  3. Keil(MDK-ARM-STM32)系列教程(五)Configuration(Ⅰ)
  4. Python : *args和**kwargs是什么东东呢?
  5. nodejs入门学习笔记一——一个完整的http路由服务实现
  6. Linux下部署LVS(DR)+keepalived+Nginx负载均衡
  7. dede织梦调用顶级二级栏目及下三级栏目方法!
  8. 首尾相接数组求子数组最大和
  9. Oracle Bitmap 索引结构、如何存储及其优势
  10. 在Python中写入文件时,权限被拒绝错误