From eaccbd0f85bff070119fc83cf94d0b73b60319a6 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 14 May 2017 22:16:15 +0800 Subject: [PATCH] Support print MP4 box. --- trunk/src/kernel/srs_kernel_mp4.cpp | 117 ++++++++++++++++++++++++- trunk/src/kernel/srs_kernel_mp4.hpp | 9 ++ trunk/src/main/srs_main_mp4_parser.cpp | 22 +++-- 3 files changed, 141 insertions(+), 7 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index 7c411d879..7e7a794bc 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace std; #define SRS_MP4_EOF_SIZE 0 @@ -40,6 +41,49 @@ using namespace std; #define SRS_MP4_BUF_SIZE 4096 +stringstream& srs_padding(stringstream& ss, int level, int tab = 4) +{ + for (int i = 0; i < level; i++) { + for (int j = 0; j < tab; j++) { + ss << " "; + } + } + return ss; +} + +stringstream& srs_print_mp4_type(stringstream& ss, uint32_t v) +{ + ss << char(v>>24) << char(v>>16) << char(v>>8) << char(v); + return ss; +} + +template +stringstream& srs_print_types(stringstream& ss, std::vector& arr) +{ + 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; +} + +stringstream& srs_print_bytes(stringstream& ss, const char* p, int size, int max = -1) +{ + if (max == -1) { + max = size; + } + + for (int i = 0; i < max; i++) { + ss << "0x" << std::setw(2) << std::setfill('0') << std::hex << (uint32_t)p[i] << std::dec; + if (i < max -1) { + ss << ", "; + } + } + return ss; +} + int srs_mp4_string_length(const string& v) { return (int)v.length()+1; @@ -160,6 +204,30 @@ int SrsMp4Box::remove(SrsMp4BoxType bt) return nb_removed; } +stringstream& SrsMp4Box::dumps(stringstream& ss, int level) +{ + srs_padding(ss, level); + srs_print_mp4_type(ss, (uint32_t)type); + + ss << ", " << sz(); + if (smallsize == SRS_MP4_USE_LARGE_SIZE) { + ss << "(large)"; + } + ss << "B"; + + dumps_detail(ss, level); + + ss << endl; + + vector::iterator it; + for (it = boxes.begin(); it != boxes.end(); ++it) { + SrsMp4Box* box = *it; + box->dumps(ss, level + 1); + } + + return ss; +} + int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox) { *ppbox = NULL; @@ -455,6 +523,11 @@ int SrsMp4Box::decode_header(SrsBuffer* buf) return ret; } +stringstream& SrsMp4Box::dumps_detail(stringstream& ss, int level) +{ + return ss; +} + SrsMp4FullBox::SrsMp4FullBox() { version = 0; @@ -520,6 +593,15 @@ int SrsMp4FullBox::decode_header(SrsBuffer* buf) return ret; } +stringstream& SrsMp4FullBox::dumps_detail(stringstream& ss, int level) +{ + if (version != 0 || flags != 0) { + ss << ", V" << uint32_t(version) + << "(0x" << std::setw(2) << std::setfill('0') << std::hex << flags << std::dec << ")"; + } + return ss; +} + SrsMp4FileTypeBox::SrsMp4FileTypeBox() { type = SrsMp4BoxTypeFTYP; @@ -542,7 +624,7 @@ void SrsMp4FileTypeBox::set_compatible_brands(SrsMp4BoxBrand b0, SrsMp4BoxBrand int SrsMp4FileTypeBox::nb_header() { - return SrsMp4Box::nb_header() + 8 + compatible_brands.size() * 4; + return (int)(SrsMp4Box::nb_header() + 8 + compatible_brands.size() * 4); } int SrsMp4FileTypeBox::encode_header(SrsBuffer* buf) @@ -588,6 +670,21 @@ int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf) return ret; } +stringstream& SrsMp4FileTypeBox::dumps_detail(stringstream& ss, int level) +{ + ss << ", brands:"; + srs_print_mp4_type(ss, (uint32_t)major_brand); + + ss << "," << minor_version; + + if (!compatible_brands.empty()) { + ss << "("; + srs_print_types(ss, compatible_brands); + ss << ")"; + } + return ss; +} + SrsMp4MediaDataBox::SrsMp4MediaDataBox() { type = SrsMp4BoxTypeMDAT; @@ -685,6 +782,18 @@ int SrsMp4FreeSpaceBox::decode_header(SrsBuffer* buf) return ret; } +stringstream& SrsMp4FreeSpaceBox::dumps_detail(stringstream& ss, int level) +{ + ss << ", free " << data.size() << "B"; + + if (!data.empty()) { + ss << endl; + srs_padding(ss, level + 1); + srs_print_bytes(ss, &data[0], (int)data.size()); + } + return ss; +} + SrsMp4MovieBox::SrsMp4MovieBox() { type = SrsMp4BoxTypeMOOV; @@ -909,6 +1018,12 @@ int SrsMp4MovieHeaderBox::decode_header(SrsBuffer* buf) return ret; } +stringstream& SrsMp4MovieHeaderBox::dumps_detail(stringstream& ss, int level) +{ + ss << ", TBN=" << timescale << ", duratoin=" << std::setprecision(2) << duration() << "ms"; + return ss; +} + SrsMp4MovieExtendsBox::SrsMp4MovieExtendsBox() { type = SrsMp4BoxTypeMVEX; diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index 23fe547b0..b474fa7a5 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -191,6 +192,8 @@ public: // Remove the contained box of specified type. // @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); /** * Discovery the box from buffer. * @param ppbox Output the discoveried box, which user must free it. @@ -215,6 +218,8 @@ protected: // It's not necessary to check the buffer, unless the box is not only determined by the verson. // Generally, it's not necessary, that is, all boxes is determinated by version. virtual int decode_header(SrsBuffer* buf); + // Dumps the detail of box. + virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); }; /** @@ -235,6 +240,7 @@ protected: virtual int nb_header(); virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); + virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); }; /** @@ -264,6 +270,7 @@ protected: virtual int nb_header(); virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); + virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); }; /** @@ -353,6 +360,7 @@ protected: virtual int nb_header(); virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); + virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); }; /** @@ -437,6 +445,7 @@ protected: virtual int nb_header(); virtual int encode_header(SrsBuffer* buf); virtual int decode_header(SrsBuffer* buf); + virtual std::stringstream& dumps_detail(std::stringstream& ss, int level); }; // The type of track, maybe combine of types. diff --git a/trunk/src/main/srs_main_mp4_parser.cpp b/trunk/src/main/srs_main_mp4_parser.cpp index 87490124e..d899c1c22 100644 --- a/trunk/src/main/srs_main_mp4_parser.cpp +++ b/trunk/src/main/srs_main_mp4_parser.cpp @@ -58,27 +58,37 @@ int parse(std::string mp4_file) } srs_trace("MP4 box reader open success"); - SrsSimpleStream stream; + SrsSimpleStream* stream = new SrsSimpleStream(); + SrsAutoFree(SrsSimpleStream, stream); + while (true) { SrsMp4Box* box = NULL; SrsAutoFree(SrsMp4Box, box); - if ((ret = br.read(&stream, &box)) != ERROR_SUCCESS) { + if ((ret = br.read(stream, &box)) != ERROR_SUCCESS) { if (ret != ERROR_SYSTEM_FILE_EOF) { srs_error("Read MP4 box failed, ret=%d", ret); + } else { + fprintf(stderr, "\n"); } return ret; } - if ((ret = br.skip(box, &stream)) != ERROR_SUCCESS) { + SrsBuffer* buffer = new SrsBuffer(stream->bytes(), stream->length()); + SrsAutoFree(SrsBuffer, buffer); + + if ((ret = box->decode(buffer)) != ERROR_SUCCESS) { + srs_error("Decode the box failed, ret=%d", ret); + return ret; + } + + if ((ret = br.skip(box, stream)) != ERROR_SUCCESS) { srs_error("Skip MP4 box failed, ret=%d", ret); return ret; } stringstream ss; - ss << "type=" << char(box->type>>24) << char(box->type>>16) << char(box->type>>8) << char(box->type) - << ", size=" << box->sz(); - srs_trace("MP4 box %s", ss.str().c_str()); + fprintf(stderr, "%s", box->dumps(ss, 1).str().c_str()); } return ret;