前面介绍过的几种格式flv、mkv、asf等。他们音视频的数据包一般都是按照文件的顺序交叉安放。你解析完头部信息后。剩下的一般就按照文件顺序一个数据包一个数据包的解析就行了。但是MP4完全不是这种概念。他的媒体信息和数据是分开存放的。就是你想获得数据之前必须要解析出每个帧数据所有的位置。mp4存放这个帧信息的是放在stbl这个box里。而真实的数据放在mdat中。接下来就讲讲stbl与mdat的对应关系。

Sample Table Box(stbl)

来一张典型的stbl结构图:
常见子box

stts:    Decoding Time to Sample Box 时间戳和Sample映射表
stsd:   Sample Description Box
stsz, stz2: Sample Size Boxes 每个Sample大小的表。
stsc: Sample to chunk 的映射表。
‘stco’, ‘co64’: Chunk位置偏移表
stss:关键帧index。

1.解析stsd可获得coding类型视频宽高、音频samplesize、channelcount这些和解码器有关信息。

  1. aligned(8) class SampleDescriptionBox (unsigned int(32) handler_type)
  2. extends FullBox('stsd', 0, 0){
  3. int i ;
  4. unsigned int(32) entry_count;
  5. for (i = 1 ; i u entry_count ; i++){
  6. switch (handler_type){
  7. case ‘soun’: // for audio tracks
  8. AudioSampleEntry();
  9. break;
  10. case ‘vide’: // for video tracks
  11. VisualSampleEntry();
  12. break;
  13. case ‘hint’: // Hint track
  14. HintSampleEntry();
  15. break;
  16. }
  17. }
  18. }
  1. aligned(8) abstract class SampleEntry (unsigned int(32) format)
  2. extends Box(format){
  3. const unsigned int(8)[6] reserved = 0;
  4. unsigned int(16) data_reference_index;
  5. }
  6. class HintSampleEntry() extends SampleEntry (protocol) {
  7. unsigned int(8) data [];
  8. }
  9. // Visual Sequences
  10. class VisualSampleEntry(codingname) extends SampleEntry (codingname){
  11. unsigned int(16) pre_defined = 0;
  12. const unsigned int(16) reserved = 0;
  13. unsigned int(32)[3] pre_defined = 0;
  14. unsigned int(16) width;
  15. unsigned int(16) height;
  16. template unsigned int(32) horizresolution = 0x00480000; // 72 dpi
  17. template unsigned int(32) vertresolution = 0x00480000; // 72 dpi
  18. const unsigned int(32) reserved = 0;
  19. template unsigned int(16) frame_count = 1;
  20. string[32] compressorname;
  21. template unsigned int(16) depth = 0x0018;
  22. int(16) pre_defined = -1;
  23. }
  24. // Audio Sequences
  25. class AudioSampleEntry(codingname) extends SampleEntry (codingname){
  26. const unsigned int(32)[2] reserved = 0;
  27. template unsigned int(16) channelcount = 2;
  28. template unsigned int(16) samplesize = 16;
  29. unsigned int(16) pre_defined = 0;
  30. const unsigned int(16) reserved = 0 ;
  31. template unsigned int(32) samplerate = {timescale of media}<<16;
  32. }

2.解析stsz box 可以获得一个sample size的表

  1. aligned(8) class SampleSizeBox extends FullBox(‘stsz’, version = 0, 0) {
  2. unsigned int(32) sample_size;
  3. unsigned int(32) sample_count;
  4. if (sample_size==0) {
  5. for (i=1; i u sample_count; i++) {
  6. unsigned int(32) entry_size;
  7. }
  8. }
  9. }

3.解析stts

  1. aligned(8) class TimeToSampleBox
  2. extends FullBox(’stts’, version = 0, 0) {
  3. unsigned int(32) entry_count;
  4. int i;
  5. for (i=0; i < entry_count; i++) {
  6. unsigned int(32) sample_count;
  7. unsigned int(32) sample_delta;
  8. }
  9. }

