function ParseManifest($cc, $parentManifest) { LogInfo("Processing manifest info...."); $xml = $this->GetManifest($cc, $parentManifest); // Extract baseUrl from manifest url $baseUrl = $xml->xpath("/ns:manifest/ns:baseURL"); if (isset($baseUrl[0])) { $baseUrl = GetString($baseUrl[0]); } else { $baseUrl = $parentManifest; if (strpos($baseUrl, '?') !== false) { $baseUrl = substr($baseUrl, 0, strpos($baseUrl, '?')); } $baseUrl = substr($baseUrl, 0, strrpos($baseUrl, '/')); } $url = $xml->xpath("/ns:manifest/ns:media[@*]"); if (isset($url[0]['href'])) { $count = 1; foreach ($url as $childManifest) { if (isset($childManifest['bitrate'])) { $bitrate = floor(GetString($childManifest['bitrate'])); } else { $bitrate = $count++; } $entry =& $childManifests[$bitrate]; $entry['bitrate'] = $bitrate; $entry['url'] = AbsoluteUrl($baseUrl, GetString($childManifest['href'])); $entry['xml'] = $this->GetManifest($cc, $entry['url']); } unset($entry, $childManifest); } else { $childManifests[0]['bitrate'] = 0; $childManifests[0]['url'] = $parentManifest; $childManifests[0]['xml'] = $xml; } $count = 1; foreach ($childManifests as $childManifest) { $xml = $childManifest['xml']; // Extract baseUrl from manifest url $baseUrl = $xml->xpath("/ns:manifest/ns:baseURL"); if (isset($baseUrl[0])) { $baseUrl = GetString($baseUrl[0]); } else { $baseUrl = $childManifest['url']; if (strpos($baseUrl, '?') !== false) { $baseUrl = substr($baseUrl, 0, strpos($baseUrl, '?')); } $baseUrl = substr($baseUrl, 0, strrpos($baseUrl, '/')); } $streams = $xml->xpath("/ns:manifest/ns:media"); foreach ($streams as $stream) { $array = array(); foreach ($stream->attributes() as $k => $v) { $array[strtolower($k)] = GetString($v); } $array['metadata'] = GetString($stream->{'metadata'}); $stream = $array; if (isset($stream['bitrate'])) { $bitrate = floor($stream['bitrate']); } else { if ($childManifest['bitrate'] > 0) { $bitrate = $childManifest['bitrate']; } else { $bitrate = $count++; } } while (isset($this->media[$bitrate])) { $bitrate++; } $streamId = isset($stream[strtolower('streamId')]) ? $stream[strtolower('streamId')] : ""; $mediaEntry =& $this->media[$bitrate]; $mediaEntry['baseUrl'] = $baseUrl; $mediaEntry['url'] = $stream['url']; if (isRtmpUrl($mediaEntry['baseUrl']) or isRtmpUrl($mediaEntry['url'])) { LogError("Provided manifest is not a valid HDS manifest"); } // Use embedded auth information when available $idx = strpos($mediaEntry['url'], '?'); if ($idx !== false) { $mediaEntry['queryString'] = substr($mediaEntry['url'], $idx); $mediaEntry['url'] = substr($mediaEntry['url'], 0, $idx); if (strlen($this->auth) != 0 and strcmp($this->auth, $mediaEntry['queryString']) != 0) { LogDebug("Manifest overrides 'auth': " . $mediaEntry['queryString']); } } else { $mediaEntry['queryString'] = $this->auth; } if (isset($stream[strtolower('bootstrapInfoId')])) { $bootstrap = $xml->xpath("/ns:manifest/ns:bootstrapInfo[@id='" . $stream[strtolower('bootstrapInfoId')] . "']"); } else { $bootstrap = $xml->xpath("/ns:manifest/ns:bootstrapInfo"); } if (isset($bootstrap[0]['url'])) { $mediaEntry['bootstrapUrl'] = AbsoluteUrl($mediaEntry['baseUrl'], GetString($bootstrap[0]['url'])); if (strpos($mediaEntry['bootstrapUrl'], '?') === false) { $mediaEntry['bootstrapUrl'] .= $this->auth; } } else { $mediaEntry['bootstrap'] = base64_decode(GetString($bootstrap[0])); } if (isset($stream['metadata'])) { $mediaEntry['metadata'] = base64_decode($stream['metadata']); } else { $mediaEntry['metadata'] = ""; } } unset($mediaEntry, $childManifest); } // Available qualities $bitrates = array(); if (!count($this->media)) { LogError("No media entry found"); } krsort($this->media, SORT_NUMERIC); LogDebug("Manifest Entries:\n"); LogDebug(sprintf(" %-8s%s", "Bitrate", "URL")); for ($i = 0; $i < count($this->media); $i++) { $key = KeyName($this->media, $i); $bitrates[] = $key; LogDebug(sprintf(" %-8d%s", $key, $this->media[$key]['url'])); } LogDebug(""); LogInfo("Quality Selection:\n Available: " . implode(' ', $bitrates)); // Quality selection if (is_numeric($this->quality) and isset($this->media[$this->quality])) { $key = $this->quality; $this->media = $this->media[$key]; } else { $this->quality = strtolower($this->quality); switch ($this->quality) { case "low": $this->quality = 2; break; case "medium": $this->quality = 1; break; default: $this->quality = 0; } while ($this->quality >= 0) { $key = KeyName($this->media, $this->quality); if ($key !== NULL) { $this->media = $this->media[$key]; break; } else { $this->quality -= 1; } } } LogInfo(" Selected : " . $key); // Parse initial bootstrap info $this->baseUrl = $this->media['baseUrl']; if (isset($this->media['bootstrapUrl'])) { $this->bootstrapUrl = $this->media['bootstrapUrl']; $this->UpdateBootstrapInfo($cc, $this->bootstrapUrl); } else { $bootstrapInfo = $this->media['bootstrap']; ReadBoxHeader($bootstrapInfo, $pos, $boxType, $boxSize); if ($boxType == "abst") { $this->ParseBootstrapBox($bootstrapInfo, $pos); } else { LogError("Failed to parse bootstrap info"); } } }
function Display($items, $format, $columns) { $numcols = $columns; $numitems = count($items); $numrows = ceil($numitems / $numcols); for ($row = 1; $row <= $numrows; $row++) { $cell = 0; for ($col = 1; $col <= $numcols; $col++) { if ($col === 1) { $cell += $row; printf($format, $cell, KeyName($items, $cell - 1)); } else { $cell += $numrows; if (isset($items[KeyName($items, $cell - 1)])) { printf($format, $cell, KeyName($items, $cell - 1)); } } } echo "\n\n"; } }
function ParseManifest($cc, $manifest) { LogInfo("Processing manifest info...."); $xml = $this->GetManifest($cc, $manifest); $baseUrl = $xml->xpath("/ns:manifest/ns:baseURL"); if (isset($baseUrl[0])) { $baseUrl = GetString($baseUrl[0]); if (substr($baseUrl, -1) != "/") { $baseUrl .= "/"; } } else { $baseUrl = ""; } $url = $xml->xpath("/ns:manifest/ns:media[@*]"); if (isset($url[0]['href'])) { foreach ($url as $manifest) { $bitrate = (int) $manifest['bitrate']; $entry =& $manifests[$bitrate]; $entry['bitrate'] = $bitrate; $href = GetString($manifest['href']); if (substr($href, 0, 1) == "/") { $href = substr($href, 1); } $entry['url'] = NormalizePath($baseUrl . $href); $entry['xml'] = $this->GetManifest($cc, $entry['url']); } } else { $manifests[0]['bitrate'] = 0; $manifests[0]['url'] = $manifest; $manifests[0]['xml'] = $xml; } foreach ($manifests as $manifest) { $xml = $manifest['xml']; // Extract baseUrl from manifest url $baseUrl = $xml->xpath("/ns:manifest/ns:baseURL"); if (isset($baseUrl[0])) { $baseUrl = GetString($baseUrl[0]); if (substr($baseUrl, -1) == "/") { $baseUrl = substr($baseUrl, 0, -1); } } else { $baseUrl = $manifest['url']; if (strpos($baseUrl, '?') !== false) { $baseUrl = substr($baseUrl, 0, strpos($baseUrl, '?')); } $baseUrl = substr($baseUrl, 0, strrpos($baseUrl, '/')); } if (!isHttpUrl($baseUrl)) { LogError("Provided manifest is not a valid HDS manifest"); } $streams = $xml->xpath("/ns:manifest/ns:media"); foreach ($streams as $stream) { $array = array(); foreach ($stream->attributes() as $k => $v) { $array[strtolower($k)] = GetString($v); } $array['metadata'] = GetString($stream->{'metadata'}); $stream = $array; $bitrate = isset($stream['bitrate']) ? (int) $stream['bitrate'] : $manifest['bitrate']; $streamId = isset($stream[strtolower('streamId')]) ? $stream[strtolower('streamId')] : ""; $mediaEntry =& $this->media[$bitrate]; $mediaEntry['baseUrl'] = $baseUrl; if (substr($stream['url'], 0, 1) == "/") { $mediaEntry['url'] = substr($stream['url'], 1); } else { $mediaEntry['url'] = $stream['url']; } if (isset($stream[strtolower('bootstrapInfoId')])) { $bootstrap = $xml->xpath("/ns:manifest/ns:bootstrapInfo[@id='" . $stream[strtolower('bootstrapInfoId')] . "']"); } else { $bootstrap = $xml->xpath("/ns:manifest/ns:bootstrapInfo"); } if (isset($bootstrap[0]['url'])) { $bootstrapUrl = GetString($bootstrap[0]['url']); if (!isHttpUrl($bootstrapUrl)) { $bootstrapUrl = $mediaEntry['baseUrl'] . "/{$bootstrapUrl}"; } $mediaEntry['bootstrapUrl'] = NormalizePath($bootstrapUrl); if ($cc->get($mediaEntry['bootstrapUrl']) != 200) { LogError("Failed to get bootstrap info"); } $mediaEntry['bootstrap'] = $cc->response; } else { $mediaEntry['bootstrap'] = base64_decode(GetString($bootstrap[0])); } if (isset($stream['metadata'])) { $mediaEntry['metadata'] = base64_decode($stream['metadata']); } else { $mediaEntry['metadata'] = ""; } } } // Available qualities $bitrates = array(); if (!count($this->media)) { LogError("No media entry found"); } krsort($this->media, SORT_NUMERIC); LogDebug("Manifest Entries:\n"); LogDebug(sprintf(" %-8s%s", "Bitrate", "URL")); for ($i = 0; $i < count($this->media); $i++) { $key = KeyName($this->media, $i); $bitrates[] = $key; LogDebug(sprintf(" %-8d%s", $key, $this->media[$key]['url'])); } LogDebug(""); LogInfo("Quality Selection:\n Available: " . implode(' ', $bitrates)); // Quality selection if (is_numeric($this->quality) and isset($this->media[$this->quality])) { $key = $this->quality; $this->media = $this->media[$key]; } else { $this->quality = strtolower($this->quality); switch ($this->quality) { case "low": $this->quality = 2; break; case "medium": $this->quality = 1; break; default: $this->quality = 0; } while ($this->quality >= 0) { $key = KeyName($this->media, $this->quality); if ($key !== NULL) { $this->media = $this->media[$key]; break; } else { $this->quality -= 1; } } } LogInfo(" Selected : " . $key); $this->baseUrl = $this->media['baseUrl']; if (isset($this->media['bootstrapUrl'])) { $this->bootstrapUrl = $this->media['bootstrapUrl']; } $bootstrapInfo = $this->media['bootstrap']; ReadBoxHeader($bootstrapInfo, $pos, $boxType, $boxSize); if ($boxType == "abst") { $this->ParseBootstrapBox($bootstrapInfo, $pos); } else { LogError("Failed to parse bootstrap info"); } }
function Display($items, $format, $columns) { global $cli; // Display formatted channels list for external script if ($cli->getParam('list')) { foreach ($items as $name => $url) { echo preg_replace('/=/', '-', $name) . "={$url}\n"; } exit(0); } $numcols = $columns; $numitems = count($items); $numrows = ceil($numitems / $numcols); for ($row = 1; $row <= $numrows; $row++) { $cell = 0; for ($col = 1; $col <= $numcols; $col++) { if ($col === 1) { $cell += $row; printf($format, $cell, KeyName($items, $cell - 1)); } else { $cell += $numrows; if (isset($items[KeyName($items, $cell - 1)])) { printf($format, $cell, KeyName($items, $cell - 1)); } } } echo "\n\n"; } }