#include "mp4_dash.h" #include "defines.h" namespace MP4 { SIDX::SIDX() { memcpy(data + 4, "sidx", 4); setVersion(0); setFlags(0); } void SIDX::setReferenceID(uint32_t newReferenceID) { setInt32(newReferenceID, 4); } uint32_t SIDX::getReferenceID() { return getInt32(4); } void SIDX::setTimescale(uint32_t newTimescale) { setInt32(newTimescale, 8); } uint32_t SIDX::getTimescale() { return getInt32(8); } void SIDX::setEarliestPresentationTime(uint64_t newEarliestPresentationTime) { if (getVersion() == 0) { setInt32(newEarliestPresentationTime, 12); } else { setInt64(newEarliestPresentationTime, 12); } } uint64_t SIDX::getEarliestPresentationTime() { if (getVersion() == 0) { return getInt32(12); } return getInt64(12); } void SIDX::setFirstOffset(uint64_t newFirstOffset) { if (getVersion() == 0) { setInt32(newFirstOffset, 16); } else { setInt64(newFirstOffset, 20); } } uint64_t SIDX::getFirstOffset() { if (getVersion() == 0) { return getInt32(16); } return getInt64(20); } uint16_t SIDX::getReferenceCount() { if (getVersion() == 0) { return getInt16(22); } return getInt16(30); } void SIDX::setReference(sidxReference & newRef, size_t index) { if (index >= getReferenceCount()) { setInt16(index + 1, (getVersion() == 0 ? 22 : 30)); } uint32_t offset = 24 + (index * 12) + (getVersion() == 0 ? 0 : 8); uint32_t tmp = (newRef.referenceType ? 0x80000000 : 0) | newRef.referencedSize; setInt32(tmp, offset); setInt32(newRef.subSegmentDuration, offset + 4); tmp = (newRef.sapStart ? 0x80000000 : 0) | ((uint32_t)(newRef.sapType & 0x70) << 24) | newRef.sapDeltaTime; setInt32(tmp, offset + 8); } sidxReference SIDX::getReference(size_t index) { sidxReference result; if (index >= getReferenceCount()) { DEVEL_MSG("Warning, attempt to obtain reference out of bounds"); return result; } uint32_t offset = 24 + (index * 12) + (getVersion() == 0 ? 0 : 8); uint32_t tmp = getInt32(offset); result.referenceType = tmp & 0x80000000; result.referencedSize = tmp & 0x7FFFFFFF; result.subSegmentDuration = getInt32(offset + 4); tmp = getInt32(offset + 8); result.sapStart = tmp & 0x80000000; result.sapType = (tmp & 0x70000000) >> 24; result.sapDeltaTime = (tmp & 0x0FFFFFFF); return result; } std::string SIDX::toPrettyString(uint32_t indent) { std::stringstream r; r << std::string(indent, ' ') << "[sidx] Segment Index Box (" << boxedSize() << ")" << std::endl; r << fullBox::toPrettyString(indent); r << std::string(indent + 1, ' ') << "ReferenceID " << getReferenceID() << std::endl; r << std::string(indent + 1, ' ') << "Timescale " << getTimescale() << std::endl; r << std::string(indent + 1, ' ') << "EarliestPresentationTime " << getEarliestPresentationTime() << std::endl; r << std::string(indent + 1, ' ') << "FirstOffset " << getFirstOffset() << std::endl; r << std::string(indent + 1, ' ') << "References [" << getReferenceCount() << "]" << std::endl; for (int i = 0; i < getReferenceCount(); i++) { sidxReference tmp = getReference(i); r << std::string(indent + 2, ' ') << "[" << i << "]" << std::endl; r << std::string(indent + 3, ' ') << "ReferenceType " << (int)tmp.referenceType << std::endl; r << std::string(indent + 3, ' ') << "ReferencedSize " << tmp.referencedSize << std::endl; r << std::string(indent + 3, ' ') << "SubSegmentDuration " << tmp.subSegmentDuration << std::endl; r << std::string(indent + 3, ' ') << "StartsWithSAP " << (int)tmp.sapStart << std::endl; r << std::string(indent + 3, ' ') << "SAP Type " << (int)tmp.sapType << std::endl; r << std::string(indent + 3, ' ') << "SAP DeltaTime " << tmp.sapDeltaTime << std::endl; } return r.str(); } TFDT::TFDT() { memcpy(data + 4, "tfdt", 4); setVersion(1); setFlags(0); setBaseMediaDecodeTime(0); } void TFDT::setBaseMediaDecodeTime(uint64_t newBaseMediaDecodeTime) { if (getVersion() == 1) { setInt64(newBaseMediaDecodeTime, 4); } else { setInt32(newBaseMediaDecodeTime, 4); } } uint64_t TFDT::getBaseMediaDecodeTime() { if (getVersion() == 1) { return getInt64(4); } return getInt32(4); } std::string TFDT::toPrettyString(uint32_t indent) { std::stringstream r; r << std::string(indent, ' ') << "[tfdt] Track Fragment Base Media Decode Time Box (" << boxedSize() << ")" << std::endl; r << fullBox::toPrettyString(indent); r << std::string(indent + 1, ' ') << "BaseMediaDecodeTime " << getBaseMediaDecodeTime() << std::endl; return r.str(); } IODS::IODS() { memcpy(data + 4, "iods", 4); setVersion(0); setFlags(0); setIODTypeTag(0x10); setDescriptorTypeLength(0x07); setODID(0x004F); setODProfileLevel(0xFF); setODSceneLevel(0xFF); setODAudioLevel(0xFF); setODVideoLevel(0xFF); setODGraphicsLevel(0xFF); } void IODS::setIODTypeTag(char value) { setInt8(value, 4); } char IODS::getIODTypeTag() { return getInt8(4); } void IODS::setDescriptorTypeLength(char length) { setInt8(length, 5); } char IODS::getDescriptorTypeLength() { return getInt8(5); } void IODS::setODID(short id) { setInt16(id, 6); } short IODS::getODID() { return getInt16(6); } void IODS::setODProfileLevel(char value) { setInt8(value, 8); } char IODS::getODProfileLevel() { return getInt8(8); } void IODS::setODSceneLevel(char value) { setInt8(value, 9); } char IODS::getODSceneLevel() { return getInt8(9); } void IODS::setODAudioLevel(char value) { setInt8(value, 10); } char IODS::getODAudioLevel() { return getInt8(10); } void IODS::setODVideoLevel(char value) { setInt8(value, 11); } char IODS::getODVideoLevel() { return getInt8(11); } void IODS::setODGraphicsLevel(char value) { setInt8(value, 12); } char IODS::getODGraphicsLevel() { return getInt8(12); } std::string IODS::toPrettyString(uint32_t indent) { std::stringstream r; r << std::string(indent, ' ') << "[iods] IODS Box (" << boxedSize() << ")" << std::endl; r << fullBox::toPrettyString(indent); r << std::string(indent + 2, ' ') << "IOD Type Tag: " << std::hex << std::setw(2) << std::setfill('0') << (int)getIODTypeTag() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "DescriptorTypeLength: " << std::hex << std::setw(2) << std::setfill('0') << (int)getDescriptorTypeLength() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD ID: " << std::hex << std::setw(4) << std::setfill('0') << (int)getODID() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD Profile Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODProfileLevel() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD Scene Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODSceneLevel() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD Audio Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODAudioLevel() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD Video Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODVideoLevel() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD Graphics Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODGraphicsLevel() << std::dec << std::endl; return r.str(); } }