Fully implemented DTSC pull support
This commit is contained in:
		
							parent
							
								
									668560ff05
								
							
						
					
					
						commit
						dda0ea669c
					
				
					 27 changed files with 930 additions and 272 deletions
				
			
		|  | @ -278,6 +278,16 @@ namespace Mist { | |||
|       onFail(); | ||||
|       return; | ||||
|     } | ||||
|     if (!source.size()){ | ||||
|       std::string strName = streamName; | ||||
|       Util::sanitizeName(strName); | ||||
|       IPC::sharedPage serverCfg("!mistConfig", DEFAULT_CONF_PAGE_SIZE, false, false); ///< Contains server configuration and capabilities
 | ||||
|       IPC::semaphore configLock("!mistConfLock", O_CREAT | O_RDWR, ACCESSPERMS, 1); | ||||
|       configLock.wait(); | ||||
|       DTSC::Scan streamCfg = DTSC::Scan(serverCfg.mapped, serverCfg.len).getMember("streams").getMember(strName); | ||||
|       source = streamCfg.getMember("source").asString(); | ||||
|       configLock.post(); | ||||
|     } | ||||
|     char pageId[NAME_BUFFER_SIZE]; | ||||
|     snprintf(pageId, NAME_BUFFER_SIZE, SHM_STREAM_INDEX, streamName.c_str()); | ||||
|     nProxy.metaPages.clear(); | ||||
|  | @ -416,9 +426,20 @@ namespace Mist { | |||
|     // when we don't see this explicitly it makes debugging the recording feature
 | ||||
|     // a bit painfull :) 
 | ||||
|     if (selectedTracks.size() == 0) { | ||||
|       WARN_MSG("We didn't find any tracks which that we can use. selectedTrack.size() is 0."); | ||||
|       INSANE_MSG("We didn't find any tracks which that we can use. selectedTrack.size() is 0."); | ||||
|       for (std::map<unsigned int,DTSC::Track>::iterator trit = myMeta.tracks.begin(); trit != myMeta.tracks.end(); trit++){ | ||||
|         WARN_MSG("Found track/codec: %s", trit->second.codec.c_str()); | ||||
|         INSANE_MSG("Found track/codec: %s", trit->second.codec.c_str()); | ||||
|       } | ||||
|       if (!myMeta.tracks.size() && (source.find("dtsc://") == 0)){ | ||||
|         //Wait 5 seconds and try again. Keep a counter, try at most 3 times
 | ||||
|         static int counter = 0; | ||||
|         if (counter++ < 10){ | ||||
|           Util::wait(1000); | ||||
|           nProxy.userClient.keepAlive(); | ||||
|           stats(); | ||||
|           updateMeta(); | ||||
|           selectDefaultTracks(); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     /*end-roxlu*/ | ||||
|  | @ -898,6 +919,25 @@ namespace Mist { | |||
|         } | ||||
|         if ( !sentHeader){ | ||||
|           DEBUG_MSG(DLVL_DONTEVEN, "sendHeader"); | ||||
|           bool waitLonger = false; | ||||
|           if (!myMeta.tracks.size()){ | ||||
|             waitLonger = true; | ||||
|           }else{ | ||||
|             for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|               if (!it->second.keys.size()){ | ||||
|                 waitLonger = true; | ||||
|                 break; | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           if (waitLonger){ | ||||
|             updateMeta(); | ||||
|             Util::sleep(1000); | ||||
|             static unsigned int metaTries = 0; | ||||
|             if(++metaTries < 7){ | ||||
|               continue; | ||||
|             } | ||||
|           } | ||||
|           sendHeader(); | ||||
|         } | ||||
|         prepareNext(); | ||||
|  |  | |||
|  | @ -108,6 +108,7 @@ namespace Mist { | |||
|       bool sought;///<If a seek has been done, this is set to true. Used for seeking on prepareNext().
 | ||||
|       bool completeKeyReadyTimeOut;//a bool to see if there has been a keyframe TimeOut for complete keys in Live
 | ||||
|     protected://these are to be messed with by child classes
 | ||||
|       std::string source; | ||||
|        | ||||
|       virtual std::string getConnectedHost(); | ||||
|       virtual std::string getConnectedBinHost(); | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ namespace Mist { | |||
|     myConn.SendNow(sSize, 4); | ||||
|     prep.sendTo(myConn); | ||||
|     pushing = false; | ||||
|     fastAsPossibleTime = 0; | ||||
|   } | ||||
| 
 | ||||
|   OutDTSC::~OutDTSC() {} | ||||
|  | @ -44,12 +45,52 @@ namespace Mist { | |||
|   } | ||||
|    | ||||
|   void OutDTSC::sendNext(){ | ||||
|     if (!realTime && thisPacket.getTime() >= fastAsPossibleTime){ | ||||
|       realTime = 1000; | ||||
|     } | ||||
|     if (thisPacket.getFlag("keyframe")){ | ||||
|       std::set<unsigned long> availableTracks; | ||||
|       for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|         if (it->second.type == "video" || it->second.type == "audio"){ | ||||
|           availableTracks.insert(it->first); | ||||
|         } | ||||
|       } | ||||
|       if (availableTracks != selectedTracks){ | ||||
|         //reset, resendheader
 | ||||
|         JSON::Value prep; | ||||
|         prep["cmd"] = "reset"; | ||||
|         /// \todo Make this securererer.
 | ||||
|         unsigned long sendSize = prep.packedSize(); | ||||
|         myConn.SendNow("DTCM"); | ||||
|         char sSize[4] = {0, 0, 0, 0}; | ||||
|         Bit::htobl(sSize, prep.packedSize()); | ||||
|         myConn.SendNow(sSize, 4); | ||||
|         prep.sendTo(myConn); | ||||
|       } | ||||
|     } | ||||
|     myConn.SendNow(thisPacket.getData(), thisPacket.getDataLen()); | ||||
|   } | ||||
| 
 | ||||
|   void OutDTSC::sendHeader(){ | ||||
|     sentHeader = true; | ||||
|     myMeta.send(myConn, true); | ||||
|     selectedTracks.clear(); | ||||
|     for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|       if (it->second.type == "video" || it->second.type == "audio"){ | ||||
|         selectedTracks.insert(it->first); | ||||
|       } | ||||
|     } | ||||
|     myMeta.send(myConn, true, selectedTracks); | ||||
|     if (myMeta.live){ | ||||
|       for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|         if (!fastAsPossibleTime || it->second.lastms < fastAsPossibleTime){ | ||||
|           fastAsPossibleTime = it->second.lastms; | ||||
|           realTime = 0; | ||||
|         } | ||||
|       } | ||||
|     }else{ | ||||
|       fastAsPossibleTime = 50000;//50 seconds
 | ||||
|       realTime = 0; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void OutDTSC::onRequest(){ | ||||
|  | @ -76,6 +117,8 @@ namespace Mist { | |||
|     streamName = dScan.getMember("stream").asString(); | ||||
|     Util::sanitizeName(streamName); | ||||
|     parseData = true; | ||||
|     INFO_MSG("Handled play for stream %s", streamName.c_str()); | ||||
|     setBlocking(false); | ||||
|   } | ||||
| 
 | ||||
|   void OutDTSC::handlePush(DTSC::Scan & dScan){ | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ namespace Mist { | |||
|       bool pushing; | ||||
|       void handlePush(DTSC::Scan & dScan); | ||||
|       void handlePlay(DTSC::Scan & dScan); | ||||
|       unsigned long long fastAsPossibleTime; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,27 @@ namespace Mist { | |||
|   ///\brief Builds an index file for HTTP Live streaming.
 | ||||
|   ///\return The index file for HTTP Live Streaming.
 | ||||
|   std::string OutHLS::liveIndex() { | ||||
| 
 | ||||
|     static int timer = 0; | ||||
|     bool checkWait = true; | ||||
|     while (checkWait && ++timer < 10){ | ||||
|       checkWait = false; | ||||
|       if (!myMeta.tracks.size()){ | ||||
|         checkWait = true; | ||||
|       } | ||||
|       for (std::map<unsigned int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|         if (it->second.keys.size() <= 3){ | ||||
|           checkWait = true; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       if (checkWait){ | ||||
|         Util::sleep(500); | ||||
|         INFO_MSG("SLeeping timer %d", timer); | ||||
|         updateMeta(); | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     std::stringstream result; | ||||
|     result << "#EXTM3U\r\n"; | ||||
|     int audioId = -1; | ||||
|  |  | |||
|  | @ -43,6 +43,9 @@ namespace Mist { | |||
| 
 | ||||
|   ///\todo This function does not indicate errors anywhere... maybe fix this...
 | ||||
|   std::string OutProgressiveMP4::DTSCMeta2MP4Header(long long & size, int fragmented) { | ||||
|     if (myMeta.live){ | ||||
|       completeKeysOnly = true; | ||||
|     } | ||||
|     //Make sure we have a proper being value for the size...
 | ||||
|     size = 0; | ||||
|     //Stores the result of the function
 | ||||
|  | @ -745,6 +748,28 @@ namespace Mist { | |||
| 
 | ||||
|   void OutProgressiveMP4::setvidTrack() { | ||||
|     vidTrack = 0; | ||||
|     static int timer = 0; | ||||
|     bool checkWait = true; | ||||
|     while (checkWait && ++timer < 10){ | ||||
|       checkWait = false; | ||||
|       if (!myMeta.tracks.size()){ | ||||
|         checkWait = true; | ||||
|       } | ||||
|       for (std::map<unsigned int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|         if (!it->second.keys.size()){ | ||||
|           checkWait = true; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       if (checkWait){ | ||||
|         Util::sleep(500); | ||||
|         updateMeta(); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (!selectedTracks.size()){ | ||||
|       selectDefaultTracks(); | ||||
|     } | ||||
|     for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++) { | ||||
|       //Find video track
 | ||||
|       if (myMeta.tracks[*it].type == "video") { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Erik Zandvliet
						Erik Zandvliet