mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #738, parse moov, get the h.264/avcC and aac/asc
This commit is contained in:
parent
e8eb050bf2
commit
bbee16e4db
3 changed files with 285 additions and 9 deletions
|
@ -97,6 +97,7 @@ enum SrsCodecVideo
|
|||
{
|
||||
// set to the zero to reserved, for array map.
|
||||
SrsCodecVideoReserved = 0,
|
||||
SrsCodecVideoForbidden = 0,
|
||||
SrsCodecVideoReserved1 = 1,
|
||||
SrsCodecVideoReserved2 = 9,
|
||||
|
||||
|
@ -135,6 +136,7 @@ enum SrsCodecAudio
|
|||
{
|
||||
// set to the max value to reserved, for array map.
|
||||
SrsCodecAudioReserved1 = 16,
|
||||
SrsCodecAudioForbidden = 16,
|
||||
|
||||
// for user to disable audio, for example, use pure video hls.
|
||||
SrsCodecAudioDisabled = 17,
|
||||
|
|
|
@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_kernel_buffer.hpp>
|
||||
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#define SRS_MP4_EOF_SIZE 0
|
||||
|
@ -672,6 +673,40 @@ SrsMp4TrackBox* SrsMp4MovieBox::audio()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int SrsMp4MovieBox::nb_vide_tracks()
|
||||
{
|
||||
int nb_tracks = 0;
|
||||
|
||||
for (int i = 0; i < boxes.size(); i++) {
|
||||
SrsMp4Box* box = boxes.at(i);
|
||||
if (box->type == SrsMp4BoxTypeTRAK) {
|
||||
SrsMp4TrackBox* trak = dynamic_cast<SrsMp4TrackBox*>(box);
|
||||
if ((trak->track_type() & SrsMp4TrackTypeVideo) == SrsMp4TrackTypeVideo) {
|
||||
nb_tracks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nb_tracks;
|
||||
}
|
||||
|
||||
int SrsMp4MovieBox::nb_soun_tracks()
|
||||
{
|
||||
int nb_tracks = 0;
|
||||
|
||||
for (int i = 0; i < boxes.size(); i++) {
|
||||
SrsMp4Box* box = boxes.at(i);
|
||||
if (box->type == SrsMp4BoxTypeTRAK) {
|
||||
SrsMp4TrackBox* trak = dynamic_cast<SrsMp4TrackBox*>(box);
|
||||
if ((trak->track_type() & SrsMp4TrackTypeAudio) == SrsMp4TrackTypeAudio) {
|
||||
nb_tracks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nb_tracks;
|
||||
}
|
||||
|
||||
int SrsMp4MovieBox::nb_header()
|
||||
{
|
||||
return SrsMp4Box::nb_header();
|
||||
|
@ -823,14 +858,102 @@ SrsMp4TrackHeaderBox::~SrsMp4TrackHeaderBox()
|
|||
|
||||
SrsMp4TrackType SrsMp4TrackBox::track_type()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeMDIA);
|
||||
// TODO: Maybe should discovery all mdia boxes.
|
||||
SrsMp4MediaBox* box = mdia();
|
||||
if (!box) {
|
||||
return SrsMp4TrackTypeForbidden;
|
||||
}
|
||||
return box->track_type();
|
||||
}
|
||||
|
||||
// TODO: Maybe should discovery all mdia boxes.
|
||||
SrsMp4MediaBox* mdia = dynamic_cast<SrsMp4MediaBox*>(box);
|
||||
return mdia->track_type();
|
||||
SrsMp4TrackHeaderBox* SrsMp4TrackBox::tkhd()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeTKHD);
|
||||
return dynamic_cast<SrsMp4TrackHeaderBox*>(box);
|
||||
}
|
||||
|
||||
SrsCodecVideo SrsMp4TrackBox::vide_codec()
|
||||
{
|
||||
SrsMp4SampleDescriptionBox* box = stsd();
|
||||
if (!box) {
|
||||
return SrsCodecVideoForbidden;
|
||||
}
|
||||
|
||||
if (box->entry_count() == 0) {
|
||||
return SrsCodecVideoForbidden;
|
||||
}
|
||||
|
||||
SrsMp4SampleEntry* entry = box->entrie_at(0);
|
||||
switch(entry->type) {
|
||||
case SrsMp4BoxTypeAVC1: return SrsCodecVideoAVC;
|
||||
default: return SrsCodecVideoForbidden;
|
||||
}
|
||||
}
|
||||
|
||||
SrsCodecAudio SrsMp4TrackBox::soun_codec()
|
||||
{
|
||||
SrsMp4SampleDescriptionBox* box = stsd();
|
||||
if (!box) {
|
||||
return SrsCodecAudioForbidden;
|
||||
}
|
||||
|
||||
if (box->entry_count() == 0) {
|
||||
return SrsCodecAudioForbidden;
|
||||
}
|
||||
|
||||
SrsMp4SampleEntry* entry = box->entrie_at(0);
|
||||
switch(entry->type) {
|
||||
case SrsMp4BoxTypeMP4A: return SrsCodecAudioAAC;
|
||||
default: return SrsCodecAudioForbidden;
|
||||
}
|
||||
}
|
||||
|
||||
SrsMp4AvccBox* SrsMp4TrackBox::avcc()
|
||||
{
|
||||
SrsMp4VisualSampleEntry* box = avc1();
|
||||
return box? box->avcC():NULL;
|
||||
}
|
||||
|
||||
SrsMp4DecoderSpecificInfo* SrsMp4TrackBox::asc()
|
||||
{
|
||||
SrsMp4AudioSampleEntry* box = mp4a();
|
||||
return box? box->asc():NULL;
|
||||
}
|
||||
|
||||
SrsMp4MediaBox* SrsMp4TrackBox::mdia()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeMDIA);
|
||||
return dynamic_cast<SrsMp4MediaBox*>(box);
|
||||
}
|
||||
|
||||
SrsMp4MediaInformationBox* SrsMp4TrackBox::minf()
|
||||
{
|
||||
SrsMp4MediaBox* box = mdia();
|
||||
return box? box->minf():NULL;
|
||||
}
|
||||
|
||||
SrsMp4SampleTableBox* SrsMp4TrackBox::stbl()
|
||||
{
|
||||
SrsMp4MediaInformationBox* box = minf();
|
||||
return box? box->stbl():NULL;
|
||||
}
|
||||
|
||||
SrsMp4SampleDescriptionBox* SrsMp4TrackBox::stsd()
|
||||
{
|
||||
SrsMp4SampleTableBox* box = stbl();
|
||||
return box? box->stsd():NULL;
|
||||
}
|
||||
|
||||
SrsMp4VisualSampleEntry* SrsMp4TrackBox::avc1()
|
||||
{
|
||||
SrsMp4SampleDescriptionBox* box = stsd();
|
||||
return box? box->avc1():NULL;
|
||||
}
|
||||
|
||||
SrsMp4AudioSampleEntry* SrsMp4TrackBox::mp4a()
|
||||
{
|
||||
SrsMp4SampleDescriptionBox* box = stsd();
|
||||
return box? box->mp4a():NULL;
|
||||
}
|
||||
|
||||
int SrsMp4TrackHeaderBox::nb_header()
|
||||
|
@ -1043,6 +1166,12 @@ SrsMp4TrackType SrsMp4MediaBox::track_type()
|
|||
}
|
||||
}
|
||||
|
||||
SrsMp4MediaInformationBox* SrsMp4MediaBox::minf()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeMINF);
|
||||
return dynamic_cast<SrsMp4MediaInformationBox*>(box);
|
||||
}
|
||||
|
||||
SrsMp4MediaHeaderBox::SrsMp4MediaHeaderBox()
|
||||
{
|
||||
type = SrsMp4BoxTypeMDHD;
|
||||
|
@ -1225,6 +1354,12 @@ SrsMp4MediaInformationBox::~SrsMp4MediaInformationBox()
|
|||
{
|
||||
}
|
||||
|
||||
SrsMp4SampleTableBox* SrsMp4MediaInformationBox::stbl()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeSTBL);
|
||||
return dynamic_cast<SrsMp4SampleTableBox*>(box);
|
||||
}
|
||||
|
||||
SrsMp4VideoMeidaHeaderBox::SrsMp4VideoMeidaHeaderBox()
|
||||
{
|
||||
type = SrsMp4BoxTypeVMHD;
|
||||
|
@ -1554,6 +1689,12 @@ SrsMp4SampleTableBox::~SrsMp4SampleTableBox()
|
|||
{
|
||||
}
|
||||
|
||||
SrsMp4SampleDescriptionBox* SrsMp4SampleTableBox::stsd()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeSTSD);
|
||||
return dynamic_cast<SrsMp4SampleDescriptionBox*>(box);
|
||||
}
|
||||
|
||||
SrsMp4SampleEntry::SrsMp4SampleEntry()
|
||||
{
|
||||
memset(reserved, 0, 6);
|
||||
|
@ -1616,6 +1757,12 @@ SrsMp4VisualSampleEntry::~SrsMp4VisualSampleEntry()
|
|||
{
|
||||
}
|
||||
|
||||
SrsMp4AvccBox* SrsMp4VisualSampleEntry::avcC()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeAVCC);
|
||||
return dynamic_cast<SrsMp4AvccBox*>(box);
|
||||
}
|
||||
|
||||
int SrsMp4VisualSampleEntry::nb_header()
|
||||
{
|
||||
return SrsMp4SampleEntry::nb_header()+2+2+12+2+2+4+4+4+2+32+2+2;
|
||||
|
@ -1733,6 +1880,18 @@ SrsMp4AudioSampleEntry::~SrsMp4AudioSampleEntry()
|
|||
{
|
||||
}
|
||||
|
||||
SrsMp4EsdsBox* SrsMp4AudioSampleEntry::esds()
|
||||
{
|
||||
SrsMp4Box* box = get(SrsMp4BoxTypeESDS);
|
||||
return dynamic_cast<SrsMp4EsdsBox*>(box);
|
||||
}
|
||||
|
||||
SrsMp4DecoderSpecificInfo* SrsMp4AudioSampleEntry::asc()
|
||||
{
|
||||
SrsMp4EsdsBox* box = esds();
|
||||
return box? box->asc():NULL;
|
||||
}
|
||||
|
||||
int SrsMp4AudioSampleEntry::nb_header()
|
||||
{
|
||||
return SrsMp4SampleEntry::nb_header()+8+2+2+2+2+4;
|
||||
|
@ -2165,6 +2324,11 @@ SrsMp4EsdsBox::~SrsMp4EsdsBox()
|
|||
srs_freep(es);
|
||||
}
|
||||
|
||||
SrsMp4DecoderSpecificInfo* SrsMp4EsdsBox::asc()
|
||||
{
|
||||
return es->decConfigDescr.decSpecificInfo;
|
||||
}
|
||||
|
||||
int SrsMp4EsdsBox::nb_header()
|
||||
{
|
||||
return SrsMp4FullBox::nb_header() + es->nb_bytes();
|
||||
|
@ -2223,6 +2387,30 @@ SrsMp4SampleDescriptionBox::~SrsMp4SampleDescriptionBox()
|
|||
entries.clear();
|
||||
}
|
||||
|
||||
SrsMp4VisualSampleEntry* SrsMp4SampleDescriptionBox::avc1()
|
||||
{
|
||||
vector<SrsMp4SampleEntry*>::iterator it;
|
||||
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||
SrsMp4SampleEntry* entry = *it;
|
||||
if (entry->type == SrsMp4BoxTypeAVC1) {
|
||||
return dynamic_cast<SrsMp4VisualSampleEntry*>(entry);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SrsMp4AudioSampleEntry* SrsMp4SampleDescriptionBox::mp4a()
|
||||
{
|
||||
vector<SrsMp4SampleEntry*>::iterator it;
|
||||
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||
SrsMp4SampleEntry* entry = *it;
|
||||
if (entry->type == SrsMp4BoxTypeMP4A) {
|
||||
return dynamic_cast<SrsMp4AudioSampleEntry*>(entry);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t SrsMp4SampleDescriptionBox::entry_count()
|
||||
{
|
||||
return (uint32_t)entries.size();
|
||||
|
@ -2839,7 +3027,7 @@ int SrsMp4Decoder::initialize(ISrsReader* r)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Parse the MOOV.
|
||||
// Parse the Movie Header Box(moov).
|
||||
SrsMp4MovieBox* moov = dynamic_cast<SrsMp4MovieBox*>(box);
|
||||
return parse_moov(moov);
|
||||
}
|
||||
|
@ -2863,7 +3051,31 @@ int SrsMp4Decoder::parse_moov(SrsMp4MovieBox* moov)
|
|||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("MP4 moov dur=%dms, vide=%d, soun=%d", mvhd->duration(), vide != NULL, soun != NULL);
|
||||
SrsMp4AvccBox* avcc = vide? vide->avcc():NULL;
|
||||
SrsMp4DecoderSpecificInfo* asc = soun? soun->asc():NULL;
|
||||
if (vide && !avcc) {
|
||||
ret = ERROR_MP4_ILLEGAL_MOOV;
|
||||
srs_error("MP4 missing video sequence header. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (soun && !asc) {
|
||||
ret = ERROR_MP4_ILLEGAL_MOOV;
|
||||
srs_error("MP4 missing audio sequence header. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stringstream ss;
|
||||
ss << "dur=" << mvhd->duration() << "ms";
|
||||
// video codec.
|
||||
ss << ", vide=" << moov->nb_vide_tracks() << "("
|
||||
<< srs_codec_video2str(vide?vide->vide_codec():SrsCodecVideoForbidden)
|
||||
<< "," << (avcc? avcc->nb_config:0) << "BSH" << ")";
|
||||
// audio codec.
|
||||
ss << ", soun=" << moov->nb_soun_tracks() << "("
|
||||
<< srs_codec_audio2str(soun?soun->soun_codec():SrsCodecAudioForbidden)
|
||||
<< "," << (asc? asc->nb_asc:0) << "BSH" << ")";
|
||||
|
||||
srs_trace("MP4 moov %s", ss.str().c_str());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -30,12 +30,26 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_core.hpp>
|
||||
|
||||
#include <srs_kernel_buffer.hpp>
|
||||
#include <srs_kernel_codec.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ISrsReader;
|
||||
class SrsMp4TrackBox;
|
||||
class SrsMp4MediaBox;
|
||||
class SrsSimpleStream;
|
||||
class SrsMp4MovieHeaderBox;
|
||||
class SrsMp4TrackHeaderBox;
|
||||
class SrsMp4SampleTableBox;
|
||||
class SrsMp4MediaInformationBox;
|
||||
class SrsMp4SampleDescriptionBox;
|
||||
class SrsMp4AvccBox;
|
||||
class SrsMp4DecoderSpecificInfo;
|
||||
class SrsMp4VisualSampleEntry;
|
||||
class SrsMp4AvccBox;
|
||||
class SrsMp4AudioSampleEntry;
|
||||
class SrsMp4EsdsBox;
|
||||
|
||||
/**
|
||||
* 4.2 Object Structure
|
||||
|
@ -264,9 +278,6 @@ protected:
|
|||
virtual int decode_header(SrsBuffer* buf);
|
||||
};
|
||||
|
||||
class SrsMp4TrackBox;
|
||||
class SrsMp4MovieHeaderBox;
|
||||
|
||||
/**
|
||||
* 8.2.1 Movie Box (moov)
|
||||
* ISO_IEC_14496-12-base-format-2012.pdf, page 30
|
||||
|
@ -285,6 +296,10 @@ public:
|
|||
virtual SrsMp4TrackBox* video();
|
||||
// Get the first audio track.
|
||||
virtual SrsMp4TrackBox* audio();
|
||||
// Get the number of video tracks.
|
||||
virtual int nb_vide_tracks();
|
||||
// Get the number of audio tracks.
|
||||
virtual int nb_soun_tracks();
|
||||
protected:
|
||||
virtual int nb_header();
|
||||
virtual int encode_header(SrsBuffer* buf);
|
||||
|
@ -366,6 +381,29 @@ public:
|
|||
// for example, it maybe Audio|Video when contains both.
|
||||
// Generally, only single type, no combination.
|
||||
virtual SrsMp4TrackType track_type();
|
||||
// Get the track header box.
|
||||
virtual SrsMp4TrackHeaderBox* tkhd();
|
||||
// For vide track, get the video codec.
|
||||
virtual SrsCodecVideo vide_codec();
|
||||
// For soun track, get the audio codec.
|
||||
virtual SrsCodecAudio soun_codec();
|
||||
// For H.264/AVC codec, get the sps/pps.
|
||||
virtual SrsMp4AvccBox* avcc();
|
||||
// For AAC codec, get the asc.
|
||||
virtual SrsMp4DecoderSpecificInfo* asc();
|
||||
private:
|
||||
// Get the media box.
|
||||
virtual SrsMp4MediaBox* mdia();
|
||||
// Get the media info box.
|
||||
virtual SrsMp4MediaInformationBox* minf();
|
||||
// Get the sample table box.
|
||||
virtual SrsMp4SampleTableBox* stbl();
|
||||
// Get the sample description box
|
||||
virtual SrsMp4SampleDescriptionBox* stsd();
|
||||
// For H.264/AVC, get the avc1 box.
|
||||
virtual SrsMp4VisualSampleEntry* avc1();
|
||||
// For AAC, get the mp4a box.
|
||||
virtual SrsMp4AudioSampleEntry* mp4a();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -502,6 +540,8 @@ public:
|
|||
// for example, it maybe Audio|Video when contains both.
|
||||
// Generally, only single type, no combination.
|
||||
virtual SrsMp4TrackType track_type();
|
||||
// Get the media info box.
|
||||
virtual SrsMp4MediaInformationBox* minf();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -592,6 +632,9 @@ class SrsMp4MediaInformationBox : public SrsMp4Box
|
|||
public:
|
||||
SrsMp4MediaInformationBox();
|
||||
virtual ~SrsMp4MediaInformationBox();
|
||||
public:
|
||||
// Get the sample table box.
|
||||
virtual SrsMp4SampleTableBox* stbl();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -734,6 +777,9 @@ class SrsMp4SampleTableBox : public SrsMp4Box
|
|||
public:
|
||||
SrsMp4SampleTableBox();
|
||||
virtual ~SrsMp4SampleTableBox();
|
||||
public:
|
||||
// Get the sample description box
|
||||
virtual SrsMp4SampleDescriptionBox* stsd();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -788,6 +834,9 @@ public:
|
|||
public:
|
||||
SrsMp4VisualSampleEntry();
|
||||
virtual ~SrsMp4VisualSampleEntry();
|
||||
public:
|
||||
// For avc1, get the avcc box.
|
||||
virtual SrsMp4AvccBox* avcC();
|
||||
protected:
|
||||
virtual int nb_header();
|
||||
virtual int encode_header(SrsBuffer* buf);
|
||||
|
@ -828,6 +877,11 @@ public:
|
|||
public:
|
||||
SrsMp4AudioSampleEntry();
|
||||
virtual ~SrsMp4AudioSampleEntry();
|
||||
public:
|
||||
// For AAC codec, get the esds.
|
||||
virtual SrsMp4EsdsBox* esds();
|
||||
// For AAC codec, get the asc.
|
||||
virtual SrsMp4DecoderSpecificInfo* asc();
|
||||
protected:
|
||||
virtual int nb_header();
|
||||
virtual int encode_header(SrsBuffer* buf);
|
||||
|
@ -1003,6 +1057,9 @@ public:
|
|||
public:
|
||||
SrsMp4EsdsBox();
|
||||
virtual ~SrsMp4EsdsBox();
|
||||
public:
|
||||
// For AAC codec, get the asc.
|
||||
virtual SrsMp4DecoderSpecificInfo* asc();
|
||||
protected:
|
||||
virtual int nb_header();
|
||||
virtual int encode_header(SrsBuffer* buf);
|
||||
|
@ -1022,6 +1079,11 @@ private:
|
|||
public:
|
||||
SrsMp4SampleDescriptionBox();
|
||||
virtual ~SrsMp4SampleDescriptionBox();
|
||||
public:
|
||||
// For H.264/AVC, get the avc1 box.
|
||||
virtual SrsMp4VisualSampleEntry* avc1();
|
||||
// For AAC, get the mp4a box.
|
||||
virtual SrsMp4AudioSampleEntry* mp4a();
|
||||
public:
|
||||
virtual uint32_t entry_count();
|
||||
virtual SrsMp4SampleEntry* entrie_at(int index);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue