软编码Flv 到Mp4 容器(八) fmp4 mdia>stbl>stsd box 讲解
来源:互联网 发布:windows.hlp官方下载 编辑:程序博客网 时间:2024/06/16 18:31
https://github.com/332065255/flv2fmp4
代码库
软编码Flv 到Mp4 容器(一)
软编码Flv 到Mp4 容器(二) flv tag拆解
软编码Flv 到Mp4 容器(三) flv metadata tag解析
软编码Flv 到Mp4 容器(四) fmp4 总览和基础讲解
软编码Flv 到Mp4 容器(五) fmp4 ftyp box 和moov>mvhd box详解
软编码Flv 到Mp4 容器(六) fmp4 moov>trak>tkhd box 和 moov>trak>mdia>mdhd box讲解
软编码Flv 到Mp4 容器(七) fmp4 mdia>hdlr box 和 mdia>minf> smhd 和dinf box讲解
软编码Flv 到Mp4 容器(八) fmp4 mdia>stbl>stsd box 讲解
软编码Flv 到Mp4 容器(九) fmp4 stts stsc stsz stco box 讲解
软编码Flv 到Mp4 容器(十) fmp4 mvex box 讲解
软编码Flv 到Mp4 容器(十一) fmp4 moof box详解
软编码Flv 到Mp4 容器(十二) fmp4 mdat box详解
软编码Flv 到Mp4 容器(十三) fmp4 生成ftyp和moov所必要的 flv数据
- ftyp - moov - mvhd - trak - tkhd - mdia - mdhd - hdlr - minf - smhd - dinf - dref - url - stbl - stsd - mp4a(avc1) - esds(avcC) - stts - stsc - stsz - stco - mvex -trex - moof - mfhd - traf -tfhd -tfdt -sdtp -trun - mdat
首先对应标题的box在 fmp4容器中的位置
这一章非常复杂,代码量很大
stbl box
Box Type: ‘stbl’
Container: Media Information Box (‘minf’)
Mandatory: Yes
Quantity: Exactly one
定义
aligned(8) class SampleTableBox extends Box(‘stbl’) { }
stbl是一个容器box
stsd box
BoxTypes: ‘stsd’
Container: Sample Table Box (‘stbl’)
Mandatory: Yes
Quantity: Exactly one
定义
aligned(8) abstract class SampleEntry (unsigned int(32) format) extends Box(format){ const unsigned int(8)[6] reserved = 0; unsigned int(16) data_reference_index;}class HintSampleEntry() extends SampleEntry (protocol) { unsigned int(8) data [];} // Visual Sequencesclass VisualSampleEntry(codingname) extends SampleEntry (codingname){ unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0;unsigned int(32)[3] pre_defined = 0;unsigned int(16) width;unsigned int(16) height;template unsigned int(32) horizresolution = 0x00480000; // 72 dpi template unsigned int(32) vertresolution = 0x00480000; // 72 dpiconst unsigned int(32) reserved = 0;template unsigned int(16) frame_count = 1;string[32] compressorname;template unsigned int(16) depth = 0x0018;int(16) pre_defined = -1;} // Audio Sequencesclass AudioSampleEntry(codingname) extends SampleEntry (codingname){ const unsigned int(32)[2] reserved = 0;template unsigned int(16) channelcount = 2;template unsigned int(16) samplesize = 16;unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0 ;template unsigned int(32) samplerate = {timescale of media}<<16;}aligned(8) class SampleDescriptionBox (unsigned int(32) handler_type) extends FullBox('stsd', 0, 0){int i ;unsigned int(32) entry_count;for (i = 1 ; i u entry_count ; i++){ switch (handler_type){ //对应 hdlr box 中的handler_type case ‘soun’: // for audio tracks AudioSampleEntry(); break; case ‘vide’: // for video tracks VisualSampleEntry(); break; case ‘hint’: // Hint track HintSampleEntry();break; }} }
stsd下的box分3种情况,soun box or vide box,另一个忽略不计
首先实现stsd box开头的Sample Entry
var STSD_PREFIX = new Uint8Array([ 0x00, 0x00, 0x00, 0x00, // version(0) + flags version字段后会有一个entry count字段 0x00, 0x00, 0x00, 0x01 // entry_count 根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio track会有“AudioSampleEntry”类型信息。 ]);
选择实现vide box
先看vide box的定义
class VisualSampleEntry(codingname) extends SampleEntry (codingname){ unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0;unsigned int(32)[3] pre_defined = 0;unsigned int(16) width;unsigned int(16) height;template unsigned int(32) horizresolution = 0x00480000; // 72 dpi template unsigned int(32) vertresolution = 0x00480000; // 72 dpiconst unsigned int(32) reserved = 0;template unsigned int(16) frame_count = 1;string[32] compressorname;template unsigned int(16) depth = 0x0018;int(16) pre_defined = -1;}
let avc1 = new Uint8Array([ 0x00, 0x00, 0x00, 0x00, // // reserved(4) 6个 保留位 Reserved:6个字节,设置为0; 0x00, 0x00, 0x00, 0x01, // reserved(2) + {{{{data_reference_index(2) 数据引用索引}}}} 0x00, 0x00, 0x00, 0x00, // pre_defined(2) + reserved(2) 0x00, 0x00, 0x00, 0x00, // pre_defined: 3 * 4 bytes 3*4个字节的保留位 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (width >>> 8) & 0xFF, // width: 2 bytes (width) & 0xFF, (height >>> 8) & 0xFF, // height: 2 bytes (height) & 0xFF, 0x00, 0x48, 0x00, 0x00, // horizresolution: 4 bytes 常数 0x00, 0x48, 0x00, 0x00, // vertresolution: 4 bytes 常数 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes 保留位 0x00, 0x01, // frame_count //frame_count表明多少帧压缩视频存储在每个样本。默认是1,每样一帧;它可能超过1每个样本的多个帧数 0x04, // strlen compressorname: 32 bytes String[32] //32个8 bit 第一个8bit表示长度,剩下31个8bit表示内容 0x67, 0x31, 0x31, 0x31, // compressorname: 32 bytes 翻译过来是g111 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, // depth 颜色深度 0xFF, 0xFF // pre_defined = -1 ]);let avcc = 暂无
avcc box
软编码Flv 到Mp4 容器(外传一)avcc box
选择实现soun box
// Audio Sequencesclass AudioSampleEntry(codingname) extends SampleEntry (codingname){ const unsigned int(32)[2] reserved = 0;template unsigned int(16) channelcount = 2;template unsigned int(16) samplesize = 16;unsigned int(16) pre_defined = 0;const unsigned int(16) reserved = 0 ;template unsigned int(32) samplerate = {timescale of media}<<16;}
static mp4a(meta) { let channelCount = meta.channelCount; let sampleRate = meta.audioSampleRate; let data = new Uint8Array([ 0x00, 0x00, 0x00, 0x00, // reserved(4) 6个字节,设置为0; 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2) 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes 保留位 0x00, 0x00, 0x00, 0x00, 0x00, channelCount, // channelCount(2) 单声道还是双声道 0x00, 0x10, // sampleSize(2) 0x00, 0x00, 0x00, 0x00, // reserved(4) 4字节保留位 (sampleRate >>> 8) & 0xFF, // Audio sample rate 显然要右移16位才有意义 template unsigned int(32) samplerate = {timescale of media}<<16; (sampleRate) & 0xFF, 0x00, 0x00 ]); return MP4.box(MP4.types.mp4a, data, MP4.esds(meta)); } static esds(meta) { let config = meta.config; let configSize = config.length; let data = new Uint8Array([ 0x00, 0x00, 0x00, 0x00, // version 0 + flags 0x03, // descriptor_type MP4ESDescrTag 0x17 + configSize, // length3 0x00, 0x01, // es_id 0x00, // stream_priority 0x04, // descriptor_type MP4DecConfigDescrTag 0x0F + configSize, // length 0x40, // codec: mpeg4_audio /** *当objectTypeIndication为0x40时,为MPEG-4 Audio(MPEG-4 Audio generally is thought of as AAC * but there is a whole framework of audio codecs that can Go in MPEG-4 Audio including AAC, BSAC, ALS, CELP, * and something called MP3On4),如果想更细分format为aac还是mp3, * 可以读取MP4DecSpecificDescr层data[0]的前五位 */ 0x15, // stream_type: Audio 0x00, 0x00, 0x00, // buffer_size 0x00, 0x00, 0x00, 0x00, // maxBitrate 0x00, 0x00, 0x00, 0x00, // avgBitrate 0x05 // descriptor_type MP4DecSpecificDescrTag ].concat([ configSize ]).concat( config ).concat([ 0x06, 0x01, 0x02 // GASpecificConfig ])); return MP4.box(MP4.types.esds, data); }
stsd介绍完毕
- 软编码Flv 到Mp4 容器(八) fmp4 mdia>stbl>stsd box 讲解
- 软编码Flv 到Mp4 容器(七) fmp4 mdia>hdlr box 和 mdia>minf> smhd 和dinf box讲解
- 软编码Flv 到Mp4 容器(六) fmp4 moov>trak>tkhd box 和 moov>trak>mdia>mdhd box讲解
- 软编码Flv 到Mp4 容器(九) fmp4 stts stsc stsz stco box 讲解
- 软编码Flv 到Mp4 容器(十) fmp4 mvex box 讲解
- 软编码Flv 到Mp4 容器(五) fmp4 ftyp box 和moov>mvhd box详解
- 软编码Flv 到Mp4 容器(十一) fmp4 moof box详解
- 软编码Flv 到Mp4 容器(十二) fmp4 mdat box详解
- 软编码Flv 到Mp4 容器(四) fmp4 总览和基础讲解
- 软编码Flv 到Mp4 容器(外传一)avcc box
- 软编码Flv 到Mp4 容器(十三) fmp4 生成ftyp和moov所必要的 flv数据
- 软编码Flv 到Mp4 容器(一)
- MP4容器系列文章之STSD BOX
- 软编码Flv 到Mp4 容器(二) flv tag拆解
- 【Mp4】Stbl box
- 软编码Flv 到Mp4 容器(三) flv metadata tag解析
- MP4学习(九)ts-mp4源码阅读(7)mdia box的解析
- mp4: stsd/mp4a/esds stsd/avc1/avcc
- 51 Nod1385凑数字
- iOS 获取Frame值异常
- linux学习之apache
- JAVA高级工程师课程笔记整理——(三)面向对象
- 使用Spring实现读写分离(MySQL实现主从复制)
- 软编码Flv 到Mp4 容器(八) fmp4 mdia>stbl>stsd box 讲解
- 动态部署动态加载--阿里atlas
- Matlab2016a破解版安装教程
- Android src和background的区别
- amchart 使用方法简介及简单中文API
- linux 安装jdk1.8操作
- STM32F303开发】+虚拟串口驱动安装失败的解决方法
- CON_PRINTBUFFER的作用
- 【游戏渲染】unity海边波浪效果的实现