1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Refine mp4 codec for mdat.

This commit is contained in:
winlin 2017-04-16 20:16:11 +08:00
parent 18d9f6c8f1
commit c9bed5a8bf
3 changed files with 118 additions and 39 deletions

View file

@ -103,6 +103,11 @@ uint64_t SrsMp4Box::sz()
return smallsize == SRS_MP4_USE_LARGE_SIZE? largesize:smallsize;
}
int SrsMp4Box::sz_header()
{
return nb_header();
}
int SrsMp4Box::left_space(SrsBuffer* buf)
{
return (int)sz() - (buf->pos() - start_pos);
@ -193,7 +198,6 @@ int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
switch(type) {
case SrsMp4BoxTypeFTYP: box = new SrsMp4FileTypeBox(); break;
case SrsMp4BoxTypeMDAT: box = new SrsMp4MediaDataBox(); break;
case SrsMp4BoxTypeFREE: case SrsMp4BoxTypeSKIP: box = new SrsMp4FreeSpaceBox(); break;
case SrsMp4BoxTypeMOOV: box = new SrsMp4MovieBox(); break;
case SrsMp4BoxTypeMVHD: box = new SrsMp4MovieHeaderBox(); break;
case SrsMp4BoxTypeTRAK: box = new SrsMp4TrackBox(); break;
@ -226,6 +230,9 @@ int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
case SrsMp4BoxTypeUDTA: box = new SrsMp4UserDataBox(); break;
case SrsMp4BoxTypeMVEX: box = new SrsMp4MovieExtendsBox(); break;
case SrsMp4BoxTypeTREX: box = new SrsMp4TrackExtendsBox(); break;
// Skip some unknown boxes.
case SrsMp4BoxTypeFREE: case SrsMp4BoxTypeSKIP: case SrsMp4BoxTypePASP:
box = new SrsMp4FreeSpaceBox(); break;
default:
ret = ERROR_MP4_BOX_ILLEGAL_TYPE;
srs_error("MP4 illegal box type=%d. ret=%d", type, ret);
@ -259,7 +266,7 @@ int SrsMp4Box::encode(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
uint64_t size = encode_actual_size();
uint64_t size = nb_bytes();
if (size > 0xffffffff) {
largesize = size;
} else {
@ -407,7 +414,7 @@ int SrsMp4Box::decode_header(SrsBuffer* buf)
type = (SrsMp4BoxType)buf->read_4bytes();
if (smallsize == SRS_MP4_EOF_SIZE) {
srs_warn("MP4 box EOF.");
srs_trace("MP4 box EOF.");
return ret;
}
@ -448,11 +455,6 @@ int SrsMp4Box::decode_header(SrsBuffer* buf)
return ret;
}
uint64_t SrsMp4Box::encode_actual_size()
{
return nb_bytes();
}
SrsMp4FullBox::SrsMp4FullBox()
{
version = 0;
@ -589,20 +591,29 @@ int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf)
SrsMp4MediaDataBox::SrsMp4MediaDataBox()
{
type = SrsMp4BoxTypeMDAT;
data = NULL;
nb_data = 0;
}
SrsMp4MediaDataBox::~SrsMp4MediaDataBox()
{
srs_freepa(data);
}
uint64_t SrsMp4MediaDataBox::encode_actual_size()
int SrsMp4MediaDataBox::nb_bytes()
{
return SrsMp4Box::nb_header() + nb_data;
}
int SrsMp4MediaDataBox::encode(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode(buf)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsMp4MediaDataBox::decode(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
@ -611,11 +622,23 @@ int SrsMp4MediaDataBox::decode(SrsBuffer* buf)
return ret;
}
nb_data = left_space(buf);
nb_data = (int)(sz() - nb_header());
// Because the
return ret;
}
int SrsMp4MediaDataBox::encode_boxes(SrsBuffer* buf)
{
return ERROR_SUCCESS;
}
int SrsMp4MediaDataBox::decode_boxes(SrsBuffer* buf)
{
return ERROR_SUCCESS;
}
SrsMp4FreeSpaceBox::SrsMp4FreeSpaceBox()
{
type = SrsMp4BoxTypeFREE; // 'free' or 'skip'
@ -627,7 +650,7 @@ SrsMp4FreeSpaceBox::~SrsMp4FreeSpaceBox()
int SrsMp4FreeSpaceBox::nb_header()
{
return SrsMp4Box::nb_header() + data.size();
return SrsMp4Box::nb_header() + (int)data.size();
}
int SrsMp4FreeSpaceBox::encode_header(SrsBuffer* buf)
@ -639,7 +662,7 @@ int SrsMp4FreeSpaceBox::encode_header(SrsBuffer* buf)
}
if (!data.empty()) {
buf->write_bytes(&data[0], data.size());
buf->write_bytes(&data[0], (int)data.size());
}
return ret;
@ -4184,7 +4207,13 @@ int SrsMp4Decoder::do_load_next_box(SrsMp4Box** ppbox, uint32_t required_box_typ
SrsMp4Box* box = NULL;
while (true) {
// For the first time to read the box, maybe it's a basic box which is only 4bytes header.
// When we disconvery the real box, we know the size of the whole box, then read again and decode it.
uint64_t required = box? box->sz():4;
// For mdat box, we only requires to decode the header.
if (box && box->is_mdat()) {
required = box->sz_header();
}
while (stream->length() < (int)required) {
ssize_t nread;
if ((ret = rsio->read(buf, SRS_MP4_BUF_SIZE, &nread)) != ERROR_SUCCESS) {
@ -4208,15 +4237,17 @@ int SrsMp4Decoder::do_load_next_box(SrsMp4Box** ppbox, uint32_t required_box_typ
return ret;
}
// Util we can demux the whole box.
// When box is discoveried, check whether we can demux the whole box.
// For mdat, only the header is required.
if (!box->is_mdat()) {
if (!buffer->require((int)box->sz())) {
continue;
}
required = (box->is_mdat()? box->sz_header():box->sz());
if (!buffer->require((int)required)) {
continue;
}
// Decode the matched box or any box is matched.
// Decode the box:
// 1. Any box, when no box type is required.
// 2. Matched box, when box type match the required type.
// 3. Mdat box, always decode the mdat because we only decode the header of it.
if (!required_box_type || box->type == required_box_type || box->is_mdat()) {
ret = box->decode(buffer);
}
@ -4316,7 +4347,7 @@ int SrsMp4Encoder::initialize(ISrsWriteSeeker* ws)
return ret;
}
int nb_data = mdat->nb_bytes();
int nb_data = mdat->sz_header();
uint8_t* data = new uint8_t[nb_data];
SrsAutoFreeA(uint8_t, data);
if ((ret = buffer->initialize((char*)data, nb_data)) != ERROR_SUCCESS) {
@ -4573,13 +4604,13 @@ int SrsMp4Encoder::flush()
return ret;
}
// Write empty mdat box,
// its payload will be writen by samples,
// Write mdat box with size of data,
// its payload already writen by samples,
// and we will update its header(size) when flush.
SrsMp4MediaDataBox* mdat = new SrsMp4MediaDataBox();
SrsAutoFree(SrsMp4MediaDataBox, mdat);
int nb_data = mdat->nb_bytes();
int nb_data = mdat->sz_header();
uint8_t* data = new uint8_t[nb_data];
SrsAutoFreeA(uint8_t, data);
if ((ret = buffer->initialize((char*)data, nb_data)) != ERROR_SUCCESS) {
@ -4606,7 +4637,7 @@ int SrsMp4Encoder::copy_sequence_header(bool vsh, uint8_t* sample, uint32_t nb_s
int ret = ERROR_SUCCESS;
if (vsh && !pavcc.empty()) {
if (nb_sample == pavcc.size() && srs_bytes_equals(sample, &pavcc[0], pavcc.size())) {
if (nb_sample == pavcc.size() && srs_bytes_equals(sample, &pavcc[0], (int)pavcc.size())) {
return ret;
}
@ -4616,7 +4647,7 @@ int SrsMp4Encoder::copy_sequence_header(bool vsh, uint8_t* sample, uint32_t nb_s
}
if (!vsh && !pasc.empty()) {
if (nb_sample == pasc.size() && srs_bytes_equals(sample, &pasc[0], pasc.size())) {
if (nb_sample == pasc.size() && srs_bytes_equals(sample, &pasc[0], (int)pasc.size())) {
return ret;
}