|
|
|
@ -3,22 +3,21 @@
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
|
|
|
|
(() => {
|
|
|
|
import * as cvatData from 'cvat-data';
|
|
|
|
const cvatData = require('cvat-data');
|
|
|
|
import { isBrowser, isNode } from 'browser-or-node';
|
|
|
|
const PluginRegistry = require('./plugins').default;
|
|
|
|
import PluginRegistry from './plugins';
|
|
|
|
const serverProxy = require('./server-proxy').default;
|
|
|
|
import serverProxy from './server-proxy';
|
|
|
|
const { isBrowser, isNode } = require('browser-or-node');
|
|
|
|
import { Exception, ArgumentError, DataError } from './exceptions';
|
|
|
|
const { Exception, ArgumentError, DataError } = require('./exceptions');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is the frames storage
|
|
|
|
// This is the frames storage
|
|
|
|
const frameDataCache = {};
|
|
|
|
const frameDataCache = {};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Class provides meta information about specific frame and frame itself
|
|
|
|
* Class provides meta information about specific frame and frame itself
|
|
|
|
* @memberof module:API.cvat.classes
|
|
|
|
* @memberof module:API.cvat.classes
|
|
|
|
* @hideconstructor
|
|
|
|
* @hideconstructor
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
class FrameData {
|
|
|
|
export class FrameData {
|
|
|
|
constructor({
|
|
|
|
constructor({
|
|
|
|
width,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
height,
|
|
|
|
@ -169,9 +168,9 @@
|
|
|
|
set imageData(imageData) {
|
|
|
|
set imageData(imageData) {
|
|
|
|
this._data.imageData = imageData;
|
|
|
|
this._data.imageData = imageData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FrameData.prototype.data.implementation = async function (onServerRequest) {
|
|
|
|
FrameData.prototype.data.implementation = async function (onServerRequest) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const resolveWrapper = (data) => {
|
|
|
|
const resolveWrapper = (data) => {
|
|
|
|
this._data = {
|
|
|
|
this._data = {
|
|
|
|
@ -383,9 +382,9 @@
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function getFrameMeta(jobID, frame) {
|
|
|
|
function getFrameMeta(jobID, frame) {
|
|
|
|
const { meta, mode, startFrame } = frameDataCache[jobID];
|
|
|
|
const { meta, mode, startFrame } = frameDataCache[jobID];
|
|
|
|
let size = null;
|
|
|
|
let size = null;
|
|
|
|
if (mode === 'interpolation') {
|
|
|
|
if (mode === 'interpolation') {
|
|
|
|
@ -400,9 +399,9 @@
|
|
|
|
throw new DataError(`Invalid mode is specified ${mode}`);
|
|
|
|
throw new DataError(`Invalid mode is specified ${mode}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class FrameBuffer {
|
|
|
|
class FrameBuffer {
|
|
|
|
constructor(size, chunkSize, stopFrame, jobID) {
|
|
|
|
constructor(size, chunkSize, stopFrame, jobID) {
|
|
|
|
this._size = size;
|
|
|
|
this._size = size;
|
|
|
|
this._buffer = {};
|
|
|
|
this._buffer = {};
|
|
|
|
@ -628,9 +627,9 @@
|
|
|
|
cachedFrames() {
|
|
|
|
cachedFrames() {
|
|
|
|
return Object.keys(this._buffer).map((f) => +f);
|
|
|
|
return Object.keys(this._buffer).map((f) => +f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function getImageContext(jobID, frame) {
|
|
|
|
async function getImageContext(jobID, frame) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
serverProxy.frames
|
|
|
|
serverProxy.frames
|
|
|
|
.getImageContext(jobID, frame)
|
|
|
|
.getImageContext(jobID, frame)
|
|
|
|
@ -650,18 +649,18 @@
|
|
|
|
reject(error);
|
|
|
|
reject(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function getContextImage(jobID, frame) {
|
|
|
|
export async function getContextImage(jobID, frame) {
|
|
|
|
if (frameDataCache[jobID].frameBuffer.isContextImageAvailable(frame)) {
|
|
|
|
if (frameDataCache[jobID].frameBuffer.isContextImageAvailable(frame)) {
|
|
|
|
return frameDataCache[jobID].frameBuffer.getContextImage(frame);
|
|
|
|
return frameDataCache[jobID].frameBuffer.getContextImage(frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const response = getImageContext(jobID, frame);
|
|
|
|
const response = getImageContext(jobID, frame);
|
|
|
|
frameDataCache[jobID].frameBuffer.addContextImage(frame, response);
|
|
|
|
frameDataCache[jobID].frameBuffer.addContextImage(frame, response);
|
|
|
|
return frameDataCache[jobID].frameBuffer.getContextImage(frame);
|
|
|
|
return frameDataCache[jobID].frameBuffer.getContextImage(frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function getPreview(taskID = null, jobID = null) {
|
|
|
|
export async function getPreview(taskID = null, jobID = null) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
// Just go to server and get preview (no any cache)
|
|
|
|
// Just go to server and get preview (no any cache)
|
|
|
|
serverProxy.frames
|
|
|
|
serverProxy.frames
|
|
|
|
@ -682,9 +681,9 @@
|
|
|
|
reject(error);
|
|
|
|
reject(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function getFrame(
|
|
|
|
export async function getFrame(
|
|
|
|
jobID,
|
|
|
|
jobID,
|
|
|
|
chunkSize,
|
|
|
|
chunkSize,
|
|
|
|
chunkType,
|
|
|
|
chunkType,
|
|
|
|
@ -695,7 +694,7 @@
|
|
|
|
isPlaying,
|
|
|
|
isPlaying,
|
|
|
|
step,
|
|
|
|
step,
|
|
|
|
dimension,
|
|
|
|
dimension,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
if (!(jobID in frameDataCache)) {
|
|
|
|
if (!(jobID in frameDataCache)) {
|
|
|
|
const blockType = chunkType === 'video' ? cvatData.BlockType.MP4VIDEO : cvatData.BlockType.ARCHIVE;
|
|
|
|
const blockType = chunkType === 'video' ? cvatData.BlockType.MP4VIDEO : cvatData.BlockType.ARCHIVE;
|
|
|
|
const meta = await serverProxy.frames.getMeta('job', jobID);
|
|
|
|
const meta = await serverProxy.frames.getMeta('job', jobID);
|
|
|
|
@ -739,9 +738,9 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return frameDataCache[jobID].frameBuffer.require(frame, jobID, isPlaying, step);
|
|
|
|
return frameDataCache[jobID].frameBuffer.require(frame, jobID, isPlaying, step);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function getDeletedFrames(instanceType, id) {
|
|
|
|
export async function getDeletedFrames(instanceType, id) {
|
|
|
|
if (instanceType === 'job') {
|
|
|
|
if (instanceType === 'job') {
|
|
|
|
const { meta } = frameDataCache[id];
|
|
|
|
const { meta } = frameDataCache[id];
|
|
|
|
return meta.deleted_frames;
|
|
|
|
return meta.deleted_frames;
|
|
|
|
@ -754,21 +753,21 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
throw new Exception(`getDeletedFrames is not implemented for ${instanceType}`);
|
|
|
|
throw new Exception(`getDeletedFrames is not implemented for ${instanceType}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function deleteFrame(jobID, frame) {
|
|
|
|
export function deleteFrame(jobID, frame) {
|
|
|
|
const { meta } = frameDataCache[jobID];
|
|
|
|
const { meta } = frameDataCache[jobID];
|
|
|
|
meta.deleted_frames[frame] = true;
|
|
|
|
meta.deleted_frames[frame] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function restoreFrame(jobID, frame) {
|
|
|
|
export function restoreFrame(jobID, frame) {
|
|
|
|
const { meta } = frameDataCache[jobID];
|
|
|
|
const { meta } = frameDataCache[jobID];
|
|
|
|
if (frame in meta.deleted_frames) {
|
|
|
|
if (frame in meta.deleted_frames) {
|
|
|
|
delete meta.deleted_frames[frame];
|
|
|
|
delete meta.deleted_frames[frame];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function patchMeta(jobID) {
|
|
|
|
export async function patchMeta(jobID) {
|
|
|
|
const { meta } = frameDataCache[jobID];
|
|
|
|
const { meta } = frameDataCache[jobID];
|
|
|
|
const newMeta = await serverProxy.frames.saveMeta('job', jobID, {
|
|
|
|
const newMeta = await serverProxy.frames.saveMeta('job', jobID, {
|
|
|
|
deleted_frames: Object.keys(meta.deleted_frames),
|
|
|
|
deleted_frames: Object.keys(meta.deleted_frames),
|
|
|
|
@ -785,9 +784,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
frameDataCache[jobID].meta = newMeta;
|
|
|
|
frameDataCache[jobID].meta = newMeta;
|
|
|
|
frameDataCache[jobID].meta.deleted_frames = prevDeletedFrames;
|
|
|
|
frameDataCache[jobID].meta.deleted_frames = prevDeletedFrames;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function findNotDeletedFrame(jobID, frameFrom, frameTo, offset) {
|
|
|
|
export async function findNotDeletedFrame(jobID, frameFrom, frameTo, offset) {
|
|
|
|
let meta;
|
|
|
|
let meta;
|
|
|
|
if (!frameDataCache[jobID]) {
|
|
|
|
if (!frameDataCache[jobID]) {
|
|
|
|
meta = await serverProxy.frames.getMeta('job', jobID);
|
|
|
|
meta = await serverProxy.frames.getMeta('job', jobID);
|
|
|
|
@ -810,9 +809,9 @@
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return lastUndeletedFrame;
|
|
|
|
return lastUndeletedFrame;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getRanges(jobID) {
|
|
|
|
export function getRanges(jobID) {
|
|
|
|
if (!(jobID in frameDataCache)) {
|
|
|
|
if (!(jobID in frameDataCache)) {
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
decoded: [],
|
|
|
|
decoded: [],
|
|
|
|
@ -824,26 +823,11 @@
|
|
|
|
decoded: frameDataCache[jobID].provider.cachedFrames,
|
|
|
|
decoded: frameDataCache[jobID].provider.cachedFrames,
|
|
|
|
buffered: frameDataCache[jobID].frameBuffer.cachedFrames(),
|
|
|
|
buffered: frameDataCache[jobID].frameBuffer.cachedFrames(),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function clear(jobID) {
|
|
|
|
export function clear(jobID) {
|
|
|
|
if (jobID in frameDataCache) {
|
|
|
|
if (jobID in frameDataCache) {
|
|
|
|
frameDataCache[jobID].frameBuffer.clear();
|
|
|
|
frameDataCache[jobID].frameBuffer.clear();
|
|
|
|
delete frameDataCache[jobID];
|
|
|
|
delete frameDataCache[jobID];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
|
|
|
FrameData,
|
|
|
|
|
|
|
|
getFrame,
|
|
|
|
|
|
|
|
getDeletedFrames,
|
|
|
|
|
|
|
|
deleteFrame,
|
|
|
|
|
|
|
|
restoreFrame,
|
|
|
|
|
|
|
|
patchMeta,
|
|
|
|
|
|
|
|
getRanges,
|
|
|
|
|
|
|
|
getPreview,
|
|
|
|
|
|
|
|
clear,
|
|
|
|
|
|
|
|
findNotDeletedFrame,
|
|
|
|
|
|
|
|
getContextImage,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|