MP4视频格式和mp4v2的移植

news2024/11/13 13:08:00

目录

1、视频文件

2、MP4

3、MP4学习方法

4、MP4文件格式解析

5、MP4Info工具使用

6、mp4v2移植和播放

6.1、下载mp4v2

6.2、配置并编译

6.3、部署

6.4、编译sample

6.5、准备TF卡

6.6、运行和测试

7、MP4打包源码解析

8.添加网络telnet调试

8.1、为什么添加telnet调试

8.2、telnet调试的原理-可以通过telnet协议远程登录一个运行了telnetd的程序

8.3、在HI3518E开发板上telnet远程登录调试

9、海思proc文件系统调试接口

9.1、proc文件系统的原理

9.2、参考 HiMPP IPC V2.0 媒体处理软件开发参考.pdf和HiISP FAQ V100版本.pdf


1、视频文件

(1)视频文件的本质:二进制文件,记录压缩后的视频帧(I帧、P帧等)并且能被播放器还原解码播放

H264码流:刷子

H264码流被播放器解码播放:刷子被人用来刷锅

mp4:将刷子拿给快递公司打包寄过去

(2)视频文件的关键:高效率记录信息(mp4)、兼容性(mp4有很多种格式)

(3)视频文件的信息:索引信息(记录有效信息是怎么被安排的)、有效信息(I帧、P帧这些)

2、MP4

(1)MP4由MP3升级而来,包含video(H.264)和audio(AAC)在内

(2)MP4是h.264的最主流打包格式

(3)MP4文件内部采用网络字节序(大端模式:高字节放在低地址)

3、MP4学习方法

(1)学习MP4的组织形式和box解析,box是mp4的最基本单元,box的种类有上百种(mp4有多种格式的原因)

(2)移植和使用mp4v2开源库来打包MP4

(3)研究MP4解包播放和mp4v2源码

(4)编程进行MP4的打包、解包、分割等。

4、MP4文件格式解析

mp4文件格式解析 - nigaopeng - 博客园 (cnblogs.com)

(1)MP4文件封装格式,对应的标准为ISO/IEC 14496-12,早期是基于QuickTime容器格式定义的

(2)MP4文件中的媒体描述与媒体数据是分开的,并且媒体数据的组织也很自由,不一定要按照时间先后顺序排列,甚至媒体数据可以直接引用外部其它视频文件,也就是内嵌其它视频

(3)MP4也支持流媒体,也就是在网上边下载边播放视频

(4)整个MP4文件由若干种不同类型的box组成,打包和解包时都是以box为单位的

(5)MP4中首先只有一个ftyp box,位于整个MP4的开头位置,ftyp box的作用是作为MP4格式的标志并包含关于一些文件信息

(6)ftyp box之后是Movie Box,MP4中也只有一个,它是container box,子box包含了媒体的metadata信息

(7)MP4文件的媒体数据被包含在mdat box(Midia Data Box)中,该box是container box,可以有多个子box,也可以没有(当媒体数据全部引用其他文件时),媒体数据的结构由metadata进行描述。

(8)box开头的4个字节(32位)为box size,该大小是整个box的大小,这样我们就可以在文件中定位各个box,如果size为1,则表示这个box的大小为large size,是一个很大的box,这里放不下他的box size值,真正的size值要在largesize域上得到。如果size为0,表示该box为文件的最后一个box,文件结尾即为该box结尾,所以mp4文件到这就结束了。

(9)size后面紧跟的32位为box type,一般是4个字符,如“ftyp”、“moov”等,这些box type都是已经预定义好的,分别表示固定的意义。如果是“uuid”,表示该box为用户扩展类型。如果box type是未定义的,应该将其忽略。

(10)  free box是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响。

5、MP4Info工具使用

(1)每一个box包含header(头)和body(主体),在moov box中

mvhd是header,其余是主体

(2)Movie Box(moov):

该box包含了文件媒体的metadata信息,“moov”是一个container box,具体内容信息由子box诠释。同File Type Box一样,该box有且只有一个,且只被包含在文件层,不会被任何box包含。一般情况下,“moov”会紧随“ftyp”出现。

“moov”中会包含1个“mvhd”和若干个“trak”。其中“mvhd”为header box,一般作为“moov”的第一个子box出现(对于其他container box来说,header box都应作为首个子box出现)。“trak”包含了一个track的相关信息,是一个container box。

