Backport of 3.0 stream selectors
This commit is contained in:
		
							parent
							
								
									6993133e62
								
							
						
					
					
						commit
						a2e2ddae1e
					
				
					 4 changed files with 611 additions and 202 deletions
				
			
		|  | @ -505,207 +505,31 @@ namespace Mist{ | |||
|       if (!isInitialized){return false;} | ||||
|     } | ||||
| 
 | ||||
|     //First, back up and wipe the existing selections, if any.
 | ||||
|     std::set<unsigned long> oldSel = selectedTracks; | ||||
|     selectedTracks.clear(); | ||||
| 
 | ||||
|     bool autoSeek = buffer.size(); | ||||
|     uint64_t seekTarget = currentTime(); | ||||
|     std::set<size_t> newSelects = Util::wouldSelect(myMeta, targetParams, capa, UA, autoSeek?seekTarget:0); | ||||
| 
 | ||||
|     /*LTS-START*/ | ||||
|     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; | ||||
|     } | ||||
|     /*LTS-END*/ | ||||
| 
 | ||||
|     //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++){ | ||||
|       if (!myMeta.tracks.count(*it)){ | ||||
|         toRemove.insert(*it); | ||||
|         continue; | ||||
|       } | ||||
|       //autoSeeking and target not in bounds? Drop it too.
 | ||||
|       if (autoSeek && myMeta.tracks[*it].lastms < std::max(seekTarget, (uint64_t)6000lu) - 6000){ | ||||
|         toRemove.insert(*it); | ||||
|       } | ||||
|     } | ||||
|     //remove those from selectedtracks
 | ||||
|     for (std::set<unsigned long>::iterator it = toRemove.begin(); it != toRemove.end(); it++){ | ||||
|       selectedTracks.erase(*it); | ||||
|     } | ||||
|      | ||||
|     //loop through all codec combinations, count max simultaneous active
 | ||||
