function processAndSendMPD($OriginalMPD, $PatchedMPD, $DASHContent, $offsetToNow) { $micro_date = microtime(); $date_array = explode(" ", $micro_date); $date_array[0] = round($date_array[0], 4); $date = date("Y-m-d H:i:s", $date_array[1]); //file_put_contents ( "timelog.txt" , "Tuned in:" . $date . $date_array[0] . " \r\n" , FILE_APPEND ); $AST_SEC = new DateTime('now', new DateTimeZone('UTC')); /* initializer for availability start time */ $AST_SEC->setTimestamp($date_array[1]); //Better use a single time than now above //$AST_SEC->add(new DateInterval('PT1S')); $AST_SEC_W3C = $AST_SEC->format(DATE_W3C); preg_match('/\\.\\d*/', $date_array[0], $dateFracPart); $extension_pos = strrpos($AST_SEC_W3C, '+'); // find position of the last + in W3C date to slip frac seconds $AST_W3C = substr($AST_SEC_W3C, 0, $extension_pos) . $dateFracPart[0] . "Z"; //substr($AST_SEC_W3C, $extension_pos); //file_put_contents ( "timelog.txt" , "Setting AST: " . $AST_W3C . " \r\n" , FILE_APPEND ); $ASTO_SEC = new DateTime('now', new DateTimeZone('UTC')); /* initializer for availability start time */ $ASTO_SEC->setTimestamp($date_array[1] - $offsetToNow); //Better use a single time than now above $ASTO_SEC_W3C = $ASTO_SEC->format(DATE_W3C); $extension_pos = strrpos($ASTO_SEC_W3C, '+'); // find position of the last + in W3C date to slip frac seconds $ASTO_W3C = substr($ASTO_SEC_W3C, 0, $extension_pos) . $dateFracPart[0] . "Z"; //substr($AST_SEC_W3C, $extension_pos); $MPD = simplexml_load_file($DASHContent . "/" . $OriginalMPD); if (!$MPD) { die("Failed loading XML file"); } $dom_sxe = dom_import_simplexml($MPD); if (!$dom_sxe) { echo 'Error while converting XML'; exit; } $dom = new DOMDocument('1.0'); $dom_sxe = $dom->importNode($dom_sxe, true); $dom_sxe = $dom->appendChild($dom_sxe); $periods = parseMPD($dom->documentElement); $cumulativeUpdatedDuration = 0; //Cumulation of period duration on updated MPD $tuneInPeriodStart = 0; $MPDNode =& $periods[0]['node']->parentNode; $MPD_AST = $MPDNode->getAttribute("availabilityStartTime"); $MPD_AST = $ASTO_W3C; //$MPDNode->getAttribute("availabilityStartTime"); preg_match('/\\.\\d*/', $MPD_AST, $matches); $fracAST = "0" . $matches[0]; $originalAST = new DateTime($MPD_AST); $deltaTimeASTTuneIn = $AST_SEC->getTimestamp() + round($date_array[0], 4) - ($originalAST->getTimestamp() + $fracAST); //Time elapsed between the original AST and Tune-in time //file_put_contents ( "timelog.txt" , "TimeOffset: " . $deltaTimeASTTuneIn . ", Original ts:" . ($originalAST->getTimestamp() + $fracAST) . "Tune-in TS: " . ($AST_SEC->getTimestamp() + round($date_array[0],4)) . "\r\n" , FILE_APPEND ); $MPDNode->setAttribute("availabilityStartTime", $AST_W3C); //Set AST to tune-in time $periodStart; //Start of this period in the iteration $duration; //Duration of current period in the iteration $lastPeriodStart; //Period start of the last period in the iteration $lastPeriodDuration; //Period duration of the last period in iteration $responseToSend[1] = count($periods) - 1; for ($periodIndex = 0; $periodIndex < count($periods); $periodIndex++) { $periodStart = $periods[$periodIndex]['node']->getAttribute("start"); $duration = somehowPleaseGetDurationInFractionalSecondsBecuasePHPHasABug($periods[$periodIndex]['node']->getAttribute("duration")); if ($periodStart === '') { $periodStart = $lastPeriodStart + $lastPeriodDuration; } else { $periodStart = somehowPleaseGetDurationInFractionalSecondsBecuasePHPHasABug($periodStart); } //Convert Duration string to number //updateTemplate(&$periods[$periodIndex]['node']); if ($deltaTimeASTTuneIn < $periodStart) { $periods[$periodIndex]['node']->setAttribute("start", "PT" . round($lastPeriodStart + $lastPeriodDuration, 4) . "S"); //Set already for the next iteration $lastPeriodStart = $lastPeriodStart + $lastPeriodDuration; $responseToSend[] = $lastPeriodStart; $lastPeriodDuration = $duration; continue; } //Set already for the next iteration $lastPeriodStart = $periodStart; $lastPeriodDuration = $duration; if ($deltaTimeASTTuneIn > $periodStart + $duration) { $dom->documentElement->removeChild($periods[$periodIndex]['node']); $responseToSend[1] = $responseToSend[1] - 1; continue; } //The only case here is the period in which we tune in $videoSegmentTemplate =& $periods[$periodIndex]['adaptationSet'][0]['representation'][0]['segmentTemplate']['node']; $audioSegmentTemplate =& $periods[$periodIndex]['adaptationSet'][1]['representation'][0]['segmentTemplate']['node']; $videoTimescale = $videoSegmentTemplate->getAttribute("timescale"); $videoSegmentDuration = $videoSegmentTemplate->getAttribute("duration"); $videoStartNum = $videoSegmentTemplate->getAttribute("startNumber"); $videoPTO = $videoSegmentTemplate->getAttribute("presentationTimeOffset"); $newVideoStartNumber = ceil(($deltaTimeASTTuneIn - $periodStart) * $videoTimescale / $videoSegmentDuration) + $videoStartNum; //file_put_contents ( "timelog.txt" , "new video offset: " . ($deltaTimeASTTuneIn - $periodStart)*$videoTimescale/$videoSegmentDuration . "\r\n" , FILE_APPEND ); $videoOffsetUpdate = ($newVideoStartNumber - $videoStartNum) * $videoSegmentDuration / $videoTimescale; $audioTimescale = $audioSegmentTemplate->getAttribute("timescale"); $audioSegmentDuration = $audioSegmentTemplate->getAttribute("duration"); $audioStartNum = $audioSegmentTemplate->getAttribute("startNumber"); $audioPTO = $audioSegmentTemplate->getAttribute("presentationTimeOffset"); $newAudioStartNumber = ceil(($deltaTimeASTTuneIn - $periodStart) * $audioTimescale / $audioSegmentDuration) + $audioStartNum; //file_put_contents ( "timelog.txt" , "new audio offset: " . ($deltaTimeASTTuneIn - $periodStart)*$audioTimescale/$audioSegmentDuration . "\r\n" , FILE_APPEND ); $audioOffsetUpdate = ($newAudioStartNumber - $audioStartNum) * $audioSegmentDuration / $audioTimescale; // Find the smaller update offset of audio and video, set the other to the smaller $offsetUpdate = min($videoOffsetUpdate, $audioOffsetUpdate); $newAudioPTO = round($offsetUpdate * $audioTimescale + $audioPTO); //Round, since PTO is int type $newVideoPTO = round($offsetUpdate * $videoTimescale + $videoPTO); //Round, since PTO is int type //The adjusted period start and duration governed by new audio/video offset above. $periods[$periodIndex]['node']->setAttribute("start", "PT" . round($offsetUpdate + $periodStart - $deltaTimeASTTuneIn, 4) . "S"); $remainingPeriodDuration = $duration - max($videoOffsetUpdate, $audioOffsetUpdate); $periods[$periodIndex]['node']->setAttribute("duration", "PT" . round($remainingPeriodDuration, 4) . "S"); //Update again the last saved values for the next iteration $lastPeriodStart = $offsetUpdate + $periodStart - $deltaTimeASTTuneIn; $lastPeriodDuration = $remainingPeriodDuration; $videoSegmentTemplate->setAttribute("presentationTimeOffset", $newVideoPTO); $videoSegmentTemplate->setAttribute("startNumber", $newVideoStartNumber); $audioSegmentTemplate->setAttribute("presentationTimeOffset", $newAudioPTO); $audioSegmentTemplate->setAttribute("startNumber", $newAudioStartNumber); //$periods[$periodIndex]['node']->removeChild ($periods[$periodIndex]['adaptationSet'][1]['node']); } //Set the updated MPD duration $MPDNode->setAttribute("mediaPresentationDuration", "PT" . round($lastPeriodStart + $lastPeriodDuration, 4) . "S"); /*if($AdSource == 1 && count($periods) >= 2) { $BaseURL = $dom->createElement( "BaseURL", "../Ad2/"); $TargetPeriod = $periods[count($periods) - 2]; $TargetAS = $TargetPeriod['adaptationSet'][0]['node']; $TargetPeriodNode = $TargetPeriod['node']; $TargetPeriodNode->insertBefore($BaseURL,$TargetAS); }*/ $BaseURL = $dom->createElement("BaseURL", $DASHContent); $TargetPeriodNode = $periods[0]['node']; $MPDNode->insertBefore($BaseURL, $TargetPeriodNode); $dom->save($PatchedMPD); corsHeader(); header("Content-Type: application/xml"); $toecho = $dom->saveXML(); echo $toecho; #file_put_contents ( "timelog.txt" , $latestFiles , FILE_APPEND ); $micro_date = microtime(); $date_array = explode(" ", $micro_date); $date = date("Y-m-d H:i:s", $date_array[1]); //file_put_contents ( "timelog.txt" , "Done:" . $date . $date_array[0] . " \r\n" , FILE_APPEND ); }
} //Set the updated MPD duration $MPDNode->setAttribute("mediaPresentationDuration", "PT" . round($lastPeriodStart + $lastPeriodDuration, 4) . "S"); /*if($AdSource == 1 && count($periods) >= 2) { $BaseURL = $dom->createElement( "BaseURL", "../Ad2/"); $TargetPeriod = $periods[count($periods) - 2]; $TargetAS = $TargetPeriod['adaptationSet'][0]['node']; $TargetPeriodNode = $TargetPeriod['node']; $TargetPeriodNode->insertBefore($BaseURL,$TargetAS); }*/ $BaseURL = $dom->createElement("BaseURL", $DASHContent); $TargetPeriodNode = $periods[0]['node']; //$MPDNode->insertBefore($BaseURL,$TargetPeriodNode); $dom->save($PatchedMPD); corsHeader(); header("Content-Type: application/xml"); $toecho = $dom->saveXML(); $timestampinms = $date_array[1] * 1000 + $date_array[0]; exec("python timer.py " . $newVideoStartNumber . " " . $newAudioStartNumber . " " . $videoSegmentDuration * 1000 / $videoTimescale . " " . $audioSegmentDuration * 1000 / $audioTimescale . " " . $timestampinms . " " . $DASHContent . " " . $cacheDir . " > pythonlog.txt &"); while (!file_exists($cacheDir . '/initialized.trig')) { usleep(1000); } echo $toecho; #file_put_contents ( "timelog.txt" , $latestFiles , FILE_APPEND ); $micro_date = microtime(); $date_array = explode(" ", $micro_date); $date = date("Y-m-d H:i:s", $date_array[1]); //file_put_contents ( "timelog.txt" , "Done:" . $date . $date_array[0] . " \r\n" , FILE_APPEND ); exit; function updateTemplate($period, $prefix)