function process_mpd() { global $Adapt_arr, $Period_arr, $repno, $repnolist, $period_url, $locate, $string_info, $count1, $count2, $perioddepth, $adaptsetdepth, $period_baseurl, $foldername, $type, $minBufferTime, $profiles, $MPD, $session_id, $progressXML; //Global variables to be used within the main function // $path_parts = pathinfo($mpdurl); $Baseurl = false; //define if Baseurl is used or no $setsegflag = false; // $mpdfilename = $path_parts['filename']; // determine name of actual MPD file if (isset($_FILES['afile']['tmp_name'])) { $_SESSION['fileContent'] = file_get_contents($_FILES['afile']['tmp_name']); } // if (isset($_POST['urlcode'])) { // in case of client send first connection attempt $sessname = 'sess' . rand(); // get a random session name session_name($sessname); // set session name $directories = array_diff(scandir(dirname(__FILE__) . '/' . 'temp'), array('..', '.')); foreach ($directories as $file) { // Clean temp folder from old sessions in order to save diskspace if (file_exists(dirname(__FILE__) . '/' . 'temp' . '/' . $file)) { // temp is folder contains all sessions folders $tempXML = simplexml_load_file(dirname(__FILE__) . '/' . 'temp' . '/' . $file . '/progress.xml'); $change1 = 0; //duration after conformance test is done $change2 = time() - filemtime(dirname(__FILE__) . '/' . 'temp' . '/' . $file); // duration of file implementation if ((string) $tempXML->completed === "true") { $change1 = time() - (int) $tempXML->completed->attributes(); } if ($change1 > 1800 || $change2 > 1800) { //clean folder after 30 mins after test completed or 30 mins after test started rrmdir(dirname(__FILE__) . '/' . 'temp' . '/' . $file); } // if last time folder was modified exceed 300 second it should be removed } } // Work out which validator binary to use $validatemp4 = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? "validatemp4-vs2010.exe" : "ValidateMP4.exe"; //var_dump( $path_parts ); if (isset($_POST['foldername'])) { $foldername = $_POST['foldername']; $paths = explode("/", $foldername); if (count($paths) > 1) { $foldername = end($paths); } } else { $foldername = 'id' . rand(); } // get random name for session folder //get a name for session folder from client. $_SESSION['foldername'] = $foldername; // rrmdir($locate); $locate = dirname(__FILE__) . '/' . 'temp' . '/' . $foldername; //session folder location $_SESSION['locate'] = $locate; // save session folder location $oldmask = umask(0); mkdir($locate, 0777, true); // create session folder umask($oldmask); // $totarr = array(); // array contains all data to be sent to client. copy(dirname(__FILE__) . "/" . $validatemp4, $locate . '/' . $validatemp4); // copy conformance tool to session folder to allow multi-session operation chmod($locate . '/' . $validatemp4, 0777); $url_array = json_decode($_POST['urlcode']); if (isset($_SESSION['fileContent'])) { // If file is uploaded file_put_contents($locate . '/uploaded.mpd', $_SESSION['fileContent']); $url_array[0] = $locate . '/uploaded.mpd'; $GLOBALS["url"] = $locate . '/uploaded.mpd'; $MPD_abs = simplexml_load_file($GLOBALS["url"]); // load mpd from url $dom_abs = dom_import_simplexml($MPD_abs); $abs = new DOMDocument('1.0'); $dom_abs = $abs->importNode($dom_abs, true); //create dom element to contain mpd $dom_abs = $abs->appendChild($dom_abs); $MPD_abs = $abs->getElementsByTagName('MPD')->item(0); // access the parent "MPD" in mpd file $Baseurl_abs = $MPD_abs->getElementsByTagName('BaseURL'); if ($Baseurl_abs->length > 0) { $Baseurl_abs = $Baseurl_abs->item(0); $absolute = $Baseurl_abs->nodeValue; if ($absolute === './' || strpos($absolute, 'http') === false) { $url_array[2] = 1; } } else { $url_array[2] = 1; } } $url_array[3] = $locate; //Used for e.g. placing intermediate files etc. copy(dirname(__FILE__) . "/" . "featuretable.html", $locate . '/' . "featuretable.html"); // copy features list html file to session folder //Create log file so that it is available if accessed $progressXML = simplexml_load_string('<root><Profile></Profile><Progress><percent>0</percent><dataProcessed>0</dataProcessed><dataDownloaded>0</dataDownloaded><CurrentAdapt>1</CurrentAdapt><CurrentRep>1</CurrentRep></Progress><completed>false</completed></root>'); // get progress bar update $progressXML->asXml($locate . '/progress.xml'); //progress xml location //libxml_use_internal_logors(true); $MPD_O = simplexml_load_file($GLOBALS["url"]); // load mpd from url if (!$MPD_O) { $progressXML->MPDError = "1"; //MPD error is updated in the progress.xml file. $progressXML->asXml(trim($locate . '/progress.xml')); echo $progressXML->asXML(); die("Error: Failed loading XML file"); } else { $progressXML->MPDError = "0"; $progressXML->asXml(trim($locate . '/progress.xml')); } $dom_sxe = dom_import_simplexml($MPD_O); if (!$dom_sxe) { echo $progressXML->asXML(); exit; } $validate_result = mpdvalidator($url_array, $locate, $foldername); $exit = $validate_result[0]; $totarr = $validate_result[1]; $schematronIssuesReport = $validate_result[2]; //MPD Conformance results are written into the progress.xml file. $temp_mpdres = ""; for ($totindex = 0; $totindex < 3; $totindex++) { if ($totarr[$totindex] == "true") { $temp_mpdres = $temp_mpdres . "true "; } else { $temp_mpdres = $temp_mpdres . "false "; } } $progressXML->MPDConformance = $temp_mpdres; $progressXML->MPDConformance->addAttribute('url', str_replace($_SERVER['DOCUMENT_ROOT'], 'http://' . $_SERVER['SERVER_NAME'], $locate . '/mpdreport.txt')); $progressXML->asXml(trim($locate . '/progress.xml')); ///////////////////////////////////////Processing mpd attributes in order to get value////////////////////////////////////////////////////////// $dom = new DOMDocument('1.0'); $dom_sxe = $dom->importNode($dom_sxe, true); //create dom element to contain mpd //$dom_sxe = $dom->appendChild($dom_sxe); $dom->appendChild($dom_sxe); $MPD = $dom->getElementsByTagName('MPD')->item(0); // access the parent "MPD" in mpd file $mediaPresentationDuration = $MPD->getAttribute('mediaPresentationDuration'); // get mediapersentation duration from mpd level $AST = $MPD->getAttribute('availabilityStartTime'); $bufferdepth = $MPD->getAttribute('timeShiftBufferDepth'); $bufferdepth = timeparsing($bufferdepth); $presentationduration = timeparsing($mediaPresentationDuration); createMpdFeatureList($dom, $schematronIssuesReport); $type = $MPD->getAttribute('type'); // get mpd type if ($type === 'dynamic' && $dom->getElementsByTagName('SegmentTemplate')->length == 0) { $totarr[] = $foldername; //This is messed up right now: dynamic conformance //$totarr[]='dynamic'; // Incase of dynamic only mpd conformance. //$exit =true; //Session destroy flag is true } if ($exit === true) { //If session should be destroyed if ($type !== 'dynamic') { $totarr[] = $foldername; } $stri = json_encode($totarr); //Send results to client // echo $stri; session_destroy(); //Destroy session $progressXML->completed = "true"; $progressXML->completed->addAttribute('time', time()); $progressXML->asXml(trim($locate . '/progress.xml')); echo $progressXML->asXML(); exit; //Exit } $minBufferTime = $MPD->getAttribute('minBufferTime'); //get min buffer time $profiles = $MPD->getAttribute('profiles'); // get profiles $progressXML->Profile = $profiles; $progressXML->asXml(trim($locate . '/progress.xml')); $periodCount = 0; foreach ($dom->documentElement->childNodes as $node) { // search for all nodes within mpd if ($node->nodeName === 'Period') { if ($periodCount === 0) { //only process the first Period $periodNode = $node; } $periodCount++; } } $val = $dom->getElementsByTagName('BaseURL'); // get BaseUrl node $segflag = $dom->getElementsByTagName('SegmentTemplate'); //check if segment template exists or not if ($segflag->length > 0) { $setsegflag = true; } // Segment template is supported if ($val->length > 0) { // if baseurl is used $Baseurl = true; // set Baseurl flag = true for ($i = 0; $i < sizeof($val); $i++) { //check if Baseurl node exist in MPD level or lower level $base = $val->item($i); $par = $base->parentNode; $name = $par->tagName; if ($name == 'MPD') { // if exist in mpd level $dir = $base->nodeValue; if (!isAbsoluteURL($dir)) { // if baseurl is relative URl $dir = dirname($GLOBALS["url"]) . '/' . $dir; } // use location of Baseurl as location of mpd location } } if (!isset($dir)) { // if there is no Baseurl in mpd level $dir = dirname($GLOBALS["url"]) . '/'; } // set location of segments dir as mpd location } else { $dir = dirname($GLOBALS["url"]) . '/'; } // if there is no Baseurl in mpd level,set location of segments dir as mpd location $start = processPeriod($periodNode, $dir); // start getting information from period level $start = timeparsing($start); //Get start time in seconds $segm_url = array(); // contains segments url within one $adapt_url = array(); // contains all segments urls within adapatations set if ($setsegflag) { // Segment template is used for ($k = 0; $k < sizeof($Period_arr); $k++) { // loop on period array $Adapt_initialization_setflag = 0; if (!empty($Period_arr[$k]['SegmentTemplate'])) { //print_r2($Period_arr[$k]['SegmentTemplate']); if (!empty($Period_arr[$k]['SegmentTemplate']['duration'])) { // get duration of segment template $duration = $Period_arr[$k]['SegmentTemplate']['duration']; } else { $duration = 0; } // if duration doesn't exist set duration to 0 if (!empty($Period_arr[$k]['SegmentTemplate']['timescale'])) { // check time scale for given segment template $timescale = $Period_arr[$k]['SegmentTemplate']['timescale']; } else { $timescale = 1; } // if doesn't exist set default to 1 if ($duration != 0) { $duration = $duration / $timescale; // get duration $segmentno = ceil(($presentationduration - $start) / $duration); //get segment number } $startnumber = $Period_arr[$k]['SegmentTemplate']['startNumber']; // get first number in segment $initialization = $Period_arr[$k]['SegmentTemplate']['initialization']; // get initialization degment if ($initialization != "") { $Adapt_initialization_setflag = 1; } $media = $Period_arr[$k]['SegmentTemplate']['media']; // get media template // $timehash = null; // used only in segment timeline $timehash = array(); // contains all segmenttimelines for all segments if (!empty($Period_arr[$k]['SegmentTemplate']['SegmentTimeline'])) { // in case of using Segment timeline $timeseg = $Period_arr[$k]['SegmentTemplate']['SegmentTimeline'][0][0]; // get time segment for ($lok = 0; $lok < sizeof($Period_arr[$k]['SegmentTemplate']['SegmentTimeline']); $lok++) { // loop on segment time line $d = $Period_arr[$k]['SegmentTemplate']['SegmentTimeline'][$lok][1]; // get d $r = $Period_arr[$k]['SegmentTemplate']['SegmentTimeline'][$lok][2]; // get r $te = $Period_arr[$k]['SegmentTemplate']['SegmentTimeline'][$lok][0]; // get t if ($r == 0) { $timehash[] = $timeseg; $timeseg = $timeseg + $d; } if ($r < 0) { //Repeat untill the last segment within presentation if (!isset($Period_arr[$k]['SegmentTemplate']['SegmentTimeline'][$lok + 1])) { $ende = $presentationduration * $timescale; } else { $ende = $Period_arr[$k]['SegmentTemplate']['SegmentTimeline'][$lok + 1]; } $ende = $ende; while ($timeseg < $ende) { // calculate time segment until the end of duration $timehash[] = $timeseg; //contain duration of all segments cumulatively $timeseg = $timeseg + $d; } } if ($r > 0) { for ($cn = 0; $cn <= $r; $cn++) { // repeat untill the amount of repeat is finished $timehash[] = $timeseg; $timeseg = $timeseg + $d; } } } } } for ($j = 0; $j < sizeof($Period_arr[$k]['Representation']['bandwidth']); $j++) { // loop on adaptationset level $direct = $dir; if ($Baseurl === true) { // incase of using Base url if (!isset($perioddepth[0])) { // period doesn't contain any baseurl infromation $perioddepth[0] = ""; } if (!isset($adaptsetdepth[$k])) { // adaptation set doesn't contain any baseurl information $adaptsetdepth[$k] = ""; } $direct = $dir . $perioddepth[0] . $adaptsetdepth[$k]; // combine baseURLs in both period level and adaptationset level } if (!empty($Period_arr[$k]['Representation']['SegmentTemplate'][$j])) { // in case of using segmenttemplate $duration = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['duration']; // get segment duration attribute if (!empty($Period_arr[$k]['Representation']['SegmentTemplate'][$j]['timescale'])) { //get time scale $timescale = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['timescale']; } else { $timescale = 1; } // set to 1 if not avaliable if ($duration != 0) { $duration = $duration / $timescale; // get duration scaled $segmentno = ceil(($presentationduration - $start) / $duration); // get number of segments //print_r2($startnumber); } $startnumber = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['startNumber']; // get start number if ($Adapt_initialization_setflag == 0) { $initialization = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['initialization']; // get initialization } $media = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['media']; // get media template if (!empty($Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline'])) { // check timeline $timeseg = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline'][0][0]; // segment start time for ($lok = 0; $lok < sizeof($Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline']); $lok++) { //loop on timeline $timehash = array(); //contains time tag for each segment $d = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline'][$lok][1]; //get d $r = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline'][$lok][2]; //get r $te = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline'][$lok][0]; //get te if ($r == 0) { // no duration repeat $timehash[] = $timeseg; //segment time stamp is same as segment time $timeseg = $timeseg + $d; } if ($r < 0) { // segments untill the end of presentation duration if (!isset($Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline'][$lok + 1])) { $ende = $presentationduration * $timescale; } else { $ende = $Period_arr[$k]['Representation']['SegmentTemplate'][$j]['SegmentTimeline'][$lok + 1]; } $ende = $ende; while ($timeseg < $ende) { $timehash[] = $timeseg; $timeseg = $timeseg + $d; //get time stamp for each segment by adding segment duration to previous time stamp } } else { for ($cn = 0; $cn <= $r; $cn++) { //if r is positive number $timehash[] = $timeseg; $timeseg = $timeseg + $d; // add duration to time segment to get time stamp for each segment } } } } } $bandwidth = $Period_arr[$k]['Representation']['bandwidth'][$j]; // get bandwidth of given representation $id = $Period_arr[$k]['Representation']['id'][$j]; // get id of given representation $init = str_replace(array('$Bandwidth$', '$RepresentationID$'), array($bandwidth, $id), $initialization); //get initialization segment template is replaced by bandwidth and id //test is $direct contains "/" in the end if (substr($direct, -1) == '/') { $initurl = $direct . $init; } else { $initurl = $direct . "/" . $init; } //full initialization URL $segm_url[] = $initurl; //add segment to URL $timehashmask = 0; // default value if timeline doesnt exist if (!empty($timehash)) { // if time line exist $segmentno = sizeof($timehash); // number of segments $startnumber = 1; // start number set to 1 $timehashmask = $timehash; } $signlocation = strpos($media, '%'); // clean media attribute from non existing values if ($signlocation !== false) { if ($signlocation - strpos($media, 'Number') === 6) { $media = str_replace('$Number', '', $media); } } if ($type === "dynamic") { // if ($dom->getElementsByTagName('SegmentTimeline')->length !== 0) { //TODO currently $duration and timing is not properly set //get $duration from "d" attribute //set proper timing from "t" attribute //check "r" etc. // } $segmentinfo = dynamicnumber($bufferdepth, $duration, $AST, $start, $Period_arr); $segmentno = $segmentinfo[1]; //Latest available segment number $i = $segmentinfo[0]; // first segment in buffer } else { $i = 0; } while ($i < $segmentno) { $segmenturl = str_replace(array('$Bandwidth$', '$Number$', '$RepresentationID$', '$Time$'), array($bandwidth, $i + $startnumber, $id, $timehashmask[$i]), $media); //replace all media template values by actuall values $segmenturl = sprintf($segmenturl, $startnumber + $i); $segmenturl = str_replace('$', '', $segmenturl); //clean segment url from any extra signs $segmenturl = $direct . "/" . $segmenturl; // get full segment url $segm_url[] = removeabunchofslashes($segmenturl); //add URL to segments URL array $i++; } $adapt_url[] = $segm_url; // contains all representations within certain adaptation set $segm_url = array(); // delete segment url array and process the next representation } $period_url[] = $adapt_url; // add all adaptationset urls to period array $adapt_url = array(); // delete adaptationset array and process the next adaptation set } } if ($Baseurl) { // in case of using Base url node for ($i = 0; $i < sizeof($period_baseurl); $i++) { // loop on base url if (!isset($perioddepth[0])) { // if period doesn't contain baseurl $perioddepth[0] = ""; } for ($j = 0; $j < sizeof($period_baseurl[$i]); $j++) { //loop on baseurl in adaptationset if (!isset($adaptsetdepth[$i])) { // if adaptationset doesn't contain baseurl $adaptsetdepth[$i] = ""; } for ($lo = 0; $lo < sizeof($period_baseurl[$i][$j]); $lo++) { // loop on baseurl in period level if (!isAbsoluteURL($period_baseurl[$i][$j][$lo])) { $period_baseurl[$i][$j][$lo] = removeabunchofslashes($dir . $perioddepth[0] . '/' . $adaptsetdepth[$i] . '/' . $period_baseurl[$i][$j][$lo]); } //combine all baseurls } } } if ($setsegflag === false) { $period_url = $period_baseurl; } // if segment template is not used, use baseurl } $_SESSION['period_url'] = $period_url; // save all period urls in session variable $_SESSION['Period_arr'] = $Period_arr; //save all period parameters in session variable $totarr[] = sizeof($period_url); // get number of adaptation sets for ($i = 0; $i < sizeof($period_url); $i++) { // loop on periods $totarr[] = sizeof($period_url[$i]); //get number of represenations per adaptation set } $totarr[] = $periodCount; $totarr[] = $foldername; // add session name $stri = json_encode($totarr); // encode array to send to client //print_r2($period_url); if (isset($_SESSION['count1'])) { // reset adaptationset counter before download start unset($_SESSION['count1']); } if (isset($_SESSION['count2'])) { //reset representation counter before download start unset($_SESSION['count2']); } $_SESSION['type'] = $type; $_SESSION['minBufferTime'] = $minBufferTime; if ($setsegflag) { // Segment template is used if ($type === "dynamic") { if ($dom->getElementsByTagName('SegmentTimeline')->length !== 0) { $totarr[] = "dynamic"; $progressXML->dynamic = "true"; // Update progress.xml file with info on dynamic MPD. $progressXML->asXml(trim($locate . '/progress.xml')); $stri = json_encode($totarr); //Send results to client // echo $stri; session_destroy(); //Destroy session $progressXML->completed = "true"; $progressXML->completed->addAttribute('time', time()); $progressXML->asXml(trim($locate . '/progress.xml')); echo $progressXML->asXML(); exit; } } else { $progressXML->dynamic = "false"; $progressXML->asXml(trim($locate . '/progress.xml')); } } //check if SegmentList exist if ($dom->getElementsByTagName('SegmentList')->length !== 0) { $progressXML->segmentList = "true"; $progressXML->asXml(trim($locate . '/progress.xml')); $stri = json_encode($totarr); //Send results to client // echo $stri; session_destroy(); //Destroy session $progressXML->completed = "true"; $progressXML->completed->addAttribute('time', time()); $progressXML->asXml(trim($locate . '/progress.xml')); echo $progressXML->asXML(); exit; } $ResultXML = $progressXML->addChild('Results'); // Create Results tree in progress.xml and updates tree later. for ($i1 = 0; $i1 < $periodCount; $i1++) { $PeriodXML = $ResultXML->addChild('Period'); for ($j1 = 0; $j1 < sizeof($period_url); $j1++) { $AdaptationXML = $PeriodXML->addChild('Adaptation'); for ($k1 = 0; $k1 < sizeof($period_url[$j1]); $k1++) { $RepXML = $AdaptationXML->addChild('Representation'); $RepXML->addAttribute('id', $k1 + 1); } } } $progressXML->asXml(trim($locate . '/progress.xml')); // echo $stri; // send no. of periods,adaptationsets, representation, mpd file to client // } //////////////////////////////////////////////////////////////////////////////////// //if (isset($_POST['download'])) { // get request from client to download segments //Segments are downloaded in a sequence and conformance results are written into progress.xml. while ($count1 <= sizeof($period_url)) { $root = dirname(__FILE__); $destiny = array(); if ($count2 >= sizeof($period_url[$count1])) { //check if all representations within a segment is downloaded $count2 = 0; // reset representation counter when new adaptation set is proccesed $count1 = $count1 + 1; // increase adapatationset counter if ($count1 < sizeof($period_url)) { //$AdaptationXML = $ResultXML->addChild('Adaptation'); //$AdaptationXML->addAttribute('id',$count1+1); $progressXML->Progress->CurrentAdapt = $count1 + 1; // Update currently running AdaptationSet, used in display status message. $progressXML->asXml(trim($locate . '/progress.xml')); } } if ($count1 >= sizeof($period_url)) { //check if all adapatationsets is processed error_log("AllAdaptDownloaded"); crossRepresentationProcess(); $missingexist = file_exists($locate . '/missinglink.txt'); //check if any broken urls is detected if ($missingexist) { $temp_string = str_replace(array('$Template$'), array("missinglink"), $string_info); file_put_contents($locate . '/missinglink.html', $temp_string); //create html file contains report for all missing segments } $file_error[] = "done"; for ($i = 0; $i < sizeof($Period_arr); $i++) { // check all info files if they contain Error if (file_exists($locate . '/Adapt' . $i . '_infofile.txt')) { $searchadapt = file_get_contents($locate . '/Adapt' . $i . '_infofile.txt'); if (strpos($searchadapt, "Error") == false) { $ResultXML->Period[0]->Adaptation[$i]->addChild('CrossRepresentation', 'noerror'); $file_error[] = "noerror"; // no error found in text file } else { $ResultXML->Period[0]->Adaptation[$i]->addChild('CrossRepresentation', 'error'); $file_error[] = "temp" . '/' . $foldername . '/' . 'Adapt' . $i . '_infofile.html'; // add error file location to array } } else { $ResultXML->Period[0]->Adaptation[$i]->addChild('CrossRepresentation', 'noerror'); $file_error[] = "noerror"; } $ResultXML->Period[0]->Adaptation[$i]->CrossRepresentation->addAttribute('url', str_replace($_SERVER['DOCUMENT_ROOT'], 'http://' . $_SERVER['SERVER_NAME'], $locate . '/Adapt' . $i . '_infofile.txt')); $progressXML->asXml(trim($locate . '/progress.xml')); } session_destroy(); if ($missingexist) { $ResultXML->addChild('BrokenURL', "error"); $ResultXML->BrokenURL->addAttribute('url', str_replace($_SERVER['DOCUMENT_ROOT'], 'http://' . $_SERVER['SERVER_NAME'], $locate . '/missinglink.txt')); $file_error[] = "temp" . '/' . $foldername . '/missinglink.html'; } else { $ResultXML->addChild('BrokenURL', "noerror"); $file_error[] = "noerror"; } $send_string = json_encode($file_error); //encode array to string and send it error_log("ReturnFinish:" . $send_string); // echo $send_string; // send string with location of all error logs to client $progressXML->completed = "true"; $progressXML->completed->addAttribute('time', time()); $progressXML->asXml(trim($locate . '/progress.xml')); echo $progressXML->asXML(); exit; } else { $repno = "Adapt" . $count1 . "rep" . $count2; // presentation unique name $pathdir = $locate . "/" . $repno . "/"; $progressXML->Progress->CurrentRep = $count2 + 1; // Update currently running Representation, used in display status message. $progressXML->asXml(trim($locate . '/progress.xml')); error_log("Download_pathdir:" . $pathdir); if (!file_exists($pathdir)) { $oldmask = umask(0); mkdir($pathdir, 0777, true); // create folder for each presentation umask($oldmask); } $tempcount1 = $count1; //don't know why we need a buffer, but it only works this way with php 7 $sizearray = downloaddata($pathdir, $period_url[$count1][$count2]); // download data if ($sizearray !== 0) { Assemble($pathdir, $period_url[$count1][$count2], $sizearray); // Assemble all presentation in to one presentation chmod($locate . '/' . "mdatoffset.txt", 0777); rename($locate . '/' . "mdatoffset.txt", $locate . '/' . $repno . "mdatoffset.txt"); //rename txt file contains mdatoffset $file_location = array(); $exeloc = dirname(__FILE__); chdir($locate); $timeSeconds = str_replace("PT", "", $minBufferTime); $timeSeconds = str_replace("S", "", $timeSeconds); $processArguments = " -minbuffertime " . $timeSeconds . " -bandwidth "; $processArguments = $processArguments . $Period_arr[$count1]['Representation']['bandwidth'][$count2] . " "; $processArguments = $processArguments . "-width "; if ($Period_arr[$count1]['width'] === 0) { $processArguments = $processArguments . $Period_arr[$count1]['Representation']['width'][$count2] . " -height "; } else { $processArguments = $processArguments . $Period_arr[$count1]['width'] . " -height "; } if ($Period_arr[$count1]['height'] === 0) { $processArguments = $processArguments . $Period_arr[$count1]['Representation']['height'][$count2] . " "; } else { $processArguments = $processArguments . $Period_arr[$count1]['height'] . " "; } if ($type === "dynamic") { $processArguments = $processArguments . "-dynamic "; } if ($Period_arr[$count1]['Representation']['startWithSAP'][$count2] != "") { $processArguments = $processArguments . "-startwithsap " . $Period_arr[$count1]['Representation']['startWithSAP'][$count2] . " "; } if (strpos($Period_arr[$count1]['Representation']['profiles'][$count2], "urn:mpeg:dash:profile:isoff-on-demand:2011") !== false) { $processArguments = $processArguments . "-isoondemand "; } if (strpos($Period_arr[$count1]['Representation']['profiles'][$count2], "urn:mpeg:dash:profile:isoff-live:2011") !== false) { $processArguments = $processArguments . "-isolive "; } if (strpos($Period_arr[$count1]['Representation']['profiles'][$count2], "urn:mpeg:dash:profile:isoff-main:2011") !== false) { $processArguments = $processArguments . "-isomain "; } $dash264 = false; if (strpos($Period_arr[$count1]['Representation']['profiles'][$count2], "http://dashif.org/guidelines/dash264") !== false) { $processArguments = $processArguments . "-dash264base "; $dash264 = true; } if ($Period_arr[$count1]['Representation']['ContentProtectionElementCount'][$count2] > 0 && $dash264 == true) { $processArguments = $processArguments . "-dash264enc "; } $processArguments = $processArguments . "-codecs "; if ($Period_arr[$count1]['codecs'] === 0) { $codecs = $Period_arr[$count1]['Representation']['codecs'][$count2]; } else { $codecs = $Period_arr[$count1]['codecs']; } $processArguments = $processArguments . $codecs; // add indexRange to process arguments to give it to MPD validator if ($Period_arr[$count1]['Representation']['indexRange'][$count2] !== null) { $indexRange = $Period_arr[$count1]['Representation']['indexRange'][$count2]; $processArguments = $processArguments . " -indexrange "; $processArguments = $processArguments . $indexRange; } elseif ($Period_arr[$count1]['indexRange'] !== null) { $indexRange = $Period_arr[$count1]['indexRange']; $processArguments = $processArguments . " -indexrange "; $processArguments = $processArguments . $indexRange; } $processArguments = $processArguments . " -audiochvalue "; if ($Period_arr[$count1]['AudioChannelValue'] === 0) { $audioChValue = $Period_arr[$count1]['Representation']['AudioChannelValue'][$count2]; } else { $audioChValue = $Period_arr[$count1]['AudioChannelValue']; } $processArguments = $processArguments . $audioChValue; // $test= $Period_arr[$count1]; // $test1= $Period_arr[$count1]['Representation']['SegmentBase']; // $test2= $Period_arr[$count1]['Representation']['SegmentBase']['RepresentationIndex']; if ($Period_arr[$count1]['Representation']['SegmentTemplate']['RepresentationIndex'] !== null || $Period_arr[$count1]['Representation']['SegmentBase']['RepresentationIndex'] !== null || $Period_arr[$count1]['SegmentTemplate']['RepresentationIndex'] !== null || $Period_arr[$count1]['SegmentBase']['RepresentationIndex'] !== null) { $processArguments = $processArguments . "-repIndex "; } error_log("validatemp4"); // Work out which validator binary to use $validatemp4 = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? "validatemp4-vs2010.exe" : "ValidateMP4.exe"; $file_loc = $locate . "/config_file.txt"; $config_file = fopen($file_loc, "w"); fwrite($config_file, $locate . '/' . $repno . ".mp4 " . "\n"); fwrite($config_file, "-infofile" . "\n"); fwrite($config_file, $locate . '/' . $repno . ".txt" . "\n"); fwrite($config_file, "-offsetinfo" . "\n"); fwrite($config_file, $locate . '/' . $repno . "mdatoffset.txt" . "\n"); //fwrite($config_file, "-logconsole"."\n"); $piece = explode(" ", $processArguments); foreach ($piece as $pie) { if ($pie !== "") { fwrite($config_file, $pie . "\n"); } } fclose($config_file); $command = $locate . '/' . $validatemp4 . " -logconsole -configfile " . $file_loc; file_put_contents("command.txt", $command); exec($command); //Excute conformance software rename($locate . '/' . "leafinfo.txt", $locate . '/' . $repno . "_infofile.txt"); //Rename infor file to contain representation number (to avoid over writing $file_location[] = "temp" . '/' . $foldername . '/' . $repno . "_infofile.html"; $destiny[] = $locate . '/' . $repno . "_infofile.txt"; rename($locate . '/' . "stderr.txt", $locate . '/' . $repno . "log.txt"); //Rename conformance software output file to representation number file $temp_string = str_replace(array('$Template$'), array($repno . "log"), $string_info); // this string shows a text file on HTML file_put_contents($locate . '/' . $repno . "log.html", $temp_string); // Create html file containing log file result $file_location[] = "temp" . '/' . $foldername . '/' . $repno . "log.html"; // add it to file location which is sent to client to get URL of log file on server $destiny[] = $locate . '/' . $repno . "log.txt"; $file_location[] = "temp" . '/' . $repno . "myfile.html"; $destiny[] = $locate . '/' . $repno . "myfile.txt"; $period_url[$count1][$count2] = null; ob_flush(); $count2 = $count2 + 1; $search = file_get_contents($locate . '/' . $repno . "log.txt"); //Search for errors within log file if (strpos($search, "error") === false) { //if no error , notify client with no error $ResultXML->Period[0]->Adaptation[$tempcount1]->Representation[$count2 - 1] = "noerror"; $file_location[] = "noerror"; } else { $ResultXML->Period[0]->Adaptation[$tempcount1]->Representation[$count2 - 1] = "error"; $file_location[] = "error"; //else notify client with error } $ResultXML->Period[0]->Adaptation[$tempcount1]->Representation[$count2 - 1]->addAttribute('url', str_replace($_SERVER['DOCUMENT_ROOT'], 'http://' . $_SERVER['SERVER_NAME'], $locate . '/' . $repno . "log.txt")); $progressXML->asXml(trim($locate . '/progress.xml')); $_SESSION['count2'] = $count2; //Save the counters to session variables in order to use it the next time the client request download of next presentation $_SESSION['count1'] = $count1; $send_string = json_encode($file_location); error_log("RepresentationDownloaded_Return:" . $send_string); // echo $send_string; } else { $count2 = $count2 + 1; $_SESSION['count2'] = $count2; $_SESSION['count1'] = $count1; $file_location[] = 'notexist'; $ResultXML->Period[0]->Adaptation[$tempcount1]->Representation[$count2 - 1] = "notexist"; $send_string = json_encode($file_location); error_log("DownloadError_Return:" . $send_string); // echo $send_string; } } } }
function processAdaptationset($Adapt, $periodProfiles, $periodBitstreamSwitching) { global $Adapt_arr, $Period_arr, $Adapt_urlbase, $adaptsetdepth, $Timeoffset, $perioddepth; //var_dump($Adapt); $dom = new DOMDocument('1.0'); $Adapt = $dom->importNode($Adapt, true); $Adapt = $dom->appendChild($Adapt); if ($Adapt->hasAttributes()) { //Get some attributes from Adaptationset $startWithSAP = $Adapt->getAttribute('startWithSAP'); $segmentAlignment = $Adapt->getAttribute('segmentAlignment'); $subsegmentAlignment = $Adapt->getAttribute('subsegmentAlignment'); $idadapt = $Adapt->getAttribute('id'); $scanType = $Adapt->getAttribute('scanType'); $mimeType = $Adapt->getAttribute('mimeType'); $codecs_AdaptSet = $Adapt->getAttribute('codecs'); // Get codecs, if present in Adaptation Set level if (empty($codecs_AdaptSet)) { $codecs_AdaptSet = 0; } $height_AdaptSet = $Adapt->getAttribute('height'); // Get height, if present in Adaptation Set level if (empty($height_AdaptSet)) { $height_AdaptSet = 0; } $width_AdaptSet = $Adapt->getAttribute('width'); // Get width, if present in Adaptation Set level if (empty($width_AdaptSet)) { $width_AdaptSet = 0; } $adapsetProfiles = $Adapt->getAttribute('profiles'); if ($adapsetProfiles === "") { $adapsetProfiles = $periodProfiles; } $bitstreamSwitching = $Adapt->getAttribute('bitstreamSwitching'); if ($bitstreamSwitching === "") { $bitstreamSwitching = $periodBitstreamSwitching; } $ContentProtection = $dom->getElementsByTagName("ContentProtection"); // Search for Content Protection element $Contentcomponent = $dom->getElementsByTagName("ContentComponent"); //Search for content component attribute $tr = $dom->childNodes->item(0)->nodeName; if ($Contentcomponent->length > 0) { //Check if content component exist $tempContentcomponent = $Contentcomponent->item(0); $contentType = $tempContentcomponent->getAttribute('contentType'); //Get content type } $Adapt_segmentbase = $Adapt->getElementsByTagName('SegmentBase'); //If segment base exist $Adapt_Timeoffset = 0; for ($i = 0; $i < $Adapt_segmentbase->length; $i++) { $base = $Adapt_segmentbase->item(0); $par = $base->parentNode; $name = $par->tagName; if ($name === 'AdaptationSet') { // Check if segment base is direct child of Adapatationset $basearray = processSegmentBase($base); //Process segmentbase if (!empty($basearray[0])) { $Adapt_Timeoffset = $basearray[0]; } //Get timeoffset if (!empty($basearray[1])) { $timescale = $basearray[1]; } //get timescale if (!empty($basearray[2])) { $indexRange_AdaptSet = $basearray[2]; //return array contains indexRange } } } if ($Adapt_Timeoffset === 0) { // if timeoffset exist then It has to replace the one existed on higher nodes $Adapt_Timeoffset = $Timeoffset; } $baseurl = $Adapt->getElementsByTagName("BaseURL"); // check and process baseurl node if it exist in adapationset level // $adaptsetdepth = array(); for ($i = 0; $i < $baseurl->length; $i++) { $base = $baseurl->item($i); $par = $base->parentNode; $name = $par->tagName; if ($name == 'AdaptationSet') { //Confirm Baseurl is direct child of adapationset $Adaptbase = $base->nodeValue; $adaptsetdepth[] = $Adaptbase; // Cumulative baseURL if (isAbsoluteURL($Adaptbase)) { // if baseurl is absolute URL, do not use the location of MPD as base URL: $dir = ""; $perioddepth[0] = ""; } } } $rep_seg_temp = array(); $segmenttemplate = $dom->getElementsByTagName("SegmentTemplate"); //Check if segment template exist in adaptationSet level if ($segmenttemplate->length > 0) { $Adapt_seg_temp_setflag = 0; for ($i = 0; $i < $segmenttemplate->length; $i++) { $seg_arr = array(); $seg = $segmenttemplate->item($i); $par = $seg->parentNode; $name = $par->tagName; if ($name == "AdaptationSet") { $Adapt_seg_temp = processTemplate($seg); $Adapt_seg_temp_setflag = 1; } else { if (!$Adapt_seg_temp_setflag) { $Adapt_seg_temp = null; } } } } else { $Adapt_seg_temp = 0; } //Check if AudioChannelConfiguration exists at AdapatationSet level. $audioChannelConfig_Adapt = $Adapt->getElementsByTagName("AudioChannelConfiguration"); if ($audioChannelConfig_Adapt->length > 0) { $audioCh_Adapt_item = $audioChannelConfig_Adapt->item(0); $parNode = $audioCh_Adapt_item->parentNode; $parName = $parNode->tagName; if ($parName == "AdaptationSet") { $audioCh_Adapt_value = $audioCh_Adapt_item->getAttribute('value'); } else { $audioCh_Adapt_value = 0; } } else { $audioCh_Adapt_value = 0; } $Representation = $dom->getElementsByTagName("Representation"); //Get representations node within Adapatationset if ($Representation->length > 0) { $rep_url = array(); $rep_seg_temp = array(); //Iterate on all representations within the given Adapatationset for ($i = 0; $i < $Representation->length; $i++) { $lastbase = array(); // Contains the latest BaseURL if exist $temprep = $Representation->item($i); $repbaseurl = $temprep->getElementsByTagName('BaseURL'); //check if representation contains BaseURL $Rep_segmentbase = $temprep->getElementsByTagName('SegmentBase'); //Check if segment Base exist if ($Rep_segmentbase->length > 0) { $base = $Rep_segmentbase->item(0); $segarray[] = processSegmentBase($base); // Process segment base if (!empty($segarray[$i][0])) { $Rep_Timeoffset[] = $segarray[$i][0]; } else { $Rep_Timeoffset[] = $Adapt_Timeoffset; } // if not exist get the upper timeoffset if (!empty($segarray[$i][1])) { $timescale = $segarray[$i][1]; } // get timescale if exist if (!empty($segarray[$i][2])) { $indexRange_RepSet[] = $segarray[$i][2]; } //get index range if it exists } else { $Rep_Timeoffset[] = $Adapt_Timeoffset; } // if not exist get the upper timeoffset for ($j = 0; $j < $repbaseurl->length; $j++) { // Get baseurl and Iterate it $base = $repbaseurl->item($j); // baseURL $lastbase[] = $base->nodeValue; // the last compnent in BaseURL } $rep_url[] = $lastbase; // add them in baseURL $repsegment = $temprep->getElementsByTagName("SegmentTemplate"); //In case presentation use SegmentTemplate $pass_seg = $repsegment->item(0); if ($repsegment->length > 0) { $rep_seg_temp[$i] = processTemplate($pass_seg); } //Process segmentTemplate $idvar = $temprep->getAttribute('id'); // Get presentation ID if (empty($idvar)) { $idvar = 0; } $id[$i] = $idvar; // save id within array of ID //Get some Attributes from Presentation $repStartWithSAP[$i] = $temprep->getAttribute('startWithSAP'); if ($repStartWithSAP[$i] === "") { $repStartWithSAP[$i] = $startWithSAP; } $repProfiles[$i] = $temprep->getAttribute('profiles'); if ($repProfiles[$i] === "") { $repProfiles[$i] = $adapsetProfiles; } $codecsvar = $temprep->getAttribute('codecs'); if (empty($codecsvar)) { $codecsvar = 0; } $codecs[$i] = $codecsvar; $widthvar = $temprep->getAttribute('width'); if (empty($widthvar)) { $widthvar = 0; } $width[$i] = $widthvar; $heightvar = $temprep->getAttribute('height'); if (empty($heightvar)) { $heightvar = 0; } $height[$i] = $heightvar; if (empty($scantypevar)) { $scantypevar = $temprep->getAttribute('scanType'); } if (empty($scantypevar)) { $scantypevar = 0; } $scanType = $scantypevar; $frameRatevar = $temprep->getAttribute('frameRate'); if (empty($frameRatevar)) { $frameRatevar = 0; } $frameRate[$i] = $frameRatevar; $sarvar = $temprep->getAttribute('sar'); if (empty($sarvar)) { $sarvar = 0; } $sar[$i] = $sarvar; $bandwidthvar = $temprep->getAttribute('bandwidth'); if (empty($bandwidthvar)) { $bandwidthvar = 0; } $bandwidth[$i] = $bandwidthvar; if ($temprep->hasAttribute('timescale')) { $timescale = $temprep->getAttribute('timescale'); } $ContentProtectionElementCountRep[$i] = $temprep->getElementsByTagName("ContentProtection")->length; //Process ContentProtection if ($ContentProtectionElementCountRep[$i] == 0) { $ContentProtectionElementCountRep[$i] = $ContentProtection->length; } $audioChannelConfig_Rep = $temprep->getElementsByTagName('AudioChannelConfiguration'); //Check if AudioChannelConfiguration exists if ($audioChannelConfig_Rep->length > 0) { $audioCh_Rep_item = $audioChannelConfig_Rep->item(0); $audioCh_Rep_value = $audioCh_Rep_item->getAttribute('value'); $audioCh_value[$i] = $audioCh_Rep_value; } else { $audioCh_value[$i] = 0; } } } } $Adapt_urlbase = $rep_url; //Incase of using BaseURL just add all BaseURLs within array containint all presentations //Array of each presentation containing all attributes and nodes within Presentations $Rep_arr = array('id' => $id, 'codecs' => $codecs, 'width' => $width, 'height' => $height, 'scanType' => $scanType, 'frameRate' => $frameRate, 'sar' => $sar, 'bandwidth' => $bandwidth, 'SegmentTemplate' => $rep_seg_temp, 'SegmentBase' => $segarray, 'startWithSAP' => $repStartWithSAP, 'profiles' => $repProfiles, 'ContentProtectionElementCount' => $ContentProtectionElementCountRep, 'presentationTimeOffset' => $Rep_Timeoffset, 'timescale' => $timescale, 'AudioChannelValue' => $audioCh_value, 'indexRange' => $indexRange_RepSet); // Array of all adapationsets containing all attributes and nodes including Presentations $Adapt_arr = array('startWithSAP' => $startWithSAP, 'segmentAlignment' => $segmentAlignment, 'subsegmentAlignment' => $subsegmentAlignment, 'bitstreamSwitching' => $bitstreamSwitching, 'id' => $idadapt, 'scanType' => $scanType, 'mimeType' => $mimeType, 'SegmentTemplate' => $Adapt_seg_temp, 'SegmentBase' => $basearray, 'codecs' => $codecs_AdaptSet, 'width' => $width_AdaptSet, 'height' => $height_AdaptSet, 'Representation' => $Rep_arr, 'AudioChannelValue' => $audioCh_Adapt_value, 'indexRange' => $indexRange_AdaptSet); /* $Rep_arr=array('id'=>$id,'codecs'=>$codecs,'width'=>$width,'height'=>$height,'scanType'=>$scanType,'frameRate'=>$frameRate, 'sar'=>$sar,'bandwidth'=>$bandwidth,'SegmentTemplate'=>$rep_seg_temp, 'startWithSAP'=>$repStartWithSAP, 'profiles'=>$repProfiles, 'ContentProtectionElementCount'=>$ContentProtectionElementCountRep,'presentationTimeOffset'=>$Rep_Timeoffset,'timescale'=>$timescale,'AudioChannelValue'=>$audioCh_value); // Array of all adapationsets containing all attributes and nodes including Presentations $Adapt_arr=array('startWithSAP'=>$startWithSAP,'segmentAlignment'=>$segmentAlignment,'subsegmentAlignment'=>$subsegmentAlignment,'bitstreamSwitching'=>$bitstreamSwitching, 'id'=>$idadapt,'scanType'=>$scanType,'mimeType'=>$mimeType,'SegmentTemplate'=>$Adapt_seg_temp,'codecs'=>$codecs_AdaptSet,'width'=>$width_AdaptSet,'height'=>$height_AdaptSet,'Representation'=>$Rep_arr,'AudioChannelValue'=>$audioCh_Adapt_value); */ }
/** * Takes in a url, determines whether that url is foreign or not * and returns a boolean * * @param string $url * * @author Andrew Darwin <*****@*****.**> */ function is_link_external($url) { global $domainName; global $DEBUG; $header = "is_link_external(): "; logMessage("{$header} Input link = '{$url}'"); $is_external = false; $relativeTeamPathUnderWWW = getAdjustedCurrentDirectory(); logMessage("{$header} relativeTeamPathUnderWWW = " . "'{$relativeTeamPathUnderWWW}'"); $strippedURL = getLocalPathFromURL($url); $strippedURL = stripLeadingSlash($strippedURL); $relativeTeamPathUnderWWW = stripLeadingSlash($relativeTeamPathUnderWWW); if ($DEBUG && isAbsoluteURL($url)) { $prototypeName = getDirectoryNameFromPath($relativeTeamPathUnderWWW); $relativeTeamPathUnderWWW = getSubstringOfABeforeOccuranceOfB($relativeTeamPathUnderWWW, $prototypeName); } logMessage("{$header} Stripped url = '{$strippedURL}'"); if (directoryAIsChildOfDirectoryB($strippedURL, $relativeTeamPathUnderWWW)) { logMessage("{$header} '{$strippedURL}' is a child of " . "'{$relativeTeamPathUnderWWW}'. Set external to false."); $is_external = false; } else { $is_external = true; logMessage("{$header} '{$strippedURL}' is not a child of " . "'{$relativeTeamPathUnderWWW}'. Set external to true."); } return $is_external; }