Fixes to CMAF output
This commit is contained in:
		
							parent
							
								
									e217f41f17
								
							
						
					
					
						commit
						a8e04e1787
					
				
					 7 changed files with 69 additions and 84 deletions
				
			
		
							
								
								
									
										84
									
								
								lib/cmaf.cpp
									
										
									
									
									
								
							
							
						
						
									
										84
									
								
								lib/cmaf.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -1,24 +1,13 @@
 | 
				
			||||||
#include "cmaf.h"
 | 
					#include "cmaf.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint64_t unixBootDiff = (Util::unixMS() - Util::bootMS());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace CMAF{
 | 
					namespace CMAF{
 | 
				
			||||||
  /// Function to determine the payload size of a CMAF fragment.
 | 
					  /// Function to determine the payload size of a CMAF fragment.
 | 
				
			||||||
  /// \parm isKeyIndex indicates whether we are sending DTSC Fragment or DTSC Key based CMAF fragments.
 | 
					  size_t payloadSize(const DTSC::Meta &M, size_t track, uint64_t startTime, uint64_t endTime){
 | 
				
			||||||
  size_t payloadSize(const DTSC::Meta &M, size_t track, size_t index, bool isKeyIndex){
 | 
					 | 
				
			||||||
    DTSC::Fragments fragments(M.fragments(track));
 | 
					 | 
				
			||||||
    DTSC::Keys keys(M.keys(track));
 | 
					 | 
				
			||||||
    DTSC::Parts parts(M.parts(track));
 | 
					    DTSC::Parts parts(M.parts(track));
 | 
				
			||||||
 | 
					    size_t firstPart = M.getPartIndex(startTime, track);
 | 
				
			||||||
    size_t firstKey = (isKeyIndex ? index : fragments.getFirstKey(index));
 | 
					    size_t endPart = M.getPartIndex(endTime, track);
 | 
				
			||||||
    size_t endKey = keys.getEndValid();
 | 
					 | 
				
			||||||
    if (isKeyIndex) {
 | 
					 | 
				
			||||||
      if (index + 1 < keys.getEndValid()){endKey = index + 1;}
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      if (index + 1 < fragments.getEndValid()){endKey = fragments.getFirstKey(index + 1);}
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t firstPart = keys.getFirstPart(firstKey);
 | 
					 | 
				
			||||||
    size_t endPart = parts.getEndValid();
 | 
					 | 
				
			||||||
    if (endKey != keys.getEndValid()){endPart = keys.getFirstPart(endKey);}
 | 
					 | 
				
			||||||
    size_t payloadSize = 0;
 | 
					    size_t payloadSize = 0;
 | 
				
			||||||
    for (size_t i = firstPart; i < endPart; i++){payloadSize += parts.getSize(i);}
 | 
					    for (size_t i = firstPart; i < endPart; i++){payloadSize += parts.getSize(i);}
 | 
				
			||||||
    return payloadSize;
 | 
					    return payloadSize;
 | 
				
			||||||
| 
						 | 
					@ -186,7 +175,7 @@ namespace CMAF{
 | 
				
			||||||
            ((i + 1 < fragments.getEndValid()) ? fragments.getFirstKey(i + 1) : keys.getEndValid());
 | 
					            ((i + 1 < fragments.getEndValid()) ? fragments.getFirstKey(i + 1) : keys.getEndValid());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MP4::sidxReference refItem;
 | 
					        MP4::sidxReference refItem;
 | 
				
			||||||
        refItem.referencedSize = payloadSize(M, track, i) + fragmentHeaderSize(M, track, i) + 8;
 | 
					        refItem.referencedSize = payloadSize(M, track, keys.getTime(firstKey), keys.getTime(endKey)) + fragmentHeaderSize(M, track, i) + 8;
 | 
				
			||||||
        refItem.subSegmentDuration =
 | 
					        refItem.subSegmentDuration =
 | 
				
			||||||
            (endKey == keys.getEndValid() ? M.getLastms(track) : keys.getTime(endKey)) - keys.getTime(firstKey);
 | 
					            (endKey == keys.getEndValid() ? M.getLastms(track) : keys.getTime(endKey)) - keys.getTime(firstKey);
 | 
				
			||||||
        refItem.sapStart = true;
 | 
					        refItem.sapStart = true;
 | 
				
			||||||
| 
						 | 
					@ -304,7 +293,7 @@ namespace CMAF{
 | 
				
			||||||
    if (M.getVod()){
 | 
					    if (M.getVod()){
 | 
				
			||||||
      tfdtBox.setBaseMediaDecodeTime(M.getTimeForFragmentIndex(track, fragment) - M.getFirstms(track));
 | 
					      tfdtBox.setBaseMediaDecodeTime(M.getTimeForFragmentIndex(track, fragment) - M.getFirstms(track));
 | 
				
			||||||
    }else{
 | 
					    }else{
 | 
				
			||||||
      tfdtBox.setBaseMediaDecodeTime((UTCTime ? Util::epoch()*1000 : M.getTimeForFragmentIndex(track, fragment)));
 | 
					      tfdtBox.setBaseMediaDecodeTime((UTCTime ? M.getTimeForFragmentIndex(track, fragment) + M.getBootMsOffset() + unixBootDiff : M.getTimeForFragmentIndex(track, fragment)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    trafBox.setContent(tfdtBox, 1);
 | 
					    trafBox.setContent(tfdtBox, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -337,50 +326,36 @@ namespace CMAF{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Calculates the full size of a 'moof' box for a DTSC::Key based fragment.
 | 
					  /// Calculates the full size of a 'moof' box for a DTSC::Key based fragment.
 | 
				
			||||||
  /// Used when building the 'moof' box to calculate the relative data offsets.
 | 
					  /// Used when building the 'moof' box to calculate the relative data offsets.
 | 
				
			||||||
  size_t keyHeaderSize(const DTSC::Meta &M, size_t track, size_t key){
 | 
					  size_t keyHeaderSize(const DTSC::Meta &M, size_t track, uint64_t startTime, uint64_t endTime){
 | 
				
			||||||
    uint64_t tmpRes = 8 + 16 + 32 + 20;
 | 
					    uint64_t tmpRes = 8 + 16 + 32 + 20;
 | 
				
			||||||
 | 
					    size_t firstPart = M.getPartIndex(startTime, track);
 | 
				
			||||||
    DTSC::Keys keys(M.keys(track));
 | 
					    size_t endPart = M.getPartIndex(endTime, track);
 | 
				
			||||||
    DTSC::Parts parts(M.parts(track));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t firstPart = keys.getFirstPart(key);
 | 
					 | 
				
			||||||
    size_t endPart = parts.getEndValid();
 | 
					 | 
				
			||||||
    if (key + 1 < keys.getEndValid()){
 | 
					 | 
				
			||||||
      endPart = keys.getFirstPart(key + 1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tmpRes += 24 + ((endPart - firstPart) * 12);
 | 
					    tmpRes += 24 + ((endPart - firstPart) * 12);
 | 
				
			||||||
    return tmpRes;
 | 
					    return tmpRes;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Generates the 'moof' box for a DTSC::Key based CMAF fragment.
 | 
					  /// Generates the 'moof' box for a DTSC::Key based CMAF fragment.
 | 
				
			||||||
  std::string keyHeader(const DTSC::Meta &M, size_t track, size_t key, bool simplifyTrackIds, bool UTCTime){
 | 
					  std::string keyHeader(const DTSC::Meta &M, size_t track, uint64_t startTime, uint64_t endTime, uint64_t segmentNum, bool simplifyTrackIds, bool UTCTime){
 | 
				
			||||||
    DTSC::Keys keys(M.keys(track));
 | 
					 | 
				
			||||||
    DTSC::Parts parts(M.parts(track));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t firstPart = keys.getFirstPart(key);
 | 
					 | 
				
			||||||
    size_t endPart = parts.getEndValid();
 | 
					 | 
				
			||||||
    if (key + 1 < keys.getEndValid()){
 | 
					 | 
				
			||||||
      endPart = keys.getFirstPart(key + 1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t firstPart = M.getPartIndex(startTime, track);
 | 
				
			||||||
 | 
					    size_t endPart = M.getPartIndex(endTime, track);
 | 
				
			||||||
    std::stringstream header;
 | 
					    std::stringstream header;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    MP4::MOOF moofBox;
 | 
					    MP4::MOOF moofBox;
 | 
				
			||||||
    MP4::MFHD mfhdBox(key + 1);
 | 
					    MP4::MFHD mfhdBox(segmentNum);
 | 
				
			||||||
    moofBox.setContent(mfhdBox, 0);
 | 
					    moofBox.setContent(mfhdBox, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::set<sortPart> trunOrder;
 | 
					    std::set<sortPart> trunOrder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //We use keyHeaderSize here to determine the relative offsets of the data in the 'mdat' box. 
 | 
					    //We use keyHeaderSize here to determine the relative offsets of the data in the 'mdat' box. 
 | 
				
			||||||
    uint64_t relativeOffset = keyHeaderSize(M, track, key) + 8;
 | 
					    uint64_t relativeOffset = keyHeaderSize(M, track, startTime, endTime) + 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sortPart temp;
 | 
					    sortPart temp;
 | 
				
			||||||
    temp.time = keys.getTime(key);
 | 
					    temp.time = startTime;
 | 
				
			||||||
    temp.partIndex = firstPart;
 | 
					    temp.partIndex = firstPart;
 | 
				
			||||||
    temp.bytePos = relativeOffset;
 | 
					    temp.bytePos = relativeOffset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DTSC::Parts parts(M.parts(track));
 | 
				
			||||||
    for (size_t p = firstPart; p < endPart; p++){
 | 
					    for (size_t p = firstPart; p < endPart; p++){
 | 
				
			||||||
      trunOrder.insert(temp);
 | 
					      trunOrder.insert(temp);
 | 
				
			||||||
      temp.time += parts.getDuration(p);
 | 
					      temp.time += parts.getDuration(p);
 | 
				
			||||||
| 
						 | 
					@ -405,9 +380,9 @@ namespace CMAF{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MP4::TFDT tfdtBox;
 | 
					    MP4::TFDT tfdtBox;
 | 
				
			||||||
    if (M.getVod()){
 | 
					    if (M.getVod()){
 | 
				
			||||||
      tfdtBox.setBaseMediaDecodeTime(keys.getTime(key) - M.getFirstms(track));
 | 
					      tfdtBox.setBaseMediaDecodeTime(startTime - M.getFirstms(track));
 | 
				
			||||||
    }else{
 | 
					    }else{
 | 
				
			||||||
      tfdtBox.setBaseMediaDecodeTime((UTCTime ? Util::epoch()*1000 : keys.getTime(key) ));
 | 
					      tfdtBox.setBaseMediaDecodeTime((UTCTime ? startTime + M.getBootMsOffset() + unixBootDiff : startTime));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    trafBox.setContent(tfdtBox, 1);
 | 
					    trafBox.setContent(tfdtBox, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -421,12 +396,21 @@ namespace CMAF{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t trunOffset = 0;
 | 
					    size_t trunOffset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (std::set<sortPart>::iterator it = trunOrder.begin(); it != trunOrder.end(); it++){
 | 
					    if (trunOrder.size()){
 | 
				
			||||||
      MP4::trunSampleInformation sampleInfo;
 | 
					      std::set<sortPart>::iterator lastOne = trunOrder.end();
 | 
				
			||||||
      sampleInfo.sampleSize = parts.getSize(it->partIndex);
 | 
					      lastOne--;
 | 
				
			||||||
      sampleInfo.sampleDuration = parts.getDuration(it->partIndex);
 | 
					      for (std::set<sortPart>::iterator it = trunOrder.begin(); it != trunOrder.end(); it++){
 | 
				
			||||||
      sampleInfo.sampleOffset = parts.getOffset(it->partIndex);
 | 
					        MP4::trunSampleInformation sampleInfo;
 | 
				
			||||||
      trunBox.setSampleInformation(sampleInfo, trunOffset++);
 | 
					        sampleInfo.sampleSize = parts.getSize(it->partIndex);
 | 
				
			||||||
 | 
					        sampleInfo.sampleDuration = parts.getDuration(it->partIndex);
 | 
				
			||||||
 | 
					        if (it == lastOne){
 | 
				
			||||||
 | 
					          sampleInfo.sampleDuration = endTime - it->time;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        sampleInfo.sampleOffset = parts.getOffset(it->partIndex);
 | 
				
			||||||
 | 
					        trunBox.setSampleInformation(sampleInfo, trunOffset++);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					      WARN_MSG("Empty CMAF header for track %zu: %zu-%zu contains no packets (first: %" PRIu64 ", last: %" PRIu64 "), firstPart=%zu, lastPart=%zu", track, startTime, endTime, M.getFirstms(track), M.getLastms(track), firstPart, endPart);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    trafBox.setContent(trunBox, 2);
 | 
					    trafBox.setContent(trunBox, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,11 +4,11 @@
 | 
				
			||||||
#include <set>
 | 
					#include <set>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace CMAF{
 | 
					namespace CMAF{
 | 
				
			||||||
  size_t payloadSize(const DTSC::Meta &M, size_t track, size_t index, bool isKeyIndex = false);
 | 
					  size_t payloadSize(const DTSC::Meta &M, size_t track, uint64_t startTime, uint64_t endTime);
 | 
				
			||||||
  size_t trackHeaderSize(const DTSC::Meta &M, size_t track);
 | 
					  size_t trackHeaderSize(const DTSC::Meta &M, size_t track);
 | 
				
			||||||
  std::string trackHeader(const DTSC::Meta &M, size_t track, bool simplifyTrackIds = false);
 | 
					  std::string trackHeader(const DTSC::Meta &M, size_t track, bool simplifyTrackIds = false);
 | 
				
			||||||
  size_t fragmentHeaderSize(const DTSC::Meta &M, size_t track, size_t fragment);
 | 
					  size_t fragmentHeaderSize(const DTSC::Meta &M, size_t track, size_t fragment);
 | 
				
			||||||
  std::string fragmentHeader(const DTSC::Meta &M, size_t track, size_t fragment, bool simplifyTrackIds = false, bool UTCTime = false);
 | 
					  std::string fragmentHeader(const DTSC::Meta &M, size_t track, size_t fragment, bool simplifyTrackIds = false, bool UTCTime = false);
 | 
				
			||||||
  size_t keyHeaderSize(const DTSC::Meta &M, size_t track, size_t key);
 | 
					  size_t keyHeaderSize(const DTSC::Meta &M, size_t track, uint64_t startTime, uint64_t endTime);
 | 
				
			||||||
  std::string keyHeader(const DTSC::Meta &M, size_t track, size_t key, bool simplifyTrackIds = false, bool UTCTime = false);
 | 
					  std::string keyHeader(const DTSC::Meta &M, size_t track, uint64_t startTime, uint64_t endTime, uint64_t segmentNum, bool simplifyTrackIds = false, bool UTCTime = false);
 | 
				
			||||||
}// namespace CMAF
 | 
					}// namespace CMAF
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								lib/dtsc.cpp
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/dtsc.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -2890,27 +2890,27 @@ namespace DTSC{
 | 
				
			||||||
    return keys.getTime(fragments.getFirstKey(fragmentIdx));
 | 
					    return keys.getTime(fragments.getFirstKey(fragmentIdx));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Returns the part index for the given DTSC::Packet by timestamp.
 | 
					  /// Returns the part index for the given timestamp.
 | 
				
			||||||
  /// Assumes the Packet is for the given track, and assumes the metadata and track data are not out
 | 
					  /// Assumes the Packet is for the given track, and assumes the metadata and track data are not out
 | 
				
			||||||
  /// of sync. Works by looking up the key for the Packet's timestamp, then walking through the
 | 
					  /// of sync. Works by looking up the key for the Packet's timestamp, then walking through the
 | 
				
			||||||
  /// parts until the time matches or exceeds the time of the Packet. Returns zero if the track
 | 
					  /// parts until the time matches or exceeds the time of the Packet. Returns zero if the track
 | 
				
			||||||
  /// index is invalid or if the timestamp cannot be found.
 | 
					  /// index is invalid or if the timestamp cannot be found.
 | 
				
			||||||
  uint32_t Meta::getPartIndex(const DTSC::Packet &pack, size_t idx) const{
 | 
					  uint32_t Meta::getPartIndex(uint64_t timestamp, size_t idx) const{
 | 
				
			||||||
    if (idx == INVALID_TRACK_ID){return 0;}
 | 
					    if (idx == INVALID_TRACK_ID){return 0;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t res = 0;
 | 
					    uint32_t res = 0;
 | 
				
			||||||
    uint32_t keyIdx = getKeyIndexForTime(idx, pack.getTime());
 | 
					    uint32_t keyIdx = getKeyIndexForTime(idx, timestamp);
 | 
				
			||||||
    DTSC::Keys Keys(keys(idx));
 | 
					    DTSC::Keys Keys(keys(idx));
 | 
				
			||||||
    DTSC::Parts Parts(parts(idx));
 | 
					    DTSC::Parts Parts(parts(idx));
 | 
				
			||||||
    uint64_t currentTime = Keys.getTime(keyIdx);
 | 
					    uint64_t currentTime = Keys.getTime(keyIdx);
 | 
				
			||||||
    res = Keys.getFirstPart(keyIdx);
 | 
					    res = Keys.getFirstPart(keyIdx);
 | 
				
			||||||
    size_t endPart = res + Keys.getParts(keyIdx);
 | 
					    size_t endPart = Parts.getEndValid();
 | 
				
			||||||
    for (size_t i = res; i < endPart; i++){
 | 
					    for (size_t i = res; i < endPart; i++){
 | 
				
			||||||
      if (currentTime >= pack.getTime()){return res;}
 | 
					      if (currentTime >= timestamp){return res;}
 | 
				
			||||||
      currentTime += Parts.getDuration(i);
 | 
					      currentTime += Parts.getDuration(i);
 | 
				
			||||||
      res++;
 | 
					      res++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Given the current page, check if the next page is available. Returns true if it is.
 | 
					  /// Given the current page, check if the next page is available. Returns true if it is.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -426,7 +426,7 @@ namespace DTSC{
 | 
				
			||||||
    uint64_t getTimeForKeyIndex(uint32_t idx, uint32_t keyIdx) const;
 | 
					    uint64_t getTimeForKeyIndex(uint32_t idx, uint32_t keyIdx) const;
 | 
				
			||||||
    uint32_t getKeyIndexForTime(uint32_t idx, uint64_t timestamp) const;
 | 
					    uint32_t getKeyIndexForTime(uint32_t idx, uint64_t timestamp) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t getPartIndex(const DTSC::Packet &pack, size_t idx) const;
 | 
					    uint32_t getPartIndex(uint64_t timestamp, size_t idx) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool nextPageAvailable(uint32_t idx, size_t currentPage) const;
 | 
					    bool nextPageAvailable(uint32_t idx, size_t currentPage) const;
 | 
				
			||||||
    size_t getPageNumberForTime(uint32_t idx, uint64_t time) const;
 | 
					    size_t getPageNumberForTime(uint32_t idx, uint64_t time) const;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1262,11 +1262,11 @@ namespace Mist{
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              if (encryption.substr(0, encryption.find('/')) == "CTR128"){
 | 
					              if (encryption.substr(0, encryption.find('/')) == "CTR128"){
 | 
				
			||||||
                DTSC::Packet encPacket = aesCipher.encryptPacketCTR(
 | 
					                DTSC::Packet encPacket = aesCipher.encryptPacketCTR(
 | 
				
			||||||
                    M, thisPacket, M.getIvec(idx) + M.getPartIndex(thisPacket, idx), idx);
 | 
					                    M, thisPacket, M.getIvec(idx) + M.getPartIndex(thisPacket.getTime(), idx), idx);
 | 
				
			||||||
                thisPacket = encPacket;
 | 
					                thisPacket = encPacket;
 | 
				
			||||||
              }else if (encryption.substr(0, encryption.find('/')) == "CBC128"){
 | 
					              }else if (encryption.substr(0, encryption.find('/')) == "CBC128"){
 | 
				
			||||||
                char ivec[] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 | 
					                char ivec[] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 | 
				
			||||||
                Bit::htobll(ivec + 8, M.getIvec(idx) + M.getPartIndex(thisPacket, idx));
 | 
					                Bit::htobll(ivec + 8, M.getIvec(idx) + M.getPartIndex(thisPacket.getTime(), idx));
 | 
				
			||||||
                DTSC::Packet encPacket = aesCipher.encryptPacketCBC(M, thisPacket, ivec, idx);
 | 
					                DTSC::Packet encPacket = aesCipher.encryptPacketCBC(M, thisPacket, ivec, idx);
 | 
				
			||||||
                thisPacket = encPacket;
 | 
					                thisPacket = encPacket;
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -725,7 +725,7 @@ namespace Mist{
 | 
				
			||||||
    if (tmpPack){
 | 
					    if (tmpPack){
 | 
				
			||||||
      HIGH_MSG("Sought to time %" PRIu64 " (yields a packet at %" PRIu64 "ms) in %s@%zu", tmp.time,
 | 
					      HIGH_MSG("Sought to time %" PRIu64 " (yields a packet at %" PRIu64 "ms) in %s@%zu", tmp.time,
 | 
				
			||||||
               tmpPack.getTime(), streamName.c_str(), tid);
 | 
					               tmpPack.getTime(), streamName.c_str(), tid);
 | 
				
			||||||
      tmp.partIndex = M.getPartIndex(tmpPack, tmp.tid);
 | 
					      tmp.partIndex = M.getPartIndex(tmpPack.getTime(), tmp.tid);
 | 
				
			||||||
      buffer.insert(tmp);
 | 
					      buffer.insert(tmp);
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -237,7 +237,7 @@ namespace Mist{
 | 
				
			||||||
    std::string headerData = CMAF::fragmentHeader(M, idx, fragmentIndex, false, false);
 | 
					    std::string headerData = CMAF::fragmentHeader(M, idx, fragmentIndex, false, false);
 | 
				
			||||||
    H.Chunkify(headerData.c_str(), headerData.size(), myConn);
 | 
					    H.Chunkify(headerData.c_str(), headerData.size(), myConn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint64_t mdatSize = 8 + CMAF::payloadSize(M, idx, fragmentIndex);
 | 
					    uint64_t mdatSize = 8 + CMAF::payloadSize(M, idx, targetTime, M.getTimeForFragmentIndex(idx, fragmentIndex+1));
 | 
				
			||||||
    char mdatHeader[] ={0x00, 0x00, 0x00, 0x00, 'm', 'd', 'a', 't'};
 | 
					    char mdatHeader[] ={0x00, 0x00, 0x00, 0x00, 'm', 'd', 'a', 't'};
 | 
				
			||||||
    Bit::htobl(mdatHeader, mdatSize);
 | 
					    Bit::htobl(mdatHeader, mdatSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -777,7 +777,6 @@ namespace Mist{
 | 
				
			||||||
    if (!pushTracks.count(idx) || !pushTracks.at(idx).D.getSocket()){return;}
 | 
					    if (!pushTracks.count(idx) || !pushTracks.at(idx).D.getSocket()){return;}
 | 
				
			||||||
    INFO_MSG("Disconnecting track %zu", idx);
 | 
					    INFO_MSG("Disconnecting track %zu", idx);
 | 
				
			||||||
    pushTracks[idx].disconnect(); 
 | 
					    pushTracks[idx].disconnect(); 
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    pushTracks.erase(idx);
 | 
					    pushTracks.erase(idx);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
| 
						 | 
					@ -803,11 +802,13 @@ namespace Mist{
 | 
				
			||||||
  /// Function that waits at most `maxWait` ms (in steps of 100ms) for the next keyframe to become available.
 | 
					  /// Function that waits at most `maxWait` ms (in steps of 100ms) for the next keyframe to become available.
 | 
				
			||||||
  /// Uses thisIdx and thisPacket to determine track and current timestamp respectively.
 | 
					  /// Uses thisIdx and thisPacket to determine track and current timestamp respectively.
 | 
				
			||||||
  bool OutCMAF::waitForNextKey(uint64_t maxWait){
 | 
					  bool OutCMAF::waitForNextKey(uint64_t maxWait){
 | 
				
			||||||
    size_t currentKey = M.getKeyIndexForTime(thisIdx, thisPacket.getTime());
 | 
					    size_t currentKey = M.getKeyIndexForTime(getMainSelectedTrack(), thisPacket.getTime());
 | 
				
			||||||
    DTSC::Keys keys(M.keys(thisIdx));
 | 
					    DTSC::Keys keys(M.keys(getMainSelectedTrack()));
 | 
				
			||||||
    size_t waitTimes = maxWait / 100; 
 | 
					    size_t waitTimes = maxWait / 100; 
 | 
				
			||||||
    for (size_t i = 0; i < waitTimes; ++i){
 | 
					    for (size_t i = 0; i < waitTimes; ++i){
 | 
				
			||||||
      if (keys.getEndValid() > currentKey + 1){return true;}
 | 
					      if (keys.getEndValid() > currentKey + 1 && M.getLastms(thisIdx) > M.getTimeForKeyIndex(getMainSelectedTrack(), currentKey+1)){
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      Util::wait(100);
 | 
					      Util::wait(100);
 | 
				
			||||||
      //Make sure we don't accidentally timeout while waiting - runs approximately every second.
 | 
					      //Make sure we don't accidentally timeout while waiting - runs approximately every second.
 | 
				
			||||||
      if (i % 10 == 0){
 | 
					      if (i % 10 == 0){
 | 
				
			||||||
| 
						 | 
					@ -817,7 +818,7 @@ namespace Mist{
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return (keys.getEndValid() > currentKey + 1);
 | 
					    return (keys.getEndValid() > currentKey + 1 && M.getLastms(thisIdx) > M.getTimeForKeyIndex(getMainSelectedTrack(), currentKey+1));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //Set up an empty connection to the target to make sure we can push data towards it.
 | 
					  //Set up an empty connection to the target to make sure we can push data towards it.
 | 
				
			||||||
| 
						 | 
					@ -833,14 +834,15 @@ namespace Mist{
 | 
				
			||||||
  void OutCMAF::pushNext() {
 | 
					  void OutCMAF::pushNext() {
 | 
				
			||||||
    //Set up a new connection if this is a new track, or if we have been disconnected.
 | 
					    //Set up a new connection if this is a new track, or if we have been disconnected.
 | 
				
			||||||
    if (!pushTracks.count(thisIdx) || !pushTracks.at(thisIdx).D.getSocket()){
 | 
					    if (!pushTracks.count(thisIdx) || !pushTracks.at(thisIdx).D.getSocket()){
 | 
				
			||||||
 | 
					      if (pushTracks.count(thisIdx)){INFO_MSG("Reconnecting existing track: socket was disconnected");}
 | 
				
			||||||
      CMAFPushTrack & track = pushTracks[thisIdx];
 | 
					      CMAFPushTrack & track = pushTracks[thisIdx];
 | 
				
			||||||
      size_t keyIndex = M.getKeyIndexForTime(thisIdx, thisPacket.getTime());
 | 
					      size_t keyIndex = M.getKeyIndexForTime(getMainSelectedTrack(), thisPacket.getTime());
 | 
				
			||||||
      track.headerFrom = M.getTimeForKeyIndex(thisIdx, keyIndex);
 | 
					      track.headerFrom = M.getTimeForKeyIndex(getMainSelectedTrack(), keyIndex);
 | 
				
			||||||
      if (track.headerFrom < thisPacket.getTime()){
 | 
					      if (track.headerFrom < thisPacket.getTime()){
 | 
				
			||||||
        track.headerFrom = M.getTimeForKeyIndex(thisIdx, keyIndex + 1);
 | 
					        track.headerFrom = M.getTimeForKeyIndex(getMainSelectedTrack(), keyIndex + 1);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      HIGH_MSG("Starting track %zu at %" PRIu64 "ms into the stream, current packet at %" PRIu64 "ms", thisIdx, track.headerFrom, thisPacket.getTime());
 | 
					      INFO_MSG("Starting track %zu at %" PRIu64 "ms into the stream, current packet at %" PRIu64 "ms", thisIdx, track.headerFrom, thisPacket.getTime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      setupTrackObject(thisIdx);
 | 
					      setupTrackObject(thisIdx);
 | 
				
			||||||
      track.headerUntil = 0;
 | 
					      track.headerUntil = 0;
 | 
				
			||||||
| 
						 | 
					@ -848,13 +850,13 @@ namespace Mist{
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    CMAFPushTrack & track = pushTracks[thisIdx];
 | 
					    CMAFPushTrack & track = pushTracks[thisIdx];
 | 
				
			||||||
    if (thisPacket.getTime() < track.headerFrom){return;}
 | 
					    if (thisPacket.getTime() < track.headerFrom){return;}
 | 
				
			||||||
    if (thisPacket.getTime() > track.headerUntil || !track.headerUntil){
 | 
					    if (thisPacket.getTime() >= track.headerUntil){
 | 
				
			||||||
      size_t keyIndex = M.getKeyIndexForTime(thisIdx, thisPacket.getTime());
 | 
					      size_t keyIndex = M.getKeyIndexForTime(getMainSelectedTrack(), thisPacket.getTime());
 | 
				
			||||||
      uint64_t keyTime = M.getTimeForKeyIndex(thisIdx, keyIndex);
 | 
					      uint64_t keyTime = M.getTimeForKeyIndex(getMainSelectedTrack(), keyIndex);
 | 
				
			||||||
      if (keyTime != thisPacket.getTime()){
 | 
					      if (keyTime > thisPacket.getTime()){
 | 
				
			||||||
        WARN_MSG("Corruption probably occured, initiating reconnect %" PRIu64 " != %" PRIu64, keyTime, thisPacket.getTime());
 | 
					        WARN_MSG("Corruption probably occurred, initiating reconnect %" PRIu64 " != %" PRIu64, keyTime, thisPacket.getTime());
 | 
				
			||||||
        onTrackEnd(thisIdx);
 | 
					        onTrackEnd(thisIdx);
 | 
				
			||||||
        track.headerFrom = M.getTimeForKeyIndex(thisIdx, keyIndex + 1);
 | 
					        track.headerFrom = M.getTimeForKeyIndex(getMainSelectedTrack(), keyIndex + 1);
 | 
				
			||||||
        track.headerUntil = 0;
 | 
					        track.headerUntil = 0;
 | 
				
			||||||
        pushNext();
 | 
					        pushNext();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
| 
						 | 
					@ -865,10 +867,9 @@ namespace Mist{
 | 
				
			||||||
        dropTrack(thisIdx, "No next keyframe available");
 | 
					        dropTrack(thisIdx, "No next keyframe available");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      track.headerUntil = M.getTimeForKeyIndex(thisIdx, keyIndex + 1) - 1;
 | 
					      track.headerUntil = M.getTimeForKeyIndex(getMainSelectedTrack(), keyIndex + 1);
 | 
				
			||||||
      std::string keyHeader = CMAF::keyHeader(M, thisIdx, keyIndex, true, true);
 | 
					      std::string keyHeader = CMAF::keyHeader(M, thisIdx, track.headerFrom, track.headerUntil, keyIndex+1, true, true);
 | 
				
			||||||
 | 
					      uint64_t mdatSize = 8 + CMAF::payloadSize(M, thisIdx, track.headerFrom, track.headerUntil);
 | 
				
			||||||
      uint64_t mdatSize = 8 + CMAF::payloadSize(M, thisIdx, keyIndex, true);
 | 
					 | 
				
			||||||
      char mdatHeader[] ={0x00, 0x00, 0x00, 0x00, 'm', 'd', 'a', 't'};
 | 
					      char mdatHeader[] ={0x00, 0x00, 0x00, 0x00, 'm', 'd', 'a', 't'};
 | 
				
			||||||
      Bit::htobl(mdatHeader, mdatSize);
 | 
					      Bit::htobl(mdatHeader, mdatSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue