diff --git a/lib/dtsc.h b/lib/dtsc.h index d95e643c..7e66519e 100644 --- a/lib/dtsc.h +++ b/lib/dtsc.h @@ -37,12 +37,8 @@ namespace DTSC { return true; }else{ if (seekTime == rhs.seekTime){ - if (bytePos < rhs.bytePos){ + if (trackID < rhs.trackID){ return true; - }else{ - if (trackID < rhs.trackID){ - return true; - } } } } diff --git a/lib/mp4.h b/lib/mp4.h index 4eeb18de..465bf88b 100644 --- a/lib/mp4.h +++ b/lib/mp4.h @@ -15,30 +15,6 @@ /// Contains all MP4 format related code. namespace MP4 { - struct keyPart{ - public: - bool operator < (const keyPart& rhs) const { - if (time < rhs.time){ - return true; - } - if (time == rhs.time){ - if (trackID < rhs.trackID){ - return true; - } - } - return false; - } - long unsigned int trackID; - long unsigned int size; - long long unsigned int time; - long long unsigned int endTime; - long unsigned int index; - }; - - class DTSC2MP4Converter{ - public: - std::string DTSCMeta2MP4Header(DTSC::Meta & metaData); - }; class Box{ public: diff --git a/lib/mp4_conv.cpp b/lib/mp4_conv.cpp deleted file mode 100644 index 4b249359..00000000 --- a/lib/mp4_conv.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#include "mp4_generic.h" -#include - -namespace MP4{ - std::string DTSC2MP4Converter::DTSCMeta2MP4Header(DTSC::Meta & metaData){ - std::stringstream header; - //ftyp box - /// \todo fill ftyp with non hardcoded values from file - MP4::FTYP ftypBox; - ftypBox.setMajorBrand(0x6D703431);//mp41 - ftypBox.setMinorVersion(0); - ftypBox.setCompatibleBrands(0x69736f6d,0); - ftypBox.setCompatibleBrands(0x69736f32,1); - ftypBox.setCompatibleBrands(0x61766331,2); - ftypBox.setCompatibleBrands(0x6D703431,3); - header << std::string(ftypBox.asBox(),ftypBox.boxedSize()); - - uint64_t mdatSize = 0; - //moov box - MP4::MOOV moovBox;{ - //calculating longest duration - long long int fileDuration = 0; - /// \todo lastms and firstms fix - for ( std::map::iterator trackIt = metaData.tracks.begin(); trackIt != metaData.tracks.end(); trackIt ++) { - if (trackIt->second.lastms - trackIt->second.firstms > fileDuration){ - fileDuration = trackIt->second.lastms - trackIt->second.firstms; - } - } - //MP4::MVHD mvhdBox(fileDuration); - MP4::MVHD mvhdBox; - mvhdBox.setVersion(0); - mvhdBox.setCreationTime(0); - mvhdBox.setModificationTime(0); - mvhdBox.setTimeScale(1000); - mvhdBox.setRate(0x10000); - mvhdBox.setDuration(fileDuration); - mvhdBox.setTrackID(0); - mvhdBox.setVolume(256); - mvhdBox.setMatrix(0x00010000,0); - mvhdBox.setMatrix(0,1); - mvhdBox.setMatrix(0,2); - mvhdBox.setMatrix(0,3); - mvhdBox.setMatrix(0x00010000,4); - mvhdBox.setMatrix(0,5); - mvhdBox.setMatrix(0,6); - mvhdBox.setMatrix(0,7); - mvhdBox.setMatrix(0x40000000,8); - moovBox.setContent(mvhdBox, 0); - } - {//start arbitrary track addition for header - int boxOffset = 1; - bool seenAudio = false; - bool seenVideo = false; - for ( std::map::iterator it = metaData.tracks.begin(); it != metaData.tracks.end(); it ++) { - if (it->second.codec != "AAC" && it->second.codec != "H264"){continue;} - if (it->second.type == "audio"){ - if (seenAudio){continue;} - seenAudio = true; - } - if (it->second.type == "video"){ - if (seenVideo){continue;} - seenVideo = true; - } - if (it->first > 0){ - int timescale = 0; - MP4::TRAK trakBox; - { - { - MP4::TKHD tkhdBox; - tkhdBox.setVersion(0); - tkhdBox.setFlags(15); - tkhdBox.setTrackID(it->second.trackID); - /// \todo duration firstms and lastms fix - tkhdBox.setDuration(it->second.lastms + it->second.firstms); - - if (it->second.type == "video"){ - tkhdBox.setWidth(it->second.width << 16); - tkhdBox.setHeight(it->second.height << 16); - tkhdBox.setVolume(0); - }else{ - tkhdBox.setVolume(256); - tkhdBox.setAlternateGroup(1); - } - tkhdBox.setMatrix(0x00010000,0); - tkhdBox.setMatrix(0,1); - tkhdBox.setMatrix(0,2); - tkhdBox.setMatrix(0,3); - tkhdBox.setMatrix(0x00010000,4); - tkhdBox.setMatrix(0,5); - tkhdBox.setMatrix(0,6); - tkhdBox.setMatrix(0,7); - tkhdBox.setMatrix(0x40000000,8); - trakBox.setContent(tkhdBox, 0); - }{ - MP4::MDIA mdiaBox; - { - MP4::MDHD mdhdBox(0);/// \todo fix constructor mdhd in lib - mdhdBox.setCreationTime(0); - mdhdBox.setModificationTime(0); - //Calculating media time based on sampledelta. Probably cheating, but it works... - timescale = ((double)(42 * it->second.parts.size() ) / (it->second.lastms + it->second.firstms)) * 1000; - mdhdBox.setTimeScale(timescale); - /// \todo fix lastms, firstms - mdhdBox.setDuration((it->second.lastms + it->second.firstms) * ((double)timescale / 1000)); - mdiaBox.setContent(mdhdBox, 0); - }//MDHD box - { - MP4::HDLR hdlrBox;/// \todo fix constructor hdlr in lib - if (it->second.type == "video"){ - hdlrBox.setHandlerType(0x76696465);//vide - }else if (it->second.type == "audio"){ - hdlrBox.setHandlerType(0x736F756E);//soun - } - hdlrBox.setName(it->second.getIdentifier()); - mdiaBox.setContent(hdlrBox, 1); - }//hdlr box - { - MP4::MINF minfBox; - if (it->second.type== "video"){ - MP4::VMHD vmhdBox; - vmhdBox.setFlags(1); - minfBox.setContent(vmhdBox,0); - }else if (it->second.type == "audio"){ - MP4::SMHD smhdBox; - minfBox.setContent(smhdBox,0); - }//type box - { - MP4::DINF dinfBox; - MP4::DREF drefBox;/// \todo fix constructor dref in lib - drefBox.setVersion(0); - MP4::URL urlBox; - urlBox.setFlags(1); - drefBox.setDataEntry(urlBox,0); - dinfBox.setContent(drefBox,0); - minfBox.setContent(dinfBox,1); - }//dinf box - { - MP4::STBL stblBox; - { - MP4::STSD stsdBox; - stsdBox.setVersion(0); - if (it->second.type == "video"){//boxname = codec - MP4::VisualSampleEntry vse; - if (it->second.codec == "H264"){ - vse.setCodec("avc1"); - } - vse.setDataReferenceIndex(1); - vse.setWidth(it->second.width); - vse.setHeight(it->second.height); - MP4::AVCC avccBox; - avccBox.setPayload(it->second.init); - vse.setCLAP(avccBox); - stsdBox.setEntry(vse,0); - }else if(it->second.type == "audio"){//boxname = codec - MP4::AudioSampleEntry ase; - if (it->second.codec == "AAC"){ - ase.setCodec("mp4a"); - ase.setDataReferenceIndex(1); - } - ase.setSampleRate(it->second.rate); - ase.setChannelCount(it->second.channels); - ase.setSampleSize(it->second.size); - //MP4::ESDS esdsBox(it->second.init, it->second.bps); - MP4::ESDS esdsBox; - - //outputting these values first, so malloc isn't called as often. - esdsBox.setESHeaderStartCodes(it->second.init); - esdsBox.setSLValue(2); - - esdsBox.setESDescriptorTypeLength(32+it->second.init.size()); - esdsBox.setESID(2); - esdsBox.setStreamPriority(0); - esdsBox.setDecoderConfigDescriptorTypeLength(18 + it->second.init.size()); - esdsBox.setByteObjectTypeID(0x40); - esdsBox.setStreamType(5); - esdsBox.setReservedFlag(1); - esdsBox.setBufferSize(1250000); - esdsBox.setMaximumBitRate(10000000); - esdsBox.setAverageBitRate(it->second.bps * 8); - esdsBox.setConfigDescriptorTypeLength(5); - esdsBox.setSLConfigDescriptorTypeTag(0x6); - esdsBox.setSLConfigExtendedDescriptorTypeTag(0x808080); - esdsBox.setSLDescriptorTypeLength(1); - ase.setCodecBox(esdsBox); - stsdBox.setEntry(ase,0); - } - stblBox.setContent(stsdBox,0); - }//stsd box - /// \todo update following stts lines - { - MP4::STTS sttsBox;//current version probably causes problems - sttsBox.setVersion(0); - MP4::STTSEntry newEntry; - newEntry.sampleCount = it->second.parts.size(); - //42, Used as magic number for timescale calculation - newEntry.sampleDelta = 42; - sttsBox.setSTTSEntry(newEntry, 0); - stblBox.setContent(sttsBox,1); - }//stts box - if (it->second.type == "video"){ - //STSS Box here - MP4::STSS stssBox; - stssBox.setVersion(0); - int tmpCount = 1; - int tmpItCount = 0; - for ( std::deque< DTSC::Key>::iterator tmpIt = it->second.keys.begin(); tmpIt != it->second.keys.end(); tmpIt ++) { - stssBox.setSampleNumber(tmpCount,tmpItCount); - tmpCount += tmpIt->getParts(); - tmpItCount ++; - } - stblBox.setContent(stssBox,2); - }//stss box - - int offset = (it->second.type == "video"); - { - MP4::STSC stscBox; - stscBox.setVersion(0); - MP4::STSCEntry stscEntry; - stscEntry.firstChunk = 1; - stscEntry.samplesPerChunk = 1; - stscEntry.sampleDescriptionIndex = 1; - stscBox.setSTSCEntry(stscEntry, 0); - stblBox.setContent(stscBox,2 + offset); - }//stsc box - { - uint32_t total = 0; - MP4::STSZ stszBox; - stszBox.setVersion(0); - total = 0; - for (std::deque< DTSC::Part>::iterator partIt = it->second.parts.begin(); partIt != it->second.parts.end(); partIt ++) { - stszBox.setEntrySize(partIt->getSize(), total);//in bytes in file - total++; - } - stblBox.setContent(stszBox,3 + offset); - }//stsz box - //add STCO boxes here - { - MP4::STCO stcoBox; - stcoBox.setVersion(1); - //Inserting empty values on purpose here, will be fixed later. - if (it->second.parts.size() != 0){ - stcoBox.setChunkOffset(0, it->second.parts.size() - 1);//this inserts all empty entries at once - } - stblBox.setContent(stcoBox,4 + offset); - }//stco box - minfBox.setContent(stblBox,2); - }//stbl box - mdiaBox.setContent(minfBox, 2); - }//minf box - trakBox.setContent(mdiaBox, 1); - } - }//trak Box - moovBox.setContent(trakBox, boxOffset); - boxOffset++; - } - } - }//end arbitrary track addition - //initial offset length ftyp, length moov + 8 - unsigned long long int byteOffset = ftypBox.boxedSize() + moovBox.boxedSize() + 8; - //update all STCO from the following map; - std::map checkStcoBoxes; - //for all tracks - for (unsigned int i = 1; i < moovBox.getContentCount(); i++){ - //10 lines to get the STCO box. - MP4::TRAK checkTrakBox; - MP4::MDIA checkMdiaBox; - MP4::MINF checkMinfBox; - MP4::STBL checkStblBox; - //MP4::STCO checkStcoBox; - checkTrakBox = ((MP4::TRAK&)moovBox.getContent(i)); - for (unsigned int j = 0; j < checkTrakBox.getContentCount(); j++){ - if (checkTrakBox.getContent(j).isType("mdia")){ - checkMdiaBox = ((MP4::MDIA&)checkTrakBox.getContent(j)); - break; - } - } - for (unsigned int j = 0; j < checkMdiaBox.getContentCount(); j++){ - if (checkMdiaBox.getContent(j).isType("minf")){ - checkMinfBox = ((MP4::MINF&)checkMdiaBox.getContent(j)); - break; - } - } - for (unsigned int j = 0; j < checkMinfBox.getContentCount(); j++){ - if (checkMinfBox.getContent(j).isType("stbl")){ - checkStblBox = ((MP4::STBL&)checkMinfBox.getContent(j)); - break; - } - } - for (unsigned int j = 0; j < checkStblBox.getContentCount(); j++){ - if (checkStblBox.getContent(j).isType("stco")){ - checkStcoBoxes.insert( std::pair(i, ((MP4::STCO&)checkStblBox.getContent(j)) )); - break; - } - } - } - //inserting right values in the STCO box header - //total = 0; - long long unsigned int totalByteOffset = 0; - //Current values are actual byte offset without header-sized offset - std::set sortSet;//filling sortset for interleaving parts - for ( std::map::iterator subIt = metaData.tracks.begin(); subIt != metaData.tracks.end(); subIt ++) { - keyPart temp; - temp.trackID = subIt->second.trackID; - temp.time = subIt->second.firstms;//timeplace of frame - temp.endTime = subIt->second.firstms + subIt->second.parts[0].getDuration(); - temp.size = subIt->second.parts[0].getSize();//bytesize of frame (alle parts all together) - temp.index = 0; - sortSet.insert(temp); - } - while (!sortSet.empty()){ - //setting the right STCO size in the STCO box - checkStcoBoxes[sortSet.begin()->trackID].setChunkOffset(totalByteOffset + byteOffset, sortSet.begin()->index); - totalByteOffset += sortSet.begin()->size; - //add keyPart to sortSet - keyPart temp; - temp.index = sortSet.begin()->index + 1; - temp.trackID = sortSet.begin()->trackID; - if(temp.index < metaData.tracks[temp.trackID].parts.size() ){//only insert when there are parts left - temp.time = sortSet.begin()->endTime;//timeplace of frame - temp.endTime = sortSet.begin()->endTime + metaData.tracks[temp.trackID].parts[temp.index].getDuration(); - temp.size = metaData.tracks[temp.trackID].parts[temp.index].getSize();//bytesize of frame - sortSet.insert(temp); - } - //remove highest keyPart - sortSet.erase(sortSet.begin()); - } - //calculating the offset where the STCO box will be in the main MOOV box - //needed for probable optimise - mdatSize = totalByteOffset; - - header << std::string(moovBox.asBox(),moovBox.boxedSize()); - - header << (char)((mdatSize>>24) & 0x000000FF) << (char)((mdatSize>>16) & 0x000000FF) << (char)((mdatSize>>8) & 0x000000FF) << (char)(mdatSize & 0x000000FF) << "mdat"; - //end of header - - return header.str(); - } - -} -