4.解析stsc 还原Sample 与chunk的映射表

Sample 是存储的最基本单元,mp4把Sample 存在chunk中。chunk的长度、chunk的大小、chunk中Sample的数量及大小都是不定的。

通过解析这部分box来还原这个映射表。

  1. aligned(8) class SampleToChunkBox
  2. extends FullBox(‘stsc’, version = 0, 0) {
  3. unsigned int(32) entry_count;
  4. for (i=1; i u entry_count; i++) {
  5. unsigned int(32) first_chunk;
  6. unsigned int(32) samples_per_chunk;
  7. unsigned int(32) sample_description_index;
  8. }
  9. }

每个entry 表示着一组数据,entry_count 表示这数量。这一组其实是相同类型的chunk。

first_chunk 表示 这一组相同类型的chunk中 的第一个chunk数。

这些chunk 中包含的Sample 数量,即samples_per_chunk 是一致的。

每个Sample 可以通过sample_description_index 去stsd box 找到描述信息。

看ffmpeg中mov_read_stsc() 它把这些数据放在一个结构体数组中备用。

  1. static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
  2. {
  3. AVStream *st;
  4. MOVStreamContext *sc;
  5. unsigned int i, entries;
  6. if (c->fc->nb_streams < 1)
  7. return 0;
  8. st = c->fc->streams[c->fc->nb_streams-1];
  9. sc = st->priv_data;
  10. avio_r8(pb); /* version */
  11. avio_rb24(pb); /* flags */
  12. entries = avio_rb32(pb);
  13. av_dlog(c->fc, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
  14. if (!entries)
  15. return 0;
  16. if (entries >= UINT_MAX / sizeof(*sc->stsc_data))
  17. return AVERROR_INVALIDDATA;
  18. sc->stsc_data = av_malloc(entries * sizeof(*sc->stsc_data));
  19. if (!sc->stsc_data)
  20. return AVERROR(ENOMEM);
  21. for (i = 0; i < entries && !pb->eof_reached; i++) {
  22. sc->stsc_data[i].first = avio_rb32(pb);
  23. sc->stsc_data[i].count = avio_rb32(pb);
  24. sc->stsc_data[i].id = avio_rb32(pb);
  25. }
  26. sc->stsc_count = i;
  27. if (pb->eof_reached)
  28. return AVERROR_EOF;
  29. return 0;
  30. }

在获得完整的映射表,我们还需要chunk总个数信息。这些信息放在‘stco’, ‘co64’中。

5.解析‘stco’, ‘co64’

“stco”定义了每个thunk在媒体流中的位置。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。

32位

  1. aligned(8) class ChunkOffsetBox
  2. extends FullBox(‘stco’, version = 0, 0) {
  3. unsigned int(32) entry_count;
  4. for (i=1; i u entry_count; i++) {
  5. unsigned int(32) chunk_offset;
  6. }
  7. }

64位

  1. aligned(8) class ChunkLargeOffsetBox
  2. extends FullBox(‘co64’, version = 0, 0) {
  3. unsigned int(32) entry_count;
  4. for (i=1; i u entry_count; i++) {
  5. unsigned int(64) chunk_offset;
  6. }
  7. }

从这个box我们就可以获得 chunk 的总数量,entry_count

from:http://blog.csdn.net/tx3344/article/details/8506131

1.解析‘stco’, ‘co64’我们有了chunk 表,知道了chunk 的总数及每个chunk所在文件的位置。

2.解析stsc 配合着上面的chunk表,我们就能弄个Sample与chunk的关系表。我们也就能获得每个Sample的位置信息。

3.配合上面的stts 时间表和解码器信息等。搞出ES流已经不成问题了。

4.想获得关键帧的index,需要解析stss’

    1. aligned(8) class SyncSampleBox
    2. extends FullBox(‘stss’, version = 0, 0) {
    3. unsigned int(32) entry_count;
    4. int i;
    5. for (i=0; i < entry_count; i++) {
    6. unsigned int(32) sample_number;
    7. }
    8. }

【多媒体封装格式详解】---MP4【4】的更多相关文章

  1. 多媒体封装格式详解---MP4

    MP4文件格式详解——结构概述 http://blog.csdn.net/pirateleo/article/details/7061452 一.基本概念 1. 文件,由许多Box和FullBox组成 ...

  2. 【多媒体封装格式详解】--- AAC ADTS格式分析

    ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式. 记得第一次做demux的时候,把AAC音频的ES流从FLV封装格式中抽出来送给硬件解码器时 ...

  3. (转)【多媒体封装格式详解】--- AAC ADTS格式分析

     出自:http://blog.csdn.net/tx3344/article/details/7414543 http://www.it6655.com/2012/08/aac-adts-html ...

  4. 【多媒体封装格式详解】---MKV

    http://blog.csdn.net/tx3344/article/details/8162656# http://blog.csdn.net/tx3344/article/details/817 ...

  5. FLV视频封装格式详解

    FLV视频封装格式详解 分类: FFMpeg编解码 2012-04-04 21:13 1378人阅读 评论(2) 收藏 举报 flvheaderaudiovideocodecfile 目录(?)[-] ...

  6. H.264标准(一)mp4封装格式详解

    在网络层,互联网提供所有应用程序都要使用的两种类型的服务,尽管目前理解这些服务的细节并不重要,但在所有TCP/IP概述中,都不能忽略他们: 无连接分组交付服务(Connectionless Packe ...

  7. 【转】FLV视频封装格式详解

    Overview Flash Video(简称FLV),是一种流行的网络格式.目前国内外大部分视频分享网站都是采用的这种格式. File Structure 从整个文件上开看,FLV是由The FLV ...

  8. 以太网帧格式、IP数据报格式、TCP段格式+UDP段格式 详解

    转载:http://www.cnblogs.com/lifan3a/articles/6649970.html 以太网帧格式.IP数据报格式.TCP段格式+UDP段格式 详解   1.ISO开放系统有 ...

  9. java分享第十五天(log4j 格式详解)

    log4j 格式详解  log4j.rootLogger=日志级别,appender1, appender2, -. 日志级别:ALL<DEBUG<INFO<WARN<ERRO ...

随机推荐

  1. NYOJ-36 最长公共子序列 AC 分类: NYOJ 2014-01-03 20:54 155人阅读 评论(0) 收藏

    #include<stdio.h> #include<string.h> #define N 1010 #define max(x,y) x>y?x:y int dp() ...

  2. C编程实现2的1000次方(使程序中的n=1000即可)

    #include<stdio.h> #include<malloc.h> void double_(int n) { ,j,s,jw=; p=(int *)malloc(siz ...

  3. cf 359A 359B

    359A 如果有点在边上则最少两次 没有则最少操作4次 #include <cstdio> #include <cstring> #include <algorithm& ...

  4. Mac和iOS开发资源汇总

    小引 本文主要汇集一些苹果开发的资源,会经常更新,建议大家把这篇文章单独收藏(在浏览器中按command+D). 今天(2013年7月19日)收录了许多中文网站和博客.大家一定要去感受一下哦. 如果大 ...

  5. 《架构探险——从零开始写Java Web框架》这书不错,能看懂的入门书

    这书适合我. 哈哈,结合 以前的知识点,勉强能看懂. 讲得细,还可以参照着弄出来. 希望能坚持 完成啦... 原来,JSTL就类似于DJANGO中的模板. 而servlet类中的res,req,玩了D ...

  6. hdu 1755 A Number Puzzle

    这题枚举k节省时间 ;}

  7. XCODE 出现 The operation couldn't be completed.(LaunchServicesError error 0.)错误修复

    XCODE 出现 The operation couldn't be completed.(LaunchServicesError error 0.)错误修复   XCODE 出现 The opera ...

  8. 测试Tomcat

  9. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...

  10. *EditPlus注册码在线生成

    http://www.jb51.net/tools/editplus/