(slightly) better MP4 ESDS box implementation
This commit is contained in:
parent
4811a7e065
commit
ac3b43c188
2 changed files with 340 additions and 293 deletions
|
@ -639,261 +639,309 @@ namespace MP4 {
|
|||
memcpy((char *)payload(), (char *)newPayload.c_str(), newPayload.size());
|
||||
}
|
||||
|
||||
//fullbox, start at 4
|
||||
Descriptor::Descriptor(){
|
||||
data = (char*)malloc(2);
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
size = 2;
|
||||
master = true;
|
||||
}
|
||||
|
||||
Descriptor::Descriptor(const char* p, const long unsigned s, const bool m){
|
||||
master = m;
|
||||
if (m){
|
||||
Descriptor();
|
||||
Descriptor tmp = Descriptor(p, s, false);
|
||||
resize(tmp.getDataSize());
|
||||
memcpy(data, p, s);
|
||||
}else{
|
||||
data = (char*)p;
|
||||
size = s;
|
||||
}
|
||||
}
|
||||
|
||||
char Descriptor::getTag(){
|
||||
return data[0];
|
||||
}
|
||||
|
||||
void Descriptor::setTag(char t){
|
||||
data[0] = t;
|
||||
}
|
||||
|
||||
unsigned long Descriptor::getDataSize(){
|
||||
unsigned int i = 1;
|
||||
unsigned long s = 0;
|
||||
for (i = 1; i< size-1; i++){
|
||||
s <<= 7;
|
||||
s |= data[i] & 0x7f;
|
||||
if ((data[i] & 0x80) != 0x80){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
unsigned long Descriptor::getFullSize(){
|
||||
unsigned long tmp = getDataSize();
|
||||
unsigned long r = tmp+2;
|
||||
if (tmp > 0x7F){
|
||||
++r;
|
||||
}
|
||||
if (tmp > 0x3FFF){
|
||||
++r;
|
||||
}
|
||||
if (tmp > 0x1FFFFF){
|
||||
++r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void Descriptor::resize(unsigned long t){
|
||||
if (!master){return;}
|
||||
unsigned long realLen = t+2;
|
||||
if (t > 0x7F){
|
||||
++realLen;
|
||||
}
|
||||
if (t > 0x3FFF){
|
||||
++realLen;
|
||||
}
|
||||
if (t > 0x1FFFFF){
|
||||
++realLen;
|
||||
}
|
||||
if (size < realLen){
|
||||
char* tmpData = (char*)realloc(data,realLen);
|
||||
if (tmpData){
|
||||
size = realLen;
|
||||
data = tmpData;
|
||||
unsigned long offset = realLen-t;
|
||||
char continueBit = 0;
|
||||
while (realLen){
|
||||
data[--offset] = (0x7f & realLen) | continueBit;
|
||||
continueBit = 0x80;
|
||||
realLen >>= 7;
|
||||
}
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* Descriptor::getData(){
|
||||
unsigned int i = 1;
|
||||
for (i = 1; i< size-1; i++){
|
||||
if ((data[i] & 0x80) != 0x80){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return data + i + 1;
|
||||
}
|
||||
|
||||
std::string Descriptor::toPrettyString(uint32_t indent){
|
||||
std::stringstream r;
|
||||
r << std::string(indent, ' ') << "[" << (int)data[0] << "] Unimplemented descriptor (" << getDataSize() << ")" << std::endl;
|
||||
return r.str();
|
||||
}
|
||||
|
||||
ESDescriptor::ESDescriptor (const char* p, const unsigned long l, const bool m) : Descriptor(p,l,m){
|
||||
}
|
||||
|
||||
DCDescriptor ESDescriptor::getDecoderConfig(){
|
||||
char * p = getData();
|
||||
char * max_p = p + getDataSize();
|
||||
bool dep = (p[2] & 0x80);
|
||||
bool url = (p[2] & 0x40);
|
||||
bool ocr = (p[2] & 0x20);
|
||||
p += 3;
|
||||
if (dep){p += 2;}
|
||||
if (url){p += (1+p[0]);}
|
||||
if (ocr){p += 2;}
|
||||
return DCDescriptor(p, max_p-p);
|
||||
}
|
||||
|
||||
std::string ESDescriptor::toPrettyString(uint32_t indent){
|
||||
std::stringstream r;
|
||||
r << std::string(indent, ' ') << "[" << (int)data[0] << "] ES Descriptor (" << getDataSize() << ")" << std::endl;
|
||||
char * p = getData();
|
||||
char * max_p = p + getDataSize();
|
||||
r << std::string(indent+1, ' ') << "ES ID: " << (unsigned int)(((unsigned int)p[0] << 8) | (unsigned int)p[1]) << std::endl;
|
||||
bool dep = (p[2] & 0x80);
|
||||
bool url = (p[2] & 0x40);
|
||||
bool ocr = (p[2] & 0x20);
|
||||
r << std::string(indent+1, ' ') << "Priority: " << int(p[2] & 0x1f) << std::endl;
|
||||
p += 3;
|
||||
if (dep){
|
||||
r << std::string(indent+1, ' ') << "Depends on ES ID: " << (unsigned int)(((unsigned int)p[0] << 8) | (unsigned int)p[1]) << std::endl;
|
||||
p += 2;
|
||||
}
|
||||
if (url){
|
||||
r << std::string(indent+1, ' ') << "URL: " << std::string(p+1, (unsigned int)p[0]) << std::endl;
|
||||
p += (1+p[0]);
|
||||
}
|
||||
if (ocr){
|
||||
r << std::string(indent+1, ' ') << "Timebase derived from ES ID: " << (unsigned int)(((unsigned int)p[0] << 8) | (unsigned int)p[1]) << std::endl;
|
||||
p += 2;
|
||||
}
|
||||
while (p < max_p){
|
||||
switch (p[0]){
|
||||
case 0x4: {
|
||||
DCDescriptor d(p, max_p - p);
|
||||
r << d.toPrettyString(indent+1);
|
||||
p += d.getFullSize();
|
||||
}
|
||||
default: {
|
||||
Descriptor d(p, max_p - p);
|
||||
r << d.toPrettyString(indent+1);
|
||||
p += d.getFullSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
return r.str();
|
||||
}
|
||||
|
||||
DCDescriptor::DCDescriptor (const char* p, const unsigned long l, const bool m) : Descriptor(p,l,m){
|
||||
}
|
||||
|
||||
DSDescriptor DCDescriptor::getSpecific(){
|
||||
char * p = getData();
|
||||
char * max_p = p + getDataSize();
|
||||
p += 13;
|
||||
if (p[0] == 0x05){
|
||||
return DSDescriptor(p, max_p-p);
|
||||
}else{
|
||||
FAIL_MSG("Expected DSDescriptor (5), but found %d!", (int)p[0]);
|
||||
return DSDescriptor(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
bool DCDescriptor::isAAC(){
|
||||
return (getData()[0] == 0x40);
|
||||
}
|
||||
|
||||
std::string DCDescriptor::toPrettyString(uint32_t indent){
|
||||
std::stringstream r;
|
||||
r << std::string(indent, ' ') << "[" << (int)data[0] << "] DecoderConfig Descriptor (" << getDataSize() << ")" << std::endl;
|
||||
char * p = getData();
|
||||
char * max_p = p + getDataSize();
|
||||
int objType = p[0];
|
||||
r << std::string(indent+1, ' ') << "Object type: ";
|
||||
switch (objType){
|
||||
case 0x40: r << "AAC (0x40)"; break;
|
||||
case 0x69: r << "MP3 (0x69)"; break;
|
||||
default: r << "Unknown (" << objType << ")"; break;
|
||||
}
|
||||
r << std::endl;
|
||||
int streamType = (p[1] >> 2) & 0x3F;
|
||||
r << std::string(indent+1, ' ') << "Stream type: ";
|
||||
switch (streamType){
|
||||
case 0x4: r << "Video (4)"; break;
|
||||
case 0x5: r << "Audio (5)"; break;
|
||||
default: r << "Unknown (" << streamType << ")"; break;
|
||||
}
|
||||
r << std::endl;
|
||||
if (p[1] & 0x2){
|
||||
r << std::string(indent+1, ' ') << "Upstream" << std::endl;
|
||||
}
|
||||
r << std::string(indent+1, ' ') << "Buffer size: " << (int)(((int)p[2] << 16) | ((int)p[3] << 8) | ((int)p[4])) << std::endl;
|
||||
r << std::string(indent+1, ' ') << "Max bps: " << (unsigned int)(((unsigned int)p[5] << 24) | ((int)p[6] << 16) | ((int)p[7] << 8) | (int)p[8]) << std::endl;
|
||||
r << std::string(indent+1, ' ') << "Avg bps: " << (unsigned int)(((unsigned int)p[9] << 24) | ((int)p[10] << 16) | ((int)p[11] << 8) | (int)p[12]) << std::endl;
|
||||
p += 13;
|
||||
while (p < max_p){
|
||||
switch (p[0]){
|
||||
case 0x5: {
|
||||
DSDescriptor d(p, max_p - p);
|
||||
r << d.toPrettyString(indent+1);
|
||||
p += d.getFullSize();
|
||||
}
|
||||
default: {
|
||||
Descriptor d(p, max_p - p);
|
||||
r << d.toPrettyString(indent+1);
|
||||
p += d.getFullSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
return r.str();
|
||||
}
|
||||
|
||||
DSDescriptor::DSDescriptor (const char* p, const unsigned long l, const bool m) : Descriptor(p,l,m){
|
||||
}
|
||||
|
||||
std::string DSDescriptor::toPrettyString(uint32_t indent){
|
||||
std::stringstream r;
|
||||
r << std::string(indent, ' ') << "[" << (int)data[0] << "] Decoder Specific Info (" << getDataSize() << ")" << std::endl;
|
||||
char * p = getData();
|
||||
char * max_p = p + getDataSize();
|
||||
r << std::string(indent+1, ' ') << "Data: ";
|
||||
while (p < max_p) {
|
||||
r << std::hex << std::setw(2) << std::setfill('0') << (int)p[0] << std::dec;
|
||||
++p;
|
||||
}
|
||||
r << std::endl;
|
||||
return r.str();
|
||||
}
|
||||
|
||||
std::string DSDescriptor::toString(){
|
||||
if (!data){
|
||||
return "";
|
||||
}
|
||||
return std::string(getData(), getDataSize());
|
||||
}
|
||||
|
||||
ESDS::ESDS() {
|
||||
memcpy(data + 4, "esds", 4);
|
||||
setESDescriptorType(0x03);
|
||||
setExtendedESDescriptorType(0x808080);
|
||||
setStreamPriority(16);
|
||||
setDecoderConfigDescriptorTag(0x04);
|
||||
setExtendedDecoderConfigDescriptorTag(0x808080);
|
||||
setReservedFlag(true);
|
||||
setDecoderDescriptorTypeTag(0x05);
|
||||
setExtendedDecoderDescriptorTypeTag(0x808080);
|
||||
setSLConfigDescriptorTypeTag(0x06);
|
||||
setSLConfigExtendedDescriptorTypeTag(0x808010);
|
||||
setSLValue(0x02);
|
||||
}
|
||||
|
||||
ESDS::ESDS(std::string init, uint32_t bps) {
|
||||
ESDS::ESDS(std::string init) {
|
||||
///\todo Do this better, in a non-hardcoded way.
|
||||
memcpy(data + 4, "esds", 4);
|
||||
char temp[] = {0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x80, 0x80, 0x00, 0x00, 0x02, 0x10, 0x04, 0x80, 0x80, 0x80, 0x00, 0x40, 0x15, 0x13, 0x12, 0xD0, 0x00, 0x98, 0x96, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x80, 0x80, 0x05};
|
||||
setString(temp, 0x23, 0);
|
||||
setESDescriptorTypeLength(32 + init.size());
|
||||
setDecoderConfigDescriptorTypeLength(18 + init.size());
|
||||
setAverageBitRate(bps * 8);
|
||||
setESHeaderStartCodes(init);
|
||||
char temp2[] = {0x05, 0x80, 0x80, 0x10, 0x01, 0x02};
|
||||
setString(temp2, 0x06, 0x23 + 32 + init.size());
|
||||
}
|
||||
|
||||
char ESDS::getESDescriptorType() {
|
||||
return getInt8(4);
|
||||
}
|
||||
|
||||
void ESDS::setESDescriptorType(char newVal) {
|
||||
setInt8(newVal, 4);
|
||||
}
|
||||
|
||||
uint32_t ESDS::getExtendedESDescriptorType() {
|
||||
return getInt24(5);
|
||||
}
|
||||
//3 bytes
|
||||
void ESDS::setExtendedESDescriptorType(uint32_t newVal) {
|
||||
setInt24(newVal, 5);
|
||||
}
|
||||
//3 bytes
|
||||
char ESDS::getESDescriptorTypeLength() {
|
||||
return getInt8(8);
|
||||
}
|
||||
|
||||
void ESDS::setESDescriptorTypeLength(char newVal) {
|
||||
setInt8(newVal, 8);
|
||||
}
|
||||
//ESID 2 bytes
|
||||
uint16_t ESDS::getESID() {
|
||||
return getInt16(9);
|
||||
}
|
||||
|
||||
void ESDS::setESID(uint16_t newVal) {
|
||||
setInt16(newVal, 9);
|
||||
}
|
||||
|
||||
//stream priority 1 byte
|
||||
char ESDS::getStreamPriority() {
|
||||
return getInt8(11);
|
||||
}
|
||||
|
||||
void ESDS::setStreamPriority(char newVal) {
|
||||
setInt8(newVal, 11);
|
||||
}
|
||||
|
||||
//decoder config descriptor tag 1byte
|
||||
char ESDS::getDecoderConfigDescriptorTag() {
|
||||
return getInt8(12);
|
||||
}
|
||||
|
||||
void ESDS::setDecoderConfigDescriptorTag(char newVal) {
|
||||
setInt8(newVal, 12);
|
||||
}
|
||||
|
||||
//extended decoder config descriptor tag 3 bytes
|
||||
uint32_t ESDS::getExtendedDecoderConfigDescriptorTag() {
|
||||
return getInt24(13);
|
||||
}
|
||||
//3 bytes
|
||||
void ESDS::setExtendedDecoderConfigDescriptorTag(uint32_t newVal) {
|
||||
setInt24(newVal, 13);
|
||||
}
|
||||
//3 bytes
|
||||
//decoder config descriptor type length
|
||||
char ESDS::getDecoderConfigDescriptorTypeLength() {
|
||||
return getInt8(16);
|
||||
}
|
||||
|
||||
void ESDS::setDecoderConfigDescriptorTypeLength(char newVal) {
|
||||
setInt8(newVal, 16);
|
||||
}
|
||||
//Note: count 8 bytes extra in the next four functions
|
||||
char ESDS::getByteObjectTypeID() {
|
||||
return getInt8(17);
|
||||
}
|
||||
|
||||
void ESDS::setByteObjectTypeID(char newVal) {
|
||||
setInt8(newVal, 17);
|
||||
}
|
||||
|
||||
char ESDS::getStreamType() {
|
||||
return getInt8(18) >> 2;
|
||||
}
|
||||
//6 bits
|
||||
void ESDS::setStreamType(char newVal) {
|
||||
setInt8(((newVal << 2) & 0xFC) + (getInt8(18) & 0x03), 18);
|
||||
}
|
||||
//6 bits
|
||||
bool ESDS::getUpstreamFlag() {
|
||||
return (((getInt8(18) >> 1) & 0x01) == 1);
|
||||
}
|
||||
|
||||
void ESDS::setUpstreamFlag(bool newVal) {
|
||||
setInt8((getStreamType() << 2) + ((uint8_t)newVal << 1) + (uint8_t)getReservedFlag() , 18);
|
||||
}
|
||||
|
||||
bool ESDS::getReservedFlag() {
|
||||
return ((getInt8(18) & 0x01) == 1);
|
||||
}
|
||||
|
||||
void ESDS::setReservedFlag(bool newVal) {
|
||||
setInt8((getInt8(18) & 0xFE) + (int)newVal, 18);
|
||||
}
|
||||
|
||||
uint32_t ESDS::getBufferSize() {
|
||||
return getInt24(19);
|
||||
}
|
||||
//3 bytes
|
||||
void ESDS::setBufferSize(uint32_t newVal) {
|
||||
setInt24(newVal, 19);
|
||||
}
|
||||
//3 bytes
|
||||
uint32_t ESDS::getMaximumBitRate() {
|
||||
return getInt32(22);
|
||||
}
|
||||
|
||||
void ESDS::setMaximumBitRate(uint32_t newVal) {
|
||||
setInt32(newVal, 22);
|
||||
}
|
||||
|
||||
uint32_t ESDS::getAverageBitRate() {
|
||||
return getInt32(26);
|
||||
}
|
||||
|
||||
void ESDS::setAverageBitRate(uint32_t newVal) {
|
||||
setInt32(newVal, 26);
|
||||
}
|
||||
|
||||
char ESDS::getDecoderDescriptorTypeTag() {
|
||||
return getInt8(30);
|
||||
}
|
||||
|
||||
void ESDS::setDecoderDescriptorTypeTag(char newVal) {
|
||||
setInt8(newVal, 30);
|
||||
}
|
||||
|
||||
uint32_t ESDS::getExtendedDecoderDescriptorTypeTag() {
|
||||
return getInt24(31);
|
||||
}
|
||||
|
||||
//3 bytes
|
||||
void ESDS::setExtendedDecoderDescriptorTypeTag(uint32_t newVal) {
|
||||
setInt24(newVal, 31);
|
||||
}
|
||||
|
||||
//3 bytes
|
||||
char ESDS::getConfigDescriptorTypeLength() {
|
||||
return getInt8(34);
|
||||
}
|
||||
|
||||
void ESDS::setConfigDescriptorTypeLength(char newVal) {
|
||||
setInt8(newVal, 34);
|
||||
}
|
||||
|
||||
std::string ESDS::getESHeaderStartCodes() {
|
||||
std::string result;
|
||||
for (int i = 0; i < getInt8(34); i++) {
|
||||
result += getInt8(35 + i);
|
||||
reserve(payloadOffset, 0, init.size() ? init.size()+26 : 24);
|
||||
unsigned int i = 12;
|
||||
data[i++] = 3;//ES_DescrTag
|
||||
data[i++] = init.size() ? init.size()+20 : 18;//size
|
||||
data[i++] = 0;//es_id
|
||||
data[i++] = 2;//es_id
|
||||
data[i++] = 0;//priority
|
||||
data[i++] = 4;//DecoderConfigDescrTag
|
||||
data[i++] = init.size() ? init.size()+15 : 13;//size
|
||||
if (init.size()){
|
||||
data[i++] = 0x40;//objType AAC
|
||||
}else{
|
||||
data[i++] = 0x69;//objType MP3
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ESDS::setESHeaderStartCodes(std::string newVal) {
|
||||
setConfigDescriptorTypeLength(newVal.size());
|
||||
for (unsigned int i = 0; i < newVal.size(); i++) {
|
||||
setInt8(newVal[i], 35 + i);
|
||||
data[i++] = 0x14;//streamType audio (5<<2)
|
||||
data[i++] = 0;//buffer size
|
||||
data[i++] = 0;//buffer size
|
||||
data[i++] = 0;//buffer size
|
||||
data[i++] = 0;//maxbps
|
||||
data[i++] = 0;//maxbps
|
||||
data[i++] = 0;//maxbps
|
||||
data[i++] = 0;//maxbps
|
||||
data[i++] = 0;//avgbps
|
||||
data[i++] = 0;//avgbps
|
||||
data[i++] = 0;//avgbps
|
||||
data[i++] = 0;//avgbps
|
||||
if (init.size()){
|
||||
data[i++] = 0x5;//DecSpecificInfoTag
|
||||
data[i++] = init.size();
|
||||
memcpy(data+i, init.data(), init.size());
|
||||
}
|
||||
}
|
||||
|
||||
char ESDS::getSLConfigDescriptorTypeTag() {
|
||||
return getInt8(35 + getInt8(34));
|
||||
bool ESDS::isAAC(){
|
||||
return getESDescriptor().getDecoderConfig().isAAC();
|
||||
}
|
||||
|
||||
void ESDS::setSLConfigDescriptorTypeTag(char newVal) {
|
||||
setInt8(newVal, 35 + getInt8(34));
|
||||
std::string ESDS::getInitData(){
|
||||
return getESDescriptor().getDecoderConfig().getSpecific().toString();
|
||||
}
|
||||
|
||||
uint32_t ESDS::getSLConfigExtendedDescriptorTypeTag() {
|
||||
return getInt24(36 + getInt8(34));
|
||||
}
|
||||
//3 bytes
|
||||
void ESDS::setSLConfigExtendedDescriptorTypeTag(uint32_t newVal) {
|
||||
setInt24(newVal, 36 + getInt8(34));
|
||||
}
|
||||
//3 bytes
|
||||
char ESDS::getSLDescriptorTypeLength() {
|
||||
return getInt8(39 + getInt8(34));
|
||||
}
|
||||
|
||||
void ESDS::setSLDescriptorTypeLength(char newVal) {
|
||||
setInt8(newVal, 39 + getInt8(34));
|
||||
}
|
||||
|
||||
char ESDS::getSLValue() {
|
||||
return getInt8(40 + getInt8(34));
|
||||
}
|
||||
|
||||
void ESDS::setSLValue(char newVal) {
|
||||
setInt8(newVal, 40 + getInt8(34));
|
||||
ESDescriptor ESDS::getESDescriptor(){
|
||||
return ESDescriptor(data+12,boxedSize()-12);
|
||||
}
|
||||
|
||||
std::string ESDS::toPrettyString(uint32_t indent) {
|
||||
std::stringstream r;
|
||||
r << std::string(indent, ' ') << "[esds] ES Descriptor Box (" << boxedSize() << ")" << std::endl;
|
||||
r << fullBox::toPrettyString(indent);
|
||||
r << std::string(indent + 1, ' ') << "ESDescriptorType: 0x" << std::hex << (int)getESDescriptorType() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ExtendedESDescriptorType: 0x" << std::hex << (int)getExtendedESDescriptorType() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ESDescriptorTypeLength:" << (int)getESDescriptorTypeLength() << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ESID: 0x" << std::hex << (int)getESID() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "StreamPriority: 0x" << std::hex << (int)getStreamPriority() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "DecoderConfigDescriptorTag: 0x" << std::hex << (int)getDecoderConfigDescriptorTag() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ExtendedDecoderConfigDescriptorTag: 0x" << std::hex << (int)getExtendedDecoderConfigDescriptorTag() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "DecoderConfigDescriptorTypeLength: " << (int)getDecoderConfigDescriptorTypeLength() << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ByteObjectTypeID: 0x" << std::hex << (int)getByteObjectTypeID() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "StreamType: 0x" << std::hex << (int)getStreamType() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "UpstreamFlag: 0x" << std::hex << (int)getUpstreamFlag() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "BufferSize: 0x" << std::hex << (int)getBufferSize() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "MaximumBitRate: 0x" << std::hex << (int)getMaximumBitRate() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "AverageBitRate: 0x" << std::hex << (int)getAverageBitRate() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "DecoderDescriptorTypeTag: 0x" << std::hex << (int)getDecoderDescriptorTypeTag() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ExtendedDecoderDescriptorTypeTag: 0x" << std::hex << (int)getExtendedDecoderDescriptorTypeTag() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ConfigDescriptorTypeLength: 0x" << std::hex << (int)getConfigDescriptorTypeLength() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "ESHeaderStartCodes: 0x";
|
||||
for (unsigned int i = 0; i < getESHeaderStartCodes().size(); i++) {
|
||||
r << std::hex << std::setw(2) << std::setfill('0') << (int)getESHeaderStartCodes()[i] << std::dec;
|
||||
}
|
||||
r << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "SLConfigDescriptorTypeTag: 0x" << std::hex << (int)getSLConfigDescriptorTypeTag() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "SLConfigExtendedDescriptorTypeTag: 0x" << std::hex << (int)getSLConfigExtendedDescriptorTypeTag() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "SLDescriptorTypeLength: 0x" << std::hex << (int)getSLDescriptorTypeLength() << std::dec << std::endl;
|
||||
r << std::string(indent + 1, ' ') << "SLValue: 0x" << std::hex << (int)getSLValue() << std::dec << std::endl;
|
||||
r << getESDescriptor().toPrettyString(indent+1);
|
||||
return r.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -122,62 +122,61 @@ namespace MP4 {
|
|||
std::string toPrettyString(uint32_t indent = 0);
|
||||
};
|
||||
|
||||
///\todo : ESDS is filthy implemented, clean up when optimising
|
||||
class Descriptor{
|
||||
public:
|
||||
Descriptor();
|
||||
Descriptor(const char* pointer, const unsigned long length, const bool master = false);
|
||||
char getTag();///< Get type of descriptor
|
||||
void setTag(char t);///< Set type of descriptor
|
||||
unsigned long getDataSize();///< Get internal size of descriptor
|
||||
unsigned long getFullSize();///< Get external size of descriptor
|
||||
void resize(unsigned long t);///< Resize descriptor
|
||||
char* getData();///< Returns pointer to start of internal data
|
||||
std::string toPrettyString(uint32_t indent = 0);///< put it into a pretty string
|
||||
protected:
|
||||
unsigned long size;///< Length of data
|
||||
char* data;///< Pointer to data in memory
|
||||
bool master;
|
||||
};
|
||||
|
||||
/// Implements ISO 14496-1 DecSpecificInfoTag
|
||||
class DSDescriptor: public Descriptor{
|
||||
public:
|
||||
DSDescriptor (const char* pointer, const unsigned long length, const bool master = false);
|
||||
std::string toPrettyString(uint32_t indent = 0);///< put it into a pretty string
|
||||
std::string toString(); ///< Return decoder specific info as standard string in binary format.
|
||||
};
|
||||
|
||||
/// Implements ISO 14496-1 DecoderConfigDescrTag
|
||||
class DCDescriptor: public Descriptor{
|
||||
public:
|
||||
DCDescriptor (const char* pointer, const unsigned long length, const bool master = false);
|
||||
bool isAAC(); ///< Returns true if this track is AAC.
|
||||
DSDescriptor getSpecific();
|
||||
std::string toPrettyString(uint32_t indent = 0);///< put it into a pretty string
|
||||
};
|
||||
|
||||
/// Implements ISO 14496-1 ES_DescrTag
|
||||
class ESDescriptor: public Descriptor{
|
||||
public:
|
||||
ESDescriptor (const char* pointer, const unsigned long length, const bool master = false);
|
||||
DCDescriptor getDecoderConfig();
|
||||
std::string toPrettyString(uint32_t indent = 0);///< put it into a pretty string
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Implements ISO 14496-1 SLConfigDescrTag
|
||||
class SLCDescriptor: public Descriptor{
|
||||
};
|
||||
|
||||
class ESDS: public fullBox {
|
||||
public:
|
||||
ESDS();
|
||||
ESDS(std::string init, uint32_t bps);
|
||||
char getESDescriptorType();
|
||||
void setESDescriptorType(char newVal);
|
||||
uint32_t getExtendedESDescriptorType();//3 bytes
|
||||
void setExtendedESDescriptorType(uint32_t newVal);//3 bytes
|
||||
char getESDescriptorTypeLength();
|
||||
void setESDescriptorTypeLength(char newVal);
|
||||
//ESID 2 bytes
|
||||
uint16_t getESID();
|
||||
void setESID(uint16_t newVal);
|
||||
//stream priority 1 byte
|
||||
char getStreamPriority();
|
||||
void setStreamPriority(char newVal);
|
||||
//decoder config descriptor tag 1byte
|
||||
char getDecoderConfigDescriptorTag();
|
||||
void setDecoderConfigDescriptorTag(char newVal);
|
||||
//extended decoder config descriptor tag 3 bytes
|
||||
uint32_t getExtendedDecoderConfigDescriptorTag();
|
||||
void setExtendedDecoderConfigDescriptorTag(uint32_t newVal);//3 bytes
|
||||
//decoder config descriptor type length
|
||||
char getDecoderConfigDescriptorTypeLength();
|
||||
void setDecoderConfigDescriptorTypeLength(char newVal);
|
||||
char getByteObjectTypeID();
|
||||
void setByteObjectTypeID(char newVal);
|
||||
char getStreamType();//6 bits
|
||||
void setStreamType(char newVal);//6 bits
|
||||
bool getUpstreamFlag();
|
||||
void setUpstreamFlag(bool newVal);
|
||||
bool getReservedFlag();
|
||||
void setReservedFlag(bool newVal);
|
||||
uint32_t getBufferSize();//3 bytes
|
||||
void setBufferSize(uint32_t newVal);//3 bytes
|
||||
uint32_t getMaximumBitRate();
|
||||
void setMaximumBitRate(uint32_t newVal);
|
||||
uint32_t getAverageBitRate();
|
||||
void setAverageBitRate(uint32_t newVal);
|
||||
char getDecoderDescriptorTypeTag();
|
||||
void setDecoderDescriptorTypeTag(char newVal);
|
||||
uint32_t getExtendedDecoderDescriptorTypeTag();//3 bytes
|
||||
void setExtendedDecoderDescriptorTypeTag(uint32_t newVal);//3 bytes
|
||||
char getConfigDescriptorTypeLength();
|
||||
void setConfigDescriptorTypeLength(char newVal);
|
||||
std::string getESHeaderStartCodes();
|
||||
void setESHeaderStartCodes(std::string newVal);
|
||||
char getSLConfigDescriptorTypeTag();
|
||||
void setSLConfigDescriptorTypeTag(char newVal);
|
||||
uint32_t getSLConfigExtendedDescriptorTypeTag();//3 bytes
|
||||
void setSLConfigExtendedDescriptorTypeTag(uint32_t newVal);//3 bytes
|
||||
char getSLDescriptorTypeLength();
|
||||
void setSLDescriptorTypeLength(char newVal);
|
||||
char getSLValue();
|
||||
void setSLValue(char newVal);
|
||||
ESDS(std::string init);
|
||||
ESDescriptor getESDescriptor();
|
||||
bool isAAC();
|
||||
std::string getInitData();
|
||||
std::string toPrettyString(uint32_t indent = 0);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue