119 lines
3.3 KiB
C
119 lines
3.3 KiB
C
#include "cell.h"
|
|
|
|
#define PL_MPEG_IMPLEMENTATION
|
|
#include "pl_mpeg.h"
|
|
|
|
struct datastream {
|
|
plm_t *plm;
|
|
JSValue callback;
|
|
JSContext *js;
|
|
int width;
|
|
int height;
|
|
};
|
|
|
|
typedef struct datastream datastream;
|
|
|
|
#include "cell.h"
|
|
|
|
#include "limits.h"
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "cbuf.h"
|
|
|
|
void datastream_free(JSRuntime *rt,datastream *ds)
|
|
{
|
|
plm_destroy(ds->plm);
|
|
free(ds);
|
|
}
|
|
|
|
QJSCLASS(datastream,)
|
|
|
|
struct datastream *ds_openvideo(void *raw, size_t rawlen)
|
|
{
|
|
struct datastream *ds = malloc(sizeof(*ds));
|
|
void *newraw = malloc(rawlen);
|
|
memcpy(newraw,raw,rawlen);
|
|
ds->plm = plm_create_with_memory(newraw, rawlen, 1);
|
|
|
|
if (!ds->plm) {
|
|
free(ds);
|
|
free(newraw);
|
|
return NULL;
|
|
}
|
|
|
|
return ds;
|
|
}
|
|
|
|
void ds_advance(struct datastream *ds, double s) {
|
|
plm_decode(ds->plm, s);
|
|
}
|
|
|
|
void ds_seek(struct datastream *ds, double time) {
|
|
plm_seek(ds->plm, time, false);
|
|
}
|
|
|
|
double ds_length(struct datastream *ds) {
|
|
return plm_get_duration(ds->plm);
|
|
}
|
|
|
|
JSC_CCALL(datastream_time, return number2js(js,plm_get_time(js2datastream(js,self)->plm)); )
|
|
JSC_CCALL(datastream_seek, ds_seek(js2datastream(js,self), js2number(js,argv[0])))
|
|
JSC_CCALL(datastream_advance, ds_advance(js2datastream(js,self), js2number(js,argv[0])))
|
|
JSC_CCALL(datastream_duration, return number2js(js,ds_length(js2datastream(js,self))))
|
|
JSC_CCALL(datastream_framerate, return number2js(js,plm_get_framerate(js2datastream(js,self)->plm)))
|
|
|
|
JSC_GETSET_CALLBACK(datastream, callback)
|
|
|
|
static const JSCFunctionListEntry js_datastream_funcs[] = {
|
|
MIST_FUNC_DEF(datastream, time, 0),
|
|
MIST_FUNC_DEF(datastream, seek, 1),
|
|
MIST_FUNC_DEF(datastream, advance, 1),
|
|
MIST_FUNC_DEF(datastream, duration, 0),
|
|
MIST_FUNC_DEF(datastream, framerate, 0),
|
|
CGETSET_ADD(datastream, callback),
|
|
};
|
|
|
|
|
|
static void render_frame(plm_t *mpeg, plm_frame_t *frame, void *d) {
|
|
datastream *ds = d;
|
|
if (JS_IsNull(ds->callback)) return;
|
|
uint8_t *rgb = malloc(frame->height*frame->width*4);
|
|
memset(rgb,255,frame->height*frame->width*4);
|
|
plm_frame_to_rgba(frame, rgb, frame->width*4);
|
|
|
|
// Create surface data object instead of SDL_Surface
|
|
JSValue surfData = JS_NewObject(ds->js);
|
|
JS_SetPropertyStr(ds->js, surfData, "width", JS_NewInt32(ds->js, frame->width));
|
|
JS_SetPropertyStr(ds->js, surfData, "height", JS_NewInt32(ds->js, frame->height));
|
|
JS_SetPropertyStr(ds->js, surfData, "format", JS_NewString(ds->js, "rgba32"));
|
|
JS_SetPropertyStr(ds->js, surfData, "pitch", JS_NewInt32(ds->js, frame->width*4));
|
|
JS_SetPropertyStr(ds->js, surfData, "pixels", js_new_blob_stoned_copy(ds->js, rgb, frame->height*frame->width*4));
|
|
|
|
JSValue s[1];
|
|
s[0] = surfData;
|
|
JSValue cb = JS_DupValue(ds->js,ds->callback);
|
|
JSValue ret = JS_Call(ds->js, cb, JS_NULL, 1, s);
|
|
JS_FreeValue(ds->js,cb);
|
|
free(rgb);
|
|
uncaught_exception(ds->js,ret);
|
|
}
|
|
|
|
JSC_CCALL(os_make_video,
|
|
size_t len;
|
|
void *data = js_get_blob_data(js,&len,argv[0]);
|
|
datastream *ds = ds_openvideo(data, len);
|
|
if (!ds) return JS_ThrowReferenceError(js, "Video file was not valid.");
|
|
ds->js = js;
|
|
ds->callback = JS_NULL;
|
|
plm_set_video_decode_callback(ds->plm, render_frame, ds);
|
|
return datastream2js(js,ds);
|
|
)
|
|
|
|
static const JSCFunctionListEntry js_video_funcs[] = {
|
|
MIST_FUNC_DEF(os, make_video, 1),
|
|
};
|
|
|
|
CELL_USE_FUNCS(js_video_funcs)
|