1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00

for #738, refine build mp4 samples from moov.

This commit is contained in:
winlin 2017-02-04 22:45:52 +08:00
parent 3025aebf42
commit e24674e9cf
2 changed files with 78 additions and 17 deletions

View file

@ -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<uint64_t, SrsMp4Sample*>& 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<uint64_t, SrsMp4Sample*>& 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<uint64_t, SrsMp4Sample*>& 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;
}

View file

@ -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);