diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index 5c5b3fb75..e4c02d92d 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -2858,6 +2858,18 @@ void SrsMp4SampleTableBox::set_stco(SrsMp4ChunkOffsetBox* v) boxes.push_back(v); } +SrsMp4ChunkLargeOffsetBox* SrsMp4SampleTableBox::co64() +{ + SrsMp4Box* box = get(SrsMp4BoxTypeCO64); + return dynamic_cast(box); +} + +void SrsMp4SampleTableBox::set_co64(SrsMp4ChunkLargeOffsetBox* v) +{ + remove(SrsMp4BoxTypeCO64); + boxes.push_back(v); +} + SrsMp4SampleSizeBox* SrsMp4SampleTableBox::stsz() { SrsMp4Box* box = get(SrsMp4BoxTypeSTSZ); @@ -4840,10 +4852,19 @@ srs_error_t SrsMp4SampleManager::write(SrsMp4MovieBox* moov) SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); stbl->set_stsz(stsz); - SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); - stbl->set_stco(stco); + SrsMp4FullBox* co = NULL; + // When sample offset less than UINT32_MAX, we use stco(support 32bit offset) box to save storage space. + if (samples.empty() || (*samples.rbegin())->offset < UINT32_MAX) { + // stco support 32bit offset. + co = new SrsMp4ChunkOffsetBox(); + stbl->set_stco(static_cast(co)); + } else { + // When sample offset bigger than UINT32_MAX, we use co64(support 64bit offset) box to avoid overflow. + co = new SrsMp4ChunkLargeOffsetBox(); + stbl->set_co64(static_cast(co)); + } - if ((err = write_track(SrsFrameTypeVideo, stts, stss, ctts, stsc, stsz, stco)) != srs_success) { + if ((err = write_track(SrsFrameTypeVideo, stts, stss, ctts, stsc, stsz, co)) != srs_success) { return srs_error_wrap(err, "write vide track"); } } @@ -4864,10 +4885,16 @@ srs_error_t SrsMp4SampleManager::write(SrsMp4MovieBox* moov) SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); stbl->set_stsz(stsz); - SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); - stbl->set_stco(stco); + SrsMp4FullBox* co = NULL; + if (samples.empty() || (*samples.rbegin())->offset < UINT32_MAX) { + co = new SrsMp4ChunkOffsetBox(); + stbl->set_stco(static_cast(co)); + } else { + co = new SrsMp4ChunkLargeOffsetBox(); + stbl->set_co64(static_cast(co)); + } - if ((err = write_track(SrsFrameTypeAudio, stts, stss, ctts, stsc, stsz, stco)) != srs_success) { + if ((err = write_track(SrsFrameTypeAudio, stts, stss, ctts, stsc, stsz, co)) != srs_success) { return srs_error_wrap(err, "write soun track"); } } @@ -4919,7 +4946,7 @@ srs_error_t SrsMp4SampleManager::write(SrsMp4MovieFragmentBox* moof, uint64_t& d srs_error_t SrsMp4SampleManager::write_track(SrsFrameType track, SrsMp4DecodingTime2SampleBox* stts, SrsMp4SyncSampleBox* stss, SrsMp4CompositionTime2SampleBox* ctts, - SrsMp4Sample2ChunkBox* stsc, SrsMp4SampleSizeBox* stsz, SrsMp4ChunkOffsetBox* stco) + SrsMp4Sample2ChunkBox* stsc, SrsMp4SampleSizeBox* stsz, SrsMp4FullBox* co) { srs_error_t err = srs_success; @@ -4930,7 +4957,7 @@ srs_error_t SrsMp4SampleManager::write_track(SrsFrameType track, vector ctts_entries; vector stsz_entries; - vector stco_entries; + vector co_entries; vector stss_entries; SrsMp4Sample* previous = NULL; @@ -4942,7 +4969,7 @@ srs_error_t SrsMp4SampleManager::write_track(SrsFrameType track, } stsz_entries.push_back(sample->nb_data); - stco_entries.push_back((uint32_t)sample->offset); + co_entries.push_back((uint64_t)sample->offset); if (sample->frame_type == SrsVideoAvcFrameTypeKeyFrame) { stss_entries.push_back(sample->index + 1); @@ -5015,11 +5042,22 @@ srs_error_t SrsMp4SampleManager::write_track(SrsFrameType track, } } - if (stco && !stco_entries.empty()) { - stco->entry_count = (uint32_t)stco_entries.size(); - stco->entries = new uint32_t[stco->entry_count]; - for (int i = 0; i < (int)stco->entry_count; i++) { - stco->entries[i] = stco_entries.at(i); + if (!co_entries.empty()) { + SrsMp4ChunkOffsetBox* stco = dynamic_cast(co); + SrsMp4ChunkLargeOffsetBox* co64 = dynamic_cast(co); + + if (stco) { + stco->entry_count = (uint32_t)co_entries.size(); + stco->entries = new uint32_t[stco->entry_count]; + for (int i = 0; i < (int)stco->entry_count; i++) { + stco->entries[i] = co_entries.at(i); + } + } else if (co64) { + co64->entry_count = (uint32_t)co_entries.size(); + co64->entries = new uint64_t[co64->entry_count]; + for (int i = 0; i < (int)co64->entry_count; i++) { + co64->entries[i] = co_entries.at(i); + } } } @@ -6162,6 +6200,7 @@ srs_error_t SrsMp4M2tsInitEncoder::write(SrsFormat* format, bool video, int tid) SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); stbl->set_stsz(stsz); + // TODO: FIXME: need to check using stco or co64? SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); stbl->set_stco(stco); @@ -6262,6 +6301,7 @@ srs_error_t SrsMp4M2tsInitEncoder::write(SrsFormat* format, bool video, int tid) SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); stbl->set_stsz(stsz); + // TODO: FIXME: need to check using stco or co64? SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); stbl->set_stco(stco); diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index 37a58cda9..76fc06d81 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -36,6 +36,7 @@ class SrsMp4AvccBox; class SrsMp4AudioSampleEntry; class SrsMp4EsdsBox; class SrsMp4ChunkOffsetBox; +class SrsMp4ChunkLargeOffsetBox; class SrsMp4SampleSizeBox; class SrsMp4Sample2ChunkBox; class SrsMp4DecodingTime2SampleBox; @@ -1188,6 +1189,9 @@ public: // Get the chunk offset box. virtual SrsMp4ChunkOffsetBox* stco(); virtual void set_stco(SrsMp4ChunkOffsetBox* v); + // Get the chunk large offset box. + virtual SrsMp4ChunkLargeOffsetBox* co64(); + virtual void set_co64(SrsMp4ChunkLargeOffsetBox* v); // Get the sample size box. virtual SrsMp4SampleSizeBox* stsz(); virtual void set_stsz(SrsMp4SampleSizeBox* v); @@ -1902,7 +1906,7 @@ public: private: virtual srs_error_t write_track(SrsFrameType track, SrsMp4DecodingTime2SampleBox* stts, SrsMp4SyncSampleBox* stss, SrsMp4CompositionTime2SampleBox* ctts, - SrsMp4Sample2ChunkBox* stsc, SrsMp4SampleSizeBox* stsz, SrsMp4ChunkOffsetBox* stco); + SrsMp4Sample2ChunkBox* stsc, SrsMp4SampleSizeBox* stsz, SrsMp4FullBox* co); virtual srs_error_t do_load(std::map& tses, SrsMp4MovieBox* moov); private: // Load the samples of track from stco, stsz and stsc.