mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
for #738, complete all mp4 boxes codec.
This commit is contained in:
parent
2ad265bd5a
commit
5a84b6ca94
2 changed files with 207 additions and 20 deletions
|
@ -61,7 +61,9 @@ using namespace std;
|
|||
#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_EOF_SIZE 0
|
||||
#define SRS_MP4_USE_LARGE_SIZE 1
|
||||
|
@ -192,6 +194,7 @@ int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
|
|||
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;
|
||||
default:
|
||||
ret = ERROR_MP4_BOX_ILLEGAL_TYPE;
|
||||
|
@ -1420,18 +1423,16 @@ int SrsMp4DataReferenceBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int left = left_space(buf);
|
||||
while (left > 0) {
|
||||
uint32_t nb_entries = buf->read_4bytes();
|
||||
for (uint32_t i = 0; i < nb_entries; i++) {
|
||||
SrsMp4Box* box = NULL;
|
||||
if ((ret = SrsMp4Box::discovery(buf, &box)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pos = buf->pos();
|
||||
if ((ret = box->decode(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
left -= buf->pos() - pos;
|
||||
|
||||
SrsMp4FullBox* fbox = dynamic_cast<SrsMp4FullBox*>(box);
|
||||
if (fbox) {
|
||||
|
@ -1660,6 +1661,8 @@ int SrsMp4SampleDescriptionBox::nb_header()
|
|||
{
|
||||
int size = SrsMp4FullBox::nb_header();
|
||||
|
||||
size += 4;
|
||||
|
||||
vector<SrsMp4SampleEntry*>::iterator it;
|
||||
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||
SrsMp4SampleEntry* entry = *it;
|
||||
|
@ -1677,6 +1680,8 @@ int SrsMp4SampleDescriptionBox::encode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(entry_count());
|
||||
|
||||
vector<SrsMp4SampleEntry*>::iterator it;
|
||||
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||
SrsMp4SampleEntry* entry = *it;
|
||||
|
@ -1696,18 +1701,16 @@ int SrsMp4SampleDescriptionBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int left = left_space(buf);
|
||||
while (left > 0) {
|
||||
uint32_t nb_entries = buf->read_4bytes();
|
||||
for (uint32_t i = 0; i < nb_entries; i++) {
|
||||
SrsMp4Box* box = NULL;
|
||||
if ((ret = SrsMp4Box::discovery(buf, &box)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pos = buf->pos();
|
||||
if ((ret = box->decode(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
left -= buf->pos() - pos;
|
||||
|
||||
SrsMp4SampleEntry* entry = dynamic_cast<SrsMp4SampleEntry*>(box);
|
||||
if (entry) {
|
||||
|
@ -1741,7 +1744,7 @@ SrsMp4DecodingTime2SampleBox::~SrsMp4DecodingTime2SampleBox()
|
|||
|
||||
int SrsMp4DecodingTime2SampleBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header();
|
||||
return SrsMp4FullBox::nb_header() + 4 + 8*entry_count;
|
||||
}
|
||||
|
||||
int SrsMp4DecodingTime2SampleBox::encode_header(SrsBuffer* buf)
|
||||
|
@ -1752,6 +1755,13 @@ int SrsMp4DecodingTime2SampleBox::encode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(entry_count);
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
SrsMp4SttsEntry& entry = entries[i];
|
||||
buf->write_4bytes(entry.sample_count);
|
||||
buf->write_4bytes(entry.sample_delta);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1763,6 +1773,16 @@ int SrsMp4DecodingTime2SampleBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
entry_count = buf->read_4bytes();
|
||||
if (entry_count) {
|
||||
entries = new SrsMp4SttsEntry[entry_count];
|
||||
}
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
SrsMp4SttsEntry& entry = entries[i];
|
||||
entry.sample_count = buf->read_4bytes();
|
||||
entry.sample_delta = buf->read_4bytes();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1787,7 +1807,7 @@ SrsMp4CompositionTime2SampleBox::~SrsMp4CompositionTime2SampleBox()
|
|||
|
||||
int SrsMp4CompositionTime2SampleBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header();
|
||||
return SrsMp4FullBox::nb_header() + 4 + 8*entry_count;
|
||||
}
|
||||
|
||||
int SrsMp4CompositionTime2SampleBox::encode_header(SrsBuffer* buf)
|
||||
|
@ -1798,6 +1818,17 @@ int SrsMp4CompositionTime2SampleBox::encode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(entry_count);
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
SrsMp4CttsEntry& entry = entries[i];
|
||||
buf->write_4bytes(entry.sample_count);
|
||||
if (version == 0) {
|
||||
buf->write_4bytes((uint32_t)entry.sample_offset);
|
||||
} else if (version == 1) {
|
||||
buf->write_4bytes((int32_t)entry.sample_offset);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1809,6 +1840,20 @@ int SrsMp4CompositionTime2SampleBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
entry_count = buf->read_4bytes();
|
||||
if (entry_count) {
|
||||
entries = new SrsMp4CttsEntry[entry_count];
|
||||
}
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
SrsMp4CttsEntry& entry = entries[i];
|
||||
entry.sample_count = buf->read_4bytes();
|
||||
if (version == 0) {
|
||||
entry.sample_offset = (uint32_t)buf->read_4bytes();
|
||||
} else if (version == 1) {
|
||||
entry.sample_offset = (int32_t)buf->read_4bytes();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1827,7 +1872,7 @@ SrsMp4SyncSampleBox::~SrsMp4SyncSampleBox()
|
|||
|
||||
int SrsMp4SyncSampleBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header();
|
||||
return SrsMp4FullBox::nb_header() +4 +4*entry_count;
|
||||
}
|
||||
|
||||
int SrsMp4SyncSampleBox::encode_header(SrsBuffer* buf)
|
||||
|
@ -1838,6 +1883,12 @@ int SrsMp4SyncSampleBox::encode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(entry_count);
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
uint32_t sample_number = sample_numbers[i];
|
||||
buf->write_4bytes(sample_number);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1849,6 +1900,15 @@ int SrsMp4SyncSampleBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
entry_count = buf->read_4bytes();
|
||||
if (entry_count > 0) {
|
||||
sample_numbers = new uint32_t[entry_count];
|
||||
}
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
uint32_t sample_number = sample_numbers[i];
|
||||
buf->write_4bytes(sample_number);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1874,7 +1934,7 @@ SrsMp4Sample2ChunkBox::~SrsMp4Sample2ChunkBox()
|
|||
|
||||
int SrsMp4Sample2ChunkBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header();
|
||||
return SrsMp4FullBox::nb_header() +4 + 12*entry_count;
|
||||
}
|
||||
|
||||
int SrsMp4Sample2ChunkBox::encode_header(SrsBuffer* buf)
|
||||
|
@ -1885,6 +1945,14 @@ int SrsMp4Sample2ChunkBox::encode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(entry_count);
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
SrsMp4StscEntry& entry = entries[i];
|
||||
buf->write_4bytes(entry.first_chunk);
|
||||
buf->write_4bytes(entry.samples_per_chunk);
|
||||
buf->write_4bytes(entry.sample_description_index);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1896,6 +1964,17 @@ int SrsMp4Sample2ChunkBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
entry_count = buf->read_4bytes();
|
||||
if (entry_count) {
|
||||
entries = new SrsMp4StscEntry[entry_count];
|
||||
}
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
SrsMp4StscEntry& entry = entries[i];
|
||||
entry.first_chunk = buf->read_4bytes();
|
||||
entry.samples_per_chunk = buf->read_4bytes();
|
||||
entry.sample_description_index = buf->read_4bytes();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1914,7 +1993,7 @@ SrsMp4ChunkOffsetBox::~SrsMp4ChunkOffsetBox()
|
|||
|
||||
int SrsMp4ChunkOffsetBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header();
|
||||
return SrsMp4FullBox::nb_header() +4 +4*entry_count;
|
||||
}
|
||||
|
||||
int SrsMp4ChunkOffsetBox::encode_header(SrsBuffer* buf)
|
||||
|
@ -1925,6 +2004,11 @@ int SrsMp4ChunkOffsetBox::encode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(entry_count);
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
buf->write_4bytes(entries[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1936,6 +2020,67 @@ int SrsMp4ChunkOffsetBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
entry_count = buf->read_4bytes();
|
||||
if (entry_count) {
|
||||
entries = new uint32_t[entry_count];
|
||||
}
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
entries[i] = buf->read_4bytes();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsMp4ChunkLargeOffsetBox::SrsMp4ChunkLargeOffsetBox()
|
||||
{
|
||||
type = SRS_MP4_BOX_CO64;
|
||||
|
||||
entry_count = 0;
|
||||
entries = NULL;
|
||||
}
|
||||
|
||||
SrsMp4ChunkLargeOffsetBox::~SrsMp4ChunkLargeOffsetBox()
|
||||
{
|
||||
srs_freepa(entries);
|
||||
}
|
||||
|
||||
int SrsMp4ChunkLargeOffsetBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header() +4 +8*entry_count;
|
||||
}
|
||||
|
||||
int SrsMp4ChunkLargeOffsetBox::encode_header(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(entry_count);
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
buf->write_8bytes(entries[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsMp4ChunkLargeOffsetBox::decode_header(SrsBuffer* buf)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
entry_count = buf->read_4bytes();
|
||||
if (entry_count) {
|
||||
entries = new uint64_t[entry_count];
|
||||
}
|
||||
for (uint32_t i = 0; i < entry_count; i++) {
|
||||
entries[i] = buf->read_8bytes();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1954,7 +2099,11 @@ SrsMp4SampleSizeBox::~SrsMp4SampleSizeBox()
|
|||
|
||||
int SrsMp4SampleSizeBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header();
|
||||
int size = SrsMp4FullBox::nb_header() +4+4;
|
||||
if (sample_size == 0) {
|
||||
size += 4*sample_count;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int SrsMp4SampleSizeBox::encode_header(SrsBuffer* buf)
|
||||
|
@ -1965,6 +2114,12 @@ int SrsMp4SampleSizeBox::encode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
buf->write_4bytes(sample_size);
|
||||
buf->write_4bytes(sample_count);
|
||||
for (uint32_t i = 0; i < sample_count && sample_size == 0; i++) {
|
||||
buf->write_4bytes(entry_sizes[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1976,6 +2131,15 @@ int SrsMp4SampleSizeBox::decode_header(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
sample_size = buf->read_4bytes();
|
||||
sample_count = buf->read_4bytes();
|
||||
if (sample_size == 0) {
|
||||
entry_sizes = new uint32_t[sample_count];
|
||||
}
|
||||
for (uint32_t i = 0; i < sample_count && sample_size == 0; i++) {
|
||||
entry_sizes[i] = buf->read_4bytes();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -761,7 +761,6 @@ protected:
|
|||
virtual int decode_header(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 8.6.1.3 Composition Time to Sample Box (ctts), for Video.
|
||||
* ISO_IEC_14496-12-base-format-2012.pdf, page 49
|
||||
|
@ -872,7 +871,7 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* 8.7.5 Chunk Offset Box (stco or co64), for Audio/Video.
|
||||
* 8.7.5 Chunk Offset Box (stco), for Audio/Video.
|
||||
* ISO_IEC_14496-12-base-format-2012.pdf, page 59
|
||||
* The chunk offset table gives the index of each chunk into the containing file. There are two variants, permitting
|
||||
* the use of 32-bit or 64-bit offsets. The latter is useful when managing very large presentations. At most one of
|
||||
|
@ -883,9 +882,9 @@ class SrsMp4ChunkOffsetBox : public SrsMp4FullBox
|
|||
public:
|
||||
// an integer that gives the number of entries in the following table
|
||||
uint32_t entry_count;
|
||||
// a 32 or 64 bit integer that gives the offset of the start of a chunk into its containing
|
||||
// a 32 bit integer that gives the offset of the start of a chunk into its containing
|
||||
// media file.
|
||||
uint64_t* entries;
|
||||
uint32_t* entries;
|
||||
public:
|
||||
SrsMp4ChunkOffsetBox();
|
||||
virtual ~SrsMp4ChunkOffsetBox();
|
||||
|
@ -896,8 +895,32 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* 8.7.3 Sample Size Boxes (stsz or stz2), for Audio/Video.
|
||||
* ISO_IEC_14496-12-base-format-2012.pdf, page 57
|
||||
* 8.7.5 Chunk Large Offset Box (co64), for Audio/Video.
|
||||
* ISO_IEC_14496-12-base-format-2012.pdf, page 59
|
||||
* The chunk offset table gives the index of each chunk into the containing file. There are two variants, permitting
|
||||
* the use of 32-bit or 64-bit offsets. The latter is useful when managing very large presentations. At most one of
|
||||
* these variants will occur in any single instance of a sample table.
|
||||
*/
|
||||
class SrsMp4ChunkLargeOffsetBox : public SrsMp4FullBox
|
||||
{
|
||||
public:
|
||||
// an integer that gives the number of entries in the following table
|
||||
uint32_t entry_count;
|
||||
// a 64 bit integer that gives the offset of the start of a chunk into its containing
|
||||
// media file.
|
||||
uint64_t* entries;
|
||||
public:
|
||||
SrsMp4ChunkLargeOffsetBox();
|
||||
virtual ~SrsMp4ChunkLargeOffsetBox();
|
||||
protected:
|
||||
virtual int nb_header();
|
||||
virtual int encode_header(SrsBuffer* buf);
|
||||
virtual int decode_header(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* 8.7.3.2 Sample Size Box (stsz), for Audio/Video.
|
||||
* ISO_IEC_14496-12-base-format-2012.pdf, page 58
|
||||
* This box contains the sample count and a table giving the size in bytes of each sample. This allows the media data
|
||||
* itself to be unframed. The total number of samples in the media is always indicated in the sample count.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue