1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00

for #738, parse mp4 moov boxes.

This commit is contained in:
winlin 2017-02-02 22:02:39 +08:00
parent 96f2e18d3a
commit ffe0a4426d
3 changed files with 368 additions and 187 deletions

View file

@ -249,6 +249,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_MP4_BOX_STRING 3073
#define ERROR_MP4_BOX_ILLEGAL_BRAND 3074
#define ERROR_MP4_NOT_NON_SEEKABLE 3075
#define ERROR_MP4_ESDS_SL_Config 3076
///////////////////////////////////////////////////////
// HTTP/StreamCaster/KAFKA protocol error.

View file

@ -33,50 +33,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <string.h>
using namespace std;
#define SRS_MP4_BOX_UUID 0x75756964 // 'uuid'
#define SRS_MP4_BOX_FTYP 0x66747970 // 'ftyp'
#define SRS_MP4_BOX_MDAT 0x6d646174 // 'mdat'
#define SRS_MP4_BOX_FREE 0x66726565 // 'free'
#define SRS_MP4_BOX_SKIP 0x736b6970 // 'skip'
#define SRS_MP4_BOX_MOOV 0x6d6f6f76 // 'moov'
#define SRS_MP4_BOX_MVHD 0x6d766864 // 'mvhd'
#define SRS_MP4_BOX_TRAK 0x7472616b // 'trak'
#define SRS_MP4_BOX_TKHD 0x746b6864 // 'tkhd'
#define SRS_MP4_BOX_EDTS 0x65647473 // 'edts'
#define SRS_MP4_BOX_ELST 0x656c7374 // 'elst'
#define SRS_MP4_BOX_MDIA 0x6d646961 // 'mdia'
#define SRS_MP4_BOX_MDHD 0x6d646864 // 'mdhd'
#define SRS_MP4_BOX_HDLR 0x68646c72 // 'hdlr'
#define SRS_MP4_BOX_MINF 0x6d696e66 // 'minf'
#define SRS_MP4_BOX_VMHD 0x766d6864 // 'vmhd'
#define SRS_MP4_BOX_SMHD 0x736d6864 // 'smhd'
#define SRS_MP4_BOX_DINF 0x64696e66 // 'dinf'
#define SRS_MP4_BOX_URL 0x75726c20 // 'url '
#define SRS_MP4_BOX_URN 0x75726e20 // 'urn '
#define SRS_MP4_BOX_DREF 0x64726566 // 'dref'
#define SRS_MP4_BOX_STBL 0x7374626c // 'stbl'
#define SRS_MP4_BOX_STSD 0x73747364 // 'stsd'
#define SRS_MP4_BOX_STTS 0x73747473 // 'stts'
#define SRS_MP4_BOX_CTTS 0x63747473 // 'ctts'
#define SRS_MP4_BOX_STSS 0x73747373 // 'stss'
#define SRS_MP4_BOX_STSC 0x73747363 // 'stsc'
#define SRS_MP4_BOX_STCO 0x7374636f // 'stco'
#define SRS_MP4_BOX_CO64 0x636f3634 // 'co64'
#define SRS_MP4_BOX_STSZ 0x7374737a // 'stsz'
#define SRS_MP4_BOX_STZ2 0x73747a32 // 'stz2'
#define SRS_MP4_BOX_AVC1 0x61766331 // 'avc1'
#define SRS_MP4_BOX_AVCC 0x61766343 // 'avcC'
#define SRS_MP4_BOX_MP4A 0x6d703461 // 'mp4a'
#define SRS_MP4_BOX_ESDS 0x65736473 // 'esds'
#define SRS_MP4_BRAND_ISOM 0x69736f6d // 'isom'
#define SRS_MP4_BRAND_ISO2 0x69736f32 // 'iso2'
#define SRS_MP4_BRAND_AVC1 0x61766331 // 'avc1'
#define SRS_MP4_BRAND_MP41 0x6d703431 // 'mp41'
#define SRS_MP4_HANDLER_VIDE 0x76696465 // 'vide'
#define SRS_MP4_HANDLER_SOUN 0x736f756e // 'soun'
#define SRS_MP4_EOF_SIZE 0
#define SRS_MP4_USE_LARGE_SIZE 1
@ -125,7 +81,7 @@ SrsMp4Box::SrsMp4Box()
largesize = 0;
usertype = NULL;
start_pos = 0;
type = 0;
type = SrsMp4BoxTypeForbidden;
}
SrsMp4Box::~SrsMp4Box()
@ -152,17 +108,17 @@ int SrsMp4Box::left_space(SrsBuffer* buf)
bool SrsMp4Box::is_ftyp()
{
return type == SRS_MP4_BOX_FTYP;
return type == SrsMp4BoxTypeFTYP;
}
bool SrsMp4Box::is_moov()
{
return type == SRS_MP4_BOX_MOOV;
return type == SrsMp4BoxTypeMOOV;
}
bool SrsMp4Box::is_mdat()
{
return type == SRS_MP4_BOX_MDAT;
return type == SrsMp4BoxTypeMDAT;
}
int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
@ -180,7 +136,7 @@ int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
// Discovery the size and type.
uint64_t largesize = 0;
uint32_t smallsize = (uint32_t)buf->read_4bytes();
uint32_t type = (uint32_t)buf->read_4bytes();
SrsMp4BoxType type = (SrsMp4BoxType)buf->read_4bytes();
if (smallsize == SRS_MP4_USE_LARGE_SIZE) {
if (!buf->require(8)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
@ -201,38 +157,38 @@ int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
SrsMp4Box* box = NULL;
switch(type) {
case SRS_MP4_BOX_FTYP: box = new SrsMp4FileTypeBox(); break;
case SRS_MP4_BOX_MDAT: box = new SrsMp4MediaDataBox(); break;
case SRS_MP4_BOX_FREE: case SRS_MP4_BOX_SKIP: box = new SrsMp4FreeSpaceBox(); break;
case SRS_MP4_BOX_MOOV: box = new SrsMp4MovieBox(); break;
case SRS_MP4_BOX_MVHD: box = new SrsMp4MovieHeaderBox(); break;
case SRS_MP4_BOX_TRAK: box = new SrsMp4TrackBox(); break;
case SRS_MP4_BOX_TKHD: box = new SrsMp4TrackHeaderBox(); break;
case SRS_MP4_BOX_EDTS: box = new SrsMp4EditBox(); break;
case SRS_MP4_BOX_ELST: box = new SrsMp4EditListBox(); break;
case SRS_MP4_BOX_MDIA: box = new SrsMp4MediaBox(); break;
case SRS_MP4_BOX_MDHD: box = new SrsMp4MediaHeaderBox(); break;
case SRS_MP4_BOX_HDLR: box = new SrsMp4HandlerReferenceBox(); break;
case SRS_MP4_BOX_MINF: box = new SrsMp4MediaInformationBox(); break;
case SRS_MP4_BOX_VMHD: box = new SrsMp4VideoMeidaHeaderBox(); break;
case SRS_MP4_BOX_SMHD: box = new SrsMp4SoundMeidaHeaderBox(); break;
case SRS_MP4_BOX_DINF: box = new SrsMp4DataInformationBox(); break;
case SRS_MP4_BOX_URL: box = new SrsMp4DataEntryUrlBox(); break;
case SRS_MP4_BOX_URN: box = new SrsMp4DataEntryUrnBox(); break;
case SRS_MP4_BOX_DREF: box = new SrsMp4DataReferenceBox(); break;
case SRS_MP4_BOX_STBL: box = new SrsMp4SampleTableBox(); break;
case SRS_MP4_BOX_STSD: box = new SrsMp4SampleDescriptionBox(); break;
case SRS_MP4_BOX_STTS: box = new SrsMp4DecodingTime2SampleBox(); break;
case SRS_MP4_BOX_CTTS: box = new SrsMp4CompositionTime2SampleBox(); break;
case SRS_MP4_BOX_STSS: box = new SrsMp4SyncSampleBox(); break;
case SRS_MP4_BOX_STSC: box = new SrsMp4Sample2ChunkBox(); break;
case SRS_MP4_BOX_STCO: box = new SrsMp4ChunkOffsetBox(); break;
case SRS_MP4_BOX_CO64: box = new SrsMp4ChunkLargeOffsetBox(); break;
case SRS_MP4_BOX_STSZ: box = new SrsMp4SampleSizeBox(); break;
case SRS_MP4_BOX_AVC1: box = new SrsMp4VisualSampleEntry(); break;
case SRS_MP4_BOX_AVCC: box = new SrsMp4AvccBox(); break;
case SRS_MP4_BOX_MP4A: box = new SrsMp4AudioSampleEntry(); break;
case SRS_MP4_BOX_ESDS: box = new SrsMp4EsdsBox(); break;
case SrsMp4BoxTypeFTYP: box = new SrsMp4FileTypeBox(); break;
case SrsMp4BoxTypeMDAT: box = new SrsMp4MediaDataBox(); break;
case SrsMp4BoxTypeFREE: case SrsMp4BoxTypeSKIP: box = new SrsMp4FreeSpaceBox(); break;
case SrsMp4BoxTypeMOOV: box = new SrsMp4MovieBox(); break;
case SrsMp4BoxTypeMVHD: box = new SrsMp4MovieHeaderBox(); break;
case SrsMp4BoxTypeTRAK: box = new SrsMp4TrackBox(); break;
case SrsMp4BoxTypeTKHD: box = new SrsMp4TrackHeaderBox(); break;
case SrsMp4BoxTypeEDTS: box = new SrsMp4EditBox(); break;
case SrsMp4BoxTypeELST: box = new SrsMp4EditListBox(); break;
case SrsMp4BoxTypeMDIA: box = new SrsMp4MediaBox(); break;
case SrsMp4BoxTypeMDHD: box = new SrsMp4MediaHeaderBox(); break;
case SrsMp4BoxTypeHDLR: box = new SrsMp4HandlerReferenceBox(); break;
case SrsMp4BoxTypeMINF: box = new SrsMp4MediaInformationBox(); break;
case SrsMp4BoxTypeVMHD: box = new SrsMp4VideoMeidaHeaderBox(); break;
case SrsMp4BoxTypeSMHD: box = new SrsMp4SoundMeidaHeaderBox(); break;
case SrsMp4BoxTypeDINF: box = new SrsMp4DataInformationBox(); break;
case SrsMp4BoxTypeURL: box = new SrsMp4DataEntryUrlBox(); break;
case SrsMp4BoxTypeURN: box = new SrsMp4DataEntryUrnBox(); break;
case SrsMp4BoxTypeDREF: box = new SrsMp4DataReferenceBox(); break;
case SrsMp4BoxTypeSTBL: box = new SrsMp4SampleTableBox(); break;
case SrsMp4BoxTypeSTSD: box = new SrsMp4SampleDescriptionBox(); break;
case SrsMp4BoxTypeSTTS: box = new SrsMp4DecodingTime2SampleBox(); break;
case SrsMp4BoxTypeCTTS: box = new SrsMp4CompositionTime2SampleBox(); break;
case SrsMp4BoxTypeSTSS: box = new SrsMp4SyncSampleBox(); break;
case SrsMp4BoxTypeSTSC: box = new SrsMp4Sample2ChunkBox(); break;
case SrsMp4BoxTypeSTCO: box = new SrsMp4ChunkOffsetBox(); break;
case SrsMp4BoxTypeCO64: box = new SrsMp4ChunkLargeOffsetBox(); break;
case SrsMp4BoxTypeSTSZ: box = new SrsMp4SampleSizeBox(); break;
case SrsMp4BoxTypeAVC1: box = new SrsMp4VisualSampleEntry(); break;
case SrsMp4BoxTypeAVCC: box = new SrsMp4AvccBox(); break;
case SrsMp4BoxTypeMP4A: box = new SrsMp4AudioSampleEntry(); break;
case SrsMp4BoxTypeESDS: box = new SrsMp4EsdsBox(); break;
default:
ret = ERROR_MP4_BOX_ILLEGAL_TYPE;
srs_error("MP4 illegal box type=%d. ret=%d", type, ret);
@ -347,7 +303,7 @@ int SrsMp4Box::nb_header()
size += 8;
}
if (type == SRS_MP4_BOX_UUID) {
if (type == SrsMp4BoxTypeUUID) {
size += 16;
}
@ -378,7 +334,7 @@ int SrsMp4Box::encode_header(SrsBuffer* buf)
}
buf->write_4bytes(type);
if (type == SRS_MP4_BOX_UUID) {
if (type == SrsMp4BoxTypeUUID) {
buf->write_bytes((char*)usertype, 16);
}
@ -395,7 +351,7 @@ int SrsMp4Box::decode_header(SrsBuffer* buf)
return ret;
}
smallsize = (uint32_t)buf->read_4bytes();
type = (uint32_t)buf->read_4bytes();
type = (SrsMp4BoxType)buf->read_4bytes();
if (smallsize == SRS_MP4_EOF_SIZE) {
srs_warn("MP4 box EOF.");
@ -418,7 +374,7 @@ int SrsMp4Box::decode_header(SrsBuffer* buf)
return ret;
}
if (type == SRS_MP4_BOX_UUID) {
if (type == SrsMp4BoxTypeUUID) {
if (!buf->require(16)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 box requires 16 bytes space. ret=%d", ret);
@ -500,10 +456,11 @@ int SrsMp4FullBox::decode_header(SrsBuffer* buf)
SrsMp4FileTypeBox::SrsMp4FileTypeBox()
{
type = SRS_MP4_BOX_FTYP;
type = SrsMp4BoxTypeFTYP;
nb_compatible_brands = 0;
compatible_brands = NULL;
major_brand = minor_version = 0;
major_brand = SrsMp4BoxBrandForbidden;
minor_version = 0;
}
SrsMp4FileTypeBox::~SrsMp4FileTypeBox()
@ -528,8 +485,7 @@ int SrsMp4FileTypeBox::encode_header(SrsBuffer* buf)
buf->write_4bytes(minor_version);
for (int i = 0; i < nb_compatible_brands; i++) {
uint32_t& cb = compatible_brands[i];
buf->write_4bytes(cb);
buf->write_4bytes(compatible_brands[i]);
}
return ret;
@ -543,7 +499,7 @@ int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf)
return ret;
}
major_brand = buf->read_4bytes();
major_brand = (SrsMp4BoxBrand)buf->read_4bytes();
minor_version = buf->read_4bytes();
// Compatible brands to the end of the box.
@ -551,12 +507,11 @@ int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf)
if (left > 0) {
nb_compatible_brands = left / 4;
compatible_brands = new uint32_t[nb_compatible_brands];
compatible_brands = new SrsMp4BoxBrand[nb_compatible_brands];
}
for (int i = 0; left > 0; i++, left -= 4){
uint32_t cb = buf->read_4bytes();
compatible_brands[i] = cb;
compatible_brands[i] = (SrsMp4BoxBrand)buf->read_4bytes();
}
return ret;
@ -564,7 +519,7 @@ int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf)
SrsMp4MediaDataBox::SrsMp4MediaDataBox()
{
type = SRS_MP4_BOX_MDAT;
type = SrsMp4BoxTypeMDAT;
data = NULL;
nb_data = 0;
}
@ -613,7 +568,7 @@ int SrsMp4MediaDataBox::decode_header(SrsBuffer* buf)
SrsMp4FreeSpaceBox::SrsMp4FreeSpaceBox()
{
type = SRS_MP4_BOX_FREE; // 'free' or 'skip'
type = SrsMp4BoxTypeFREE; // 'free' or 'skip'
data = NULL;
nb_data = 0;
}
@ -662,7 +617,7 @@ int SrsMp4FreeSpaceBox::decode_header(SrsBuffer* buf)
SrsMp4MovieBox::SrsMp4MovieBox()
{
type = SRS_MP4_BOX_MOOV;
type = SrsMp4BoxTypeMOOV;
}
SrsMp4MovieBox::~SrsMp4MovieBox()
@ -671,7 +626,7 @@ SrsMp4MovieBox::~SrsMp4MovieBox()
SrsMp4MovieHeaderBox::SrsMp4MovieHeaderBox()
{
type = SRS_MP4_BOX_MVHD;
type = SrsMp4BoxTypeMVHD;
rate = 0x00010000; // typically 1.0
volume = 0x0100; // typically, full volume
@ -773,7 +728,7 @@ int SrsMp4MovieHeaderBox::decode_header(SrsBuffer* buf)
SrsMp4TrackBox::SrsMp4TrackBox()
{
type = SRS_MP4_BOX_TRAK;
type = SrsMp4BoxTypeTRAK;
}
SrsMp4TrackBox::~SrsMp4TrackBox()
@ -782,7 +737,7 @@ SrsMp4TrackBox::~SrsMp4TrackBox()
SrsMp4TrackHeaderBox::SrsMp4TrackHeaderBox()
{
type = SRS_MP4_BOX_TKHD;
type = SrsMp4BoxTypeTKHD;
reserved0 = 0;
reserved1 = 0;
@ -887,7 +842,7 @@ int SrsMp4TrackHeaderBox::decode_header(SrsBuffer* buf)
SrsMp4EditBox::SrsMp4EditBox()
{
type = SRS_MP4_BOX_EDTS;
type = SrsMp4BoxTypeEDTS;
}
SrsMp4EditBox::~SrsMp4EditBox()
@ -901,7 +856,7 @@ SrsMp4ElstEntry::SrsMp4ElstEntry()
SrsMp4EditListBox::SrsMp4EditListBox()
{
type = SRS_MP4_BOX_ELST;
type = SrsMp4BoxTypeELST;
entry_count = 0;
entries = NULL;
@ -984,7 +939,7 @@ int SrsMp4EditListBox::decode_header(SrsBuffer* buf)
SrsMp4MediaBox::SrsMp4MediaBox()
{
type = SRS_MP4_BOX_MDIA;
type = SrsMp4BoxTypeMDIA;
}
SrsMp4MediaBox::~SrsMp4MediaBox()
@ -993,7 +948,7 @@ SrsMp4MediaBox::~SrsMp4MediaBox()
SrsMp4MediaHeaderBox::SrsMp4MediaHeaderBox()
{
type = SRS_MP4_BOX_MDHD;
type = SrsMp4BoxTypeMDHD;
language = 0;
pre_defined = 0;
}
@ -1101,7 +1056,7 @@ int SrsMp4MediaHeaderBox::decode_header(SrsBuffer* buf)
SrsMp4HandlerReferenceBox::SrsMp4HandlerReferenceBox()
{
type = SRS_MP4_BOX_HDLR;
type = SrsMp4BoxTypeHDLR;
pre_defined = 0;
memset(reserved, 0, 12);
@ -1113,12 +1068,12 @@ SrsMp4HandlerReferenceBox::~SrsMp4HandlerReferenceBox()
bool SrsMp4HandlerReferenceBox::is_video()
{
return handler_type == SRS_MP4_HANDLER_VIDE;
return handler_type == SrsMp4BoxTypeVIDE;
}
bool SrsMp4HandlerReferenceBox::is_audio()
{
return handler_type == SRS_MP4_HANDLER_SOUN;
return handler_type == SrsMp4BoxTypeSOUN;
}
int SrsMp4HandlerReferenceBox::nb_header()
@ -1166,7 +1121,7 @@ int SrsMp4HandlerReferenceBox::decode_header(SrsBuffer* buf)
SrsMp4MediaInformationBox::SrsMp4MediaInformationBox()
{
type = SRS_MP4_BOX_MINF;
type = SrsMp4BoxTypeMINF;
}
SrsMp4MediaInformationBox::~SrsMp4MediaInformationBox()
@ -1175,7 +1130,7 @@ SrsMp4MediaInformationBox::~SrsMp4MediaInformationBox()
SrsMp4VideoMeidaHeaderBox::SrsMp4VideoMeidaHeaderBox()
{
type = SRS_MP4_BOX_VMHD;
type = SrsMp4BoxTypeVMHD;
version = 0;
flags = 1;
@ -1226,7 +1181,7 @@ int SrsMp4VideoMeidaHeaderBox::decode_header(SrsBuffer* buf)
SrsMp4SoundMeidaHeaderBox::SrsMp4SoundMeidaHeaderBox()
{
type = SRS_MP4_BOX_SMHD;
type = SrsMp4BoxTypeSMHD;
reserved = balance = 0;
}
@ -1270,7 +1225,7 @@ int SrsMp4SoundMeidaHeaderBox::decode_header(SrsBuffer* buf)
SrsMp4DataInformationBox::SrsMp4DataInformationBox()
{
type = SRS_MP4_BOX_DINF;
type = SrsMp4BoxTypeDINF;
}
SrsMp4DataInformationBox::~SrsMp4DataInformationBox()
@ -1287,7 +1242,7 @@ SrsMp4DataEntryBox::~SrsMp4DataEntryBox()
SrsMp4DataEntryUrlBox::SrsMp4DataEntryUrlBox()
{
type = SRS_MP4_BOX_URL;
type = SrsMp4BoxTypeURL;
}
SrsMp4DataEntryUrlBox::~SrsMp4DataEntryUrlBox()
@ -1348,7 +1303,7 @@ int SrsMp4DataEntryUrlBox::decode_header(SrsBuffer* buf)
SrsMp4DataEntryUrnBox::SrsMp4DataEntryUrnBox()
{
type = SRS_MP4_BOX_URN;
type = SrsMp4BoxTypeURN;
}
SrsMp4DataEntryUrnBox::~SrsMp4DataEntryUrnBox()
@ -1397,7 +1352,7 @@ int SrsMp4DataEntryUrnBox::decode_header(SrsBuffer* buf)
SrsMp4DataReferenceBox::SrsMp4DataReferenceBox()
{
type = SRS_MP4_BOX_DREF;
type = SrsMp4BoxTypeDREF;
}
SrsMp4DataReferenceBox::~SrsMp4DataReferenceBox()
@ -1481,9 +1436,9 @@ int SrsMp4DataReferenceBox::decode_header(SrsBuffer* buf)
fbox->flags = flags;
}
if (box->type == SRS_MP4_BOX_URL) {
if (box->type == SrsMp4BoxTypeURL) {
entries.push_back(dynamic_cast<SrsMp4DataEntryUrlBox*>(box));
} else if (box->type == SRS_MP4_BOX_URN) {
} else if (box->type == SrsMp4BoxTypeURN) {
entries.push_back(dynamic_cast<SrsMp4DataEntryUrnBox*>(box));
} else {
srs_freep(box);
@ -1495,7 +1450,7 @@ int SrsMp4DataReferenceBox::decode_header(SrsBuffer* buf)
SrsMp4SampleTableBox::SrsMp4SampleTableBox()
{
type = SRS_MP4_BOX_STBL;
type = SrsMp4BoxTypeSTBL;
}
SrsMp4SampleTableBox::~SrsMp4SampleTableBox()
@ -1621,7 +1576,7 @@ int SrsMp4VisualSampleEntry::decode_header(SrsBuffer* buf)
SrsMp4AvccBox::SrsMp4AvccBox()
{
type = SRS_MP4_BOX_AVCC;
type = SrsMp4BoxTypeAVCC;
nb_config = 0;
avc_config = NULL;
}
@ -1724,20 +1679,27 @@ int SrsMp4AudioSampleEntry::decode_header(SrsBuffer* buf)
SrsMp4BaseDescriptor::SrsMp4BaseDescriptor()
{
tag = SRS_MP4_ES_TAG_ES_forbidden;
tag = SrsMp4ESTagESforbidden;
vlen = -1;
start_pos = 0;
}
SrsMp4BaseDescriptor::~SrsMp4BaseDescriptor()
{
}
int SrsMp4BaseDescriptor::left_space(SrsBuffer* buf)
{
return vlen - (buf->pos() - start_pos);
}
int SrsMp4BaseDescriptor::nb_bytes()
{
// 1 byte tag.
int size = 1;
// 1-3 bytes size.
uint32_t length = nb_payload();
int32_t length = vlen = nb_payload(); // bit(8) to bit(32)
if (length > 0x1fffff) {
size += 4;
} else if (length > 0x3fff) {
@ -1769,7 +1731,23 @@ int SrsMp4BaseDescriptor::encode(SrsBuffer* buf)
// As an expandable class the size of each class instance in bytes is encoded and accessible
// through the instance variable sizeOfInstance (see 8.3.3).
uint32_t length = nb_payload(); // bit(8) to bit(32)
int32_t length = vlen; // bit(8) to bit(32)
srs_assert(vlen > 0);
if (length > 0x1fffff) {
buf->write_1bytes(uint8_t(length>>21)|0x80);
}
if (length > 0x3fff) {
buf->write_1bytes(uint8_t(length>>14)|0x80);
}
if (length > 0x7f) {
buf->write_1bytes(uint8_t(length>>7)|0x80);
}
buf->write_1bytes(length&0x7f);
if ((ret = encode_payload(buf)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
@ -1785,65 +1763,184 @@ int SrsMp4BaseDescriptor::decode(SrsBuffer* buf)
return ret;
}
tag = (SRS_MP4_ES_TAG_ES)buf->read_1bytes();
tag = (SrsMp4ESTagEs)buf->read_1bytes();
uint8_t v = 0x80;
int32_t length = 0x00;
while ((v&0x80) == 0x80) {
if (!buf->require(1)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires 1 byte space. ret=%d", ret);
return ret;
}
v = buf->read_1bytes();
length = (length<<7) | (v&0x7f);
}
vlen = length;
if (!buf->require(vlen)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires %d bytes space. ret=%d", vlen, ret);
return ret;
}
start_pos = buf->pos();
if ((ret = decode_payload(buf)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
SrsMp4DecoderSpecificInfo::SrsMp4DecoderSpecificInfo()
{
tag = SrsMp4ESTagESDecSpecificInfoTag;
nb_asc = 0;
asc = NULL;
}
SrsMp4DecoderSpecificInfo::~SrsMp4DecoderSpecificInfo()
{
srs_freepa(asc);
}
int32_t SrsMp4DecoderSpecificInfo::nb_payload()
{
return nb_asc;
}
int SrsMp4DecoderSpecificInfo::encode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if (nb_asc) {
buf->write_bytes((char*)asc, nb_asc);
}
return ret;
}
int SrsMp4DecoderSpecificInfo::decode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
nb_asc = vlen;
if (nb_asc) {
asc = new uint8_t[nb_asc];
buf->read_bytes((char*)asc, nb_asc);
}
return ret;
}
SrsMp4DecoderConfigDescriptor::SrsMp4DecoderConfigDescriptor()
{
tag = SRS_MP4_ES_TAG_ES_DecoderConfigDescrTag;
tag = SrsMp4ESTagESDecoderConfigDescrTag;
objectTypeIndication = SrsMp4ObjectTypeForbidden;
streamType = SrsMp4StreamTypeForbidden;
decSpecificInfo = NULL;
reserved = 1;
}
SrsMp4DecoderConfigDescriptor::~SrsMp4DecoderConfigDescriptor()
{
srs_freep(decSpecificInfo);
}
uint32_t SrsMp4DecoderConfigDescriptor::nb_payload()
int32_t SrsMp4DecoderConfigDescriptor::nb_payload()
{
return 0;
return 12 + (decSpecificInfo? decSpecificInfo->nb_bytes():0);
}
int SrsMp4DecoderConfigDescriptor::encode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
buf->write_1bytes(objectTypeIndication);
uint8_t v = reserved;
v |= (upStream&0x01)<<1;
v |= uint8_t(streamType&0x3f)<<2;
buf->write_1bytes(v);
buf->write_3bytes(bufferSizeDB);
buf->write_4bytes(maxBitrate);
buf->write_4bytes(avgBitrate);
return ret;
}
int SrsMp4DecoderConfigDescriptor::decode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
objectTypeIndication = (SrsMp4ObjectType)buf->read_1bytes();
uint8_t v = buf->read_1bytes();
upStream = (v>>1) & 0x01;
streamType = (SrsMp4StreamType)((v>>2) & 0x3f);
reserved = v&0x01;
bufferSizeDB = buf->read_3bytes();
maxBitrate = buf->read_4bytes();
avgBitrate = buf->read_4bytes();
int left = left_space(buf);
if (left > 0) {
decSpecificInfo = new SrsMp4DecoderSpecificInfo();
if ((ret = decSpecificInfo->decode(buf)) != ERROR_SUCCESS) {
return ret;
}
}
return ret;
}
SrsMp4SLConfigDescriptor::SrsMp4SLConfigDescriptor()
{
tag = SRS_MP4_ES_TAG_ES_SLConfigDescrTag;
tag = SrsMp4ESTagESSLConfigDescrTag;
predefined = 2;
}
SrsMp4SLConfigDescriptor::~SrsMp4SLConfigDescriptor()
{
}
uint32_t SrsMp4SLConfigDescriptor::nb_payload()
int32_t SrsMp4SLConfigDescriptor::nb_payload()
{
return 0;
return 1;
}
int SrsMp4SLConfigDescriptor::encode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
buf->write_1bytes(predefined);
return ret;
}
int SrsMp4SLConfigDescriptor::decode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
predefined = buf->read_1bytes();
// TODO: FIXME: To support complete SL Config.
if (predefined != 0x02) {
ret = ERROR_MP4_ESDS_SL_Config;
srs_error("MP4 illegal ESDS SL Config, predefined=%d. ret=%d", predefined, ret);
return ret;
}
return ret;
}
SrsMp4ES_Descriptor::SrsMp4ES_Descriptor()
{
tag = SRS_MP4_ES_TAG_ES_DescrTag;
tag = SrsMp4ESTagESDescrTag;
streamDependenceFlag = URL_Flag = OCRstreamFlag = 0;
URLlength = 0;
URLstring = NULL;
@ -1854,7 +1951,7 @@ SrsMp4ES_Descriptor::~SrsMp4ES_Descriptor()
srs_freepa(URLstring);
}
uint32_t SrsMp4ES_Descriptor::nb_payload()
int32_t SrsMp4ES_Descriptor::nb_payload()
{
int size = 2 +1;
size += streamDependenceFlag? 2:0;
@ -1962,7 +2059,7 @@ int SrsMp4ES_Descriptor::decode_payload(SrsBuffer* buf)
SrsMp4EsdsBox::SrsMp4EsdsBox()
{
type = SRS_MP4_BOX_ESDS;
type = SrsMp4BoxTypeESDS;
es = new SrsMp4ES_Descriptor();
}
@ -2016,7 +2113,7 @@ int SrsMp4EsdsBox::decode_header(SrsBuffer* buf)
SrsMp4SampleDescriptionBox::SrsMp4SampleDescriptionBox()
{
type = SRS_MP4_BOX_STSD;
type = SrsMp4BoxTypeSTSD;
}
SrsMp4SampleDescriptionBox::~SrsMp4SampleDescriptionBox()
@ -2113,7 +2210,7 @@ SrsMp4SttsEntry::SrsMp4SttsEntry()
SrsMp4DecodingTime2SampleBox::SrsMp4DecodingTime2SampleBox()
{
type = SRS_MP4_BOX_STTS;
type = SrsMp4BoxTypeSTTS;
entry_count = 0;
entries = NULL;
@ -2176,7 +2273,7 @@ SrsMp4CttsEntry::SrsMp4CttsEntry()
SrsMp4CompositionTime2SampleBox::SrsMp4CompositionTime2SampleBox()
{
type = SRS_MP4_BOX_CTTS;
type = SrsMp4BoxTypeCTTS;
entry_count = 0;
entries = NULL;
@ -2241,7 +2338,7 @@ int SrsMp4CompositionTime2SampleBox::decode_header(SrsBuffer* buf)
SrsMp4SyncSampleBox::SrsMp4SyncSampleBox()
{
type = SRS_MP4_BOX_STSS;
type = SrsMp4BoxTypeSTSS;
entry_count = 0;
sample_numbers = NULL;
@ -2302,7 +2399,7 @@ SrsMp4StscEntry::SrsMp4StscEntry()
SrsMp4Sample2ChunkBox::SrsMp4Sample2ChunkBox()
{
type = SRS_MP4_BOX_STSC;
type = SrsMp4BoxTypeSTSC;
entry_count = 0;
entries = NULL;
@ -2361,7 +2458,7 @@ int SrsMp4Sample2ChunkBox::decode_header(SrsBuffer* buf)
SrsMp4ChunkOffsetBox::SrsMp4ChunkOffsetBox()
{
type = SRS_MP4_BOX_STCO;
type = SrsMp4BoxTypeSTCO;
entry_count = 0;
entries = NULL;
@ -2414,7 +2511,7 @@ int SrsMp4ChunkOffsetBox::decode_header(SrsBuffer* buf)
SrsMp4ChunkLargeOffsetBox::SrsMp4ChunkLargeOffsetBox()
{
type = SRS_MP4_BOX_CO64;
type = SrsMp4BoxTypeCO64;
entry_count = 0;
entries = NULL;
@ -2467,7 +2564,7 @@ int SrsMp4ChunkLargeOffsetBox::decode_header(SrsBuffer* buf)
SrsMp4SampleSizeBox::SrsMp4SampleSizeBox()
{
type = SRS_MP4_BOX_STSZ;
type = SrsMp4BoxTypeSTSZ;
sample_size = sample_count = 0;
entry_sizes = NULL;
@ -2551,16 +2648,16 @@ int SrsMp4Decoder::initialize(ISrsReader* r)
SrsMp4Box* box = NULL;
SrsAutoFree(SrsMp4Box, box);
if ((ret = load_next_box(&box, SRS_MP4_BOX_FTYP)) != ERROR_SUCCESS) {
if ((ret = load_next_box(&box, SrsMp4BoxTypeFTYP)) != ERROR_SUCCESS) {
return ret;
}
SrsMp4FileTypeBox* ftyp = dynamic_cast<SrsMp4FileTypeBox*>(box);
bool legal_brand = false;
static uint32_t legal_brands[] = {
SRS_MP4_BRAND_ISOM, SRS_MP4_BRAND_ISO2, SRS_MP4_BRAND_AVC1, SRS_MP4_BRAND_MP41
static SrsMp4BoxBrand legal_brands[] = {
SrsMp4BoxBrandISOM, SrsMp4BoxBrandISO2, SrsMp4BoxBrandAVC1, SrsMp4BoxBrandMP41
};
for (int i = 0; i < sizeof(legal_brands)/sizeof(uint32_t); i++) {
for (int i = 0; i < sizeof(legal_brands)/sizeof(SrsMp4BoxBrand); i++) {
if (ftyp->major_brand == legal_brands[i]) {
legal_brand = true;
break;

View file

@ -37,6 +37,67 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class ISrsReader;
class SrsSimpleStream;
/**
* 4.2 Object Structure
* ISO_IEC_14496-12-base-format-2012.pdf, page 16
*/
enum SrsMp4BoxType
{
SrsMp4BoxTypeForbidden = 0x00,
SrsMp4BoxTypeUUID = 0x75756964, // 'uuid'
SrsMp4BoxTypeFTYP = 0x66747970, // 'ftyp'
SrsMp4BoxTypeMDAT = 0x6d646174, // 'mdat'
SrsMp4BoxTypeFREE = 0x66726565, // 'free'
SrsMp4BoxTypeSKIP = 0x736b6970, // 'skip'
SrsMp4BoxTypeMOOV = 0x6d6f6f76, // 'moov'
SrsMp4BoxTypeMVHD = 0x6d766864, // 'mvhd'
SrsMp4BoxTypeTRAK = 0x7472616b, // 'trak'
SrsMp4BoxTypeTKHD = 0x746b6864, // 'tkhd'
SrsMp4BoxTypeEDTS = 0x65647473, // 'edts'
SrsMp4BoxTypeELST = 0x656c7374, // 'elst'
SrsMp4BoxTypeMDIA = 0x6d646961, // 'mdia'
SrsMp4BoxTypeMDHD = 0x6d646864, // 'mdhd'
SrsMp4BoxTypeHDLR = 0x68646c72, // 'hdlr'
SrsMp4BoxTypeMINF = 0x6d696e66, // 'minf'
SrsMp4BoxTypeVMHD = 0x766d6864, // 'vmhd'
SrsMp4BoxTypeSMHD = 0x736d6864, // 'smhd'
SrsMp4BoxTypeDINF = 0x64696e66, // 'dinf'
SrsMp4BoxTypeURL = 0x75726c20, // 'url '
SrsMp4BoxTypeURN = 0x75726e20, // 'urn '
SrsMp4BoxTypeDREF = 0x64726566, // 'dref'
SrsMp4BoxTypeSTBL = 0x7374626c, // 'stbl'
SrsMp4BoxTypeSTSD = 0x73747364, // 'stsd'
SrsMp4BoxTypeSTTS = 0x73747473, // 'stts'
SrsMp4BoxTypeCTTS = 0x63747473, // 'ctts'
SrsMp4BoxTypeSTSS = 0x73747373, // 'stss'
SrsMp4BoxTypeSTSC = 0x73747363, // 'stsc'
SrsMp4BoxTypeSTCO = 0x7374636f, // 'stco'
SrsMp4BoxTypeCO64 = 0x636f3634, // 'co64'
SrsMp4BoxTypeSTSZ = 0x7374737a, // 'stsz'
SrsMp4BoxTypeSTZ2 = 0x73747a32, // 'stz2'
SrsMp4BoxTypeAVC1 = 0x61766331, // 'avc1'
SrsMp4BoxTypeAVCC = 0x61766343, // 'avcC'
SrsMp4BoxTypeMP4A = 0x6d703461, // 'mp4a'
SrsMp4BoxTypeESDS = 0x65736473, // 'esds'
SrsMp4BoxTypeVIDE = 0x76696465, // 'vide'
SrsMp4BoxTypeSOUN = 0x736f756e, // 'soun'
};
/**
* File format brands
* ISO_IEC_14496-12-base-format-2012.pdf, page 166
*/
enum SrsMp4BoxBrand
{
SrsMp4BoxBrandForbidden = 0x00,
SrsMp4BoxBrandISOM = 0x69736f6d, // 'isom'
SrsMp4BoxBrandISO2 = 0x69736f32, // 'iso2'
SrsMp4BoxBrandAVC1 = 0x61766331, // 'avc1'
SrsMp4BoxBrandMP41 = 0x6d703431, // 'mp41'
};
/**
* 4.2 Object Structure
* ISO_IEC_14496-12-base-format-2012.pdf, page 16
@ -56,7 +117,7 @@ public:
// identifies the box type; standard boxes use a compact type, which is normally four printable
// characters, to permit ease of identification, and is shown so in the boxes below. User extensions use
// an extended type; in this case, the type field is set to uuid.
uint32_t type;
SrsMp4BoxType type;
// For box 'uuid'.
uint8_t* usertype;
private:
@ -133,13 +194,13 @@ class SrsMp4FileTypeBox : public SrsMp4Box
{
public:
// a brand identifier
uint32_t major_brand;
SrsMp4BoxBrand major_brand;
// an informative integer for the minor version of the major brand
uint32_t minor_version;
private:
// a list, to the end of the box, of brands
int nb_compatible_brands;
uint32_t* compatible_brands;
SrsMp4BoxBrand* compatible_brands;
public:
SrsMp4FileTypeBox();
virtual ~SrsMp4FileTypeBox();
@ -726,15 +787,15 @@ protected:
// Table 1 — List of Class Tags for Descriptors
// ISO_IEC_14496-1-System-2010.pdf, page 31
enum SRS_MP4_ES_TAG_ES {
SRS_MP4_ES_TAG_ES_forbidden = 0x00,
SRS_MP4_ES_TAG_ES_ObjectDescrTag = 0x01,
SRS_MP4_ES_TAG_ES_InitialObjectDescrTag = 0x02,
SRS_MP4_ES_TAG_ES_DescrTag = 0x03,
SRS_MP4_ES_TAG_ES_DecoderConfigDescrTag = 0x04,
SRS_MP4_ES_TAG_ES_DecSpecificInfoTag = 0x05,
SRS_MP4_ES_TAG_ES_SLConfigDescrTag = 0x06,
SRS_MP4_ES_TAG_ES_ExtSLConfigDescrTag = 0x064,
enum SrsMp4ESTagEs {
SrsMp4ESTagESforbidden = 0x00,
SrsMp4ESTagESObjectDescrTag = 0x01,
SrsMp4ESTagESInitialObjectDescrTag = 0x02,
SrsMp4ESTagESDescrTag = 0x03,
SrsMp4ESTagESDecoderConfigDescrTag = 0x04,
SrsMp4ESTagESDecSpecificInfoTag = 0x05,
SrsMp4ESTagESSLConfigDescrTag = 0x06,
SrsMp4ESTagESExtSLConfigDescrTag = 0x064,
};
/**
@ -747,21 +808,66 @@ public:
// The values of the class tags are
// defined in Table 2. As an expandable class the size of each class instance in bytes is encoded and accessible
// through the instance variable sizeOfInstance (see 8.3.3).
SRS_MP4_ES_TAG_ES tag; // bit(8)
SrsMp4ESTagEs tag; // bit(8)
// The decoded or encoded variant length.
int32_t vlen; // bit(28)
private:
// The position at buffer to start demux the box.
int start_pos;
public:
SrsMp4BaseDescriptor();
virtual ~SrsMp4BaseDescriptor();
public:
// Get the left space of box, for decoder.
virtual int left_space(SrsBuffer* buf);
// Interface ISrsCodec
public:
virtual int nb_bytes();
virtual int encode(SrsBuffer* buf);
virtual int decode(SrsBuffer* buf);
protected:
virtual uint32_t nb_payload() = 0;
virtual int32_t nb_payload() = 0;
virtual int encode_payload(SrsBuffer* buf) = 0;
virtual int decode_payload(SrsBuffer* buf) = 0;
};
// Table 5 — objectTypeIndication Values
// ISO_IEC_14496-1-System-2010.pdf, page 49
enum SrsMp4ObjectType
{
SrsMp4ObjectTypeForbidden = 0x00,
// Audio ISO/IEC 14496-3
SrsMp4ObjectTypeAac = 0x40,
};
// Table 6 — streamType Values
// ISO_IEC_14496-1-System-2010.pdf, page 51
enum SrsMp4StreamType
{
SrsMp4StreamTypeForbidden = 0x00,
SrsMp4StreamTypeAudioStream = 0x05,
};
/**
* 7.2.6.7 DecoderSpecificInfo
* ISO_IEC_14496-1-System-2010.pdf, page 51
*/
class SrsMp4DecoderSpecificInfo : public SrsMp4BaseDescriptor
{
public:
// AAC Audio Specific Config.
// 1.6.2.1 AudioSpecificConfig, in ISO_IEC_14496-3-AAC-2001.pdf, page 33.
int nb_asc;
uint8_t* asc;
public:
SrsMp4DecoderSpecificInfo();
virtual ~SrsMp4DecoderSpecificInfo();
protected:
virtual int32_t nb_payload();
virtual int encode_payload(SrsBuffer* buf);
virtual int decode_payload(SrsBuffer* buf);
};
/**
* 7.2.6.6 DecoderConfigDescriptor
* ISO_IEC_14496-1-System-2010.pdf, page 48
@ -769,18 +875,21 @@ protected:
class SrsMp4DecoderConfigDescriptor : public SrsMp4BaseDescriptor
{
public:
uint8_t objectTypeIndication;
uint8_t streamType; // bit(6)
// an indication of the object or scene description type that needs to be supported
// by the decoder for this elementary stream as per Table 5.
SrsMp4ObjectType objectTypeIndication;
SrsMp4StreamType streamType; // bit(6)
uint8_t upStream; // bit(1)
uint8_t reserved; // bit(1)
uint32_t bufferSizeDB; // bit(24)
uint32_t maxBitrate;
uint32_t avgBitrate;
SrsMp4DecoderSpecificInfo* decSpecificInfo; // optional.
public:
SrsMp4DecoderConfigDescriptor();
virtual ~SrsMp4DecoderConfigDescriptor();
protected:
virtual uint32_t nb_payload();
virtual int32_t nb_payload();
virtual int encode_payload(SrsBuffer* buf);
virtual int decode_payload(SrsBuffer* buf);
};
@ -793,37 +902,11 @@ class SrsMp4SLConfigDescriptor : public SrsMp4BaseDescriptor
{
public:
uint8_t predefined;
// if (predefined==0)
uint8_t useAccessUnitStartFlag; // bit(1)
uint8_t useAccessUnitEndFlag; // bit(1)
uint8_t useRandomAccessPointFlag; // bit(1)
uint8_t hasRandomAccessUnitsOnlyFlag; // bit(1)
uint8_t usePaddingFlag; // bit(1)
uint8_t useTimeStampsFlag; // bit(1)
uint8_t useIdleFlag; // bit(1)
uint8_t durationFlag; // bit(1)
uint32_t timeStampResolution;
uint32_t OCRResolution;
uint8_t timeStampLength; // must be ≤ 64
uint8_t OCRLength; // must be ≤ 64
uint8_t AU_Length; // must be ≤ 32
uint8_t instantBitrateLength;
uint8_t degradationPriorityLength; // bit(4)
uint8_t AU_seqNumLength; // bit(5) // must be ≤ 16
uint8_t packetSeqNumLength; // bit(5) // must be ≤ 16
uint8_t reserved; // bit(2) // 0b11
// if (durationFlag)
uint32_t timeScale;
uint16_t accessUnitDuration;
uint16_t compositionUnitDuration;
// if (!useTimeStampsFlag)
uint64_t startDecodingTimeStamp; // bit(timeStampLength)
uint64_t startCompositionTimeStamp; // bit(timeStampLength)
public:
SrsMp4SLConfigDescriptor();
virtual ~SrsMp4SLConfigDescriptor();
protected:
virtual uint32_t nb_payload();
virtual int32_t nb_payload();
virtual int encode_payload(SrsBuffer* buf);
virtual int decode_payload(SrsBuffer* buf);
};
@ -853,7 +936,7 @@ public:
SrsMp4ES_Descriptor();
virtual ~SrsMp4ES_Descriptor();
protected:
virtual uint32_t nb_payload();
virtual int32_t nb_payload();
virtual int encode_payload(SrsBuffer* buf);
virtual int decode_payload(SrsBuffer* buf);
};