Android中取得mp4文件播放时长的处理位于MPEG4Extractor::parseChunk函数中,是从mdhd box中取得timescale和duration后,通过公式播放时长 = duration / timescale 计算出播放时长的,单位为秒(s)。

Android与一般从mvhd box中取得mp4播放时长的处理不一样。(参考:计算MP4文件播放时长的方法

mdhd位于"moov/trak/mdia/" box下面,如下图所示,是一个audio track展开后显示的box结构。(mp4 chunk在apple的规范中称作atom,在标准mp4中称为box。)

Android MP4取得播放时长的方法_第1张图片

下面先介绍下mdhd box的相关知识:

1.MediaAtoms-MDIA

Mediaatoms定义了track的媒体类型和sample数据,例如音频或视频,描述sample数据的mediahandler componentmediatimescale and track duration以及media-and-track-specific信息,例如音量和图形模式。它也可以包含一个引用,指明媒体数据存储在另一个文件中。也可以包含一个sampletable atoms,指明sampledescription, duration, and byte offset from the data reference foreach media sample.

Mediaatom的类型是'mdia'。它是一个容器atom,必须包含一个mediaheader atom ('mdhd'),一个handlerreference ('hdlr'),一个媒体信息引用('minf')和用户数据atom('udta').

Android MP4取得播放时长的方法_第2张图片

字段

长度(字节)

描述

尺寸

4

这个atom的字节数

类型

4

Edts

2.MediaHeaderAtoms-MDHD

Mediaheader atom定义了媒体的特性,例如timescaleduration。它的类型是'mdhd'.

Android MP4取得播放时长的方法_第3张图片

各个字段的解释:

字段

长度(字节)

描述

尺寸

4

这个atom的字节数

类型

4

mdhd

版本

1

这个atom的版本

标志

3

这里为0

生成时间

4

Movieatom的起始时间。基准时间是1904-1-10:00 AM

修订时间

4

Movieatom的修订时间。基准时间是1904-1-10:00 AM

Time scale

4

A time valuethat indicates the time scale for this media—that is, the numberof time units that pass per second in its time coordinate system.

Duration

4

The durationof this media in units of its time scale.

语言

2

媒体的语言码

质量

2

媒体的回放质量???怎样生成此质量,什么是参照点

还是以上一篇(计算MP4文件播放时长的方法)中时长为70秒的1Mt.mp4文件为例:

(1)Audiotrack的值

Android MP4取得播放时长的方法_第4张图片

蓝色阴影部分是audio track的mdhd box,长度为十六进制20,即十进制32个字节。

其中红色框内四个字节位于mdhd box的第21-24字节,为timescale的值,十六进制为00 00 1F 40,转换为十进制的8000。

绿色框内内四个字节位于mdhd box的第25-28字节,为duration的值,十六进制为00 08 8C 00,对应十进制的560128。

所以根据公式:播放时长 = duration / timescale = 560128 / 8000 = 70.016秒,即音频时长约为70秒。

(2)Videotrack的值

与audio track的mdhd box类似,可以计算出video track的播放时长。


3.下面是取得时长的代码处理,在MPEG4Extractor::parseChunk函数函数中

        case FOURCC('m', 'd', 'h', 'd'): // mdhd box        {            if (chunk_data_size < 4) {                return ERROR_MALFORMED;            }            uint8_t version;            if (mDataSource->readAt(                        data_offset, &version, sizeof(version))                    < (ssize_t)sizeof(version)) {                return ERROR_IO;            }            off_t timescale_offset;      // 取得timescale相对与mvhd初始位置的偏移量            if (version == 1) {                timescale_offset = data_offset + 4 + 16;            } else if (version == 0) {                timescale_offset = data_offset + 4 + 8;            } else {                return ERROR_IO;            }      // 读取timescale值            uint32_t timescale;            if (mDataSource->readAt(                        timescale_offset, ×cale, sizeof(timescale))                    < (ssize_t)sizeof(timescale)) {                return ERROR_IO;            }            mLastTrack->timescale = ntohl(timescale);      // 读取duration时长值,version版本1的读取方便与其他版本有区别,需要分开读            int64_t duration;            if (version == 1) {                if (mDataSource->readAt(                            timescale_offset + 4, &duration, sizeof(duration))                        < (ssize_t)sizeof(duration)) {                    return ERROR_IO;                }                duration = ntoh64(duration);            } else {                int32_t duration32;                if (mDataSource->readAt(                            timescale_offset + 4, &duration32, sizeof(duration32))                        < (ssize_t)sizeof(duration32)) {                    return ERROR_IO;                }                duration = ntohl(duration32);            }            mLastTrack->meta->setInt64(                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale); // 播放时长 = duraion / timescale            *offset += chunk_size;            break;        }



更多相关文章

  1. Android中执行java命令的方法及java代码执行并解析shell命令
  2. Android 导入项目时报Android.jar包丢失解决方法
  3. 干货 | 聊聊这些年总结的一些学习方法
  4. Android手机访问Django测试服务器方法
  5. android Map 使用方法
  6. Android实现屏幕旋转方法总结
  7. #菜鸟之旅#Android Studio开发JNI工程——Native调用Java方法获
  8. Android 资源文件使用方法详解

随机推荐

  1. SQL Server设置主键自增长列(使用sql语句
  2. 常用SQL语句(嵌套子查询/随机等等)详细整
  3. SQL语句的各个关键字的解析过程详细总结
  4. 存储过程实现(可带查询条件/万能分页/通
  5. 获取数据库中两个时间字段的相差天数及AB
  6. 向数据库中插入数据并返回当前插入的行数
  7. sql函数实现去除字符串中的相同的字符串
  8. SQLSERVER的非聚集索引结构深度理解
  9. SQL Server简单模式下误删除堆表记录恢复
  10. SQLSERVER对索引的利用及非SARG运算符认