1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-24 15:04:20 +00:00
srs/trunk/src/kernel/srs_kernel_mp4.cpp

2847 lines
65 KiB
C++
Raw Normal View History

/*
The MIT License (MIT)
Copyright (c) 2013-2017 SRS(ossrs)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_kernel_mp4.hpp>
2017-01-31 13:36:51 +00:00
#include <srs_kernel_log.hpp>
2017-01-31 12:43:48 +00:00
#include <srs_kernel_error.hpp>
2017-02-01 13:57:32 +00:00
#include <srs_kernel_stream.hpp>
#include <srs_core_autofree.hpp>
#include <srs_kernel_io.hpp>
#include <srs_kernel_buffer.hpp>
#include <string.h>
using namespace std;
#define SRS_MP4_EOF_SIZE 0
#define SRS_MP4_USE_LARGE_SIZE 1
int srs_mp4_string_length(const string& v)
{
return (int)v.length()+1;
}
void srs_mp4_string_write(SrsBuffer* buf, const string& v)
{
// Nothing for empty string.
if (v.empty()) {
return;
2017-02-01 13:57:32 +00:00
}
buf->write_bytes((char*)v.data(), (int)v.length());
2017-02-01 13:57:32 +00:00
buf->write_1bytes(0x00);
}
int srs_mp4_string_read(SrsBuffer* buf, string& v, int left)
{
int ret = ERROR_SUCCESS;
if (left == 0) {
return ret;
}
2017-02-01 13:57:32 +00:00
char* start = buf->data() + buf->pos();
size_t len = strnlen(start, left);
if (len == left) {
ret = ERROR_MP4_BOX_STRING;
srs_error("MP4 string corrupt, left=%d. ret=%d", left, ret);
return ret;
2017-02-01 13:57:32 +00:00
}
v.append(start, len);
buf->skip((int)len + 1);
2017-02-01 13:57:32 +00:00
return ret;
}
2017-01-31 12:43:48 +00:00
2017-01-28 11:32:43 +00:00
SrsMp4Box::SrsMp4Box()
2017-01-27 12:54:05 +00:00
{
2017-02-01 13:57:32 +00:00
smallsize = 0;
largesize = 0;
usertype = NULL;
start_pos = 0;
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeForbidden;
2017-01-27 12:54:05 +00:00
}
SrsMp4Box::~SrsMp4Box()
{
2017-02-01 13:57:32 +00:00
vector<SrsMp4Box*>::iterator it;
for (it = boxes.begin(); it != boxes.end(); ++it) {
SrsMp4Box* box = *it;
srs_freep(box);
}
boxes.clear();
srs_freepa(usertype);
}
uint64_t SrsMp4Box::sz()
{
return smallsize == SRS_MP4_USE_LARGE_SIZE? largesize:smallsize;
}
int SrsMp4Box::left_space(SrsBuffer* buf)
{
return (int)sz() - (buf->pos() - start_pos);
}
bool SrsMp4Box::is_ftyp()
{
2017-02-02 14:02:39 +00:00
return type == SrsMp4BoxTypeFTYP;
}
bool SrsMp4Box::is_moov()
{
2017-02-02 14:02:39 +00:00
return type == SrsMp4BoxTypeMOOV;
}
bool SrsMp4Box::is_mdat()
{
2017-02-02 14:02:39 +00:00
return type == SrsMp4BoxTypeMDAT;
}
2017-02-01 13:57:32 +00:00
int SrsMp4Box::discovery(SrsBuffer* buf, SrsMp4Box** ppbox)
{
*ppbox = NULL;
int ret = ERROR_SUCCESS;
if (!buf->require(8)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 discovery require 8 bytes space. ret=%d", ret);
return ret;
}
// Discovery the size and type.
uint64_t largesize = 0;
uint32_t smallsize = (uint32_t)buf->read_4bytes();
2017-02-02 14:02:39 +00:00
SrsMp4BoxType type = (SrsMp4BoxType)buf->read_4bytes();
2017-02-01 13:57:32 +00:00
if (smallsize == SRS_MP4_USE_LARGE_SIZE) {
if (!buf->require(8)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 discovery require 16 bytes space. ret=%d", ret);
return ret;
}
largesize = (uint64_t)buf->read_8bytes();
buf->skip(-8);
}
buf->skip(-8);
// Only support 31bits size.
if (largesize > 0x7fffffff) {
ret = ERROR_MP4_BOX_OVERFLOW;
srs_error("MP4 discovery overflow 31bits, size=%"PRId64". ret=%d", largesize, ret);
return ret;
}
SrsMp4Box* box = NULL;
switch(type) {
2017-02-02 14:02:39 +00:00
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;
case SrsMp4BoxTypeTKHD: box = new SrsMp4TrackHeaderBox(); break;
case SrsMp4BoxTypeEDTS: box = new SrsMp4EditBox(); break;
case SrsMp4BoxTypeELST: box = new SrsMp4EditListBox(); break;
case SrsMp4BoxTypeMDIA: box = new SrsMp4MediaBox(); break;
case SrsMp4BoxTypeMDHD: box = new SrsMp4MediaHeaderBox(); break;
case SrsMp4BoxTypeHDLR: box = new SrsMp4HandlerReferenceBox(); break;
case SrsMp4BoxTypeMINF: box = new SrsMp4MediaInformationBox(); break;
case SrsMp4BoxTypeVMHD: box = new SrsMp4VideoMeidaHeaderBox(); break;
case SrsMp4BoxTypeSMHD: box = new SrsMp4SoundMeidaHeaderBox(); break;
case SrsMp4BoxTypeDINF: box = new SrsMp4DataInformationBox(); break;
case SrsMp4BoxTypeURL: box = new SrsMp4DataEntryUrlBox(); break;
case SrsMp4BoxTypeURN: box = new SrsMp4DataEntryUrnBox(); break;
case SrsMp4BoxTypeDREF: box = new SrsMp4DataReferenceBox(); break;
case SrsMp4BoxTypeSTBL: box = new SrsMp4SampleTableBox(); break;
case SrsMp4BoxTypeSTSD: box = new SrsMp4SampleDescriptionBox(); break;
case SrsMp4BoxTypeSTTS: box = new SrsMp4DecodingTime2SampleBox(); break;
case SrsMp4BoxTypeCTTS: box = new SrsMp4CompositionTime2SampleBox(); break;
case SrsMp4BoxTypeSTSS: box = new SrsMp4SyncSampleBox(); break;
case SrsMp4BoxTypeSTSC: box = new SrsMp4Sample2ChunkBox(); break;
case SrsMp4BoxTypeSTCO: box = new SrsMp4ChunkOffsetBox(); break;
case SrsMp4BoxTypeCO64: box = new SrsMp4ChunkLargeOffsetBox(); break;
case SrsMp4BoxTypeSTSZ: box = new SrsMp4SampleSizeBox(); break;
case SrsMp4BoxTypeAVC1: box = new SrsMp4VisualSampleEntry(); break;
case SrsMp4BoxTypeAVCC: box = new SrsMp4AvccBox(); break;
case SrsMp4BoxTypeMP4A: box = new SrsMp4AudioSampleEntry(); break;
case SrsMp4BoxTypeESDS: box = new SrsMp4EsdsBox(); break;
case SrsMp4BoxTypeUDTA: box = new SrsMp4UserDataBox(); break;
2017-02-01 13:57:32 +00:00
default:
ret = ERROR_MP4_BOX_ILLEGAL_TYPE;
srs_error("MP4 illegal box type=%d. ret=%d", type, ret);
break;
}
if (box) {
box->smallsize = smallsize;
box->largesize = largesize;
box->type = type;
*ppbox = box;
}
return ret;
}
int SrsMp4Box::nb_bytes()
{
int sz = nb_header();
vector<SrsMp4Box*>::iterator it;
for (it = boxes.begin(); it != boxes.end(); ++it) {
SrsMp4Box* box = *it;
sz += box->nb_bytes();
}
return sz;
}
int SrsMp4Box::encode(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = encode_header(buf)) != ERROR_SUCCESS) {
srs_error("MP4 encode box header failed. ret=%d", ret);
return ret;
}
if ((ret = encode_boxes(buf)) != ERROR_SUCCESS) {
srs_error("MP4 encode contained boxes failed. ret=%d", ret);
return ret;
}
return ret;
}
int SrsMp4Box::decode(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
start_pos = buf->pos();
if ((ret = decode_header(buf)) != ERROR_SUCCESS) {
srs_error("MP4 decode box header failed. ret=%d", ret);
return ret;
}
if ((ret = decode_boxes(buf)) != ERROR_SUCCESS) {
srs_error("MP4 decode contained boxes failed. ret=%d", ret);
return ret;
}
return ret;
}
int SrsMp4Box::encode_boxes(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
vector<SrsMp4Box*>::iterator it;
for (it = boxes.begin(); it != boxes.end(); ++it) {
SrsMp4Box* box = *it;
if ((ret = box->encode(buf)) != ERROR_SUCCESS) {
srs_error("MP4 encode contained box failed. ret=%d", ret);
return ret;
}
}
return ret;
}
int SrsMp4Box::decode_boxes(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
int left = left_space(buf);
while (left > 0) {
SrsMp4Box* box = NULL;
if ((ret = discovery(buf, &box)) != ERROR_SUCCESS) {
srs_error("MP4 discovery contained box failed. ret=%d", ret);
return ret;
}
srs_assert(box);
if ((ret = box->decode(buf)) != ERROR_SUCCESS) {
srs_freep(box);
srs_error("MP4 decode contained box failed. ret=%d", ret);
return ret;
}
boxes.push_back(box);
left -= box->sz();
}
return ret;
}
int SrsMp4Box::nb_header()
{
int size = 8;
if (smallsize == SRS_MP4_USE_LARGE_SIZE) {
size += 8;
}
2017-02-02 14:02:39 +00:00
if (type == SrsMp4BoxTypeUUID) {
2017-02-01 13:57:32 +00:00
size += 16;
}
return size;
}
int SrsMp4Box::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
// Only support 31bits size.
if (sz() > 0x7fffffff) {
ret = ERROR_MP4_BOX_OVERFLOW;
srs_error("MP4 box size overflow 31bits, size=%"PRId64". ret=%d", sz(), ret);
return ret;
}
int size = nb_header();
if (!buf->require(size)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 box require %d bytes space. ret=%d", size, ret);
return ret;
}
buf->write_4bytes(smallsize);
if (smallsize == SRS_MP4_USE_LARGE_SIZE) {
buf->write_8bytes(largesize);
}
buf->write_4bytes(type);
2017-02-02 14:02:39 +00:00
if (type == SrsMp4BoxTypeUUID) {
2017-02-01 13:57:32 +00:00
buf->write_bytes((char*)usertype, 16);
}
return ret;
}
int SrsMp4Box::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if (!buf->require(8)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 box require 8 bytes space. ret=%d", ret);
return ret;
}
smallsize = (uint32_t)buf->read_4bytes();
2017-02-02 14:02:39 +00:00
type = (SrsMp4BoxType)buf->read_4bytes();
2017-02-01 13:57:32 +00:00
if (smallsize == SRS_MP4_EOF_SIZE) {
srs_warn("MP4 box EOF.");
return ret;
}
if (smallsize == SRS_MP4_USE_LARGE_SIZE) {
if (!buf->require(8)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 box require 8 bytes space. ret=%d", ret);
return ret;
}
largesize = (uint64_t)buf->read_8bytes();
}
// Only support 31bits size.
if (sz() > 0x7fffffff) {
ret = ERROR_MP4_BOX_OVERFLOW;
srs_error("MP4 box size overflow 31bits, size=%"PRId64". ret=%d", sz(), ret);
return ret;
}
2017-02-02 14:02:39 +00:00
if (type == SrsMp4BoxTypeUUID) {
2017-02-01 13:57:32 +00:00
if (!buf->require(16)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 box requires 16 bytes space. ret=%d", ret);
return ret;
}
usertype = new uint8_t[16];
buf->read_bytes((char*)usertype, 16);
}
// The left required size, determined by the default version(0).
int lrsz = nb_header() - SrsMp4Box::nb_header();
if (!buf->require(lrsz)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 box requires %d bytes space. ret=%d", lrsz, ret);
return ret;
}
return ret;
2017-01-27 12:54:05 +00:00
}
2017-01-28 11:32:43 +00:00
SrsMp4FullBox::SrsMp4FullBox()
2017-01-27 12:54:05 +00:00
{
2017-01-28 11:32:43 +00:00
version = 0;
flags = 0;
2017-01-27 12:54:05 +00:00
}
SrsMp4FullBox::~SrsMp4FullBox()
{
}
2017-02-01 13:57:32 +00:00
int SrsMp4FullBox::nb_header()
{
return SrsMp4Box::nb_header() + 1 + 3;
}
int SrsMp4FullBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_1bytes(version);
buf->write_3bytes(flags);
return ret;
}
int SrsMp4FullBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (!buf->require(4)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 full box requires 4 bytes space. ret=%d", ret);
return ret;
}
flags = (uint32_t)buf->read_4bytes();
version = (uint8_t)((flags >> 24) & 0xff);
flags &= 0x00ffffff;
// The left required size, determined by the version.
int lrsz = nb_header() - SrsMp4FullBox::nb_header();
if (!buf->require(lrsz)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 full box requires %d bytes space. ret=%d", lrsz, ret);
return ret;
}
return ret;
}
2017-01-28 11:32:43 +00:00
SrsMp4FileTypeBox::SrsMp4FileTypeBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeFTYP;
2017-01-28 11:32:43 +00:00
nb_compatible_brands = 0;
compatible_brands = NULL;
2017-02-02 14:02:39 +00:00
major_brand = SrsMp4BoxBrandForbidden;
minor_version = 0;
2017-01-28 11:32:43 +00:00
}
SrsMp4FileTypeBox::~SrsMp4FileTypeBox()
{
srs_freepa(compatible_brands);
}
2017-02-01 13:57:32 +00:00
int SrsMp4FileTypeBox::nb_header()
{
return SrsMp4Box::nb_header() + 8 + nb_compatible_brands * 4;
}
int SrsMp4FileTypeBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(major_brand);
buf->write_4bytes(minor_version);
for (int i = 0; i < nb_compatible_brands; i++) {
2017-02-02 14:02:39 +00:00
buf->write_4bytes(compatible_brands[i]);
2017-02-01 13:57:32 +00:00
}
return ret;
}
int SrsMp4FileTypeBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
2017-02-02 14:02:39 +00:00
major_brand = (SrsMp4BoxBrand)buf->read_4bytes();
2017-02-01 13:57:32 +00:00
minor_version = buf->read_4bytes();
// Compatible brands to the end of the box.
int left = left_space(buf);
if (left > 0) {
nb_compatible_brands = left / 4;
2017-02-02 14:02:39 +00:00
compatible_brands = new SrsMp4BoxBrand[nb_compatible_brands];
2017-02-01 13:57:32 +00:00
}
for (int i = 0; left > 0; i++, left -= 4){
2017-02-02 14:02:39 +00:00
compatible_brands[i] = (SrsMp4BoxBrand)buf->read_4bytes();
2017-02-01 13:57:32 +00:00
}
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4MediaDataBox::SrsMp4MediaDataBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeMDAT;
2017-01-29 07:45:27 +00:00
data = NULL;
nb_data = 0;
}
SrsMp4MediaDataBox::~SrsMp4MediaDataBox()
{
srs_freepa(data);
}
2017-02-01 13:57:32 +00:00
int SrsMp4MediaDataBox::nb_header()
{
return SrsMp4Box::nb_header() + nb_data;
}
int SrsMp4MediaDataBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (nb_data) {
buf->write_bytes((char*)data, nb_data);
}
return ret;
}
int SrsMp4MediaDataBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
int left = left_space(buf);
if (left) {
data = new uint8_t[left];
buf->read_bytes((char*)data, left);
}
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4FreeSpaceBox::SrsMp4FreeSpaceBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeFREE; // 'free' or 'skip'
2017-02-01 13:57:32 +00:00
data = NULL;
nb_data = 0;
2017-01-29 07:45:27 +00:00
}
SrsMp4FreeSpaceBox::~SrsMp4FreeSpaceBox()
{
2017-02-01 13:57:32 +00:00
srs_freepa(data);
}
int SrsMp4FreeSpaceBox::nb_header()
{
return SrsMp4Box::nb_header() + nb_data;
}
int SrsMp4FreeSpaceBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (nb_data) {
buf->write_bytes((char*)data, nb_data);
}
return ret;
}
int SrsMp4FreeSpaceBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
int left = left_space(buf);
if (left) {
data = new uint8_t[left];
buf->read_bytes((char*)data, left);
}
return ret;
2017-01-29 07:45:27 +00:00
}
2017-01-28 11:32:43 +00:00
SrsMp4MovieBox::SrsMp4MovieBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeMOOV;
2017-01-28 11:32:43 +00:00
}
SrsMp4MovieBox::~SrsMp4MovieBox()
{
}
int SrsMp4MovieBox::nb_header()
{
return SrsMp4Box::nb_header();
}
int SrsMp4MovieBox::encode_header(SrsBuffer* buf)
{
return SrsMp4Box::encode_header(buf);
}
int SrsMp4MovieBox::decode_header(SrsBuffer* buf)
{
return SrsMp4Box::decode_header(buf);
}
2017-01-28 11:32:43 +00:00
SrsMp4MovieHeaderBox::SrsMp4MovieHeaderBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeMVHD;
2017-01-29 07:45:27 +00:00
rate = 0x00010000; // typically 1.0
volume = 0x0100; // typically, full volume
reserved0 = 0;
reserved1 = 0;
int32_t v[] = {0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000};
memcpy(matrix, v, 36);
memset(pre_defined, 0, 24);
2017-01-28 11:32:43 +00:00
}
SrsMp4MovieHeaderBox::~SrsMp4MovieHeaderBox()
{
}
2017-02-01 13:57:32 +00:00
int SrsMp4MovieHeaderBox::nb_header()
{
int size = SrsMp4FullBox::nb_header();
if (version == 1) {
size += 8+8+4+8;
} else {
size += 4+4+4+4;
}
size += 4+2+2+8+36+24+4;
return size;
}
int SrsMp4MovieHeaderBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (version == 1) {
buf->write_8bytes(creation_time);
buf->write_8bytes(modification_time);
buf->write_4bytes(timescale);
buf->write_8bytes(duration);
} else {
buf->write_4bytes((uint32_t)creation_time);
buf->write_4bytes((uint32_t)modification_time);
buf->write_4bytes(timescale);
buf->write_4bytes((uint32_t)duration);
}
buf->write_4bytes(rate);
buf->write_2bytes(volume);
buf->write_2bytes(reserved0);
buf->write_8bytes(reserved1);
for (int i = 0; i < 9; i++) {
buf->write_4bytes(matrix[i]);
}
for (int i = 0; i < 6; i++) {
buf->write_4bytes(pre_defined[i]);
}
buf->write_4bytes(next_track_ID);
return ret;
}
int SrsMp4MovieHeaderBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (version == 1) {
creation_time = buf->read_8bytes();
modification_time = buf->read_8bytes();
timescale = buf->read_4bytes();
duration = buf->read_8bytes();
} else {
creation_time = buf->read_4bytes();
modification_time = buf->read_4bytes();
timescale = buf->read_4bytes();
duration = buf->read_4bytes();
}
rate = buf->read_4bytes();
volume = buf->read_2bytes();
2017-02-01 13:57:32 +00:00
buf->skip(2);
buf->skip(8);
for (int i = 0; i < 9; i++) {
matrix[i] = buf->read_4bytes();
}
buf->skip(24);
next_track_ID = buf->read_4bytes();
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4TrackBox::SrsMp4TrackBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeTRAK;
2017-01-29 07:45:27 +00:00
}
SrsMp4TrackBox::~SrsMp4TrackBox()
{
}
SrsMp4TrackHeaderBox::SrsMp4TrackHeaderBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeTKHD;
2017-01-29 07:45:27 +00:00
reserved0 = 0;
reserved1 = 0;
reserved2 = 0;
layer = alternate_group = 0;
2017-02-01 13:57:32 +00:00
volume = 0; // if track_is_audio 0x0100 else 0
2017-01-29 07:45:27 +00:00
int32_t v[] = {0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000};
memcpy(matrix, v, 36);
}
SrsMp4TrackHeaderBox::~SrsMp4TrackHeaderBox()
{
}
2017-02-01 13:57:32 +00:00
int SrsMp4TrackHeaderBox::nb_header()
{
int size = SrsMp4FullBox::nb_header();
if (version == 1) {
size += 8+8+4+4+8;
} else {
size += 4+4+4+4+4;
}
size += 8+2+2+2+2+36+4+4;
return size;
}
int SrsMp4TrackHeaderBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (version == 1) {
buf->write_8bytes(creation_time);
buf->write_8bytes(modification_time);
buf->write_4bytes(track_ID);
buf->write_4bytes(reserved0);
buf->write_8bytes(duration);
} else {
buf->write_4bytes((uint32_t)creation_time);
buf->write_4bytes((uint32_t)modification_time);
buf->write_4bytes(track_ID);
buf->write_4bytes(reserved0);
buf->write_4bytes((uint32_t)duration);
}
buf->write_8bytes(reserved1);
buf->write_2bytes(layer);
buf->write_2bytes(alternate_group);
buf->write_2bytes(volume);
buf->write_2bytes(reserved2);
for (int i = 0; i < 9; i++) {
buf->write_4bytes(matrix[i]);
}
buf->write_4bytes(width);
buf->write_4bytes(height);
return ret;
}
int SrsMp4TrackHeaderBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (version == 1) {
creation_time = buf->read_8bytes();
modification_time = buf->read_8bytes();
track_ID = buf->read_4bytes();
buf->skip(4);
duration = buf->read_8bytes();
} else {
creation_time = buf->read_4bytes();
modification_time = buf->read_4bytes();
track_ID = buf->read_4bytes();
buf->skip(4);
duration = buf->read_4bytes();
}
buf->skip(8);
layer = buf->read_2bytes();
alternate_group = buf->read_2bytes();
volume = buf->read_2bytes();
buf->skip(2);
for (int i = 0; i < 9; i++) {
matrix[i] = buf->read_4bytes();
}
width = buf->read_4bytes();
height = buf->read_4bytes();
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4EditBox::SrsMp4EditBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeEDTS;
2017-01-29 07:45:27 +00:00
}
SrsMp4EditBox::~SrsMp4EditBox()
{
}
SrsMp4ElstEntry::SrsMp4ElstEntry()
{
media_rate_fraction = 0;
}
SrsMp4EditListBox::SrsMp4EditListBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeELST;
2017-01-29 07:45:27 +00:00
entry_count = 0;
entries = NULL;
}
SrsMp4EditListBox::~SrsMp4EditListBox()
{
srs_freepa(entries);
}
2017-02-01 13:57:32 +00:00
int SrsMp4EditListBox::nb_header()
{
int size = SrsMp4FullBox::nb_header() + 4;
2017-02-01 13:57:32 +00:00
if (version == 1) {
size += entry_count * (2+2+8+8);
} else {
size += entry_count * (2+2+4+4);
2017-02-01 13:57:32 +00:00
}
return size;
}
int SrsMp4EditListBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count);
2017-02-01 13:57:32 +00:00
for (uint32_t i = 0; i < entry_count; i++) {
SrsMp4ElstEntry& entry = entries[i];
if (version == 1) {
buf->write_8bytes(entry.segment_duration);
buf->write_8bytes(entry.media_time);
} else {
buf->write_4bytes((uint32_t)entry.segment_duration);
buf->write_4bytes((int32_t)entry.media_time);
2017-02-01 13:57:32 +00:00
}
buf->write_2bytes(entry.media_rate_integer);
buf->write_2bytes(entry.media_rate_fraction);
2017-02-01 13:57:32 +00:00
}
return ret;
}
int SrsMp4EditListBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
entry_count = buf->read_4bytes();
2017-02-01 13:57:32 +00:00
if (entry_count > 0) {
entries = new SrsMp4ElstEntry[entry_count];
}
for (int i = 0; i < entry_count; i++) {
SrsMp4ElstEntry& entry = entries[i];
if (version == 1) {
entry.segment_duration = buf->read_8bytes();
entry.media_time = buf->read_8bytes();
} else {
entry.segment_duration = buf->read_4bytes();
entry.media_time = buf->read_4bytes();
2017-02-01 13:57:32 +00:00
}
entry.media_rate_integer = buf->read_2bytes();
entry.media_rate_fraction = buf->read_2bytes();
2017-02-01 13:57:32 +00:00
}
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4MediaBox::SrsMp4MediaBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeMDIA;
2017-01-29 07:45:27 +00:00
}
SrsMp4MediaBox::~SrsMp4MediaBox()
{
}
SrsMp4MediaHeaderBox::SrsMp4MediaHeaderBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeMDHD;
2017-02-01 13:57:32 +00:00
language = 0;
2017-01-29 07:45:27 +00:00
pre_defined = 0;
}
SrsMp4MediaHeaderBox::~SrsMp4MediaHeaderBox()
{
}
2017-02-01 13:57:32 +00:00
uint8_t SrsMp4MediaHeaderBox::language0()
{
return (language >> 10) & 0x1f;
}
void SrsMp4MediaHeaderBox::set_language0(uint8_t v)
{
language |= uint16_t(v & 0x1f) << 10;
}
uint8_t SrsMp4MediaHeaderBox::language1()
{
return (language >> 5) & 0x1f;
}
void SrsMp4MediaHeaderBox::set_language1(uint8_t v)
{
language |= uint16_t(v & 0x1f) << 5;
}
uint8_t SrsMp4MediaHeaderBox::language2()
{
return language & 0x1f;
}
void SrsMp4MediaHeaderBox::set_language2(uint8_t v)
{
language |= uint16_t(v & 0x1f);
}
int SrsMp4MediaHeaderBox::nb_header()
{
int size = SrsMp4FullBox::nb_header();
if (version == 1) {
size += 8+8+4+8;
} else {
size += 4+4+4+4;
}
size += 2+2;
return size;
}
int SrsMp4MediaHeaderBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (version == 1) {
buf->write_8bytes(creation_time);
buf->write_8bytes(modification_time);
buf->write_4bytes(timescale);
buf->write_8bytes(duration);
} else {
buf->write_4bytes((uint32_t)creation_time);
buf->write_4bytes((uint32_t)modification_time);
buf->write_4bytes(timescale);
buf->write_4bytes((uint32_t)duration);
}
buf->write_2bytes(language);
buf->write_2bytes(pre_defined);
return ret;
}
int SrsMp4MediaHeaderBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (version == 1) {
creation_time = buf->read_8bytes();
modification_time = buf->read_8bytes();
timescale = buf->read_4bytes();
duration = buf->read_8bytes();
} else {
creation_time = buf->read_4bytes();
modification_time = buf->read_4bytes();
timescale = buf->read_4bytes();
duration = buf->read_4bytes();
}
language = buf->read_2bytes();
buf->skip(2);
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4HandlerReferenceBox::SrsMp4HandlerReferenceBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeHDLR;
2017-02-01 13:57:32 +00:00
pre_defined = 0;
memset(reserved, 0, 12);
}
SrsMp4HandlerReferenceBox::~SrsMp4HandlerReferenceBox()
{
}
bool SrsMp4HandlerReferenceBox::is_video()
{
2017-02-02 14:02:39 +00:00
return handler_type == SrsMp4BoxTypeVIDE;
}
bool SrsMp4HandlerReferenceBox::is_audio()
{
2017-02-02 14:02:39 +00:00
return handler_type == SrsMp4BoxTypeSOUN;
}
2017-02-01 13:57:32 +00:00
int SrsMp4HandlerReferenceBox::nb_header()
{
return SrsMp4FullBox::nb_header()+4+4+12+srs_mp4_string_length(name);
}
int SrsMp4HandlerReferenceBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(pre_defined);
buf->write_4bytes(handler_type);
buf->write_4bytes(reserved[0]);
buf->write_4bytes(reserved[1]);
buf->write_4bytes(reserved[2]);
srs_mp4_string_write(buf, name);
return ret;
}
int SrsMp4HandlerReferenceBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->skip(4);
handler_type = buf->read_4bytes();
buf->skip(12);
if ((ret = srs_mp4_string_read(buf, name, left_space(buf))) != ERROR_SUCCESS) {
srs_error("MP4 hdlr read string failed. ret=%d", ret);
return ret;
}
return ret;
}
SrsMp4MediaInformationBox::SrsMp4MediaInformationBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeMINF;
2017-02-01 13:57:32 +00:00
}
SrsMp4MediaInformationBox::~SrsMp4MediaInformationBox()
{
}
SrsMp4VideoMeidaHeaderBox::SrsMp4VideoMeidaHeaderBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeVMHD;
2017-02-01 13:57:32 +00:00
version = 0;
flags = 1;
graphicsmode = 0;
memset(opcolor, 0, 6);
}
SrsMp4VideoMeidaHeaderBox::~SrsMp4VideoMeidaHeaderBox()
{
}
int SrsMp4VideoMeidaHeaderBox::nb_header()
{
return SrsMp4FullBox::nb_header()+2+6;
}
int SrsMp4VideoMeidaHeaderBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_2bytes(graphicsmode);
buf->write_2bytes(opcolor[0]);
buf->write_2bytes(opcolor[1]);
buf->write_2bytes(opcolor[2]);
return ret;
}
int SrsMp4VideoMeidaHeaderBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
graphicsmode = buf->read_2bytes();
opcolor[0] = buf->read_2bytes();
opcolor[1] = buf->read_2bytes();
opcolor[2] = buf->read_2bytes();
return ret;
}
SrsMp4SoundMeidaHeaderBox::SrsMp4SoundMeidaHeaderBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSMHD;
2017-02-01 13:57:32 +00:00
reserved = balance = 0;
}
SrsMp4SoundMeidaHeaderBox::~SrsMp4SoundMeidaHeaderBox()
{
}
int SrsMp4SoundMeidaHeaderBox::nb_header()
{
return SrsMp4FullBox::nb_header()+2+2;
}
int SrsMp4SoundMeidaHeaderBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_2bytes(balance);
buf->write_2bytes(reserved);
return ret;
}
int SrsMp4SoundMeidaHeaderBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
balance = buf->read_2bytes();
buf->skip(2);
return ret;
}
SrsMp4DataInformationBox::SrsMp4DataInformationBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeDINF;
2017-02-01 13:57:32 +00:00
}
SrsMp4DataInformationBox::~SrsMp4DataInformationBox()
{
}
SrsMp4DataEntryBox::SrsMp4DataEntryBox()
{
}
SrsMp4DataEntryBox::~SrsMp4DataEntryBox()
{
}
SrsMp4DataEntryUrlBox::SrsMp4DataEntryUrlBox()
2017-02-01 13:57:32 +00:00
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeURL;
}
SrsMp4DataEntryUrlBox::~SrsMp4DataEntryUrlBox()
{
}
int SrsMp4DataEntryUrlBox::nb_header()
{
// a 24-bit integer with flags; one flag is defined (x000001) which means that the media
// data is in the same file as the Movie Box containing this data reference.
if (flags == 1) {
return SrsMp4FullBox::nb_header();
}
2017-02-01 13:57:32 +00:00
return SrsMp4FullBox::nb_header()+srs_mp4_string_length(location);
}
int SrsMp4DataEntryUrlBox::encode_header(SrsBuffer* buf)
2017-02-01 13:57:32 +00:00
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
// a 24-bit integer with flags; one flag is defined (x000001) which means that the media
// data is in the same file as the Movie Box containing this data reference.
if (location.empty()) {
flags = 0x01;
return ret;
}
2017-02-01 13:57:32 +00:00
srs_mp4_string_write(buf, location);
return ret;
}
int SrsMp4DataEntryUrlBox::decode_header(SrsBuffer* buf)
2017-02-01 13:57:32 +00:00
{
int ret = ERROR_SUCCESS;
2017-01-29 07:45:27 +00:00
2017-02-01 13:57:32 +00:00
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
// a 24-bit integer with flags; one flag is defined (x000001) which means that the media
// data is in the same file as the Movie Box containing this data reference.
if (flags == 0x01) {
return ret;
}
2017-02-01 13:57:32 +00:00
if ((ret = srs_mp4_string_read(buf, location, left_space(buf))) != ERROR_SUCCESS) {
srs_error("MP4 url read location failed. ret=%d", ret);
2017-02-01 13:57:32 +00:00
return ret;
}
return ret;
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
SrsMp4DataEntryUrnBox::SrsMp4DataEntryUrnBox()
2017-01-29 07:45:27 +00:00
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeURN;
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
SrsMp4DataEntryUrnBox::~SrsMp4DataEntryUrnBox()
2017-01-29 07:45:27 +00:00
{
}
2017-02-01 13:57:32 +00:00
int SrsMp4DataEntryUrnBox::nb_header()
2017-01-29 07:45:27 +00:00
{
return SrsMp4FullBox::nb_header()+srs_mp4_string_length(location)+srs_mp4_string_length(name);
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
int SrsMp4DataEntryUrnBox::encode_header(SrsBuffer* buf)
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
int ret = ERROR_SUCCESS;
2017-01-29 07:45:27 +00:00
2017-02-01 13:57:32 +00:00
if ((ret = SrsMp4DataEntryBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
srs_mp4_string_write(buf, location);
2017-02-01 13:57:32 +00:00
srs_mp4_string_write(buf, name);
return ret;
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
int SrsMp4DataEntryUrnBox::decode_header(SrsBuffer* buf)
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4DataEntryBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = srs_mp4_string_read(buf, location, left_space(buf))) != ERROR_SUCCESS) {
srs_error("MP4 urn read location failed. ret=%d", ret);
return ret;
}
2017-02-01 13:57:32 +00:00
if ((ret = srs_mp4_string_read(buf, name, left_space(buf))) != ERROR_SUCCESS) {
srs_error("MP4 urn read name failed. ret=%d", ret);
2017-02-01 13:57:32 +00:00
return ret;
}
return ret;
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
SrsMp4DataReferenceBox::SrsMp4DataReferenceBox()
2017-01-29 07:45:27 +00:00
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeDREF;
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
SrsMp4DataReferenceBox::~SrsMp4DataReferenceBox()
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
vector<SrsMp4DataEntryBox*>::iterator it;
for (it = entries.begin(); it != entries.end(); ++it) {
SrsMp4DataEntryBox* entry = *it;
srs_freep(entry);
}
entries.clear();
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
uint32_t SrsMp4DataReferenceBox::entry_count()
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
return (uint32_t)entries.size();
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
SrsMp4DataEntryBox* SrsMp4DataReferenceBox::entry_at(int index)
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
return entries.at(index);
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
int SrsMp4DataReferenceBox::nb_header()
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
int size = SrsMp4FullBox::nb_header();
size += 4;
vector<SrsMp4DataEntryBox*>::iterator it;
for (it = entries.begin(); it != entries.end(); ++it) {
SrsMp4DataEntryBox* entry = *it;
size += entry->nb_bytes();
}
return size;
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
int SrsMp4DataReferenceBox::encode_header(SrsBuffer* buf)
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
int ret = ERROR_SUCCESS;
2017-01-29 07:45:27 +00:00
2017-02-01 13:57:32 +00:00
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes((int32_t)entries.size());
vector<SrsMp4DataEntryBox*>::iterator it;
for (it = entries.begin(); it != entries.end(); ++it) {
SrsMp4DataEntryBox* entry = *it;
if ((ret = entry->encode(buf)) != ERROR_SUCCESS) {
return ret;
}
}
return ret;
2017-01-29 07:45:27 +00:00
}
2017-02-01 13:57:32 +00:00
int SrsMp4DataReferenceBox::decode_header(SrsBuffer* buf)
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
uint32_t nb_entries = buf->read_4bytes();
for (uint32_t i = 0; i < nb_entries; i++) {
2017-02-01 13:57:32 +00:00
SrsMp4Box* box = NULL;
if ((ret = SrsMp4Box::discovery(buf, &box)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = box->decode(buf)) != ERROR_SUCCESS) {
return ret;
}
SrsMp4FullBox* fbox = dynamic_cast<SrsMp4FullBox*>(box);
if (fbox) {
fbox->version = version;
fbox->flags = flags;
}
2017-02-02 14:02:39 +00:00
if (box->type == SrsMp4BoxTypeURL) {
2017-02-01 13:57:32 +00:00
entries.push_back(dynamic_cast<SrsMp4DataEntryUrlBox*>(box));
2017-02-02 14:02:39 +00:00
} else if (box->type == SrsMp4BoxTypeURN) {
2017-02-01 13:57:32 +00:00
entries.push_back(dynamic_cast<SrsMp4DataEntryUrnBox*>(box));
} else {
srs_freep(box);
}
}
return ret;
2017-01-29 07:45:27 +00:00
}
SrsMp4SampleTableBox::SrsMp4SampleTableBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSTBL;
2017-01-29 07:45:27 +00:00
}
SrsMp4SampleTableBox::~SrsMp4SampleTableBox()
{
}
SrsMp4SampleEntry::SrsMp4SampleEntry()
{
memset(reserved, 0, 6);
}
SrsMp4SampleEntry::~SrsMp4SampleEntry()
{
}
2017-02-01 13:57:32 +00:00
int SrsMp4SampleEntry::nb_header()
{
return SrsMp4Box::nb_header()+6+2;
}
int SrsMp4SampleEntry::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
for (int i = 0; i < 6; i++) {
buf->write_1bytes(reserved[i]);
}
buf->write_2bytes(data_reference_index);
return ret;
}
int SrsMp4SampleEntry::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->skip(6);
data_reference_index = buf->read_2bytes();
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4VisualSampleEntry::SrsMp4VisualSampleEntry()
{
pre_defined0 = 0;
reserved0 = 0;
reserved1 = 0;
memset(pre_defined1, 0, 12);
memset(compressorname, 0, 32);
frame_count = 1;
horizresolution = 0x00480000; // 72 dpi
vertresolution = 0x00480000; // 72 dpi
depth = 0x0018;
pre_defined2 = -1;
}
SrsMp4VisualSampleEntry::~SrsMp4VisualSampleEntry()
{
}
2017-02-01 13:57:32 +00:00
int SrsMp4VisualSampleEntry::nb_header()
{
return SrsMp4SampleEntry::nb_header()+2+2+12+2+2+4+4+4+2+32+2+2;
}
int SrsMp4VisualSampleEntry::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4SampleEntry::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_2bytes(pre_defined0);
buf->write_2bytes(reserved0);
buf->write_4bytes(pre_defined1[0]);
buf->write_4bytes(pre_defined1[1]);
buf->write_4bytes(pre_defined1[2]);
buf->write_2bytes(width);
buf->write_2bytes(height);
buf->write_4bytes(horizresolution);
buf->write_4bytes(vertresolution);
buf->write_4bytes(reserved1);
buf->write_2bytes(frame_count);
buf->write_bytes(compressorname, 32);
buf->write_2bytes(depth);
buf->write_2bytes(pre_defined2);
return ret;
}
int SrsMp4VisualSampleEntry::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4SampleEntry::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->skip(2);
buf->skip(2);
buf->skip(12);
width = buf->read_2bytes();
height = buf->read_2bytes();
horizresolution = buf->read_4bytes();
vertresolution = buf->read_4bytes();
buf->skip(4);
frame_count = buf->read_2bytes();
buf->read_bytes(compressorname, 32);
depth = buf->read_2bytes();
buf->skip(2);
return ret;
}
SrsMp4AvccBox::SrsMp4AvccBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeAVCC;
nb_config = 0;
avc_config = NULL;
}
SrsMp4AvccBox::~SrsMp4AvccBox()
{
srs_freepa(avc_config);
}
int SrsMp4AvccBox::nb_header()
{
return SrsMp4Box::nb_header()+nb_config;
}
int SrsMp4AvccBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (nb_config) {
buf->write_bytes((char*)avc_config, nb_config);
}
return ret;
}
int SrsMp4AvccBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
nb_config = left_space(buf);
if (nb_config) {
avc_config = new uint8_t[nb_config];
buf->read_bytes((char*)avc_config, nb_config);
}
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4AudioSampleEntry::SrsMp4AudioSampleEntry()
{
2017-02-01 13:57:32 +00:00
reserved0 = 0;
2017-01-29 07:45:27 +00:00
pre_defined0 = 0;
reserved1 = 0;
channelcount = 2;
samplesize = 16;
}
SrsMp4AudioSampleEntry::~SrsMp4AudioSampleEntry()
{
}
2017-02-01 13:57:32 +00:00
int SrsMp4AudioSampleEntry::nb_header()
{
return SrsMp4SampleEntry::nb_header()+8+2+2+2+2+4;
}
int SrsMp4AudioSampleEntry::encode_header(SrsBuffer* buf)
2017-01-29 07:45:27 +00:00
{
2017-02-01 13:57:32 +00:00
int ret = ERROR_SUCCESS;
2017-01-29 07:45:27 +00:00
2017-02-01 13:57:32 +00:00
if ((ret = SrsMp4SampleEntry::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_8bytes(reserved0);
buf->write_2bytes(channelcount);
buf->write_2bytes(samplesize);
buf->write_2bytes(pre_defined0);
buf->write_2bytes(reserved1);
buf->write_4bytes(samplerate);
return ret;
}
int SrsMp4AudioSampleEntry::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4SampleEntry::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->skip(8);
channelcount = buf->read_2bytes();
samplesize = buf->read_2bytes();
buf->skip(2);
buf->skip(2);
samplerate = buf->read_4bytes();
return ret;
}
2017-02-02 11:05:08 +00:00
SrsMp4BaseDescriptor::SrsMp4BaseDescriptor()
{
2017-02-02 14:02:39 +00:00
tag = SrsMp4ESTagESforbidden;
vlen = -1;
start_pos = 0;
2017-02-02 11:05:08 +00:00
}
SrsMp4BaseDescriptor::~SrsMp4BaseDescriptor()
{
}
2017-02-02 14:02:39 +00:00
int SrsMp4BaseDescriptor::left_space(SrsBuffer* buf)
{
return vlen - (buf->pos() - start_pos);
}
2017-02-02 11:05:08 +00:00
int SrsMp4BaseDescriptor::nb_bytes()
{
// 1 byte tag.
int size = 1;
// 1-3 bytes size.
2017-02-02 14:02:39 +00:00
int32_t length = vlen = nb_payload(); // bit(8) to bit(32)
2017-02-02 11:05:08 +00:00
if (length > 0x1fffff) {
size += 4;
} else if (length > 0x3fff) {
size += 3;
} else if (length > 0x7f) {
size += 2;
} else {
size += 1;
}
// length bytes payload.
size += length;
return size;
}
int SrsMp4BaseDescriptor::encode(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
int size = nb_bytes();
if (!buf->require(size)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires %d bytes space. ret=%d", size, ret);
return ret;
}
buf->write_1bytes((uint8_t)tag);
// As an expandable class the size of each class instance in bytes is encoded and accessible
// through the instance variable sizeOfInstance (see 8.3.3).
2017-02-02 14:02:39 +00:00
int32_t length = vlen; // bit(8) to bit(32)
srs_assert(vlen > 0);
if (length > 0x1fffff) {
buf->write_1bytes(uint8_t(length>>21)|0x80);
}
if (length > 0x3fff) {
buf->write_1bytes(uint8_t(length>>14)|0x80);
}
if (length > 0x7f) {
buf->write_1bytes(uint8_t(length>>7)|0x80);
}
buf->write_1bytes(length&0x7f);
if ((ret = encode_payload(buf)) != ERROR_SUCCESS) {
return ret;
}
2017-02-02 11:05:08 +00:00
return ret;
}
int SrsMp4BaseDescriptor::decode(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
int size = nb_bytes();
if (!buf->require(size)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires %d bytes space. ret=%d", size, ret);
return ret;
}
2017-02-02 14:02:39 +00:00
tag = (SrsMp4ESTagEs)buf->read_1bytes();
uint8_t v = 0x80;
int32_t length = 0x00;
while ((v&0x80) == 0x80) {
if (!buf->require(1)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires 1 byte space. ret=%d", ret);
return ret;
}
v = buf->read_1bytes();
length = (length<<7) | (v&0x7f);
}
vlen = length;
if (!buf->require(vlen)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires %d bytes space. ret=%d", vlen, ret);
return ret;
}
start_pos = buf->pos();
if ((ret = decode_payload(buf)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
SrsMp4DecoderSpecificInfo::SrsMp4DecoderSpecificInfo()
{
tag = SrsMp4ESTagESDecSpecificInfoTag;
nb_asc = 0;
asc = NULL;
}
SrsMp4DecoderSpecificInfo::~SrsMp4DecoderSpecificInfo()
{
srs_freepa(asc);
}
int32_t SrsMp4DecoderSpecificInfo::nb_payload()
{
return nb_asc;
}
int SrsMp4DecoderSpecificInfo::encode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if (nb_asc) {
buf->write_bytes((char*)asc, nb_asc);
}
return ret;
}
int SrsMp4DecoderSpecificInfo::decode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
nb_asc = vlen;
if (nb_asc) {
asc = new uint8_t[nb_asc];
buf->read_bytes((char*)asc, nb_asc);
}
2017-02-02 11:05:08 +00:00
return ret;
}
SrsMp4DecoderConfigDescriptor::SrsMp4DecoderConfigDescriptor()
{
2017-02-02 14:02:39 +00:00
tag = SrsMp4ESTagESDecoderConfigDescrTag;
objectTypeIndication = SrsMp4ObjectTypeForbidden;
streamType = SrsMp4StreamTypeForbidden;
decSpecificInfo = NULL;
reserved = 1;
2017-02-02 11:05:08 +00:00
}
SrsMp4DecoderConfigDescriptor::~SrsMp4DecoderConfigDescriptor()
{
2017-02-02 14:02:39 +00:00
srs_freep(decSpecificInfo);
2017-02-02 11:05:08 +00:00
}
2017-02-02 14:02:39 +00:00
int32_t SrsMp4DecoderConfigDescriptor::nb_payload()
2017-02-02 11:05:08 +00:00
{
2017-02-02 14:02:39 +00:00
return 12 + (decSpecificInfo? decSpecificInfo->nb_bytes():0);
2017-02-02 11:05:08 +00:00
}
int SrsMp4DecoderConfigDescriptor::encode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
2017-02-02 14:02:39 +00:00
buf->write_1bytes(objectTypeIndication);
uint8_t v = reserved;
v |= (upStream&0x01)<<1;
v |= uint8_t(streamType&0x3f)<<2;
buf->write_1bytes(v);
buf->write_3bytes(bufferSizeDB);
buf->write_4bytes(maxBitrate);
buf->write_4bytes(avgBitrate);
2017-02-02 11:05:08 +00:00
return ret;
}
int SrsMp4DecoderConfigDescriptor::decode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
2017-02-02 14:02:39 +00:00
objectTypeIndication = (SrsMp4ObjectType)buf->read_1bytes();
uint8_t v = buf->read_1bytes();
upStream = (v>>1) & 0x01;
streamType = (SrsMp4StreamType)((v>>2) & 0x3f);
reserved = v&0x01;
bufferSizeDB = buf->read_3bytes();
maxBitrate = buf->read_4bytes();
avgBitrate = buf->read_4bytes();
int left = left_space(buf);
if (left > 0) {
decSpecificInfo = new SrsMp4DecoderSpecificInfo();
if ((ret = decSpecificInfo->decode(buf)) != ERROR_SUCCESS) {
return ret;
}
}
2017-02-02 11:05:08 +00:00
return ret;
}
SrsMp4SLConfigDescriptor::SrsMp4SLConfigDescriptor()
{
2017-02-02 14:02:39 +00:00
tag = SrsMp4ESTagESSLConfigDescrTag;
predefined = 2;
2017-02-02 11:05:08 +00:00
}
SrsMp4SLConfigDescriptor::~SrsMp4SLConfigDescriptor()
{
}
2017-02-02 14:02:39 +00:00
int32_t SrsMp4SLConfigDescriptor::nb_payload()
2017-02-02 11:05:08 +00:00
{
2017-02-02 14:02:39 +00:00
return 1;
2017-02-02 11:05:08 +00:00
}
int SrsMp4SLConfigDescriptor::encode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
2017-02-02 14:02:39 +00:00
buf->write_1bytes(predefined);
2017-02-02 11:05:08 +00:00
return ret;
}
int SrsMp4SLConfigDescriptor::decode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
2017-02-02 14:02:39 +00:00
predefined = buf->read_1bytes();
// TODO: FIXME: To support complete SL Config.
if (predefined != 0x02) {
ret = ERROR_MP4_ESDS_SL_Config;
srs_error("MP4 illegal ESDS SL Config, predefined=%d. ret=%d", predefined, ret);
return ret;
}
2017-02-02 11:05:08 +00:00
return ret;
}
SrsMp4ES_Descriptor::SrsMp4ES_Descriptor()
{
2017-02-02 14:02:39 +00:00
tag = SrsMp4ESTagESDescrTag;
2017-02-02 11:05:08 +00:00
streamDependenceFlag = URL_Flag = OCRstreamFlag = 0;
URLlength = 0;
URLstring = NULL;
}
SrsMp4ES_Descriptor::~SrsMp4ES_Descriptor()
{
srs_freepa(URLstring);
}
2017-02-02 14:02:39 +00:00
int32_t SrsMp4ES_Descriptor::nb_payload()
2017-02-02 11:05:08 +00:00
{
int size = 2 +1;
size += streamDependenceFlag? 2:0;
if (URL_Flag) {
size += 1 + URLlength;
}
size += OCRstreamFlag? 2:0;
size += decConfigDescr.nb_bytes() +slConfigDescr.nb_bytes();
return size;
}
int SrsMp4ES_Descriptor::encode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
buf->write_2bytes(ES_ID);
uint8_t v = streamPriority & 0x1f;
v |= (streamDependenceFlag & 0x01) << 7;
v |= (URL_Flag & 0x01) << 6;
v |= (OCRstreamFlag & 0x01) << 5;
buf->write_1bytes(v);
if (streamDependenceFlag) {
buf->write_2bytes(dependsOn_ES_ID);
}
if (URL_Flag && URLlength) {
buf->write_1bytes(URLlength);
buf->write_bytes((char*)URLstring, URLlength);
}
if (OCRstreamFlag) {
buf->write_2bytes(OCR_ES_Id);
}
if ((ret = decConfigDescr.encode(buf)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = slConfigDescr.encode(buf)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsMp4ES_Descriptor::decode_payload(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
ES_ID = buf->read_2bytes();
uint8_t v = buf->read_1bytes();
streamPriority = v & 0x1f;
streamDependenceFlag = (v >> 7) & 0x01;
URL_Flag = (v >> 6) & 0x01;
OCRstreamFlag = (v >> 5) & 0x01;
if (streamDependenceFlag) {
if (!buf->require(2)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires 2 bytes space. ret=%d", ret);
return ret;
}
dependsOn_ES_ID = buf->read_2bytes();
}
if (URL_Flag) {
if (!buf->require(1)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires 1 byte space. ret=%d", ret);
return ret;
}
URLlength = buf->read_1bytes();
if (!buf->require(URLlength)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires %d bytes space. ret=%d", URLlength, ret);
return ret;
}
URLstring = new uint8_t[URLlength];
buf->read_bytes((char*)URLstring, URLlength);
}
if (OCRstreamFlag) {
if (!buf->require(2)) {
ret = ERROR_MP4_BOX_REQUIRE_SPACE;
srs_error("MP4 ES requires 2 bytes space. ret=%d", ret);
return ret;
}
OCR_ES_Id = buf->read_2bytes();
}
if ((ret = decConfigDescr.decode(buf)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = slConfigDescr.decode(buf)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
SrsMp4EsdsBox::SrsMp4EsdsBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeESDS;
2017-02-02 11:05:08 +00:00
es = new SrsMp4ES_Descriptor();
}
SrsMp4EsdsBox::~SrsMp4EsdsBox()
{
srs_freep(es);
}
int SrsMp4EsdsBox::nb_header()
{
return SrsMp4FullBox::nb_header() + es->nb_bytes();
}
int SrsMp4EsdsBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
int left = left_space(buf);
SrsBuffer buffer(buf->data() + buf->pos(), left);
if ((ret = es->encode(&buffer)) != ERROR_SUCCESS) {
return ret;
}
buf->skip(buffer.pos());
return ret;
}
int SrsMp4EsdsBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
int left = left_space(buf);
SrsBuffer buffer(buf->data() + buf->pos(), left);
if ((ret = es->decode(&buffer)) != ERROR_SUCCESS) {
return ret;
}
buf->skip(buffer.pos());
return ret;
}
2017-02-01 13:57:32 +00:00
SrsMp4SampleDescriptionBox::SrsMp4SampleDescriptionBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSTSD;
2017-01-29 07:45:27 +00:00
}
SrsMp4SampleDescriptionBox::~SrsMp4SampleDescriptionBox()
{
2017-02-01 13:57:32 +00:00
vector<SrsMp4SampleEntry*>::iterator it;
for (it = entries.begin(); it != entries.end(); ++it) {
SrsMp4SampleEntry* entry = *it;
srs_freep(entry);
}
entries.clear();
}
uint32_t SrsMp4SampleDescriptionBox::entry_count()
{
return (uint32_t)entries.size();
}
SrsMp4SampleEntry* SrsMp4SampleDescriptionBox::entrie_at(int index)
{
return entries.at(index);
}
int SrsMp4SampleDescriptionBox::nb_header()
{
int size = SrsMp4FullBox::nb_header();
size += 4;
2017-02-01 13:57:32 +00:00
vector<SrsMp4SampleEntry*>::iterator it;
for (it = entries.begin(); it != entries.end(); ++it) {
SrsMp4SampleEntry* entry = *it;
size += entry->nb_bytes();
}
return size;
}
int SrsMp4SampleDescriptionBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count());
2017-02-01 13:57:32 +00:00
vector<SrsMp4SampleEntry*>::iterator it;
for (it = entries.begin(); it != entries.end(); ++it) {
SrsMp4SampleEntry* entry = *it;
if ((ret = entry->encode(buf)) != ERROR_SUCCESS) {
return ret;
}
}
return ret;
}
int SrsMp4SampleDescriptionBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
uint32_t nb_entries = buf->read_4bytes();
for (uint32_t i = 0; i < nb_entries; i++) {
2017-02-01 13:57:32 +00:00
SrsMp4Box* box = NULL;
if ((ret = SrsMp4Box::discovery(buf, &box)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = box->decode(buf)) != ERROR_SUCCESS) {
return ret;
}
SrsMp4SampleEntry* entry = dynamic_cast<SrsMp4SampleEntry*>(box);
if (entry) {
entries.push_back(entry);
} else {
srs_freep(box);
}
}
return ret;
2017-01-29 07:45:27 +00:00
}
SrsMp4SttsEntry::SrsMp4SttsEntry()
{
sample_count = 0;
sample_delta = 0;
}
SrsMp4DecodingTime2SampleBox::SrsMp4DecodingTime2SampleBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSTTS;
2017-01-29 07:45:27 +00:00
entry_count = 0;
entries = NULL;
}
SrsMp4DecodingTime2SampleBox::~SrsMp4DecodingTime2SampleBox()
{
srs_freepa(entries);
}
2017-02-01 13:57:32 +00:00
int SrsMp4DecodingTime2SampleBox::nb_header()
{
return SrsMp4FullBox::nb_header() + 4 + 8*entry_count;
2017-02-01 13:57:32 +00:00
}
int SrsMp4DecodingTime2SampleBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count);
for (uint32_t i = 0; i < entry_count; i++) {
SrsMp4SttsEntry& entry = entries[i];
buf->write_4bytes(entry.sample_count);
buf->write_4bytes(entry.sample_delta);
}
2017-02-01 13:57:32 +00:00
return ret;
}
int SrsMp4DecodingTime2SampleBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
entry_count = buf->read_4bytes();
if (entry_count) {
entries = new SrsMp4SttsEntry[entry_count];
}
for (uint32_t i = 0; i < entry_count; i++) {
SrsMp4SttsEntry& entry = entries[i];
entry.sample_count = buf->read_4bytes();
entry.sample_delta = buf->read_4bytes();
}
2017-02-01 13:57:32 +00:00
return ret;
}
2017-01-29 07:45:27 +00:00
SrsMp4CttsEntry::SrsMp4CttsEntry()
{
sample_count = 0;
sample_offset = 0;
}
SrsMp4CompositionTime2SampleBox::SrsMp4CompositionTime2SampleBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeCTTS;
2017-01-29 07:45:27 +00:00
entry_count = 0;
entries = NULL;
}
SrsMp4CompositionTime2SampleBox::~SrsMp4CompositionTime2SampleBox()
{
srs_freepa(entries);
}
2017-02-01 13:57:32 +00:00
int SrsMp4CompositionTime2SampleBox::nb_header()
{
return SrsMp4FullBox::nb_header() + 4 + 8*entry_count;
2017-02-01 13:57:32 +00:00
}
int SrsMp4CompositionTime2SampleBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count);
for (uint32_t i = 0; i < entry_count; i++) {
SrsMp4CttsEntry& entry = entries[i];
buf->write_4bytes(entry.sample_count);
if (version == 0) {
buf->write_4bytes((uint32_t)entry.sample_offset);
} else if (version == 1) {
buf->write_4bytes((int32_t)entry.sample_offset);
}
}
2017-02-01 13:57:32 +00:00
return ret;
}
int SrsMp4CompositionTime2SampleBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
entry_count = buf->read_4bytes();
if (entry_count) {
entries = new SrsMp4CttsEntry[entry_count];
}
for (uint32_t i = 0; i < entry_count; i++) {
SrsMp4CttsEntry& entry = entries[i];
entry.sample_count = buf->read_4bytes();
if (version == 0) {
entry.sample_offset = (uint32_t)buf->read_4bytes();
} else if (version == 1) {
entry.sample_offset = (int32_t)buf->read_4bytes();
}
}
2017-02-01 13:57:32 +00:00
return ret;
}
2017-01-29 09:16:20 +00:00
SrsMp4SyncSampleBox::SrsMp4SyncSampleBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSTSS;
2017-01-29 09:16:20 +00:00
entry_count = 0;
sample_numbers = NULL;
}
SrsMp4SyncSampleBox::~SrsMp4SyncSampleBox()
{
srs_freepa(sample_numbers);
}
2017-02-01 13:57:32 +00:00
int SrsMp4SyncSampleBox::nb_header()
{
return SrsMp4FullBox::nb_header() +4 +4*entry_count;
2017-02-01 13:57:32 +00:00
}
int SrsMp4SyncSampleBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count);
for (uint32_t i = 0; i < entry_count; i++) {
uint32_t sample_number = sample_numbers[i];
buf->write_4bytes(sample_number);
}
2017-02-01 13:57:32 +00:00
return ret;
}
int SrsMp4SyncSampleBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
entry_count = buf->read_4bytes();
if (entry_count > 0) {
sample_numbers = new uint32_t[entry_count];
}
for (uint32_t i = 0; i < entry_count; i++) {
sample_numbers[i] = buf->read_4bytes();
}
2017-02-01 13:57:32 +00:00
return ret;
}
2017-01-29 09:16:20 +00:00
SrsMp4StscEntry::SrsMp4StscEntry()
{
first_chunk = 0;
samples_per_chunk = 0;
sample_description_index = 0;
}
SrsMp4Sample2ChunkBox::SrsMp4Sample2ChunkBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSTSC;
2017-01-29 09:16:20 +00:00
entry_count = 0;
entries = NULL;
}
SrsMp4Sample2ChunkBox::~SrsMp4Sample2ChunkBox()
{
srs_freepa(entries);
}
2017-02-01 13:57:32 +00:00
int SrsMp4Sample2ChunkBox::nb_header()
{
return SrsMp4FullBox::nb_header() +4 + 12*entry_count;
2017-02-01 13:57:32 +00:00
}
int SrsMp4Sample2ChunkBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count);
for (uint32_t i = 0; i < entry_count; i++) {
SrsMp4StscEntry& entry = entries[i];
buf->write_4bytes(entry.first_chunk);
buf->write_4bytes(entry.samples_per_chunk);
buf->write_4bytes(entry.sample_description_index);
}
2017-02-01 13:57:32 +00:00
return ret;
}
int SrsMp4Sample2ChunkBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
entry_count = buf->read_4bytes();
if (entry_count) {
entries = new SrsMp4StscEntry[entry_count];
}
for (uint32_t i = 0; i < entry_count; i++) {
SrsMp4StscEntry& entry = entries[i];
entry.first_chunk = buf->read_4bytes();
entry.samples_per_chunk = buf->read_4bytes();
entry.sample_description_index = buf->read_4bytes();
}
2017-02-01 13:57:32 +00:00
return ret;
}
2017-01-29 09:16:20 +00:00
SrsMp4ChunkOffsetBox::SrsMp4ChunkOffsetBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSTCO;
2017-01-29 09:16:20 +00:00
entry_count = 0;
entries = NULL;
}
SrsMp4ChunkOffsetBox::~SrsMp4ChunkOffsetBox()
{
srs_freepa(entries);
}
2017-02-01 13:57:32 +00:00
int SrsMp4ChunkOffsetBox::nb_header()
{
return SrsMp4FullBox::nb_header() +4 +4*entry_count;
2017-02-01 13:57:32 +00:00
}
int SrsMp4ChunkOffsetBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count);
for (uint32_t i = 0; i < entry_count; i++) {
buf->write_4bytes(entries[i]);
}
2017-02-01 13:57:32 +00:00
return ret;
}
int SrsMp4ChunkOffsetBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
entry_count = buf->read_4bytes();
if (entry_count) {
entries = new uint32_t[entry_count];
}
for (uint32_t i = 0; i < entry_count; i++) {
entries[i] = buf->read_4bytes();
}
return ret;
}
SrsMp4ChunkLargeOffsetBox::SrsMp4ChunkLargeOffsetBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeCO64;
entry_count = 0;
entries = NULL;
}
SrsMp4ChunkLargeOffsetBox::~SrsMp4ChunkLargeOffsetBox()
{
srs_freepa(entries);
}
int SrsMp4ChunkLargeOffsetBox::nb_header()
{
return SrsMp4FullBox::nb_header() +4 +8*entry_count;
}
int SrsMp4ChunkLargeOffsetBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(entry_count);
for (uint32_t i = 0; i < entry_count; i++) {
buf->write_8bytes(entries[i]);
}
return ret;
}
int SrsMp4ChunkLargeOffsetBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
entry_count = buf->read_4bytes();
if (entry_count) {
entries = new uint64_t[entry_count];
}
for (uint32_t i = 0; i < entry_count; i++) {
entries[i] = buf->read_8bytes();
}
2017-02-01 13:57:32 +00:00
return ret;
}
2017-01-29 09:16:20 +00:00
SrsMp4SampleSizeBox::SrsMp4SampleSizeBox()
{
2017-02-02 14:02:39 +00:00
type = SrsMp4BoxTypeSTSZ;
2017-01-29 09:16:20 +00:00
sample_size = sample_count = 0;
entry_sizes = NULL;
}
SrsMp4SampleSizeBox::~SrsMp4SampleSizeBox()
{
srs_freepa(entry_sizes);
}
2017-02-01 13:57:32 +00:00
int SrsMp4SampleSizeBox::nb_header()
{
int size = SrsMp4FullBox::nb_header() +4+4;
if (sample_size == 0) {
size += 4*sample_count;
}
return size;
2017-02-01 13:57:32 +00:00
}
int SrsMp4SampleSizeBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
buf->write_4bytes(sample_size);
buf->write_4bytes(sample_count);
for (uint32_t i = 0; i < sample_count && sample_size == 0; i++) {
buf->write_4bytes(entry_sizes[i]);
}
2017-02-01 13:57:32 +00:00
return ret;
}
int SrsMp4SampleSizeBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4FullBox::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
sample_size = buf->read_4bytes();
sample_count = buf->read_4bytes();
if (sample_size == 0) {
entry_sizes = new uint32_t[sample_count];
}
for (uint32_t i = 0; i < sample_count && sample_size == 0; i++) {
entry_sizes[i] = buf->read_4bytes();
}
2017-02-01 13:57:32 +00:00
return ret;
}
SrsMp4UserDataBox::SrsMp4UserDataBox()
{
type = SrsMp4BoxTypeUDTA;
nb_data = 0;
data = NULL;
}
SrsMp4UserDataBox::~SrsMp4UserDataBox()
{
srs_freepa(data);
}
int SrsMp4UserDataBox::nb_header()
{
return SrsMp4Box::nb_header()+nb_data;
}
int SrsMp4UserDataBox::encode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::encode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
if (nb_data) {
buf->write_bytes((char*)data, nb_data);
}
return ret;
}
int SrsMp4UserDataBox::decode_header(SrsBuffer* buf)
{
int ret = ERROR_SUCCESS;
if ((ret = SrsMp4Box::decode_header(buf)) != ERROR_SUCCESS) {
return ret;
}
nb_data = left_space(buf);
if (nb_data) {
data = new uint8_t[nb_data];
buf->read_bytes((char*)data, nb_data);
}
return ret;
}
#define SRS_MP4_BUF_SIZE 4096
2017-01-31 12:43:48 +00:00
SrsMp4Decoder::SrsMp4Decoder()
{
2017-02-01 13:57:32 +00:00
reader = NULL;
buf = new char[SRS_MP4_BUF_SIZE];
2017-02-01 13:57:32 +00:00
stream = new SrsSimpleStream();
2017-01-31 12:43:48 +00:00
}
SrsMp4Decoder::~SrsMp4Decoder()
{
srs_freepa(buf);
2017-02-01 13:57:32 +00:00
srs_freep(stream);
2017-01-31 12:43:48 +00:00
}
int SrsMp4Decoder::initialize(ISrsReader* r)
{
2017-01-31 13:36:51 +00:00
int ret = ERROR_SUCCESS;
2017-01-31 12:43:48 +00:00
srs_assert(r);
reader = r;
// File Type Box (ftyp)
if (true) {
SrsMp4Box* box = NULL;
SrsAutoFree(SrsMp4Box, box);
2017-02-02 14:02:39 +00:00
if ((ret = load_next_box(&box, SrsMp4BoxTypeFTYP)) != ERROR_SUCCESS) {
return ret;
}
SrsMp4FileTypeBox* ftyp = dynamic_cast<SrsMp4FileTypeBox*>(box);
bool legal_brand = false;
2017-02-02 14:02:39 +00:00
static SrsMp4BoxBrand legal_brands[] = {
SrsMp4BoxBrandISOM, SrsMp4BoxBrandISO2, SrsMp4BoxBrandAVC1, SrsMp4BoxBrandMP41
};
2017-02-02 14:02:39 +00:00
for (int i = 0; i < sizeof(legal_brands)/sizeof(SrsMp4BoxBrand); i++) {
if (ftyp->major_brand == legal_brands[i]) {
legal_brand = true;
break;
}
}
if (!legal_brand) {
ret = ERROR_MP4_BOX_ILLEGAL_BRAND;
srs_error("MP4 brand is illegal, brand=%d. ret=%d", ftyp->major_brand, ret);
return ret;
}
}
// Media Data Box (mdat) or Movie Box (moov)
SrsMp4Box* box = NULL;
SrsAutoFree(SrsMp4Box, box);
while (true) {
if ((ret = load_next_box(&box, 0)) != ERROR_SUCCESS) {
return ret;
}
if (!box->is_mdat() && !box->is_moov()) {
srs_freep(box);
continue;
}
break;
2017-02-01 13:57:32 +00:00
}
// Only support non-seek mp4, that is, mdat should never before moov.
// @see https://github.com/ossrs/srs/issues/738#issuecomment-276343669
if (box->is_mdat()) {
ret = ERROR_MP4_NOT_NON_SEEKABLE;
srs_error("MP4 is not non-seekable. ret=%d", ret);
2017-02-01 13:57:32 +00:00
return ret;
}
// Parse the MOOV.
SrsMp4MovieBox* moov = dynamic_cast<SrsMp4MovieBox*>(box);
return parse_moov(moov);
}
int SrsMp4Decoder::parse_moov(SrsMp4MovieBox* moov)
{
int ret = ERROR_SUCCESS;
2017-02-01 13:57:32 +00:00
return ret;
}
int SrsMp4Decoder::load_next_box(SrsMp4Box** ppbox, uint32_t required_box_type)
2017-02-01 13:57:32 +00:00
{
int ret = ERROR_SUCCESS;
while (true) {
SrsMp4Box* box = NULL;
if ((ret = do_load_next_box(&box, required_box_type)) != ERROR_SUCCESS) {
srs_freep(box);
return ret;
}
if (!required_box_type || box->type == required_box_type) {
*ppbox = box;
break;
}
srs_freep(box);
2017-02-01 13:57:32 +00:00
}
return ret;
}
int SrsMp4Decoder::do_load_next_box(SrsMp4Box** ppbox, uint32_t required_box_type)
{
int ret = ERROR_SUCCESS;
2017-02-01 13:57:32 +00:00
SrsMp4Box* box = NULL;
2017-02-01 13:57:32 +00:00
while (true) {
uint64_t required = box? box->sz():4;
2017-02-01 13:57:32 +00:00
while (stream->length() < required) {
ssize_t nread;
if ((ret = reader->read(buf, SRS_MP4_BUF_SIZE, &nread)) != ERROR_SUCCESS) {
2017-02-01 13:57:32 +00:00
srs_error("MP4 load failed, nread=%d, required=%d. ret=%d", nread, required, ret);
return ret;
}
srs_assert(nread > 0);
stream->append(buf, (int)nread);
}
SrsBuffer* buffer = new SrsBuffer(stream->bytes(), stream->length());
SrsAutoFree(SrsBuffer, buffer);
// Discovery the box with basic header.
if (!box && (ret = SrsMp4Box::discovery(buffer, &box)) != ERROR_SUCCESS) {
2017-02-01 13:57:32 +00:00
if (ret == ERROR_MP4_BOX_REQUIRE_SPACE) {
continue;
}
srs_error("MP4 load box failed. ret=%d", ret);
return ret;
}
// Decode util we can demux the whole box.
if (!buffer->require((int)box->sz())) {
2017-02-01 13:57:32 +00:00
continue;
}
if (!required_box_type || box->type == required_box_type) {
ret = box->decode(buffer);
}
2017-02-01 13:57:32 +00:00
// Remove the consumed bytes.
stream->erase((int)box->sz());
if (ret != ERROR_SUCCESS) {
srs_freep(box);
} else {
*ppbox = box;
}
2017-02-01 13:57:32 +00:00
break;
}
2017-01-31 13:36:51 +00:00
return ret;
2017-01-31 12:43:48 +00:00
}