(3)Movie Header Box(mvhd):

字段

字节数

意义

box size

4

box大小,

这里是00 00 00 6C

box type

4

box类型,

这里是6D 76 68 64

version

1

box版本,0或1,一般为0。(以下字节数均按version=0),这里是00

flags

3

这里是00 00 00 

creation time

4

创建时间(相对于UTC时间1904-01-01零点的秒数),

这里是00 00 00 00,这是抖音下载的视频,不知道为啥是00 00 00 00,其它视频是正确的创建时间

modification time

4

修改时间,

这里是00 00 00 00,同上

time scale

4

文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数,

这里是00 00 03 E8

duration

4

该track的时间长度,用duration和time scale值可以计算track时长,比如audio track的time scale = 8000, duration = 560128,时长为70.016,video track的time scale = 600, duration = 42000,时长为70

rate

4

推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式,该值为1.0(0x00010000)表示正常前向播放

volume

2

与rate类似,[8.8] 格式,1.0(0x0100)表示最大音量

reserved

10

保留位

matrix

36

视频变换矩阵

pre-defined

24

next track id

4

下一个track使用的id号

(4)Track Box(trak):

    “trak”也是一个container box,其子box包含了该track的媒体数据引用和描述(hint track除外)。一个MP4文件中的媒体可以至少包含有一个track,这些track之间彼此独立,有各自的时间和空间信息。“trak”必须包含一个“tkhd”和一个“mdia”,此外还有很多可选的box(略)。其中“tkhd”为track header box,“mdia”为media box,该box是一个包含一些track媒体数据信息box的container box。

(5)Track Header Box(tkhd)、Media Box(mdia)等详见博文

(6)Sample Table Box(stbl):该box是有效信息的索引

    “stbl”几乎是普通的MP4文件中最复杂的一个box了,首先需要回忆一下sample的概念。sample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同,如下图所示。

 “stbl”包含了关于track中sample所有时间和位置的信息,以及sample的编解码等信息。利用这个表,可以解释sample的时序、类型、大小以及在各自存储容器中的位置。“stbl”是一个container box,其子box包括:sample description box(stsd)、time to sample box(stts)、sample size box(stsz或stz2)、sample to chunk box(stsc)、chunk offset box(stco或co64)、composition time to sample box(ctts)、sync sample box(stss)等。

    “stsd”必不可少,且至少包含一个条目,该box包含了data reference box进行sample数据检索的信息。没有“stsd”就无法计算media sample的存储位置。“stsd”包含了编码的信息,其存储的信息随媒体类型不同而不同。

6、mp4v2移植和播放

6.1、下载mp4v2

(1)2.0.0~dfsg0-6 : mp4v2 package : Ubuntu

(2)解压,并在目录内创建_install目录作为安装目录

6.2、配置并编译

(1)sudo PATH=$PATH:/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin CC=arm-hisiv300-linux-gcc CXX=arm-hisiv300-linux-gcc ./configure --host=arm-hisiv300-linux --prefix=/home/aston/sambashare/mp4v2-2.0.0/_install --disable-option-checking --disable-debug --disable-optimize --disable-fvisibility --disable-gch --disable-largefile --disable-util --disable-dependency-tracking --disable-libtool-lock

(2)make

(3)make install

(4)检查各必要文件

6.3、部署

(1)生成的lib加到mpp lib里面

(2)include下文件夹添加到mpp/include中去

(3)lib/so加到开发板lib目录下

6.4、编译sample

(1)make

6.5、准备TF卡

(1)TF卡格式化为FAT32文件系统,若失败可试试低层格式化软件如SDFormat之类

(2)先检测下TF卡可用 ls /dev/mmcblk0p1

(3)开机后将TF卡进行挂载 mount -t vfat /dev/mmcblk0p1 /usr/mmc

6.6、运行和测试

(1)运行sample_venc,用rtsp测试确认有图像

(2)终止程序,取出TF卡用读卡器接电脑查看

7、MP4打包源码解析

HI_S32 SAMPLE_COMM_VENC_MP4(VENC_STREAM_S *stStream)
{
    static int nRecordFlag = 0x00;
    static int recording = 0x1;
    static int spsflag = 0;
    static int ppsflag = 0;
    static MP4TrackId video = 0;
    static MP4FileHandle hMP4File = NULL;//MP4文件的句柄

    static char recordfish = 0x1;//这个变量表示我们录制有没有结束
    //多次调用函数时,以上变量是累积的
    int j = 0;
    int len = 0;
    char *pData = NULL;
    char isSyncSample = 0;
    
    if(recordfish == 0x00){//录制结束
        return 0;
    }

    if(hMP4File == NULL){//创建MP4文件
        hMP4File = MP4CreateEx("/usr/mmc/test.mp4",0, 1, 1, 0, 0, 0, 0);            //文件存储路径
        if (hMP4File == MP4_INVALID_FILE_HANDLE)    {
            printf("open file fialed.\n");
            return -1;
        }
    
        MP4SetTimeScale(hMP4File, 90000);
    }
    
    if(recording && stStream->u32Seq > 30){            //丢弃前面不完整的一个序列,也可以不丢弃
        //if(stStream->u32PackCount >= 3){            //从下一个序列的I帧开始编码,保证文件开始就能播放
            nRecordFlag = 1;
        //}
    
        if(nRecordFlag){
            for(j = 0;j < stStream->u32PackCount;j++){
                len     = stStream->pstPack[j].u32Len - stStream->pstPack[j].u32Offset;
                pData    = (stStream->pstPack[j].pu8Addr + stStream->pstPack[j].u32Offset);                        
    
                if(stStream->pstPack[j].DataType.enH264EType == H264E_NALU_SPS){
                    if(spsflag == 0x00){
                        spsflag = 0x1;
                        //写sps
                        printf("Write sps =================\n");    
    
                        //把一个视频的Track添加到文件中去
                        video = MP4AddH264VideoTrack(hMP4File, 90000, 90000 / 30, 1280, 720,
                                                                pData[4+1], //sps[1] AVCProfileIndication
                                                                pData[4+2], //sps[2] profile_compat
                                                                pData[4+3], //sps[3] AVCLevelIndication
                                                                3); // 4 bytes length before each NAL unit
                            MP4SetVideoProfileLevel(hMP4File, 0x7F);//视频质量的级别
                            MP4AddH264SequenceParameterSet(hMP4File, video, pData+4, len-4);                                        
                    }
                    
                    continue;
                }
                
                if(stStream->pstPack[j].DataType.enH264EType == H264E_NALU_PPS){
                    if(ppsflag == 0x00){
                        ppsflag = 0x1;
                        //写pps                                    
                        printf("Write pps -------------------\n");                                        
                        MP4AddH264PictureParameterSet(hMP4File, video, pData+4, len-4);
                    }
                    
                    continue;
                }
    
                isSyncSample = (stStream->pstPack[j].DataType.enH264EType == H264E_NALU_ISLICE)    ?  (1) : (0);
                pData[0] = (len - 4) >> 24;
                pData[1] = (len - 4) >> 16;
                pData[2] = (len - 4) >> 8;
                pData[3] = len - 4;                             
    
                printf("Write date type = %d  isSyncSample = %d\n",stStream->pstPack[j].DataType.enH264EType,isSyncSample);                                
    
                MP4WriteSample(hMP4File, video, pData, len , MP4_INVALID_DURATION, 0, isSyncSample);
    
                
            }                    
        }
    }
    
    if((recording && stStream->u32Seq > 900)){        //控制文件时长
        recording = 0x00;
        printf("Close mp4 file\n");                        
        MP4Close(hMP4File, 0);
        hMP4File = NULL;
        video = 0;
        recordfish = 0x00;
    }

}

8.添加网络telnet调试

8.1、为什么添加telnet调试

(1)linux系统的用户界面就是commandline,本质上由busybox提供

(2)busybox的命令行只有1个,一旦前台被占用就无法做其他操作

(3)解决方案有2个:一个是建立多个commandline,一个是开放其他用户界面。

8.2、telnet调试的原理-可以通过telnet协议远程登录一个运行了telnetd的程序

(1)在开发板中提前运行telnetd(服务器)

(2)远程通过telnet的client连接server,构建一个用户界面

(3)这是非常传统典型的远程登录的方式···其实用过的

8.3、在HI3518E开发板上telnet远程登录调试

busybox本身已支持telnet远程登录

(1)命令行执行telnetd &后台运行,然后Windows打开CRT配置SSH至192.168.1.10开发板网口

