for #738, complete all mp4 boxes codec.

pull/756/head
winlin 8 years ago
parent 2ad265bd5a
commit 5a84b6ca94

@ -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…
Cancel
Save