mirror of
https://github.com/ossrs/srs.git
synced 2025-02-14 12:21:55 +00:00
for #738, demux the aac mp4a and esds
This commit is contained in:
parent
128a1fd3db
commit
96f2e18d3a
3 changed files with 446 additions and 0 deletions
BIN
trunk/doc/ISO_IEC_14496-1-System-2010.pdf
Normal file
BIN
trunk/doc/ISO_IEC_14496-1-System-2010.pdf
Normal file
Binary file not shown.
|
@ -232,6 +232,7 @@ int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
|
|||
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;
|
||||
default:
|
||||
ret = ERROR_MP4_BOX_ILLEGAL_TYPE;
|
||||
srs_error("MP4 illegal box type=%d. ret=%d", type, ret);
|
||||
|
@ -1721,6 +1722,298 @@ int SrsMp4AudioSampleEntry::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
SrsMp4BaseDescriptor::SrsMp4BaseDescriptor()
|
||||
{
|
||||
tag = SRS_MP4_ES_TAG_ES_forbidden;
|
||||
}
|
||||
|
||||
SrsMp4BaseDescriptor::~SrsMp4BaseDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
int SrsMp4BaseDescriptor::nb_bytes()
|
||||
{
|
||||
// 1 byte tag.
|
||||
int size = 1;
|
||||
|
||||
// 1-3 bytes size.
|
||||
uint32_t length = nb_payload();
|
||||
if (length > 0x1fffff) {
|
||||
size += 4;
|
||||
} else if (length > 0x3fff) {
|
||||
size += 3;
|
||||
} else if (length > 0x7f) {
|
||||
size += 2;
|
||||
} else {
|
||||
size += 1;
|
||||
}
|
||||
|
||||
// length bytes payload.
|
||||
size += length;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int SrsMp4BaseDescriptor::encode(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
int size = nb_bytes();
|
||||
if (!buf->require(size)) {
|
||||
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
|
||||
srs_error("MP4 ES requires %d bytes space. ret=%d", size, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf->write_1bytes((uint8_t)tag);
|
||||
|
||||
// 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)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsMp4BaseDescriptor::decode(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
int size = nb_bytes();
|
||||
if (!buf->require(size)) {
|
||||
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
|
||||
srs_error("MP4 ES requires %d bytes space. ret=%d", size, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tag = (SRS_MP4_ES_TAG_ES)buf->read_1bytes();
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsMp4DecoderConfigDescriptor::SrsMp4DecoderConfigDescriptor()
|
||||
{
|
||||
tag = SRS_MP4_ES_TAG_ES_DecoderConfigDescrTag;
|
||||
}
|
||||
|
||||
SrsMp4DecoderConfigDescriptor::~SrsMp4DecoderConfigDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t SrsMp4DecoderConfigDescriptor::nb_payload()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SrsMp4DecoderConfigDescriptor::encode_payload(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsMp4DecoderConfigDescriptor::decode_payload(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsMp4SLConfigDescriptor::SrsMp4SLConfigDescriptor()
|
||||
{
|
||||
tag = SRS_MP4_ES_TAG_ES_SLConfigDescrTag;
|
||||
}
|
||||
|
||||
SrsMp4SLConfigDescriptor::~SrsMp4SLConfigDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t SrsMp4SLConfigDescriptor::nb_payload()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SrsMp4SLConfigDescriptor::encode_payload(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsMp4SLConfigDescriptor::decode_payload(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsMp4ES_Descriptor::SrsMp4ES_Descriptor()
|
||||
{
|
||||
tag = SRS_MP4_ES_TAG_ES_DescrTag;
|
||||
streamDependenceFlag = URL_Flag = OCRstreamFlag = 0;
|
||||
URLlength = 0;
|
||||
URLstring = NULL;
|
||||
}
|
||||
|
||||
SrsMp4ES_Descriptor::~SrsMp4ES_Descriptor()
|
||||
{
|
||||
srs_freepa(URLstring);
|
||||
}
|
||||
|
||||
uint32_t SrsMp4ES_Descriptor::nb_payload()
|
||||
{
|
||||
int size = 2 +1;
|
||||
size += streamDependenceFlag? 2:0;
|
||||
if (URL_Flag) {
|
||||
size += 1 + URLlength;
|
||||
}
|
||||
size += OCRstreamFlag? 2:0;
|
||||
size += decConfigDescr.nb_bytes() +slConfigDescr.nb_bytes();
|
||||
return size;
|
||||
}
|
||||
|
||||
int SrsMp4ES_Descriptor::encode_payload(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
buf->write_2bytes(ES_ID);
|
||||
|
||||
uint8_t v = streamPriority & 0x1f;
|
||||
v |= (streamDependenceFlag & 0x01) << 7;
|
||||
v |= (URL_Flag & 0x01) << 6;
|
||||
v |= (OCRstreamFlag & 0x01) << 5;
|
||||
buf->write_1bytes(v);
|
||||
|
||||
if (streamDependenceFlag) {
|
||||
buf->write_2bytes(dependsOn_ES_ID);
|
||||
}
|
||||
|
||||
if (URL_Flag && URLlength) {
|
||||
buf->write_1bytes(URLlength);
|
||||
buf->write_bytes((char*)URLstring, URLlength);
|
||||
}
|
||||
|
||||
if (OCRstreamFlag) {
|
||||
buf->write_2bytes(OCR_ES_Id);
|
||||
}
|
||||
|
||||
if ((ret = decConfigDescr.encode(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = slConfigDescr.encode(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsMp4ES_Descriptor::decode_payload(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
ES_ID = buf->read_2bytes();
|
||||
|
||||
uint8_t v = buf->read_1bytes();
|
||||
streamPriority = v & 0x1f;
|
||||
streamDependenceFlag = (v >> 7) & 0x01;
|
||||
URL_Flag = (v >> 6) & 0x01;
|
||||
OCRstreamFlag = (v >> 5) & 0x01;
|
||||
|
||||
if (streamDependenceFlag) {
|
||||
if (!buf->require(2)) {
|
||||
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
|
||||
srs_error("MP4 ES requires 2 bytes space. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
dependsOn_ES_ID = buf->read_2bytes();
|
||||
}
|
||||
|
||||
if (URL_Flag) {
|
||||
if (!buf->require(1)) {
|
||||
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
|
||||
srs_error("MP4 ES requires 1 byte space. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
URLlength = buf->read_1bytes();
|
||||
|
||||
if (!buf->require(URLlength)) {
|
||||
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
|
||||
srs_error("MP4 ES requires %d bytes space. ret=%d", URLlength, ret);
|
||||
return ret;
|
||||
}
|
||||
URLstring = new uint8_t[URLlength];
|
||||
buf->read_bytes((char*)URLstring, URLlength);
|
||||
}
|
||||
|
||||
if (OCRstreamFlag) {
|
||||
if (!buf->require(2)) {
|
||||
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
|
||||
srs_error("MP4 ES requires 2 bytes space. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
OCR_ES_Id = buf->read_2bytes();
|
||||
}
|
||||
|
||||
if ((ret = decConfigDescr.decode(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = slConfigDescr.decode(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsMp4EsdsBox::SrsMp4EsdsBox()
|
||||
{
|
||||
type = SRS_MP4_BOX_ESDS;
|
||||
es = new SrsMp4ES_Descriptor();
|
||||
}
|
||||
|
||||
SrsMp4EsdsBox::~SrsMp4EsdsBox()
|
||||
{
|
||||
srs_freep(es);
|
||||
}
|
||||
|
||||
int SrsMp4EsdsBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header() + es->nb_bytes();
|
||||
}
|
||||
|
||||
int SrsMp4EsdsBox::encode_header(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int left = left_space(buf);
|
||||
SrsBuffer buffer(buf->data() + buf->pos(), left);
|
||||
if ((ret = es->encode(&buffer)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf->skip(buffer.pos());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsMp4EsdsBox::decode_header(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int left = left_space(buf);
|
||||
SrsBuffer buffer(buf->data() + buf->pos(), left);
|
||||
if ((ret = es->decode(&buffer)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf->skip(buffer.pos());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsMp4SampleDescriptionBox::SrsMp4SampleDescriptionBox()
|
||||
{
|
||||
type = SRS_MP4_BOX_STSD;
|
||||
|
|
|
@ -724,6 +724,159 @@ protected:
|
|||
virtual int decode_header(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
// 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,
|
||||
};
|
||||
|
||||
/**
|
||||
* 7.2.2.2 BaseDescriptor
|
||||
* ISO_IEC_14496-1-System-2010.pdf, page 32
|
||||
*/
|
||||
class SrsMp4BaseDescriptor : public ISrsCodec
|
||||
{
|
||||
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)
|
||||
public:
|
||||
SrsMp4BaseDescriptor();
|
||||
virtual ~SrsMp4BaseDescriptor();
|
||||
// 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 int encode_payload(SrsBuffer* buf) = 0;
|
||||
virtual int decode_payload(SrsBuffer* buf) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 7.2.6.6 DecoderConfigDescriptor
|
||||
* ISO_IEC_14496-1-System-2010.pdf, page 48
|
||||
*/
|
||||
class SrsMp4DecoderConfigDescriptor : public SrsMp4BaseDescriptor
|
||||
{
|
||||
public:
|
||||
uint8_t objectTypeIndication;
|
||||
uint8_t streamType; // bit(6)
|
||||
uint8_t upStream; // bit(1)
|
||||
uint8_t reserved; // bit(1)
|
||||
uint32_t bufferSizeDB; // bit(24)
|
||||
uint32_t maxBitrate;
|
||||
uint32_t avgBitrate;
|
||||
public:
|
||||
SrsMp4DecoderConfigDescriptor();
|
||||
virtual ~SrsMp4DecoderConfigDescriptor();
|
||||
protected:
|
||||
virtual uint32_t nb_payload();
|
||||
virtual int encode_payload(SrsBuffer* buf);
|
||||
virtual int decode_payload(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* 7.3.2.3 SL Packet Header Configuration
|
||||
* ISO_IEC_14496-1-System-2010.pdf, page 92
|
||||
*/
|
||||
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 int encode_payload(SrsBuffer* buf);
|
||||
virtual int decode_payload(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* 7.2.6.5 ES_Descriptor
|
||||
* ISO_IEC_14496-1-System-2010.pdf, page 47
|
||||
*/
|
||||
class SrsMp4ES_Descriptor : public SrsMp4BaseDescriptor
|
||||
{
|
||||
public:
|
||||
uint16_t ES_ID;
|
||||
uint8_t streamDependenceFlag; // bit(1)
|
||||
uint8_t URL_Flag; // bit(1)
|
||||
uint8_t OCRstreamFlag; // bit(1)
|
||||
uint8_t streamPriority; // bit(5)
|
||||
// if (streamDependenceFlag)
|
||||
uint16_t dependsOn_ES_ID;
|
||||
// if (URL_Flag)
|
||||
uint8_t URLlength;
|
||||
uint8_t* URLstring;
|
||||
// if (OCRstreamFlag)
|
||||
uint16_t OCR_ES_Id;
|
||||
SrsMp4DecoderConfigDescriptor decConfigDescr;
|
||||
SrsMp4SLConfigDescriptor slConfigDescr;
|
||||
public:
|
||||
SrsMp4ES_Descriptor();
|
||||
virtual ~SrsMp4ES_Descriptor();
|
||||
protected:
|
||||
virtual uint32_t nb_payload();
|
||||
virtual int encode_payload(SrsBuffer* buf);
|
||||
virtual int decode_payload(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* 5.6 Sample Description Boxes
|
||||
* Elementary Stream Descriptors (esds)
|
||||
* ISO_IEC_14496-14-MP4-2003.pdf, page 15
|
||||
* @see http://www.mp4ra.org/codecs.html
|
||||
*/
|
||||
class SrsMp4EsdsBox : public SrsMp4FullBox
|
||||
{
|
||||
public:
|
||||
SrsMp4ES_Descriptor* es;
|
||||
public:
|
||||
SrsMp4EsdsBox();
|
||||
virtual ~SrsMp4EsdsBox();
|
||||
protected:
|
||||
virtual int nb_header();
|
||||
virtual int encode_header(SrsBuffer* buf);
|
||||
virtual int decode_header(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* 8.5.2 Sample Description Box (stsd), for Audio/Video.
|
||||
* ISO_IEC_14496-12-base-format-2012.pdf, page 40
|
||||
|
|
Loading…
Reference in a new issue