mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Support print MP4 box.
This commit is contained in:
parent
fe43a31d06
commit
eaccbd0f85
3 changed files with 141 additions and 7 deletions
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define SRS_MP4_EOF_SIZE 0
|
#define SRS_MP4_EOF_SIZE 0
|
||||||
|
@ -40,6 +41,49 @@ using namespace std;
|
||||||
|
|
||||||
#define SRS_MP4_BUF_SIZE 4096
|
#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<typename T>
|
||||||
|
stringstream& srs_print_types(stringstream& ss, std::vector<T>& 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)
|
int srs_mp4_string_length(const string& v)
|
||||||
{
|
{
|
||||||
return (int)v.length()+1;
|
return (int)v.length()+1;
|
||||||
|
@ -160,6 +204,30 @@ int SrsMp4Box::remove(SrsMp4BoxType bt)
|
||||||
return nb_removed;
|
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<SrsMp4Box*>::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)
|
int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
|
||||||
{
|
{
|
||||||
*ppbox = NULL;
|
*ppbox = NULL;
|
||||||
|
@ -455,6 +523,11 @@ int SrsMp4Box::decode_header(SrsBuffer* buf)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stringstream& SrsMp4Box::dumps_detail(stringstream& ss, int level)
|
||||||
|
{
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
SrsMp4FullBox::SrsMp4FullBox()
|
SrsMp4FullBox::SrsMp4FullBox()
|
||||||
{
|
{
|
||||||
version = 0;
|
version = 0;
|
||||||
|
@ -520,6 +593,15 @@ int SrsMp4FullBox::decode_header(SrsBuffer* buf)
|
||||||
return ret;
|
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()
|
SrsMp4FileTypeBox::SrsMp4FileTypeBox()
|
||||||
{
|
{
|
||||||
type = SrsMp4BoxTypeFTYP;
|
type = SrsMp4BoxTypeFTYP;
|
||||||
|
@ -542,7 +624,7 @@ void SrsMp4FileTypeBox::set_compatible_brands(SrsMp4BoxBrand b0, SrsMp4BoxBrand
|
||||||
|
|
||||||
int SrsMp4FileTypeBox::nb_header()
|
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)
|
int SrsMp4FileTypeBox::encode_header(SrsBuffer* buf)
|
||||||
|
@ -588,6 +670,21 @@ int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf)
|
||||||
return ret;
|
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()
|
SrsMp4MediaDataBox::SrsMp4MediaDataBox()
|
||||||
{
|
{
|
||||||
type = SrsMp4BoxTypeMDAT;
|
type = SrsMp4BoxTypeMDAT;
|
||||||
|
@ -685,6 +782,18 @@ int SrsMp4FreeSpaceBox::decode_header(SrsBuffer* buf)
|
||||||
return ret;
|
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()
|
SrsMp4MovieBox::SrsMp4MovieBox()
|
||||||
{
|
{
|
||||||
type = SrsMp4BoxTypeMOOV;
|
type = SrsMp4BoxTypeMOOV;
|
||||||
|
@ -909,6 +1018,12 @@ int SrsMp4MovieHeaderBox::decode_header(SrsBuffer* buf)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stringstream& SrsMp4MovieHeaderBox::dumps_detail(stringstream& ss, int level)
|
||||||
|
{
|
||||||
|
ss << ", TBN=" << timescale << ", duratoin=" << std::setprecision(2) << duration() << "ms";
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
SrsMp4MovieExtendsBox::SrsMp4MovieExtendsBox()
|
SrsMp4MovieExtendsBox::SrsMp4MovieExtendsBox()
|
||||||
{
|
{
|
||||||
type = SrsMp4BoxTypeMVEX;
|
type = SrsMp4BoxTypeMVEX;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <srs_kernel_codec.hpp>
|
#include <srs_kernel_codec.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -191,6 +192,8 @@ public:
|
||||||
// Remove the contained box of specified type.
|
// Remove the contained box of specified type.
|
||||||
// @return The removed count.
|
// @return The removed count.
|
||||||
virtual int remove(SrsMp4BoxType bt);
|
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.
|
* Discovery the box from buffer.
|
||||||
* @param ppbox Output the discoveried box, which user must free it.
|
* @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.
|
// 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.
|
// Generally, it's not necessary, that is, all boxes is determinated by version.
|
||||||
virtual int decode_header(SrsBuffer* buf);
|
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 nb_header();
|
||||||
virtual int encode_header(SrsBuffer* buf);
|
virtual int encode_header(SrsBuffer* buf);
|
||||||
virtual int decode_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 nb_header();
|
||||||
virtual int encode_header(SrsBuffer* buf);
|
virtual int encode_header(SrsBuffer* buf);
|
||||||
virtual int decode_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 nb_header();
|
||||||
virtual int encode_header(SrsBuffer* buf);
|
virtual int encode_header(SrsBuffer* buf);
|
||||||
virtual int decode_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 nb_header();
|
||||||
virtual int encode_header(SrsBuffer* buf);
|
virtual int encode_header(SrsBuffer* buf);
|
||||||
virtual int decode_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.
|
// The type of track, maybe combine of types.
|
||||||
|
|
|
@ -58,27 +58,37 @@ int parse(std::string mp4_file)
|
||||||
}
|
}
|
||||||
srs_trace("MP4 box reader open success");
|
srs_trace("MP4 box reader open success");
|
||||||
|
|
||||||
SrsSimpleStream stream;
|
SrsSimpleStream* stream = new SrsSimpleStream();
|
||||||
|
SrsAutoFree(SrsSimpleStream, stream);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
SrsMp4Box* box = NULL;
|
SrsMp4Box* box = NULL;
|
||||||
SrsAutoFree(SrsMp4Box, box);
|
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) {
|
if (ret != ERROR_SYSTEM_FILE_EOF) {
|
||||||
srs_error("Read MP4 box failed, ret=%d", ret);
|
srs_error("Read MP4 box failed, ret=%d", ret);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
return ret;
|
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);
|
srs_error("Skip MP4 box failed, ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
ss << "type=" << char(box->type>>24) << char(box->type>>16) << char(box->type>>8) << char(box->type)
|
fprintf(stderr, "%s", box->dumps(ss, 1).str().c_str());
|
||||||
<< ", size=" << box->sz();
|
|
||||||
srs_trace("MP4 box %s", ss.str().c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue