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 );
}
function generateFDTAndTimingSlS($videoSegmentDuration, $videoTimescale, $audioSegmentDuration, $audioTimescale, $mediaPresentationDuration)
{
    global $mpdEFDTFile, $mpdTimingFile, $ASTUNIX, $mpdDoc, $mpdInstance, $mpdTOI, $slsFrequencyDuration, $slsObjectsSent;
    $mpdDoc = new DOMDocument('1.0');
    $mpdDoc->formatOutput = true;
    $mpdInstance = $mpdDoc->createElement('EFDT-Instance');
    $mpdInstance->setAttribute("TSI", "0");
    $mpdInstance->setAttribute("IDRef", "file:///efdt_MPD.xml");
    $mpdDoc->appendChild($mpdInstance);
    $fdtparametersMpd = $mpdDoc->createElement('FDT-Parameters');
    $fdtparametersMpd->setAttribute("Expires", "32511974400");
    $fdtparametersMpd->setAttribute("FEC-OTI-FEC-Encoding-ID", "0");
    $fdtparametersMpd->setAttribute("FEC-OTI-Maximum-Source-Block-Length", "5000");
    $fdtparametersMpd->setAttribute("FEC-OTI-Encoding-Symbol-Length", "1428");
    $mpdInstance->appendChild($fdtparametersMpd);
    unlink($mpdTimingFile);
    $slsFrequencyDuration = 0.1;
    // How often to send the SLT segments in seconds
    // 0.1s means, for every 100ms we will send S-TSID, USBD (also, maybe the .mpd) segments.
    // In the SLT segments, we send .mpd related information as often as the smallest of audio or video segment.
    if ($videoSegmentDuration / $videoTimescale > $audioSegmentDuration / $audioTimescale) {
        $mpdFrequencyDuration = round($audioSegmentDuration / $audioTimescale, 1);
        // We have set to one degree of precision.
    } else {
        $mpdFrequencyDuration = round($videoSegmentDuration / $videoTimescale, 1);
        // We have set to one degree of precision.
    }
    $mpdFrequency = $mpdFrequencyDuration / $slsFrequencyDuration;
    //$mpdFrequency = 1; Set this to send .mpd all the time.
    // The mpd frequency in relative SLT frequency duration.
    // For example, mpdFrequency = 10 will imply that => for every 10 S-TSID and USBD segments we will send one MPD segment.
    //echo "The mpd frequency is ".$mpdFrequency.PHP_EOL;
    //echo "The SLT duration is" . $slsFrequencyDuration . PHP_EOL;
    //echo "MPD duration " . $mediaPresentationDuration . PHP_EOL;
    $duration = somehowPleaseGetDurationInFractionalSecondsBecuasePHPHasABug($mediaPresentationDuration);
    for ($mpdIndex = 1;; $mpdIndex++) {
        if ($mpdIndex * $slsFrequencyDuration >= $duration) {
            break;
        }
        // Keep sending the SLS segment until the end of the presentation duration
        file_put_contents($mpdTimingFile, $mpdTOI . " " . intval($ASTUNIX + $slsObjectsSent * $slsFrequencyDuration * 1000000) . "\n", FILE_APPEND);
        //$tmp_to_slt1 = $start + ($audioIndex - $audioStartNum - 1)*$slsFrequencyDuration;
        //$tmp_to_slt2 = ($audioIndex - $audioStartNum - 1);
        //$tmp_to_slt3 = $slsFrequencyDuration;
        //echo "SLT time = " . $start . "+" . $tmp_to_slt2 . "x" . $tmp_to_slt3. " = " . $tmp_to_slt1 . PHP_EOL;
        //$tmp_to_audio = ($start + ($audioIndex - $audioStartNum - 1)*$audioSegmentDuration/$audioTimescale + $deltaAudio);
        //$tmp_to_audio = ($audioIndex - $audioStartNum - 1)*$slsFrequencyDuration;
        //echo "Audio time = " . $tmp_to_audio . PHP_EOL;
        // In the same audio loop we will be writing out two files,
        // efdt_Audio.xml and efdt_MPD.xml
        //$file = $mpdDoc->createElement('File');
        //$file->setAttribute("TOI",$mpdTOI);$mpdTOI++;
        //$file->setAttribute("Content-Location",'file:///usbd.xml');
        //$file->setAttribute("Content-Length","USBDSizePlaceholder");
        //$mpdInstance->appendChild($file);
        $file = $mpdDoc->createElement('File');
        $file->setAttribute("TOI", $mpdTOI);
        $mpdTOI++;
        $file->setAttribute("Content-Location", 'file:///S-TSID.xml');
        $file->setAttribute("Content-Length", "S_TSIDSizePlaceholder");
        $mpdInstance->appendChild($file);
        $slsObjectsSent++;
        if ($slsObjectsSent % 3 == 0) {
            // Just send MPD after 3 S-TSID files sent.
            $file = $mpdDoc->createElement('File');
            $file->setAttribute("TOI", $mpdTOI);
            $mpdTOI++;
            $file->setAttribute("Content-Location", 'file:///' . "MPDNamePlaceholder");
            $file->setAttribute("Content-Length", "MPDSizePlaceholder");
            $mpdInstance->appendChild($file);
        }
    }
    $mpdDoc->save($mpdEFDTFile);
}
Beispiel #3
0
$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
    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']);
Beispiel #4
0
$profiles = $periods[0]['node']->parentNode->getAttribute("profiles");
$periods[0]['node']->parentNode->removeAttribute("profiles");
$periods[0]['node']->parentNode->setAttribute("availabilityStartTime", $AST_W3C);
//Set AST to tune-in time
$periods[0]['node']->parentNode->setAttribute("timeShiftBufferDepth", "PT60S");
$periods[0]['node']->parentNode->setAttribute("mediaPresentationDuration", $mediaPresentationDuration);
$periods[0]['node']->parentNode->setAttribute("profiles", $profiles);
$savedTotalDuration = 0;
$restPeriodDuration = 0;
$numVideoSegments = 0;
$numAudioSegments = 0;
$deltaAudio = 0;
$deltaVideo = 0;
for ($periodIndex = 0; $periodIndex < count($periods); $periodIndex++) {
    $durationInMPD = $periods[$periodIndex]['node']->getAttribute("duration");
    $duration = somehowPleaseGetDurationInFractionalSecondsBecuasePHPHasABug($durationInMPD);
    if ($adInsertion) {
        $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");
        $audioTimescale = $audioSegmentTemplate->getAttribute("timescale");
        $audioSegmentDuration = $audioSegmentTemplate->getAttribute("duration");
        $audioStartNum = $audioSegmentTemplate->getAttribute("startNumber");
        $audioPTO = $audioSegmentTemplate->getAttribute("presentationTimeOffset");
        if ($periodIndex == 0) {
            $adInsertionTime = getadInsertionTime($adInsertionTimeRequest, $videoSegmentDuration / $videoTimescale, 0, $audioSegmentDuration / $audioTimescale, 0);
            $numVideoSegments = round($adInsertionTime * $videoTimescale / $videoSegmentDuration);
            $numAudioSegments = round($adInsertionTime * $audioTimescale / $audioSegmentDuration);