From 6c64297264474b6f9e99aa86646bf0f9bd8fede8 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 30 May 2017 19:40:03 +0800 Subject: [PATCH] Fix #821, support MP4 file parser. 3.0.24 --- README.md | 2 + trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_mp4.cpp | 306 +++++++++++++++---------- trunk/src/kernel/srs_kernel_mp4.hpp | 83 ++++--- trunk/src/main/srs_main_mp4_parser.cpp | 24 +- 5 files changed, 254 insertions(+), 163 deletions(-) diff --git a/README.md b/README.md index 8f02ddb245..214aaef827 100755 --- a/README.md +++ b/README.md @@ -190,6 +190,7 @@ Please select your language: ### V3 changes +* v3.0, 2017-05-30, Fix [#821][bug #821], support MP4 file parser. 3.0.24 * v3.0, 2017-05-30, Fix [#904][bug #904], replace NXJSON(LGPL) with json-parser(BSD). 3.0.23 * v3.0, 2017-04-16, Fix [#547][bug #547], support HLS audio in TS. 3.0.22 * v3.0, 2017-03-26, Fix [#820][bug #820], extract service for modules. 3.0.21 @@ -1420,6 +1421,7 @@ Winlin [bug #820]: https://github.com/ossrs/srs/issues/820 [bug #547]: https://github.com/ossrs/srs/issues/547 [bug #904]: https://github.com/ossrs/srs/issues/904 +[bug #821]: https://github.com/ossrs/srs/issues/821 [bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index f5c7520203..e6d755f95d 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -27,7 +27,7 @@ // current release version #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_REVISION 23 +#define VERSION_REVISION 24 // generated by configure, only macros. #include diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index 9e0d690fe9..f9cbb27628 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -41,9 +41,9 @@ using namespace std; #define SRS_MP4_BUF_SIZE 4096 -stringstream& srs_padding(stringstream& ss, int level, int tab = 4) +stringstream& srs_padding(stringstream& ss, SrsMp4DumpContext dc, int tab = 4) { - for (int i = 0; i < level; i++) { + for (int i = 0; i < dc.level; i++) { for (int j = 0; j < tab; j++) { ss << " "; } @@ -57,89 +57,105 @@ stringstream& srs_print_mp4_type(stringstream& ss, uint32_t v) return ss; } +#define SrsSummaryCount 8 + template -stringstream& __srs_print_mp4_vector(std::vector& arr, stringstream& ss, int level, bool is_box) +stringstream& srs_dumps_array(std::vector&arr, stringstream& ss, SrsMp4DumpContext dc, + void (*pfn)(T&, stringstream&, SrsMp4DumpContext), + void (*delimiter)(stringstream&,SrsMp4DumpContext)) { - for (size_t i = 0; i < arr.size(); i++) { - T elem = arr[i]; + int limit = arr.size(); + if (dc.summary) { + limit = srs_min(SrsSummaryCount, limit); + } + + for (size_t i = 0; i < limit; i++) { + T& elem = arr[i]; - if (is_box) { - elem.dumps(ss, level); - } else { - elem.dumps_detail(ss, level); - } + pfn(elem, ss, dc); - if (i < arr.size() - 1) { - ss << endl; - srs_padding(ss, level); + if (i < limit - 1) { + delimiter(ss, dc); } } return ss; } template -stringstream& srs_print_mp4_vector(std::vector& arr, stringstream& ss, int level) -{ - return __srs_print_mp4_vector(arr, ss, level, false); -} - -template -stringstream& __srs_print_mp4_vector_ptr(std::vector& arr, stringstream& ss, int level, bool is_box) +stringstream& srs_dumps_array(T* arr, int size, stringstream& ss, SrsMp4DumpContext dc, + void (*pfn)(T&, stringstream&, SrsMp4DumpContext), + void (*delimiter)(stringstream&, SrsMp4DumpContext)) { - for (size_t i = 0; i < arr.size(); i++) { - T elem = arr[i]; + int limit = size; + if (dc.summary) { + limit = srs_min(SrsSummaryCount, limit); + } + + for (size_t i = 0; i < limit; i++) { + T& elem = arr[i]; - if (is_box) { - elem->dumps(ss, level); - } else { - elem->dumps_detail(ss, level); - } + pfn(elem, ss, dc); - if (i < arr.size() - 1) { - ss << endl; - srs_padding(ss, level); + if (i < limit - 1) { + delimiter(ss, dc); } } return ss; } +void srs_delimiter_inline(stringstream& ss, SrsMp4DumpContext dc) +{ + ss << ","; +} + +void srs_delimiter_inlinespace(stringstream& ss, SrsMp4DumpContext dc) +{ + ss << ", "; +} + +void srs_delimiter_newline(stringstream& ss, SrsMp4DumpContext dc) +{ + ss << endl; + srs_padding(ss, dc); +} + template -stringstream& srs_print_mp4_vector_ptr(std::vector& arr, stringstream& ss, int level) { - return __srs_print_mp4_vector_ptr(arr, ss, level, false); +void srs_pfn_box(T& elem, stringstream& ss, SrsMp4DumpContext dc) +{ + elem.dumps(ss, dc); } template -stringstream& srs_print_mp4_vector_elem(std::vector& arr, stringstream& ss, int level) +void srs_pfn_detail(T& elem, stringstream& ss, SrsMp4DumpContext dc) { - for (size_t i = 0; i < arr.size(); i++) { - srs_print_mp4_type(ss, (uint32_t)arr[i]); - - if (i < arr.size() - 1) { - ss << ","; - } - } - return ss; + elem.dumps_detail(ss, dc); +} + +template +void srs_pfn_pbox(T*& elem, stringstream& ss, SrsMp4DumpContext dc) +{ + elem->dumps(ss, dc); } -template<> -stringstream& srs_print_mp4_vector(std::vector& arr, stringstream& ss, int level) +template +void srs_pfn_pdetail(T*& elem, stringstream& ss, SrsMp4DumpContext dc) { - return srs_print_mp4_vector_elem(arr, ss, level); + elem->dumps_detail(ss, dc); } -template<> -stringstream& srs_print_mp4_vector(std::vector& arr, stringstream& ss, int level) +template +void srs_pfn_types(T& elem, stringstream& ss, SrsMp4DumpContext dc) { - return srs_print_mp4_vector_ptr(arr, ss, level); + srs_print_mp4_type(ss, (uint32_t)elem); } -template<> -stringstream& srs_print_mp4_vector(std::vector& arr, stringstream& ss, int level) +template +void srs_pfn_elems(T& elem, stringstream& ss, SrsMp4DumpContext dc) { - return __srs_print_mp4_vector_ptr(arr, ss, level, true); + ss << elem; } -stringstream& srs_print_bytes(stringstream& ss, const char* p, int size, int level, int line = 16, int max = -1) +stringstream& srs_print_bytes(stringstream& ss, const char* p, int size, SrsMp4DumpContext dc, int line = 16, int max = -1) { if (max == -1) { max = size; @@ -151,7 +167,7 @@ stringstream& srs_print_bytes(stringstream& ss, const char* p, int size, int lev ss << ", "; if (((i+1)%line) == 0) { ss << endl; - srs_padding(ss, level); + srs_padding(ss, dc); } } } @@ -197,6 +213,13 @@ int srs_mp4_string_read(SrsBuffer* buf, string& v, int left) return ret; } +SrsMp4DumpContext SrsMp4DumpContext::indent() +{ + SrsMp4DumpContext ctx = *this; + ctx.level++; + return ctx; +} + SrsMp4Box::SrsMp4Box() { smallsize = 0; @@ -278,9 +301,9 @@ int SrsMp4Box::remove(SrsMp4BoxType bt) return nb_removed; } -stringstream& SrsMp4Box::dumps(stringstream& ss, int level) +stringstream& SrsMp4Box::dumps(stringstream& ss, SrsMp4DumpContext dc) { - srs_padding(ss, level); + srs_padding(ss, dc); srs_print_mp4_type(ss, (uint32_t)type); ss << ", " << sz(); @@ -289,7 +312,7 @@ stringstream& SrsMp4Box::dumps(stringstream& ss, int level) } ss << "B"; - dumps_detail(ss, level); + dumps_detail(ss, dc); if (!boxes.empty()) { ss << ", " << boxes.size() << " boxes"; @@ -304,7 +327,7 @@ stringstream& SrsMp4Box::dumps(stringstream& ss, int level) vector::iterator it; for (it = boxes.begin(); it != boxes.end(); ++it) { SrsMp4Box* box = *it; - box->dumps(ss, level + 1); + box->dumps(ss, dc.indent()); } return ss; @@ -610,7 +633,7 @@ bool SrsMp4Box::boxes_in_header() return false; } -stringstream& SrsMp4Box::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4Box::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { return ss; } @@ -680,7 +703,7 @@ int SrsMp4FullBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4FullBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4FullBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { if (version != 0 || flags != 0) { ss << ", V" << uint32_t(version) @@ -757,7 +780,7 @@ int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4FileTypeBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4FileTypeBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", brands:"; srs_print_mp4_type(ss, (uint32_t)major_brand); @@ -766,7 +789,7 @@ stringstream& SrsMp4FileTypeBox::dumps_detail(stringstream& ss, int level) if (!compatible_brands.empty()) { ss << "("; - srs_print_mp4_vector(compatible_brands, ss, level); + srs_dumps_array(compatible_brands, ss, dc, srs_pfn_types, srs_delimiter_inline); ss << ")"; } return ss; @@ -869,14 +892,14 @@ int SrsMp4FreeSpaceBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4FreeSpaceBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4FreeSpaceBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", free " << data.size() << "B"; if (!data.empty()) { ss << endl; - srs_padding(ss, level + 1); - srs_print_bytes(ss, &data[0], (int)data.size(), level + 1); + srs_padding(ss, dc.indent()); + srs_print_bytes(ss, &data[0], (int)data.size(), dc.indent()); } return ss; } @@ -1105,7 +1128,7 @@ int SrsMp4MovieHeaderBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4MovieHeaderBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4MovieHeaderBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", " << std::setprecision(2) << duration() << "ms, TBN=" << timescale << ", nTID=" << next_track_ID; return ss; @@ -1453,7 +1476,7 @@ int SrsMp4TrackHeaderBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4TrackHeaderBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4TrackHeaderBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", track #" << track_ID << ", " << duration << "TBN"; @@ -1482,12 +1505,12 @@ SrsMp4ElstEntry::SrsMp4ElstEntry() media_rate_fraction = 0; } -stringstream& SrsMp4ElstEntry::dumps(stringstream& ss, int level) +stringstream& SrsMp4ElstEntry::dumps(stringstream& ss, SrsMp4DumpContext dc) { - return dumps_detail(ss, level); + return dumps_detail(ss, dc); } -stringstream& SrsMp4ElstEntry::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4ElstEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << "Entry, " << segment_duration << "TBN, start=" << media_time << "TBN" << ", rate=" << media_rate_integer << "," << media_rate_fraction; @@ -1573,14 +1596,14 @@ int SrsMp4EditListBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4EditListBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4EditListBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", " << entries.size() << " childs"; if (!entries.empty()) { ss << "(+)" << endl; - srs_padding(ss, level + 1); - srs_print_mp4_vector(entries, ss, level + 1); + srs_padding(ss, dc.indent()); + srs_dumps_array(entries, ss, dc.indent(), srs_pfn_detail, srs_delimiter_newline); } return ss; @@ -1756,7 +1779,7 @@ int SrsMp4MediaHeaderBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4MediaHeaderBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4MediaHeaderBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", TBN=" << timescale << ", " << duration << "TBN"; if (language) { @@ -1830,7 +1853,7 @@ int SrsMp4HandlerReferenceBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4HandlerReferenceBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4HandlerReferenceBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", "; srs_print_mp4_type(ss, (uint32_t)handler_type); @@ -2082,7 +2105,7 @@ int SrsMp4DataEntryUrlBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4DataEntryUrlBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4DataEntryUrlBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << "URL: " << location; if (location.empty()) { @@ -2140,7 +2163,7 @@ int SrsMp4DataEntryUrnBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4DataEntryUrnBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4DataEntryUrnBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << "URN: " << name << ", " << location; return ss; @@ -2250,13 +2273,13 @@ int SrsMp4DataReferenceBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4DataReferenceBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4DataReferenceBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", " << entries.size() << " childs"; if (!entries.empty()) { ss << "(+)" << endl; - srs_padding(ss, level + 1); - srs_print_mp4_vector(entries, ss, level + 1); + srs_padding(ss, dc.indent()); + srs_dumps_array(entries, ss, dc.indent(), srs_pfn_pdetail, srs_delimiter_newline); } return ss; } @@ -2413,7 +2436,7 @@ int SrsMp4SampleEntry::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4SampleEntry::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4SampleEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", refs#" << data_reference_index; return ss; @@ -2506,9 +2529,9 @@ int SrsMp4VisualSampleEntry::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4VisualSampleEntry::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4VisualSampleEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { - SrsMp4SampleEntry::dumps_detail(ss, level); + SrsMp4SampleEntry::dumps_detail(ss, dc); ss << ", size=" << width << "x" << height; return ss; @@ -2560,11 +2583,11 @@ int SrsMp4AvccBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4AvccBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4AvccBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", AVC Config: " << (int)avc_config.size() << "B" << endl; - srs_padding(ss, level + 1); - srs_print_bytes(ss, (const char*)&avc_config[0], (int)avc_config.size(), level + 1); + srs_padding(ss, dc.indent()); + srs_print_bytes(ss, (const char*)&avc_config[0], (int)avc_config.size(), dc.indent()); return ss; } @@ -2642,9 +2665,9 @@ int SrsMp4AudioSampleEntry::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4AudioSampleEntry::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4AudioSampleEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { - SrsMp4SampleEntry::dumps_detail(ss, level); + SrsMp4SampleEntry::dumps_detail(ss, dc); ss << ", " << channelcount << " channels, " << samplesize << " bits" << ", " << (samplerate>>16) << " Hz"; @@ -2768,7 +2791,7 @@ int SrsMp4BaseDescriptor::decode(SrsBuffer* buf) return ret; } -stringstream& SrsMp4BaseDescriptor::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4BaseDescriptor::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", tag=" << "0x" << std::setw(2) << std::setfill('0') << std::hex << (uint32_t)(uint8_t)tag << std::dec; return ss; @@ -2812,15 +2835,15 @@ int SrsMp4DecoderSpecificInfo::decode_payload(SrsBuffer* buf) return ret; } -stringstream& SrsMp4DecoderSpecificInfo::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4DecoderSpecificInfo::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { - SrsMp4BaseDescriptor::dumps_detail(ss, level); + SrsMp4BaseDescriptor::dumps_detail(ss, dc); ss << ", ASC " << asc.size() << "B"; ss << endl; - srs_padding(ss, level + 1); - return srs_print_bytes(ss, (const char*)&asc[0], (int)asc.size(), level + 1); + srs_padding(ss, dc.indent()); + return srs_print_bytes(ss, (const char*)&asc[0], (int)asc.size(), dc.indent()); } SrsMp4DecoderConfigDescriptor::SrsMp4DecoderConfigDescriptor() @@ -2890,17 +2913,17 @@ int SrsMp4DecoderConfigDescriptor::decode_payload(SrsBuffer* buf) return ret; } -stringstream& SrsMp4DecoderConfigDescriptor::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4DecoderConfigDescriptor::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { - SrsMp4BaseDescriptor::dumps_detail(ss, level); + SrsMp4BaseDescriptor::dumps_detail(ss, dc); ss << ", type=" << objectTypeIndication << ", stream=" << streamType; ss << endl; - srs_padding(ss, level + 1); + srs_padding(ss, dc.indent()); ss << "decoder specific"; - return decSpecificInfo->dumps_detail(ss, level + 1); + return decSpecificInfo->dumps_detail(ss, dc.indent()); } SrsMp4SLConfigDescriptor::SrsMp4SLConfigDescriptor() @@ -3059,17 +3082,17 @@ int SrsMp4ES_Descriptor::decode_payload(SrsBuffer* buf) return ret; } -stringstream& SrsMp4ES_Descriptor::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4ES_Descriptor::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { - SrsMp4BaseDescriptor::dumps_detail(ss, level); + SrsMp4BaseDescriptor::dumps_detail(ss, dc); ss << ", ID=" << ES_ID; ss << endl; - srs_padding(ss, level + 1); + srs_padding(ss, dc.indent()); ss << "decoder config"; - decConfigDescr.dumps_detail(ss, level + 1); + decConfigDescr.dumps_detail(ss, dc.indent()); return ss; } @@ -3132,9 +3155,9 @@ int SrsMp4EsdsBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4EsdsBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4EsdsBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { - return es->dumps_detail(ss, level); + return es->dumps_detail(ss, dc); } SrsMp4SampleDescriptionBox::SrsMp4SampleDescriptionBox() @@ -3263,12 +3286,12 @@ bool SrsMp4SampleDescriptionBox::boxes_in_header() return true; } -stringstream& SrsMp4SampleDescriptionBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4SampleDescriptionBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { ss << ", " << entries.size() << " childs"; if (!entries.empty()) { ss << "(+)" << endl; - srs_print_mp4_vector(entries, ss, level + 1); + srs_dumps_array(entries, ss, dc.indent(), srs_pfn_pbox, srs_delimiter_newline); } return ss; } @@ -3279,8 +3302,9 @@ SrsMp4SttsEntry::SrsMp4SttsEntry() sample_delta = 0; } -stringstream& SrsMp4SttsEntry::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4SttsEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << "count=" << sample_count << ", delta=" << sample_delta; return ss; } @@ -3334,7 +3358,7 @@ int SrsMp4DecodingTime2SampleBox::on_sample(uint32_t sample_index, SrsMp4SttsEnt int SrsMp4DecodingTime2SampleBox::nb_header() { - return SrsMp4FullBox::nb_header() + 4 + 8 * entries.size(); + return SrsMp4FullBox::nb_header() + 4 + 8 * (int)entries.size(); } int SrsMp4DecodingTime2SampleBox::encode_header(SrsBuffer* buf) @@ -3345,7 +3369,7 @@ int SrsMp4DecodingTime2SampleBox::encode_header(SrsBuffer* buf) return ret; } - buf->write_4bytes(entries.size()); + buf->write_4bytes((int)entries.size()); for (size_t i = 0; i < entries.size(); i++) { SrsMp4SttsEntry& entry = entries[i]; buf->write_4bytes(entry.sample_count); @@ -3376,8 +3400,14 @@ int SrsMp4DecodingTime2SampleBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4DecodingTime2SampleBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4DecodingTime2SampleBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << ", " << entries.size() << " childs (+)"; + if (!entries.empty()) { + ss << endl; + srs_padding(ss, dc.indent()); + srs_dumps_array(entries, ss, dc.indent(), srs_pfn_detail, srs_delimiter_newline); + } return ss; } @@ -3387,8 +3417,9 @@ SrsMp4CttsEntry::SrsMp4CttsEntry() sample_offset = 0; } -stringstream& SrsMp4CttsEntry::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4CttsEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << "count=" << sample_count << ", offset=" << sample_offset; return ss; } @@ -3442,7 +3473,7 @@ int SrsMp4CompositionTime2SampleBox::on_sample(uint32_t sample_index, SrsMp4Ctts int SrsMp4CompositionTime2SampleBox::nb_header() { - return SrsMp4FullBox::nb_header() + 4 + 8 * entries.size(); + return SrsMp4FullBox::nb_header() + 4 + 8 * (int)entries.size(); } int SrsMp4CompositionTime2SampleBox::encode_header(SrsBuffer* buf) @@ -3453,7 +3484,7 @@ int SrsMp4CompositionTime2SampleBox::encode_header(SrsBuffer* buf) return ret; } - buf->write_4bytes(entries.size()); + buf->write_4bytes((int)entries.size()); for (size_t i = 0; i < entries.size(); i++) { SrsMp4CttsEntry& entry = entries[i]; buf->write_4bytes(entry.sample_count); @@ -3492,8 +3523,14 @@ int SrsMp4CompositionTime2SampleBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4CompositionTime2SampleBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4CompositionTime2SampleBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << ", " << entries.size() << " childs (+)"; + if (!entries.empty()) { + ss << endl; + srs_padding(ss, dc.indent()); + srs_dumps_array(entries, ss, dc.indent(), srs_pfn_detail, srs_delimiter_newline); + } return ss; } @@ -3561,8 +3598,14 @@ int SrsMp4SyncSampleBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4SyncSampleBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4SyncSampleBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << ", count=" << entry_count; + if (entry_count > 0) { + ss << endl; + srs_padding(ss, dc.indent()); + srs_dumps_array(sample_numbers, entry_count, ss, dc.indent(), srs_pfn_elems, srs_delimiter_inlinespace); + } return ss; } @@ -3573,8 +3616,9 @@ SrsMp4StscEntry::SrsMp4StscEntry() sample_description_index = 0; } -stringstream& SrsMp4StscEntry::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4StscEntry::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << "first=" << first_chunk << ", samples=" << samples_per_chunk << ", index=" << sample_description_index; return ss; } @@ -3657,8 +3701,14 @@ int SrsMp4Sample2ChunkBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4Sample2ChunkBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4Sample2ChunkBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << ", " << entry_count << " childs (+)"; + if (entry_count > 0) { + ss << endl; + srs_padding(ss, dc.indent()); + srs_dumps_array(entries, entry_count, ss, dc.indent(), srs_pfn_detail, srs_delimiter_newline); + } return ss; } @@ -3715,8 +3765,14 @@ int SrsMp4ChunkOffsetBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4ChunkOffsetBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4ChunkOffsetBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << ", " << entry_count << " childs (+)"; + if (entry_count > 0) { + ss << endl; + srs_padding(ss, dc.indent()); + srs_dumps_array(entries, entry_count, ss, dc.indent(), srs_pfn_elems, srs_delimiter_inlinespace); + } return ss; } @@ -3773,8 +3829,14 @@ int SrsMp4ChunkLargeOffsetBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4ChunkLargeOffsetBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4ChunkLargeOffsetBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << ", " << entry_count << " childs (+)"; + if (entry_count > 0) { + ss << endl; + srs_padding(ss, dc.indent()); + srs_dumps_array(entries, entry_count, ss, dc.indent(), srs_pfn_elems, srs_delimiter_inlinespace); + } return ss; } @@ -3845,7 +3907,7 @@ int SrsMp4SampleSizeBox::decode_header(SrsBuffer* buf) sample_size = buf->read_4bytes(); sample_count = buf->read_4bytes(); - if (sample_size == 0) { + if (!sample_size && sample_count) { entry_sizes = new uint32_t[sample_count]; } for (uint32_t i = 0; i < sample_count && sample_size == 0; i++) { @@ -3855,8 +3917,14 @@ int SrsMp4SampleSizeBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4SampleSizeBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4SampleSizeBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { + ss << ", size=" << sample_size << ", " << sample_count << " childs (+)"; + if (!sample_size && sample_count> 0) { + ss << endl; + srs_padding(ss, dc.indent()); + srs_dumps_array(entry_sizes, sample_count, ss, dc.indent(), srs_pfn_elems, srs_delimiter_inlinespace); + } return ss; } @@ -3906,7 +3974,7 @@ int SrsMp4UserDataBox::decode_header(SrsBuffer* buf) return ret; } -stringstream& SrsMp4UserDataBox::dumps_detail(stringstream& ss, int level) +stringstream& SrsMp4UserDataBox::dumps_detail(stringstream& ss, SrsMp4DumpContext dc) { return ss; } diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index a0ecde1450..a82a7892b6 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -143,6 +143,17 @@ enum SrsMp4BoxBrand SrsMp4BoxBrandDASH = 0x64617368, // 'dash' }; +/** + * The context to dump. + */ +struct SrsMp4DumpContext +{ + int level; + bool summary; + + SrsMp4DumpContext indent(); +}; + /** * 4.2 Object Structure * ISO_IEC_14496-12-base-format-2012.pdf, page 16 @@ -193,7 +204,7 @@ class SrsMp4Box : public ISrsCodec // @return The removed count. virtual int remove(SrsMp4BoxType bt); // Dumps the box and all contained boxes. - virtual std::stringstream& dumps(std::stringstream& ss, int level); + virtual std::stringstream& dumps(std::stringstream& ss, SrsMp4DumpContext dc); /** * Discovery the box from buffer. * @param ppbox Output the discoveried box, which user must free it. @@ -223,7 +234,7 @@ class SrsMp4Box : public ISrsCodec // @remark internal for template methods. public: // Dumps the detail of box. - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -245,7 +256,7 @@ class SrsMp4FullBox : public SrsMp4Box virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -276,7 +287,7 @@ class SrsMp4FileTypeBox : public SrsMp4Box virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -367,7 +378,7 @@ class SrsMp4FreeSpaceBox : public SrsMp4Box virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -453,7 +464,7 @@ class SrsMp4MovieHeaderBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; // The type of track, maybe combine of types. @@ -623,7 +634,7 @@ class SrsMp4TrackHeaderBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -663,8 +674,8 @@ struct SrsMp4ElstEntry public: SrsMp4ElstEntry(); public: - virtual std::stringstream& dumps(std::stringstream& ss, int level); - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps(std::stringstream& ss, SrsMp4DumpContext dc); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -687,7 +698,7 @@ class SrsMp4EditListBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -767,7 +778,7 @@ class SrsMp4MediaHeaderBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -799,7 +810,7 @@ class SrsMp4HandlerReferenceBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -918,7 +929,7 @@ class SrsMp4DataEntryUrlBox : public SrsMp4DataEntryBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -937,7 +948,7 @@ class SrsMp4DataEntryUrnBox : public SrsMp4DataEntryBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -963,7 +974,7 @@ class SrsMp4DataReferenceBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1026,7 +1037,7 @@ class SrsMp4SampleEntry : public SrsMp4Box virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1069,7 +1080,7 @@ class SrsMp4VisualSampleEntry : public SrsMp4SampleEntry virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1088,7 +1099,7 @@ class SrsMp4AvccBox : public SrsMp4Box virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1118,7 +1129,7 @@ class SrsMp4AudioSampleEntry : public SrsMp4SampleEntry virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; // Table 1 — List of Class Tags for Descriptors @@ -1166,7 +1177,7 @@ class SrsMp4BaseDescriptor : public ISrsCodec virtual int encode_payload(SrsBuffer* buf) = 0; virtual int decode_payload(SrsBuffer* buf) = 0; public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; // Table 5 — objectTypeIndication Values @@ -1204,7 +1215,7 @@ class SrsMp4DecoderSpecificInfo : public SrsMp4BaseDescriptor virtual int encode_payload(SrsBuffer* buf); virtual int decode_payload(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1232,7 +1243,7 @@ class SrsMp4DecoderConfigDescriptor : public SrsMp4BaseDescriptor virtual int encode_payload(SrsBuffer* buf); virtual int decode_payload(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1280,7 +1291,7 @@ class SrsMp4ES_Descriptor : public SrsMp4BaseDescriptor virtual int encode_payload(SrsBuffer* buf); virtual int decode_payload(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1304,7 +1315,7 @@ class SrsMp4EsdsBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1335,7 +1346,7 @@ class SrsMp4SampleDescriptionBox : public SrsMp4FullBox virtual int decode_header(SrsBuffer* buf); virtual bool boxes_in_header(); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1352,7 +1363,7 @@ struct SrsMp4SttsEntry // Constructor SrsMp4SttsEntry(); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1385,7 +1396,7 @@ class SrsMp4DecodingTime2SampleBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1404,7 +1415,7 @@ struct SrsMp4CttsEntry // Constructor SrsMp4CttsEntry(); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1439,7 +1450,7 @@ class SrsMp4CompositionTime2SampleBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1467,7 +1478,7 @@ class SrsMp4SyncSampleBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1490,7 +1501,7 @@ struct SrsMp4StscEntry // Constructor SrsMp4StscEntry(); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1523,7 +1534,7 @@ class SrsMp4Sample2ChunkBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1549,7 +1560,7 @@ class SrsMp4ChunkOffsetBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1575,7 +1586,7 @@ class SrsMp4ChunkLargeOffsetBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1608,7 +1619,7 @@ class SrsMp4SampleSizeBox : public SrsMp4FullBox virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** @@ -1629,7 +1640,7 @@ class SrsMp4UserDataBox : public SrsMp4Box virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); public: - virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); + virtual std::stringstream& dumps_detail(std::stringstream& ss, SrsMp4DumpContext dc); }; /** diff --git a/trunk/src/main/srs_main_mp4_parser.cpp b/trunk/src/main/srs_main_mp4_parser.cpp index 14e275c7af..c46cf07610 100644 --- a/trunk/src/main/srs_main_mp4_parser.cpp +++ b/trunk/src/main/srs_main_mp4_parser.cpp @@ -40,7 +40,7 @@ using namespace std; ISrsLog* _srs_log = new SrsConsoleLog(SrsLogLevelTrace, false); ISrsThreadContext* _srs_context = new SrsThreadContext(); -int parse(std::string mp4_file) +int parse(std::string mp4_file, bool verbose) { int ret = ERROR_SUCCESS; @@ -88,8 +88,12 @@ int parse(std::string mp4_file) return ret; } + SrsMp4DumpContext ctx; + ctx.level = 1; + ctx.summary = !verbose; + stringstream ss; - fprintf(stderr, "%s", box->dumps(ss, 1).str().c_str()); + fprintf(stderr, "%s", box->dumps(ss, ctx).str().c_str()); } return ret; @@ -103,18 +107,24 @@ int main(int argc, char** argv) VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); if (argc < 2) { - printf("Usage: %s \n" + printf("Usage: %s [verbose]\n" " mp4_file The MP4 file path to parse.\n" + " verbose Whether print verbose of box.\n" "For example:\n" - " %s doc/source.200kbps.768x320.mp4\n", - argv[0], argv[0]); + " %s doc/source.200kbps.768x320.mp4\n" + " %s doc/source.200kbps.768x320.mp4 verbose\n", + argv[0], argv[0], argv[0]); exit(-1); } string mp4_file = argv[1]; - srs_trace("Parse MP4 file %s", mp4_file.c_str()); + bool verbose = false; + if (argc > 2) { + verbose = true; + } + srs_trace("Parse MP4 file %s, verbose=%s", mp4_file.c_str(), verbose); - ret = parse(mp4_file); + ret = parse(mp4_file, verbose); if (ret == ERROR_SYSTEM_FILE_EOF) { srs_trace("Parse complete");