(2)输入ssid:root,password:直接回车,进入

(3)问题:若遇到不断挂载和insmod驱动模块,可以将etc/profile 中的加载项移至/etc/init.d中的rcS文件中。这是因为因为开启telnet服务会多次加载profile

(4)可以将telnetd &加入rcS中开机默认加载

9、海思proc文件系统调试接口

9.1、proc文件系统的原理

proc文件系统是linux内核提供的一种调试机制,这种方式已经sys文件系统被替代,但原理是一样的

它是把内核一些关键变量以文件的方式呈现在用户层,我们因此可以知道内核的一些情况

9.2、参考 HiMPP IPC V2.0 媒体处理软件开发参考.pdf和HiISP FAQ V100版本.pdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java进程注入

本文重点java Instrumentation java Instrumentation指的是可以用独立于应用程序之外的代理&#xff08;agent&#xff09;程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态&#xff0c;替换和修改类定义等。简单一句话概括下&#xff1a;…

11 通信的基本概念

目录 通信分类概览 串行通讯与并行通讯 全双工、半双工及单工通讯 同步通讯与异步通讯 通讯速率 注意 通信分类概览 串行通讯与并行通讯 串行通讯是指设备之间通过少量数据信号线(一般是 8 根以下)&#xff0c;地线以及控制信号线&#xff0c;按数据位形式一位一位地传输…

Windows下创建进程的理解

创建windows进程&#xff0c;需要考虑两个点&#xff0c;即session和权限问题。了解这两点&#xff0c;网络上服务创建界面进程&#xff0c;管理员权限进程创建普通权限进程的代码则很好理解。 1、基础知识 (1) session (2) 权限 CreateProcessAsUser需要传入一个token&#x…

LeetCode 打卡day45--完全背包问题之最小填充次数

一个人的朝圣 — LeetCode打卡第45天 知识总结Leetcode 70. 爬楼梯题目说明代码说明 Leetcode 322. 零钱兑换题目说明代码说明 Leetcode 279. 完全平方数题目说明代码说明 知识总结 今天的问题都可以归结一句话, 在完全背包的问题设置下, 问将该背包填满最少需要放几件物品. L…

java基础(并发编程)-异步模式之生产者/消费者

一、定义要点 与前面的保护性暂停中的GuardedObject不同&#xff0c;不需要产生结果和消费结果的线程一一对应消费队列可以用来平衡生产和消费的线程资源生产者仅负责产生结果数据&#xff0c;不关心数据该如何处理&#xff0c;而消费者专心处理结果数据消息队列是有容量限制的…

代码随想录算法训练营第17期第1天 | 704. 二分查找、27. 移除元素

从头开始&#xff0c;重新再来&#xff0c;但是又不完全一样&#xff0c;之前是擅长的python&#xff0c;现在是C&#xff0c;能坚持下来么&#xff1f; 704. 二分查找 704. 二分查找https://leetcode.cn/problems/binary-search/ 上次写这道题已经是两个月之前&#xff0c;说…

Openresty原理概念篇(七)OpenResty 中用到的 NGINX 知识

一 OpenResty 中用到的 NGINX 知识 Luaj 是一个 Java 的 Lua 解释器,基于 Lua 5.2.x 版本 luaj ① 说明 1) 本文可有可无原因&#xff1a;如果你之前没有接触过nginx或者涉及一点nginx,那么建议阅读2) 由于自己已经对nginx整个脉络体系进行讲解,本文只是机械的摘录,构成…

Java使用RabbitMQ实战,Springboot使用rabbitMQ实战

文章目录 一、Java原生API1、简单实例2、延迟消息3、消费端限流4、消息属性设置5、消息可靠投递 二、Spring-API1、简单实例&#xff08;1&#xff09;引入rabbitMQ.xml&#xff08;2&#xff09;生产者&#xff08;3&#xff09;消费者&#xff08;4&#xff09;测试类 三、Sp…

使用VSCODE跑orbslam2踩的坑

我用的是ubuntu22.04&#xff0c;opencv是4.7&#xff0c;使用其他的库感觉就算版本不一样&#xff0c;也能跑。 一、运行build.sh能够产生可执行文件遇到的问题 1.由于opencv版本高带来的问题 这些问题怎么定位出现在哪些文件中&#xff0c;你通过命令行&#xff0c;运行下…