|     unsigned int bestSoFar = 0; | ||||
|     unsigned int bestSoFarCount = 0; | ||||
|     unsigned int index = 0; | ||||
|     jsonForEach(capa["codecs"], it){ | ||||
|       unsigned int selCounter = 0; | ||||
|       if ((*it).size() > 0){ | ||||
|         jsonForEach((*it), itb){ | ||||
|           if ((*itb).size() > 0){ | ||||
|             jsonForEach(*itb, itc){ | ||||
|               const std::string & strRef = (*itc).asStringRef(); | ||||
|               bool byType = false; | ||||
|               bool multiSel = false; | ||||
|               uint8_t shift = 0; | ||||
|               if (strRef[shift] == '@'){byType = true; ++shift;} | ||||
|               if (strRef[shift] == '+'){multiSel = true; ++shift;} | ||||
|               for (std::set<unsigned long>::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){ | ||||
|                 if ((!byType && myMeta.tracks[*itd].codec == strRef.substr(shift)) || (byType && myMeta.tracks[*itd].type == strRef.substr(shift)) || strRef.substr(shift) == "*"){ | ||||
|                   //user-agent-check
 | ||||
|                   bool problems = false; | ||||
|                   if (capa.isMember("exceptions") && capa["exceptions"].isObject() && capa["exceptions"].size()){ | ||||
|                     jsonForEach(capa["exceptions"], ex){ | ||||
|                       if (ex.key() == "codec:"+strRef.substr(shift)){ | ||||
|                         problems = !Util::checkException(*ex, UA); | ||||
|                         break; | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                   if (problems){break;} | ||||
|                   selCounter++; | ||||
|                   if (!multiSel){ | ||||
|                     break; | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         if (selCounter == selectedTracks.size()){ | ||||
|           if (selCounter > bestSoFarCount){ | ||||
|             bestSoFarCount = selCounter; | ||||
|             bestSoFar = index; | ||||
|             HIGH_MSG("Matched %u: %s", selCounter, (*it).toString().c_str()); | ||||
|           } | ||||
|         }else{ | ||||
|           VERYHIGH_MSG("Not a match for currently selected tracks: %s", (*it).toString().c_str()); | ||||
|         } | ||||
|       } | ||||
|       index++; | ||||
|     } | ||||
|      | ||||
|     MEDIUM_MSG("Trying to fill: %s", capa["codecs"][bestSoFar].toString().c_str()); | ||||
|     //try to fill as many codecs simultaneously as possible
 | ||||
|     if (capa["codecs"][bestSoFar].size() > 0){ | ||||
|       jsonForEach(capa["codecs"][bestSoFar], itb){ | ||||
|         if ((*itb).size() && myMeta.tracks.size()){ | ||||
|           bool found = false; | ||||
|           bool multiFind = false; | ||||
|           jsonForEach((*itb), itc){ | ||||
|             const std::string & strRef = (*itc).asStringRef(); | ||||
|             bool byType = false; | ||||
|             uint8_t shift = 0; | ||||
|             if (strRef[shift] == '@'){byType = true; ++shift;} | ||||
|             if (strRef[shift] == '+'){multiFind = true; ++shift;} | ||||
|             for (std::set<unsigned long>::iterator itd = selectedTracks.begin(); itd != selectedTracks.end(); itd++){ | ||||
|               if ((!byType && myMeta.tracks[*itd].codec == strRef.substr(shift)) || (byType && myMeta.tracks[*itd].type == strRef.substr(shift)) || strRef.substr(shift) == "*"){ | ||||
|                 found = true; | ||||
|                 break; | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           if (!found || multiFind){ | ||||
|             jsonForEach((*itb), itc){ | ||||
|               const std::string & strRef = (*itc).asStringRef(); | ||||
|               bool byType = false; | ||||
|               bool multiSel = false; | ||||
|               uint8_t shift = 0; | ||||
|               if (strRef[shift] == '@'){byType = true; ++shift;} | ||||
|               if (strRef[shift] == '+'){multiSel = true; ++shift;} | ||||
|               if (found && !multiSel){continue;} | ||||
|               if (myMeta.live){ | ||||
|                 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;} | ||||
|                     /*LTS-START*/ | ||||
|                     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;} | ||||
|                     /*LTS-END*/ | ||||
|                     //user-agent-check
 | ||||
|                     bool problems = false; | ||||
|                     if (capa.isMember("exceptions") && capa["exceptions"].isObject() && capa["exceptions"].size()){ | ||||
|                       jsonForEach(capa["exceptions"], ex){ | ||||
|                         if (ex.key() == "codec:"+strRef.substr(shift)){ | ||||
|                           problems = !Util::checkException(*ex, UA); | ||||
|                           break; | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                     if (problems){continue;} | ||||
|                     selectedTracks.insert(trit->first); | ||||
|                     found = true; | ||||
|                     if (!multiSel){break;} | ||||
|                   } | ||||
|                 } | ||||
|               }else{ | ||||
|                 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;} | ||||
|                     /*LTS-START*/ | ||||
|                     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;} | ||||
|                     /*LTS-END*/ | ||||
|                     //user-agent-check
 | ||||
|                     bool problems = false; | ||||
|                     if (capa.isMember("exceptions") && capa["exceptions"].isObject() && capa["exceptions"].size()){ | ||||
|                       jsonForEach(capa["exceptions"], ex){ | ||||
|                         if (ex.key() == "codec:"+strRef.substr(shift)){ | ||||
|                           problems = !Util::checkException(*ex, UA); | ||||
|                           break; | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                     if (problems){continue;} | ||||
|                     selectedTracks.insert(trit->first); | ||||
|                     found = true; | ||||
|                     if (!multiSel){break;} | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     std::set<size_t> oldSel; | ||||
|     for (std::set<unsigned long>::iterator selIt = selectedTracks.begin(); selIt != selectedTracks.end(); ++selIt){ | ||||
|       oldSel.insert(*selIt); | ||||
|     } | ||||
| 
 | ||||
|     if (Util::Config::printDebugLevel >= DLVL_MEDIUM){ | ||||
|       //print the selected tracks
 | ||||
|       std::stringstream selected; | ||||
|       if (selectedTracks.size()){ | ||||
|         for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ | ||||
|           if (it != selectedTracks.begin()){ | ||||
|             selected << ", "; | ||||
|           } | ||||
|           selected << (*it); | ||||
|         } | ||||
|       } | ||||
|       MEDIUM_MSG("Selected tracks: %s (%lu)", selected.str().c_str(), selectedTracks.size());     | ||||
|     if (oldSel == newSelects){ | ||||
|       //No new selections? Do nothing, return no change.
 | ||||
|       return false; | ||||
|     } | ||||
|      | ||||
|     if (!selectedTracks.size() && myMeta.tracks.size() && capa["codecs"][bestSoFar].size()){ | ||||
|       WARN_MSG("No tracks selected (%u total) for stream %s!", myMeta.tracks.size(), streamName.c_str()); | ||||
| 
 | ||||
|     //We changed the selection! Change to the new selection.
 | ||||
|     selectedTracks.clear(); | ||||
|     for (std::set<size_t>::iterator reselIt = newSelects.begin(); reselIt != newSelects.end(); ++reselIt){ | ||||
|       selectedTracks.insert(*reselIt); | ||||
|     } | ||||
|     bool madeChange = (oldSel != selectedTracks); | ||||
|     if (autoSeek && madeChange){ | ||||
| 
 | ||||
|     if (autoSeek){ | ||||
|       INFO_MSG("Automatically seeking to position %llu to resume playback", seekTarget); | ||||
|       seek(seekTarget); | ||||
|     } | ||||
|     return madeChange; | ||||
|     return true; | ||||
|   } | ||||
|    | ||||
|   /// Clears the buffer, sets parseData to false, and generally makes not very much happen at all.
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Thulinma
						Thulinma