Track selector and language code support backported from Pro edition
This commit is contained in:
		
							parent
							
								
									58919a9346
								
							
						
					
					
						commit
						320c8ab29f
					
				
					 5 changed files with 792 additions and 2 deletions
				
			
		|  | @ -12,6 +12,7 @@ | |||
| #include <mist/http_parser.h> | ||||
| #include <mist/timing.h> | ||||
| #include <mist/util.h> | ||||
| #include <mist/langcodes.h> | ||||
| #include "output.h" | ||||
| 
 | ||||
| namespace Mist{ | ||||
|  | @ -267,6 +268,63 @@ namespace Mist{ | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Selects a specific track or set of tracks of the given trackType, using trackVal to decide.
 | ||||
|   /// trackVal may be a comma-separated list of numbers, codecs or the word "all"/"none" or an asterisk.
 | ||||
|   /// Does not do any checks if the protocol supports these tracks, just selects blindly.
 | ||||
|   void Output::selectTrack(const std::string &trackType, const std::string &trackVal){ | ||||
|     if (!trackVal.size() || trackVal == "0" || trackVal == "none"){return;}//don't select anything in particular
 | ||||
|     if (trackVal.find(',') != std::string::npos){ | ||||
|       //Comma-separated list, recurse.
 | ||||
|       std::stringstream ss(trackVal); | ||||
|       std::string item; | ||||
|       while (std::getline(ss, item, ',')){selectTrack(trackType, item);} | ||||
|       return; | ||||
|     } | ||||
|     uint64_t trackNo = JSON::Value(trackVal).asInt(); | ||||
|     if (trackVal == JSON::Value(trackNo).asString()){ | ||||
|       //It's an integer number
 | ||||
|       if (!myMeta.tracks.count(trackNo)){ | ||||
|         INFO_MSG("Track %lld does not exist in stream, cannot select", trackNo); | ||||
|         return; | ||||
|       } | ||||
|       const DTSC::Track & Trk = myMeta.tracks[trackNo]; | ||||
|       if (Trk.type != trackType && Trk.codec != trackType){ | ||||
|         INFO_MSG("Track %lld is not %s (%s/%s), cannot select", trackNo, trackType.c_str(), Trk.type.c_str(), Trk.codec.c_str()); | ||||
|         return; | ||||
|       } | ||||
|       INFO_MSG("Selecting %s track %lld (%s/%s)", trackType.c_str(), trackNo, Trk.type.c_str(), Trk.codec.c_str()); | ||||
|       selectedTracks.insert(trackNo); | ||||
|       return; | ||||
|     } | ||||
|     std::string trackLow = trackVal; | ||||
|     Util::stringToLower(trackLow); | ||||
|     if (trackLow == "all" || trackLow == "*"){ | ||||
|       //select all tracks of this type
 | ||||
|       for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|         const DTSC::Track & Trk = it->second; | ||||
|         if (Trk.type == trackType || Trk.codec == trackType){ | ||||
|           selectedTracks.insert(it->first); | ||||
|           INFO_MSG("Selecting %s track %lu (%s/%s)", trackType.c_str(), it->first, Trk.type.c_str(), Trk.codec.c_str()); | ||||
|         } | ||||
|       } | ||||
|       return; | ||||
|     } | ||||
|     //attempt to do language/codec matching
 | ||||
|     //convert 2-character language codes into 3-character language codes
 | ||||
|     if (trackLow.size() == 2){trackLow = Encodings::ISO639::twoToThree(trackLow);} | ||||
|     for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){ | ||||
|       const DTSC::Track & Trk = it->second; | ||||
|       if (Trk.type == trackType || Trk.codec == trackType){ | ||||
|         std::string codecLow = Trk.codec; | ||||
|         Util::stringToLower(codecLow); | ||||
|         if (Trk.lang == trackLow || trackLow == codecLow){ | ||||
|           selectedTracks.insert(it->first); | ||||
|           INFO_MSG("Selecting %s track %lu (%s/%s)", trackType.c_str(), it->first, Trk.type.c_str(), Trk.codec.c_str()); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Automatically selects the tracks that are possible and/or wanted.
 | ||||
|   /// Returns true if the track selection changed in any way.
 | ||||
|   bool Output::selectDefaultTracks(){ | ||||
|  | @ -282,6 +340,21 @@ namespace Mist{ | |||
|     bool autoSeek = buffer.size(); | ||||
|     uint64_t seekTarget = currentTime(); | ||||
| 
 | ||||
|     bool noSelAudio = false, noSelVideo = false, noSelSub = false; | ||||
|     //Then, select the tracks we've been asked to select.
 | ||||
|     if (targetParams.count("audio") && targetParams["audio"].size()){ | ||||
|       selectTrack("audio", targetParams["audio"]); | ||||
|       noSelAudio = true; | ||||
|     } | ||||
|     if (targetParams.count("video") && targetParams["video"].size()){ | ||||
|       selectTrack("video", targetParams["video"]); | ||||
|       noSelVideo = true; | ||||
|     } | ||||
|     if (targetParams.count("subtitle") && targetParams["subtitle"].size()){ | ||||
|       selectTrack("subtitle", targetParams["subtitle"]); | ||||
|       noSelSub = true; | ||||
|     } | ||||
|      | ||||
|     //check which tracks don't actually exist
 | ||||
|     std::set<unsigned long> toRemove; | ||||
|     for (std::set<unsigned long>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ | ||||
|  | @ -383,6 +456,9 @@ namespace Mist{ | |||
|                 for (std::map<unsigned int, DTSC::Track>::reverse_iterator trit = myMeta.tracks.rbegin(); trit != myMeta.tracks.rend(); trit++){ | ||||
|                   if ((!byType && trit->second.codec == strRef.substr(shift)) || (byType && trit->second.type == strRef.substr(shift)) || strRef.substr(shift) == "*"){ | ||||
|                     if (autoSeek && trit->second.lastms < std::max(seekTarget, (uint64_t)6000lu) - 6000){continue;} | ||||
|                     if (noSelAudio && trit->second.type == "audio"){continue;} | ||||
|                     if (noSelVideo && trit->second.type == "video"){continue;} | ||||
|                     if (noSelSub && (trit->second.type == "subtitle" || trit->second.codec == "subtitle")){continue;} | ||||
|                     //user-agent-check
 | ||||
|                     bool problems = false; | ||||
|                     if (capa.isMember("exceptions") && capa["exceptions"].isObject() && capa["exceptions"].size()){ | ||||
|  | @ -403,6 +479,9 @@ namespace Mist{ | |||
|                 for (std::map<unsigned int, DTSC::Track>::iterator trit = myMeta.tracks.begin(); trit != myMeta.tracks.end(); trit++){ | ||||
|                   if ((!byType && trit->second.codec == strRef.substr(shift)) || (byType && trit->second.type == strRef.substr(shift)) || strRef.substr(shift) == "*"){ | ||||
|                     if (autoSeek && trit->second.lastms < std::max(seekTarget, (uint64_t)6000lu) - 6000){continue;} | ||||
|                     if (noSelAudio && trit->second.type == "audio"){continue;} | ||||
|                     if (noSelVideo && trit->second.type == "video"){continue;} | ||||
|                     if (noSelSub && (trit->second.type == "subtitle" || trit->second.codec == "subtitle")){continue;} | ||||
|                     //user-agent-check
 | ||||
|                     bool problems = false; | ||||
|                     if (capa.isMember("exceptions") && capa["exceptions"].isObject() && capa["exceptions"].size()){ | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ namespace Mist { | |||
|       uint64_t liveTime(); | ||||
|       void setBlocking(bool blocking); | ||||
|       void updateMeta(); | ||||
|       void selectTrack(const std::string &trackType, const std::string &trackVal); | ||||
|       bool selectDefaultTracks(); | ||||
|       bool connectToFile(std::string file); | ||||
|       static bool listenMode(){return true;} | ||||
|  | @ -88,6 +89,7 @@ namespace Mist { | |||
|       bool sought;///<If a seek has been done, this is set to true. Used for seeking on prepareNext().
 | ||||
|     protected://these are to be messed with by child classes
 | ||||
|       bool pushing; | ||||
|       std::map<std::string, std::string> targetParams; | ||||
|       std::string UA; ///< User Agent string, if known.
 | ||||
|       uint16_t uaDelay;///<Seconds to wait before setting the UA.
 | ||||
|       uint64_t lastRecv; | ||||
|  |  | |||
|  | @ -234,6 +234,9 @@ namespace Mist { | |||
|         crc = checksum::crc32(0, mixed_ua.data(), mixed_ua.size()); | ||||
|       } | ||||
| 
 | ||||
|       if (H.GetVar("audio") != ""){targetParams["audio"] = H.GetVar("audio");} | ||||
|       if (H.GetVar("video") != ""){targetParams["video"] = H.GetVar("video");} | ||||
|       if (H.GetVar("subtitle") != ""){targetParams["subtitle"] = H.GetVar("subtitle");} | ||||
|       //Handle upgrade to websocket if the output supports it
 | ||||
|       if (doesWebsockets() && H.GetHeader("Upgrade") == "websocket"){ | ||||
|         INFO_MSG("Switching to Websocket mode"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Thulinma
						Thulinma