更灵活的CSS3新特性:帮你简化样式管理和优化网站性能

文章目录 I. 前言&#xff1a;介绍CSS3的进化和发展趋势CSS3的历史和版本CSS3的标准化和浏览器支持情况 II. 新的CSS选择器&#xff1a;扩展选择器的功能属性选择器&#xff1a;更多方式选择元素伪类和伪元素&#xff1a;更方便地定义样式 III. 改进的排版和布局&#xff1a;实…

在 EulerOS 系统中设置 Chrony 时间同步服务

以下是在 EulerOS 系统中设置 Chrony 时间同步服务的所有步骤。 1.查看系统版本 [rootservice11 ~]# cat /etc/redhat-release EulerOS release 2.0 (SP5)2.检查是否已安装chrony软件 [rootservice11 ~]# rpm -qa|grep chrony chrony-3.2-2.eulerosv2r7.x86_64如果没有安装…

Openlayers实战教程学习大纲及引导

本系列教程是Openlayers的实战教程&#xff0c;介绍Openlayes的一些基础知识&#xff0c;并重点讲述哪些地方是openlayers项目中常用的&#xff0c;给出具体示例&#xff0c;起到一个很好的引导学习作用。 版本说明 Openlayers的实战教程 分为**图文版** 和 **视频版**&#x…

【经验分享】全志科技官方Ubuntu16.04根文件系统镜像的替换和测试方法

本文主要基于全志A40i开发板——TLA40i-EVM&#xff0c;一款基于全志科技A40i处理器设计的4核ARM Cortex-A7高性能低功耗国产评估板&#xff0c;演示Ubuntu根文件系统镜像的替换和测试方法。 创龙科技TLA40i-EVM评估板接口资源丰富&#xff0c;引出双路网口、双路CAN、双路USB…

7.5_1散列查找(上)

基于一种数据结构&#xff1a; 散列表&#xff08;Hash Table&#xff09;&#xff0c;又称作哈希表 特点&#xff1a;数据元素的关键字与其存储地址直接相关 其实这个散列表也是基于数组实现的 加入19对13取余 加入再次插入1的话&#xff0c;塞不进去 数据元素不会直接存放到…

深入浅出设计模式 - 适配器模式

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

Presto(Trino)分布式(物理)执行计划的生成和调度

文章目录 1.前言2.物理执行生成(Stage)的生成2.1不同的调度分区策略2.1.1 Connector自己提供的分区策略2.1.2 Presto提供的Partition策略(SystemPartitioningHandle)&#xff1a; 2.2 为Stage创建StageScheduler2.2.1 普通的非bucket表的TableScan StageSplit 放置策略解析 2.2…

UE5.1.1 c++从0开始(14.用C++写UMG类)

先在这里放一个链接防止第一次看的朋友们不知道我在讲什么&#xff1a;https://www.bilibili.com/video/BV1nU4y1X7iQ/ 这一段的教程不难&#xff0c;唯一新建的C类是UMG的一个类。这个类用来写绑定在ai身上的血条。 总结一下一共做了什么事情&#xff1a; 给ai写了一个血条…

LeetCode Java两个单链表相交的一系列问题

题目描述 单链表可能有环&#xff0c;也可能无环。给定两个单链表的头节点 head1和head2&#xff0c;这两个链表可能相交&#xff0c;也可能不相交。 请实现一个函数&#xff0c;如果两个链表相交&#xff0c;请返回相交的第一个节点&#xff1b;如果不相交&#xff0c;返回n…

Android 渐变背景色

目录 一、背景 二、渐变 2.1 线性渐变背景色 1.新建资源文件 2.编辑样式文件 3.使用 4.编辑样式参数说明 2.2 圆角按钮渐变背景色 2.3 放射渐变 2.4 扫描线渐变 一、背景 单纯的颜色背景已经不能够满足UI大佬们的发挥&#xff0c;渐变色背景无疑成了一个炫技的方向。现在…

chatgpt赋能python:Python调用同一个类中方法详解

Python调用同一个类中方法详解 在Python编程中&#xff0c;类是一种非常重要的概念&#xff0c;可用于组织和管理代码。在同一个类中&#xff0c;可以定义多个方法。本文将详细介绍如何调用同一个类中的方法。 什么是类方法&#xff1f; 在Python中&#xff0c;类方法是指类…