Camera2比起Camera的自定义程度更高一点,比如可以同时输出多个视频流分别用于显示预览画面和录制视频。但是!不同于Camera可以直接使用setOrientation方法直接设置视频旋转角度,Camera2没有提供类似的方法。此外,由于MediaRecorder类的一些问题,我使用了自定义的类来对输出的视频流进行处理,也没法使用MediaRecorder类的设置旋转角度方法。

这样的结果就是,使用前置摄像头录制的视频,默认视角是旋转了90°的,不符合正常观看的要求。

为了解决这个问题,我查了不少资料,对Camera2自身设置属性和对自定义的视频录制类的修改都没有正确的旋转视频的角度。在失败了很多次之后我选择了从MP4本身的文件格式入手。

这个方法的原理是模仿Camera中的setOrientation。这个方法并没有真正旋转视频的内容,只是在MP4视频的内容中对应旋转的标志位加入了旋转的记号,这样,在播放器进行播放时,读取到对应的内容就知道应该如何旋转视频的角度。我想模仿这个方法,通过解析MP4文件的二进制内容,找到标记旋转角度的位置并进行修改,实现视频录制文件的旋转。

我参考了这两个网站

Online Mp4 Parser : https://www.onlinemp4parser.com/

MP4文件格式解析 : https://www.cnblogs.com/ranson7zop/p/7889272.html

Online MP4 parser可以解析mp4文件的格式,这些树形结构的具体含义是什么呢?可以结合《MP4文件格式解析》这篇文章来看

MP4文件中的所有数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每个box有类型和长度,可以将box理解为一个数据对象块。

box中可以包含另一个box,这种box称为container box。

一个MP4文件首先会有且只有一个“ftyp”类型的box,作为MP4格式的标志并包含关于文件的一些信息;之后会有且只有一个“moov”类型的box(Movie Box)......MP4文件的媒体数据包含在“mdat”类型的box(Midia Data Box)中......

我们并不需要完全了解所有的mp4格式信息,只要找到负责标志旋转角度的位置即可。

标准的box开头的4个字节(32位)为box size,该大小包括box header和box body整个box的大小,这样我们就可以在文件中定位各个box。

size后面紧跟的32位为box type,一般是4个字符,如“ftyp”、“moov”等,这些box type都是已经预定义好的,分别表示固定的意义。

非常重要,我们需要通过这两条规则来检查这个MP4文件是否符合应该有的格式,以及快速定位到旋转标志位

我们来用ftyp这个MP4开头的box进行一次检测的示范

使用文本编辑器(比如我用的是sublime text)打开一个MP4视频(最好不要用太大的,我用的是一个300kb左右的视频),可以看到文件的二进制内容

注意这里都是16进制的数字

ftyp是MP4文件的第一个box,所以我们从文件开头开始看起。最开始的4个字节00 00 00 18对应这个box的box size字段,也就是18(16进制)=24(10进制)个字节。size之后的4个字节66 74 79 70就是box type字段,转换成对应的char字符正是"ftyp"这四个字符

我们在Online MP4 parser中同样能看到同样的信息,验证了我们的推算。

MP4的文件格式中,moov的子box中可以包含多个trak,分别对应不同的轨道,例如音频轨道和视频轨道。由于我使用了自定义的录制方式,实际需要解析的视频不包含音频轨道,所以没有对trak进行特别的区分。如果需要区分,也可以通过对trak的具体解析进行区分。

我们需要定位的视频旋转标志位位于这里

moov/trak/tkhd

其中有matrix字段,这就是旋转标志位,其他box的具体含义可以参考《MP4文件格式解析》

matrix相对于tkhd的头部的偏移量是一个固定值,找到tkhd头部的位置即可确定matrix的位置,从而修改和设置旋转矩阵

具体定位tkhd头部的方法,就是依次打开每一个box的头部,通过box type确定格式没错,通过box size确定应该往后找多少个字节,直到找到正确的位置

示例代码如下:

//计算偏移量/*24个字节 固定 fytp8个字节 size0和”moov”头部size1个字节 ,标志”mvhd”头部size2个字节,标志”meta”头部8个字节,后四个为固定字符“trak”8个字节,后四个为固定字符”tkhd”从trak字符结束后往后48个字符开始。*/int mp4FormatErrorStep = 0;
//      int boxSize = 0;matrixOffset = 24;if(data[matrixOffset+4] == 'm' &&data[matrixOffset+5] == 'o' &&data[matrixOffset+6] == 'o' &&data[matrixOffset+7] == 'v' ){//pass}else{mp4FormatErrorStep = 1;}matrixOffset += 8;if(data[matrixOffset+4] == 'm' &&data[matrixOffset+5] == 'v' &&data[matrixOffset+6] == 'h' &&data[matrixOffset+7] == 'd' ){//pass}else{mp4FormatErrorStep = 2;}matrixOffset +=(data[matrixOffset+3] +data[matrixOffset+2] * 16 +data[matrixOffset+1] * 16*16 +data[matrixOffset] * 16*16*16);if(data[matrixOffset+4] == 'm' &&data[matrixOffset+5] == 'e' &&data[matrixOffset+6] == 't' &&data[matrixOffset+7] == 'a' ){//pass}else{mp4FormatErrorStep = 3;}matrixOffset += (data[matrixOffset+3] +data[matrixOffset+2] * 16 +data[matrixOffset+1] * 16*16 +data[matrixOffset] * 16*16*16);if(data[matrixOffset+4] == 't' &&data[matrixOffset+5] == 'r' &&data[matrixOffset+6] == 'a' &&data[matrixOffset+7] == 'k' ){//pass}else{mp4FormatErrorStep = 4;}matrixOffset += 8;if(data[matrixOffset+4] == 't' &&data[matrixOffset+5] == 'k' &&data[matrixOffset+6] == 'h' &&data[matrixOffset+7] == 'd' ){//pass}else{mp4FormatErrorStep = 5;}matrixOffset += 48;if(mp4FormatErrorStep == 0) {//旋转90°System.arraycopy(orientation90Matrix, 0, data, matrixOffset, orientation90Matrix.length);}}

这段代码只针对了我使用的mp4录制方式,如果要用在别的地方,需要对目标类型的MP4进行手动解析,修改为适用的模式

修改MP4文件二进制内容,实现安卓Camera2旋转录制视频画面功能相关推荐

  1. 用Python批量修改hex文件的内容

    用Python批量修改hex文件的内容 文章目录 用Python批量修改hex文件的内容 0.前言 1.代码 0.前言 先保存下来,电脑要清空了..... 后续补上:大概关于hex校验码,从大的hex ...

  2. 如何修改jar文件的内容

    在做(或修改别人的)项目的时候,可能遇到要修改调用的的jar包内的类属性或方法的问题.在eclipse或是其他的IDE中是无法直接修改的,所以需要一个解压jar-->修改文件-->编译-- ...

  3. 如何修改.json文件的内容?

    以下是项目过程中遇到的一些数据清洗,预处理和统计等常规操作,有需要的可以自行借鉴下相关模块代码,转载或引用请注明. ########################################## ...

  4. 修改mp4文件的moov atom,使其位置在文件的前面

    mp4文件录制的时候,先写mdat atom对应的音视频数据,最后在尾部写上moov atom对应的一些索引信息.一些软件在录制后会再处理一次,把moov atom的位置搬到文件的前面,而把mdat ...

  5. php合并播放mp4文件_如何将百度的流畅版视频m3u8合并为正确的mp4文件?

    本帖最后由 autoav 于 2020-10-16 11:05 编辑 我在百度网盘保存了很多视频,很多视频本身比较大,手机看的话,只要下载流畅版就可以了,但是只能用百度网盘app看,我想合并成mp4文 ...

  6. type=file的未选择任何文件修改_PDF文件怎样输入到CAD图纸中?懂得这个功能可以快速实现...

    PDF和DWG是CAD设计师经常会用到的文档格式.一般来说,PDF文件主要用于信息交流,设计师将DWG图纸输出为PDF文件,可以避免数据被修改.有些情况下,设计师也需要反向将PDF文件转换为DWG数据 ...

  7. dataframe保存为txt_如何批量查找并修改替换 Word、PPT、Excel、PDF、TXT等文件的内容...

    概要 平时的工作中,我们避免不了与众多 Word 文件.PPT 文件.PDF 文件.TXT 等文件打交道,有时候我们需要对这些文件进行批量修改与替换内容.这里我们介绍了这样的一款工具,它可以很方便快速 ...

  8. 如何在ppt下面加入讲解内容_如何批量查找并修改替换 Word、PPT、Excel、PDF、TXT等文件的内容——我的ABC...

    概要:平时的工作中,我们避免不了与众多 Word 文件.PPT 文件.PDF 文件.TXT 等文件打交道,有时候我们需要对这些文件进行批量修改与替换内容.这里我们介绍了这样的一款工具,它可以很方便快速 ...

  9. 怎么修改PDF文件的文字内容

    怎么修改PDF文件中的文字内容呢?现在很多的PDF文件中的文字需要进行修改,但是找不到修改PDF文件的软件,想要修改PDF文件中的文字内容就可以使用PDF编辑器来进行操作,推荐使用迅捷PDF编辑器,下 ...

最新文章

  1. SharePoint 2013 REST 服务使用简介
  2. python中统计列表各个元素的个数
  3. debian 文件夹中文件大小_debian 记录用到的命令 文件夹 目录等操作
  4. 智源-知乎联合发布大规模用户关系数据集,同步开启10万元竞赛
  5. SAP ABAP实用技巧介绍系列之使用代码获得某个structure上的扩展字段
  6. 好玩的表情包机器人小程序源码_支持直接搜索仿聊天界面获取源码
  7. Python版常见的排序算法
  8. 如果让你手写个栈和队列,你还会写吗?
  9. MySQL实现时间按月,日,小时分组查询
  10. 运用ffmpeg生成MP4文件
  11. 正则表达式高级用法: 分组
  12. nyoj 366 D的小L(数的全排)
  13. 感动13亿中国人的芭蕾舞小女孩
  14. 底物的分子描述符计算及 CYP450 酶-底物选择性技术研究
  15. Unity之使用贝塞尔曲线制作图片轮播
  16. 上网时遇到的 404 是什么意思?
  17. ID3西瓜决策树python实现
  18. sql复杂查询语句的使用
  19. 发自肺腑深入肌肤 —— 一位武汉老程序员的自白
  20. 单片机多电梯控制系统

热门文章

  1. 网管必知:常用电脑密码破解
  2. 蓝牙认证,蓝牙BQB认证,蓝牙BQB测试内容,蓝牙BQB认证多少钱?蓝牙BQB认证流程
  3. C语言:指针三(线性表的存储结构)
  4. 英特尔Skylake处理器全面入驻Google Compute Engine
  5. stm32-DHT11原理及代码解读
  6. 异常:egret获取引擎列表失败
  7. 英文事件抽取论文整理
  8. Java 简单的用户管理系统(代码注释超全超详细!!!)
  9. tableau免费版无法更新数据
  10. 2020寒假【gmoj2417】【Loan Repayment】【二分】