rx-player
Version:
Canal+ HTML5 Video Player
98 lines (93 loc) • 2.97 kB
text/typescript
import type { ISegment } from "../../manifest";
import type { ICdnMetadata } from "../../parsers/manifest";
import request from "../../utils/request/xhr";
import type { CancellationSignal } from "../../utils/task_canceller";
import type {
IRequestedData,
IThumbnailContext,
IThumbnailLoaderOptions,
IThumbnailResponse,
} from "../types";
import addQueryString from "../utils/add_query_string";
import byteRange from "../utils/byte_range";
import constructSegmentUrl from "./construct_segment_url";
/**
* Load thumbnails for DASH content.
* @param {Object|null} wantedCdn
* @param {Object} thumbnail
* @param {Object} options
* @param {Object} cancelSignal
* @returns {Promise}
*/
export async function loadThumbnail(
wantedCdn: ICdnMetadata | null,
thumbnail: ISegment,
options: IThumbnailLoaderOptions,
cancelSignal: CancellationSignal,
): Promise<IRequestedData<ArrayBuffer>> {
const initialUrl = constructSegmentUrl(wantedCdn, thumbnail);
if (initialUrl === null) {
return Promise.reject(new Error("Cannot load thumbnail: no URL"));
}
const url =
options.cmcdPayload?.type === "query"
? addQueryString(initialUrl, options.cmcdPayload.value)
: initialUrl;
const cmcdHeaders =
options.cmcdPayload?.type === "headers" ? options.cmcdPayload.value : undefined;
let headers;
if (thumbnail.range !== undefined) {
headers = {
...cmcdHeaders,
Range: byteRange(thumbnail.range),
};
} else if (cmcdHeaders !== undefined) {
headers = cmcdHeaders;
}
return request({
url,
responseType: "arraybuffer",
headers,
timeout: options.timeout,
connectionTimeout: options.connectionTimeout,
cancelSignal,
});
}
/**
* Parse loaded thumbnail data into exploitable thumbnail data and metadata.
* @param {ArrayBuffer} data - The loaded thumbnail data
* @param {Object} context
* @returns {Object}
*/
export function parseThumbnail(
data: ArrayBuffer,
context: IThumbnailContext,
): IThumbnailResponse {
const { thumbnailTrack, thumbnail: wantedThumbnail } = context;
const height = thumbnailTrack.height / thumbnailTrack.verticalTiles;
const width = thumbnailTrack.width / thumbnailTrack.horizontalTiles;
const thumbnails = [];
const tileDuration =
thumbnailTrack.tileDuration ??
(wantedThumbnail.end - wantedThumbnail.time) /
(thumbnailTrack.horizontalTiles * thumbnailTrack.verticalTiles);
let start = wantedThumbnail.time;
for (let row = 0; row < thumbnailTrack.verticalTiles; row++) {
for (let column = 0; column < thumbnailTrack.horizontalTiles; column++) {
thumbnails.push({
start,
end: start + tileDuration,
offsetX: Math.round(column * width),
offsetY: Math.round(row * height),
height: Math.floor(height),
width: Math.floor(width),
});
start += tileDuration;
}
}
return {
mimeType: thumbnailTrack.mimeType,
data,
thumbnails,
};
}