diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index 5481919cc..fc02b9586 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -2798,6 +2798,16 @@ SrsMp4SyncSampleBox::~SrsMp4SyncSampleBox() srs_freepa(sample_numbers); } +bool SrsMp4SyncSampleBox::is_sync(uint32_t sample_index) +{ + for (uint32_t i = 0; i < entry_count; i++) { + if (sample_index + 1 == sample_numbers[i]) { + return true; + } + } + return false; +} + int SrsMp4SyncSampleBox::nb_header() { return SrsMp4FullBox::nb_header() +4 +4*entry_count; @@ -2852,6 +2862,7 @@ SrsMp4Sample2ChunkBox::SrsMp4Sample2ChunkBox() entry_count = 0; entries = NULL; + index = 0; } SrsMp4Sample2ChunkBox::~SrsMp4Sample2ChunkBox() @@ -2859,6 +2870,25 @@ SrsMp4Sample2ChunkBox::~SrsMp4Sample2ChunkBox() srs_freepa(entries); } +void SrsMp4Sample2ChunkBox::initialize_counter() +{ + index = 0; +} + +SrsMp4StscEntry* SrsMp4Sample2ChunkBox::on_chunk(uint32_t chunk_index) +{ + // Last chunk? + if (index >= entry_count - 1) { + return &entries[index]; + } + + // Move next chunk? + if (chunk_index + 1 >= entries[index + 1].first_chunk) { + index++; + } + return &entries[index]; +} + int SrsMp4Sample2ChunkBox::nb_header() { return SrsMp4FullBox::nb_header() +4 + 12*entry_count; @@ -3024,6 +3054,24 @@ SrsMp4SampleSizeBox::~SrsMp4SampleSizeBox() srs_freepa(entry_sizes); } +int SrsMp4SampleSizeBox::get_sample_size(uint32_t sample_index, uint32_t* psample_size) +{ + int ret = ERROR_SUCCESS; + + if (sample_size != 0) { + *psample_size = sample_size; + return ret; + } + + if (sample_index >= sample_count) { + ret = ERROR_MP4_MOOV_OVERFLOW; + srs_error("MP4 stsz overflow, sample_count=%d. ret=%d", sample_count, ret); + } + *psample_size = entry_sizes[sample_index]; + + return ret; +} + int SrsMp4SampleSizeBox::nb_header() { int size = SrsMp4FullBox::nb_header() +4+4; @@ -3247,7 +3295,7 @@ int SrsMp4SampleManager::load_trak(map& tses, SrsCodecF int ret = ERROR_SUCCESS; // Samples per chunk. - uint32_t stsci = 0; + stsc->initialize_counter(); // DTS box. if ((ret = stts->initialize_counter()) != ERROR_SUCCESS) { @@ -3262,29 +3310,20 @@ int SrsMp4SampleManager::load_trak(map& tses, SrsCodecF SrsMp4Sample* previous = NULL; // For each chunk offset. - for (uint32_t stcoi = 0; stcoi < stco->entry_count; stcoi++) { - uint32_t chunk_offset = stco->entries[stcoi]; - + for (uint32_t ci = 0; ci < stco->entry_count; ci++) { // Find how many samples from stsc. - if (stsci < stsc->entry_count - 1 && stcoi + 1 >= stsc->entries[stsci + 1].first_chunk) { - stsci++; - } - uint32_t samples_per_chunk = stsc->entries[stsci].samples_per_chunk; - for (uint32_t i = 0; i < samples_per_chunk; i++) { + SrsMp4StscEntry* stsc_entry = stsc->on_chunk(ci); + for (uint32_t i = 0; i < stsc_entry->samples_per_chunk; i++) { SrsMp4Sample* sample = new SrsMp4Sample(); sample->type = tt; sample->index = (previous? previous->index+1:0); sample->tbn = mdhd->timescale; - uint32_t sample_size = stsz->sample_size; - if (sample_size == 0) { - if (sample->index >= stsz->sample_count) { - ret = ERROR_MP4_MOOV_OVERFLOW; - srs_error("MP4 stsz overflow, sample_count=%d. ret=%d", stsz->sample_count, ret); - } - sample_size = stsz->entry_sizes[sample->index]; + uint32_t sample_size = 0; + if ((ret = stsz->get_sample_size(sample->index, &sample_size)) != ERROR_SUCCESS) { + return ret; } - sample->offset = chunk_offset + sample_size * i; + sample->offset = stco->entries[ci] + sample_size * i; SrsMp4SttsEntry* stts_entry = NULL; if ((ret = stts->on_sample(sample->index, &stts_entry)) != ERROR_SUCCESS) { @@ -3302,6 +3341,14 @@ int SrsMp4SampleManager::load_trak(map& tses, SrsCodecF sample->pts = sample->dts + ctts_entry->sample_offset; } + if (tt == SrsCodecFlvTagVideo) { + if (!stss || stss->is_sync(sample->index)) { + sample->frame_type = SrsCodecVideoAVCFrameKeyFrame; + } else { + sample->frame_type = SrsCodecVideoAVCFrameInterFrame; + } + } + previous = sample; tses[sample->offset] = sample; } diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index f1341d13a..a9c48bdc4 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -1247,6 +1247,9 @@ public: public: SrsMp4SyncSampleBox(); virtual ~SrsMp4SyncSampleBox(); +public: + // Whether the sample is sync, index starts from 0. + virtual bool is_sync(uint32_t sample_index); protected: virtual int nb_header(); virtual int encode_header(SrsBuffer* buf); @@ -1288,9 +1291,17 @@ public: uint32_t entry_count; // the numbers of the samples that are sync samples in the stream. SrsMp4StscEntry* entries; +private: + // The index for counter to calc the dts for samples. + uint32_t index; public: SrsMp4Sample2ChunkBox(); virtual ~SrsMp4Sample2ChunkBox(); +public: + // Initialize the counter. + virtual void initialize_counter(); + // When got an chunk, index starts from 0. + virtual SrsMp4StscEntry* on_chunk(uint32_t chunk_index); protected: virtual int nb_header(); virtual int encode_header(SrsBuffer* buf); @@ -1367,6 +1378,9 @@ public: public: SrsMp4SampleSizeBox(); virtual ~SrsMp4SampleSizeBox(); +public: + // Get the size of sample. + virtual int get_sample_size(uint32_t sample_index, uint32_t* psample_size); protected: virtual int nb_header(); virtual int encode_header(SrsBuffer* buf);