From 721a8457c2bba2892a1d32652867a1447933dbd0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 19 Mar 2017 12:29:38 +0800 Subject: [PATCH] For #299, Refine init mp4, use fragment --- .gitignore | 1 + trunk/.gitignore | 1 + trunk/src/app/srs_app_dash.cpp | 505 +++++++++++++++++---------------- trunk/src/app/srs_app_dash.hpp | 18 +- 4 files changed, 280 insertions(+), 245 deletions(-) diff --git a/.gitignore b/.gitignore index 399419fa4..5d1abdd98 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ # by winlin *.pyc *.swp +.DS_Store /trunk/Makefile /trunk/objs /trunk/src/build-qt-Desktop-Debug diff --git a/trunk/.gitignore b/trunk/.gitignore index e7e378513..8d1f8e4ec 100644 --- a/trunk/.gitignore +++ b/trunk/.gitignore @@ -1,5 +1,6 @@ .idea/ /*.conf +/*.txt /*.flv /doc/frozen*.flv /doc/kungfupanda*.flv diff --git a/trunk/src/app/srs_app_dash.cpp b/trunk/src/app/srs_app_dash.cpp index f12f0e958..4f0552130 100644 --- a/trunk/src/app/srs_app_dash.cpp +++ b/trunk/src/app/srs_app_dash.cpp @@ -37,6 +37,258 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include using namespace std; +SrsInitMp4::SrsInitMp4() +{ + fw = new SrsFileWriter(); +} + +SrsInitMp4::~SrsInitMp4() +{ + srs_freep(fw); +} + +int SrsInitMp4::write(SrsFormat* format, bool video, int tid) +{ + int ret = ERROR_SUCCESS; + + string path_tmp = fullpath() + ".tmp"; + if ((ret = fw->open(path_tmp)) != ERROR_SUCCESS) { + srs_error("DASH: Open media failed, path=%s, ret=%d", path_tmp.c_str(), ret); + return ret; + } + + // Write ftyp box. + SrsMp4FileTypeBox* ftyp = new SrsMp4FileTypeBox(); + SrsAutoFree(SrsMp4FileTypeBox, ftyp); + if (true) { + ftyp->major_brand = SrsMp4BoxBrandISO5; + ftyp->minor_version = 0; + ftyp->set_compatible_brands(SrsMp4BoxBrandISOM, SrsMp4BoxBrandISO5, SrsMp4BoxBrandDASH, SrsMp4BoxBrandMP42); + } + + // Write moov. + SrsMp4MovieBox* moov = new SrsMp4MovieBox(); + SrsAutoFree(SrsMp4MovieBox, moov); + if (true) { + SrsMp4MovieHeaderBox* mvhd = new SrsMp4MovieHeaderBox(); + moov->set_mvhd(mvhd); + + mvhd->timescale = 1000; // Use tbn ms. + mvhd->duration_in_tbn = 0; + mvhd->next_track_ID = tid; + + if (video) { + SrsMp4TrackBox* trak = new SrsMp4TrackBox(); + moov->add_trak(trak); + + SrsMp4TrackHeaderBox* tkhd = new SrsMp4TrackHeaderBox(); + trak->set_tkhd(tkhd); + + tkhd->track_ID = mvhd->next_track_ID++; + tkhd->duration = 0; + tkhd->width = (format->vcodec->width << 16); + tkhd->height = (format->vcodec->height << 16); + + SrsMp4MediaBox* mdia = new SrsMp4MediaBox(); + trak->set_mdia(mdia); + + SrsMp4MediaHeaderBox* mdhd = new SrsMp4MediaHeaderBox(); + mdia->set_mdhd(mdhd); + + mdhd->timescale = 1000; + mdhd->duration = 0; + mdhd->set_language0('u'); + mdhd->set_language1('n'); + mdhd->set_language2('d'); + + SrsMp4HandlerReferenceBox* hdlr = new SrsMp4HandlerReferenceBox(); + mdia->set_hdlr(hdlr); + + hdlr->handler_type = SrsMp4HandlerTypeVIDE; + hdlr->name = "VideoHandler"; + + SrsMp4MediaInformationBox* minf = new SrsMp4MediaInformationBox(); + mdia->set_minf(minf); + + SrsMp4VideoMeidaHeaderBox* vmhd = new SrsMp4VideoMeidaHeaderBox(); + minf->set_vmhd(vmhd); + + SrsMp4DataInformationBox* dinf = new SrsMp4DataInformationBox(); + minf->set_dinf(dinf); + + SrsMp4DataReferenceBox* dref = new SrsMp4DataReferenceBox(); + dinf->set_dref(dref); + + SrsMp4DataEntryBox* url = new SrsMp4DataEntryUrlBox(); + dref->append(url); + + SrsMp4SampleTableBox* stbl = new SrsMp4SampleTableBox(); + minf->set_stbl(stbl); + + SrsMp4SampleDescriptionBox* stsd = new SrsMp4SampleDescriptionBox(); + stbl->set_stsd(stsd); + + SrsMp4VisualSampleEntry* avc1 = new SrsMp4VisualSampleEntry(); + stsd->append(avc1); + + avc1->width = format->vcodec->width; + avc1->height = format->vcodec->height; + + SrsMp4AvccBox* avcC = new SrsMp4AvccBox(); + avc1->set_avcC(avcC); + + avcC->nb_config = format->vcodec->avc_extra_size; + avcC->avc_config = new uint8_t[format->vcodec->avc_extra_size]; + memcpy(avcC->avc_config, format->vcodec->avc_extra_data, format->vcodec->avc_extra_size); + + SrsMp4DecodingTime2SampleBox* stts = new SrsMp4DecodingTime2SampleBox(); + stbl->set_stts(stts); + + SrsMp4Sample2ChunkBox* stsc = new SrsMp4Sample2ChunkBox(); + stbl->set_stsc(stsc); + + SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); + stbl->set_stsz(stsz); + + SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); + stbl->set_stco(stco); + + SrsMp4MovieExtendsBox* mvex = new SrsMp4MovieExtendsBox(); + moov->set_mvex(mvex); + + SrsMp4TrackExtendsBox* trex = new SrsMp4TrackExtendsBox(); + mvex->set_trex(trex); + + trex->track_ID = tid; + trex->default_sample_description_index = 1; + } else { + SrsMp4TrackBox* trak = new SrsMp4TrackBox(); + moov->add_trak(trak); + + SrsMp4TrackHeaderBox* tkhd = new SrsMp4TrackHeaderBox(); + tkhd->volume = 0x0100; + trak->set_tkhd(tkhd); + + tkhd->track_ID = mvhd->next_track_ID++; + tkhd->duration = 0; + + SrsMp4MediaBox* mdia = new SrsMp4MediaBox(); + trak->set_mdia(mdia); + + SrsMp4MediaHeaderBox* mdhd = new SrsMp4MediaHeaderBox(); + mdia->set_mdhd(mdhd); + + mdhd->timescale = 1000; + mdhd->duration = 0; + mdhd->set_language0('u'); + mdhd->set_language1('n'); + mdhd->set_language2('d'); + + SrsMp4HandlerReferenceBox* hdlr = new SrsMp4HandlerReferenceBox(); + mdia->set_hdlr(hdlr); + + hdlr->handler_type = SrsMp4HandlerTypeSOUN; + hdlr->name = "SoundHandler"; + + SrsMp4MediaInformationBox* minf = new SrsMp4MediaInformationBox(); + mdia->set_minf(minf); + + SrsMp4SoundMeidaHeaderBox* smhd = new SrsMp4SoundMeidaHeaderBox(); + minf->set_smhd(smhd); + + SrsMp4DataInformationBox* dinf = new SrsMp4DataInformationBox(); + minf->set_dinf(dinf); + + SrsMp4DataReferenceBox* dref = new SrsMp4DataReferenceBox(); + dinf->set_dref(dref); + + SrsMp4DataEntryBox* url = new SrsMp4DataEntryUrlBox(); + dref->append(url); + + SrsMp4SampleTableBox* stbl = new SrsMp4SampleTableBox(); + minf->set_stbl(stbl); + + SrsMp4SampleDescriptionBox* stsd = new SrsMp4SampleDescriptionBox(); + stbl->set_stsd(stsd); + + SrsMp4AudioSampleEntry* mp4a = new SrsMp4AudioSampleEntry(); + mp4a->samplerate = uint32_t(srs_flv_srates[format->acodec->sound_rate]) << 16; + if (format->acodec->sound_size == SrsAudioSampleBits16bit) { + mp4a->samplesize = 16; + } else { + mp4a->samplesize = 8; + } + if (format->acodec->sound_type == SrsAudioChannelsStereo) { + mp4a->channelcount = 2; + } else { + mp4a->channelcount = 1; + } + stsd->append(mp4a); + + SrsMp4EsdsBox* esds = new SrsMp4EsdsBox(); + mp4a->set_esds(esds); + + SrsMp4ES_Descriptor* es = esds->es; + es->ES_ID = 0x02; + + SrsMp4DecoderConfigDescriptor& desc = es->decConfigDescr; + desc.objectTypeIndication = SrsMp4ObjectTypeAac; + desc.streamType = SrsMp4StreamTypeAudioStream; + srs_freep(desc.decSpecificInfo); + + SrsMp4DecoderSpecificInfo* asc = new SrsMp4DecoderSpecificInfo(); + desc.decSpecificInfo = asc; + asc->nb_asc = format->acodec->aac_extra_size; + asc->asc = new uint8_t[format->acodec->aac_extra_size]; + memcpy(asc->asc, format->acodec->aac_extra_data, format->acodec->aac_extra_size); + + SrsMp4DecodingTime2SampleBox* stts = new SrsMp4DecodingTime2SampleBox(); + stbl->set_stts(stts); + + SrsMp4Sample2ChunkBox* stsc = new SrsMp4Sample2ChunkBox(); + stbl->set_stsc(stsc); + + SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); + stbl->set_stsz(stsz); + + SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); + stbl->set_stco(stco); + + SrsMp4MovieExtendsBox* mvex = new SrsMp4MovieExtendsBox(); + moov->set_mvex(mvex); + + SrsMp4TrackExtendsBox* trex = new SrsMp4TrackExtendsBox(); + mvex->set_trex(trex); + + trex->track_ID = tid; + trex->default_sample_description_index = 1; + } + } + + int nb_data = ftyp->nb_bytes() + moov->nb_bytes(); + uint8_t* data = new uint8_t[nb_data]; + SrsAutoFreeA(uint8_t, data); + + SrsBuffer* buffer = new SrsBuffer(); + SrsAutoFree(SrsBuffer, buffer); + if ((ret = buffer->initialize((char*)data, nb_data)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = ftyp->encode(buffer)) != ERROR_SUCCESS) { + return ret; + } + if ((ret = moov->encode(buffer)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = fw->write(data, nb_data, NULL)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + SrsFragmentedMp4::SrsFragmentedMp4() { } @@ -153,18 +405,13 @@ SrsDashController::SrsDashController() video_tack_id = 2; audio_track_id = 1; mpd = new SrsMpdWriter(); + fragments = new SrsFragmentWindow(); } SrsDashController::~SrsDashController() { srs_freep(mpd); - - vector::iterator it; - for (it = fragments.begin(); it != fragments.end(); ++it) { - SrsFragmentedMp4* fragment = *it; - srs_freep(fragment); - } - fragments.clear(); + srs_freep(fragments); } int SrsDashController::initialize(SrsRequest* r) @@ -252,247 +499,17 @@ int SrsDashController::refresh_init_mp4(SrsSharedPtrMessage* msg, SrsFormat* for path += "/audio-init.mp4"; } - SrsFileWriter* fw = new SrsFileWriter(); - SrsAutoFree(SrsFileWriter, fw); + SrsInitMp4* init_mp4 = new SrsInitMp4(); + SrsAutoFree(SrsInitMp4, init_mp4); - string path_tmp = path + ".tmp"; - if ((ret = fw->open(path_tmp)) != ERROR_SUCCESS) { - srs_error("DASH: Open media failed, path=%s, ret=%d", path_tmp.c_str(), ret); + init_mp4->set_path(path); + + int tid = msg->is_video()? video_tack_id:audio_track_id; + if ((ret = init_mp4->write(format, msg->is_video(), tid)) != ERROR_SUCCESS) { return ret; } - // Write ftyp box. - SrsMp4FileTypeBox* ftyp = new SrsMp4FileTypeBox(); - SrsAutoFree(SrsMp4FileTypeBox, ftyp); - if (true) { - ftyp->major_brand = SrsMp4BoxBrandISO5; - ftyp->minor_version = 0; - ftyp->set_compatible_brands(SrsMp4BoxBrandISOM, SrsMp4BoxBrandISO5, SrsMp4BoxBrandDASH, SrsMp4BoxBrandMP42); - } - - // Write moov. - SrsMp4MovieBox* moov = new SrsMp4MovieBox(); - SrsAutoFree(SrsMp4MovieBox, moov); - if (true) { - SrsMp4MovieHeaderBox* mvhd = new SrsMp4MovieHeaderBox(); - moov->set_mvhd(mvhd); - - mvhd->timescale = 1000; // Use tbn ms. - mvhd->duration_in_tbn = 0; - mvhd->next_track_ID = (msg->is_video()? video_tack_id : audio_track_id); - - if (msg->is_video()) { - SrsMp4TrackBox* trak = new SrsMp4TrackBox(); - moov->add_trak(trak); - - SrsMp4TrackHeaderBox* tkhd = new SrsMp4TrackHeaderBox(); - trak->set_tkhd(tkhd); - - tkhd->track_ID = mvhd->next_track_ID++; - tkhd->duration = 0; - tkhd->width = (format->vcodec->width << 16); - tkhd->height = (format->vcodec->height << 16); - - SrsMp4MediaBox* mdia = new SrsMp4MediaBox(); - trak->set_mdia(mdia); - - SrsMp4MediaHeaderBox* mdhd = new SrsMp4MediaHeaderBox(); - mdia->set_mdhd(mdhd); - - mdhd->timescale = 1000; - mdhd->duration = 0; - mdhd->set_language0('u'); - mdhd->set_language1('n'); - mdhd->set_language2('d'); - - SrsMp4HandlerReferenceBox* hdlr = new SrsMp4HandlerReferenceBox(); - mdia->set_hdlr(hdlr); - - hdlr->handler_type = SrsMp4HandlerTypeVIDE; - hdlr->name = "VideoHandler"; - - SrsMp4MediaInformationBox* minf = new SrsMp4MediaInformationBox(); - mdia->set_minf(minf); - - SrsMp4VideoMeidaHeaderBox* vmhd = new SrsMp4VideoMeidaHeaderBox(); - minf->set_vmhd(vmhd); - - SrsMp4DataInformationBox* dinf = new SrsMp4DataInformationBox(); - minf->set_dinf(dinf); - - SrsMp4DataReferenceBox* dref = new SrsMp4DataReferenceBox(); - dinf->set_dref(dref); - - SrsMp4DataEntryBox* url = new SrsMp4DataEntryUrlBox(); - dref->append(url); - - SrsMp4SampleTableBox* stbl = new SrsMp4SampleTableBox(); - minf->set_stbl(stbl); - - SrsMp4SampleDescriptionBox* stsd = new SrsMp4SampleDescriptionBox(); - stbl->set_stsd(stsd); - - SrsMp4VisualSampleEntry* avc1 = new SrsMp4VisualSampleEntry(); - stsd->append(avc1); - - avc1->width = format->vcodec->width; - avc1->height = format->vcodec->height; - - SrsMp4AvccBox* avcC = new SrsMp4AvccBox(); - avc1->set_avcC(avcC); - - avcC->nb_config = format->vcodec->avc_extra_size; - avcC->avc_config = new uint8_t[format->vcodec->avc_extra_size]; - memcpy(avcC->avc_config, format->vcodec->avc_extra_data, format->vcodec->avc_extra_size); - - SrsMp4DecodingTime2SampleBox* stts = new SrsMp4DecodingTime2SampleBox(); - stbl->set_stts(stts); - - SrsMp4Sample2ChunkBox* stsc = new SrsMp4Sample2ChunkBox(); - stbl->set_stsc(stsc); - - SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); - stbl->set_stsz(stsz); - - SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); - stbl->set_stco(stco); - - SrsMp4MovieExtendsBox* mvex = new SrsMp4MovieExtendsBox(); - moov->set_mvex(mvex); - - SrsMp4TrackExtendsBox* trex = new SrsMp4TrackExtendsBox(); - mvex->set_trex(trex); - - trex->track_ID = video_tack_id; - trex->default_sample_description_index = 1; - } else { - SrsMp4TrackBox* trak = new SrsMp4TrackBox(); - moov->add_trak(trak); - - SrsMp4TrackHeaderBox* tkhd = new SrsMp4TrackHeaderBox(); - tkhd->volume = 0x0100; - trak->set_tkhd(tkhd); - - tkhd->track_ID = mvhd->next_track_ID++; - tkhd->duration = 0; - - SrsMp4MediaBox* mdia = new SrsMp4MediaBox(); - trak->set_mdia(mdia); - - SrsMp4MediaHeaderBox* mdhd = new SrsMp4MediaHeaderBox(); - mdia->set_mdhd(mdhd); - - mdhd->timescale = 1000; - mdhd->duration = 0; - mdhd->set_language0('u'); - mdhd->set_language1('n'); - mdhd->set_language2('d'); - - SrsMp4HandlerReferenceBox* hdlr = new SrsMp4HandlerReferenceBox(); - mdia->set_hdlr(hdlr); - - hdlr->handler_type = SrsMp4HandlerTypeSOUN; - hdlr->name = "SoundHandler"; - - SrsMp4MediaInformationBox* minf = new SrsMp4MediaInformationBox(); - mdia->set_minf(minf); - - SrsMp4SoundMeidaHeaderBox* smhd = new SrsMp4SoundMeidaHeaderBox(); - minf->set_smhd(smhd); - - SrsMp4DataInformationBox* dinf = new SrsMp4DataInformationBox(); - minf->set_dinf(dinf); - - SrsMp4DataReferenceBox* dref = new SrsMp4DataReferenceBox(); - dinf->set_dref(dref); - - SrsMp4DataEntryBox* url = new SrsMp4DataEntryUrlBox(); - dref->append(url); - - SrsMp4SampleTableBox* stbl = new SrsMp4SampleTableBox(); - minf->set_stbl(stbl); - - SrsMp4SampleDescriptionBox* stsd = new SrsMp4SampleDescriptionBox(); - stbl->set_stsd(stsd); - - SrsMp4AudioSampleEntry* mp4a = new SrsMp4AudioSampleEntry(); - mp4a->samplerate = uint32_t(srs_flv_srates[format->acodec->sound_rate]) << 16; - if (format->acodec->sound_size == SrsAudioSampleBits16bit) { - mp4a->samplesize = 16; - } else { - mp4a->samplesize = 8; - } - if (format->acodec->sound_type == SrsAudioChannelsStereo) { - mp4a->channelcount = 2; - } else { - mp4a->channelcount = 1; - } - stsd->append(mp4a); - - SrsMp4EsdsBox* esds = new SrsMp4EsdsBox(); - mp4a->set_esds(esds); - - SrsMp4ES_Descriptor* es = esds->es; - es->ES_ID = 0x02; - - SrsMp4DecoderConfigDescriptor& desc = es->decConfigDescr; - desc.objectTypeIndication = SrsMp4ObjectTypeAac; - desc.streamType = SrsMp4StreamTypeAudioStream; - srs_freep(desc.decSpecificInfo); - - SrsMp4DecoderSpecificInfo* asc = new SrsMp4DecoderSpecificInfo(); - desc.decSpecificInfo = asc; - asc->nb_asc = format->acodec->aac_extra_size; - asc->asc = new uint8_t[format->acodec->aac_extra_size]; - memcpy(asc->asc, format->acodec->aac_extra_data, format->acodec->aac_extra_size); - - SrsMp4DecodingTime2SampleBox* stts = new SrsMp4DecodingTime2SampleBox(); - stbl->set_stts(stts); - - SrsMp4Sample2ChunkBox* stsc = new SrsMp4Sample2ChunkBox(); - stbl->set_stsc(stsc); - - SrsMp4SampleSizeBox* stsz = new SrsMp4SampleSizeBox(); - stbl->set_stsz(stsz); - - SrsMp4ChunkOffsetBox* stco = new SrsMp4ChunkOffsetBox(); - stbl->set_stco(stco); - - SrsMp4MovieExtendsBox* mvex = new SrsMp4MovieExtendsBox(); - moov->set_mvex(mvex); - - SrsMp4TrackExtendsBox* trex = new SrsMp4TrackExtendsBox(); - mvex->set_trex(trex); - - trex->track_ID = audio_track_id; - trex->default_sample_description_index = 1; - } - } - - int nb_data = ftyp->nb_bytes() + moov->nb_bytes(); - uint8_t* data = new uint8_t[nb_data]; - SrsAutoFreeA(uint8_t, data); - - SrsBuffer* buffer = new SrsBuffer(); - SrsAutoFree(SrsBuffer, buffer); - if ((ret = buffer->initialize((char*)data, nb_data)) != ERROR_SUCCESS) { - return ret; - } - - if ((ret = ftyp->encode(buffer)) != ERROR_SUCCESS) { - return ret; - } - if ((ret = moov->encode(buffer)) != ERROR_SUCCESS) { - return ret; - } - - if ((ret = fw->write(data, nb_data, NULL)) != ERROR_SUCCESS) { - return ret; - } - - if (::rename(path_tmp.c_str(), path.c_str()) < 0) { - ret = ERROR_DASH_WRITE_FAILED; - srs_error("DASH: Rename %s to %s failed, ret=%d", path_tmp.c_str(), path.c_str(), ret); + if ((ret = init_mp4->rename()) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/app/srs_app_dash.hpp b/trunk/src/app/srs_app_dash.hpp index cda6f6520..46ab9d4c7 100644 --- a/trunk/src/app/srs_app_dash.hpp +++ b/trunk/src/app/srs_app_dash.hpp @@ -38,6 +38,22 @@ class SrsRequest; class SrsOriginHub; class SrsSharedPtrMessage; class SrsFormat; +class SrsFileWriter; + +/** + * The init mp4 for FMP4. + */ +class SrsInitMp4 : public SrsFragment +{ +private: + SrsFileWriter* fw; +public: + SrsInitMp4(); + virtual ~SrsInitMp4(); +public: + // Write the init mp4 file, with the tid(track id). + virtual int write(SrsFormat* format, bool video, int tid); +}; /** * The FMP4(Fragmented MP4) for DASH streaming. @@ -85,7 +101,7 @@ class SrsDashController private: SrsRequest* req; SrsMpdWriter* mpd; - std::vector fragments; + SrsFragmentWindow* fragments; private: std::string home; int video_tack_id;