chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer, web workflow engine and protocol, tooling, docs and task records. Large generated evidence, user-testing archives, build snapshots and imported test assets remain untracked. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
32
tools/web/patches/cpython-3.13-webengine-unraisable.patch
Normal file
32
tools/web/patches/cpython-3.13-webengine-unraisable.patch
Normal file
@@ -0,0 +1,32 @@
|
||||
--- a/Python/errors.c
|
||||
+++ b/Python/errors.c
|
||||
@@ -1584,6 +1584,15 @@
|
||||
|
||||
An exception must be set when calling this function. */
|
||||
|
||||
+#ifdef __EMSCRIPTEN__
|
||||
+/* Optional native embedder notification, before allocation, exception
|
||||
+ * normalization, audit hooks or sys.unraisablehook. The embedder must not call
|
||||
+ * Python or retain the exception. Standalone CPython keeps its usual behavior.
|
||||
+ * This also covers a deleted sys.unraisablehook and hook-argument OOM. */
|
||||
+extern void web_engine_python_unraisable(const char *exception_type)
|
||||
+ __attribute__((weak));
|
||||
+#endif
|
||||
+
|
||||
static void
|
||||
format_unraisable_v(const char *format, va_list va, PyObject *obj)
|
||||
{
|
||||
@@ -1598,6 +1607,13 @@
|
||||
PyObject *exc_type, *exc_value, *exc_tb;
|
||||
_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
|
||||
|
||||
+#ifdef __EMSCRIPTEN__
|
||||
+ if (web_engine_python_unraisable != NULL) {
|
||||
+ web_engine_python_unraisable(
|
||||
+ exc_type != NULL && PyType_Check(exc_type)
|
||||
+ ? ((PyTypeObject *)exc_type)->tp_name : NULL);
|
||||
+ }
|
||||
+#endif
|
||||
assert(exc_type != NULL);
|
||||
|
||||
if (exc_type == NULL) {
|
||||
142
tools/web/patches/libsndfile-vorbis-bitrate.patch
Normal file
142
tools/web/patches/libsndfile-vorbis-bitrate.patch
Normal file
@@ -0,0 +1,142 @@
|
||||
--- a/include/sndfile.h
|
||||
+++ b/include/sndfile.h
|
||||
@@ -229,6 +229,9 @@
|
||||
SFC_GET_BITRATE_MODE = 0x1304,
|
||||
SFC_SET_BITRATE_MODE = 0x1305,
|
||||
|
||||
+ /* WebEngine extension: int target bits/s, native Vorbis managed encoding. */
|
||||
+ SFC_WEB_SET_VORBIS_BITRATE = 0x7B01,
|
||||
+
|
||||
/* Cart Chunk support */
|
||||
SFC_SET_CART_INFO = 0x1400,
|
||||
SFC_GET_CART_INFO = 0x1401,
|
||||
--- a/src/ogg_vorbis.c
|
||||
+++ b/src/ogg_vorbis.c
|
||||
@@ -137,6 +137,9 @@
|
||||
vorbis_block vblock ;
|
||||
/* Encoding quality in range [0.0, 1.0]. */
|
||||
double quality ;
|
||||
+ /* WebEngine: zero keeps upstream VBR quality mode. */
|
||||
+ int nominal_bitrate ;
|
||||
+ int header_ready ;
|
||||
/* Offset of the first samples' granule position. */
|
||||
uint64_t pcm_start ;
|
||||
/* Last valid samples' granule position. */
|
||||
@@ -313,20 +316,22 @@
|
||||
VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
|
||||
int k, ret ;
|
||||
|
||||
+ if (vdata->header_ready)
|
||||
+ return 0 ;
|
||||
+
|
||||
vorbis_info_init (&vdata->vinfo) ;
|
||||
|
||||
- /* The style of encoding should be selectable here, VBR quality mode. */
|
||||
- ret = vorbis_encode_init_vbr (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, vdata->quality) ;
|
||||
-
|
||||
-#if 0
|
||||
- ret = vorbis_encode_init (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) ; /* average bitrate mode */
|
||||
- ret = ( vorbis_encode_setup_managed (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1)
|
||||
- || vorbis_encode_ctl (&vdata->vinfo, OV_ECTL_RATEMANAGE_AVG, NULL)
|
||||
- || vorbis_encode_setup_init (&vdata->vinfo)
|
||||
- ) ;
|
||||
-#endif
|
||||
+ /* Select libvorbis' original managed average bitrate encoder when requested.
|
||||
+ ** No bitrate-to-quality approximation: the native codec owns rate control. */
|
||||
+ if (vdata->nominal_bitrate > 0)
|
||||
+ ret = vorbis_encode_init (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate,
|
||||
+ -1, vdata->nominal_bitrate, -1) ;
|
||||
+ else
|
||||
+ ret = vorbis_encode_init_vbr (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, vdata->quality) ;
|
||||
if (ret)
|
||||
+ { vorbis_info_clear (&vdata->vinfo) ;
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
+ } ;
|
||||
|
||||
vdata->gp = 0 ;
|
||||
|
||||
@@ -395,6 +400,7 @@
|
||||
} ;
|
||||
}
|
||||
|
||||
+ vdata->header_ready = SF_TRUE ;
|
||||
return 0 ;
|
||||
} /* vorbis_write_header */
|
||||
|
||||
@@ -402,6 +408,7 @@
|
||||
vorbis_close (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = psf->container_data ;
|
||||
VORBIS_PRIVATE *vdata = psf->codec_data ;
|
||||
+ int error = 0 ;
|
||||
|
||||
if (odata == NULL || vdata == NULL)
|
||||
return 0 ;
|
||||
@@ -411,8 +418,10 @@
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{
|
||||
- if (psf->write_current <= 0)
|
||||
- vorbis_write_header (psf, 0) ;
|
||||
+ /* A rejected rate/rate-channel combination must never drain an
|
||||
+ ** uninitialized encoder or leak its native allocations on close. */
|
||||
+ if (! vdata->header_ready && (error = vorbis_write_header (psf, 0)))
|
||||
+ goto cleanup ;
|
||||
|
||||
vorbis_analysis_wrote (&vdata->vdsp, 0) ;
|
||||
while (vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock) == 1)
|
||||
@@ -441,6 +450,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
+cleanup:
|
||||
/* ogg_page and ogg_packet structs always point to storage in
|
||||
libvorbis. They are never freed or manipulated directly */
|
||||
|
||||
@@ -449,7 +459,7 @@
|
||||
vorbis_comment_clear (&vdata->vcomment) ;
|
||||
vorbis_info_clear (&vdata->vinfo) ;
|
||||
|
||||
- return 0 ;
|
||||
+ return error ;
|
||||
} /* vorbis_close */
|
||||
|
||||
int
|
||||
@@ -515,12 +525,36 @@
|
||||
VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
|
||||
|
||||
switch (command)
|
||||
- { case SFC_SET_COMPRESSION_LEVEL :
|
||||
+ { case SFC_WEB_SET_VORBIS_BITRATE :
|
||||
+ { vorbis_info candidate ;
|
||||
+ int bitrate, result ;
|
||||
+ if (psf->file.mode != SFM_WRITE || psf->have_written || vdata->header_ready ||
|
||||
+ data == NULL || datasize != sizeof (int))
|
||||
+ return SF_FALSE ;
|
||||
+ bitrate = *((int *) data) ;
|
||||
+ if (bitrate <= 0)
|
||||
+ return SF_FALSE ;
|
||||
+
|
||||
+ /* Ask the same encoder to accept the complete rate/channel tuple
|
||||
+ ** before retaining it. A failed command leaves settings unchanged. */
|
||||
+ vorbis_info_init (&candidate) ;
|
||||
+ result = vorbis_encode_init (&candidate, psf->sf.channels, psf->sf.samplerate,
|
||||
+ -1, bitrate, -1) ;
|
||||
+ vorbis_info_clear (&candidate) ;
|
||||
+ if (result)
|
||||
+ return SF_FALSE ;
|
||||
+ vdata->nominal_bitrate = bitrate ;
|
||||
+ return SF_TRUE ;
|
||||
+ } ;
|
||||
+
|
||||
+ case SFC_SET_COMPRESSION_LEVEL :
|
||||
if (data == NULL || datasize != sizeof (double))
|
||||
return SF_FALSE ;
|
||||
|
||||
- if (psf->have_written)
|
||||
+ if (psf->file.mode != SFM_WRITE || psf->have_written || vdata->header_ready)
|
||||
return SF_FALSE ;
|
||||
+
|
||||
+ vdata->nominal_bitrate = 0 ;
|
||||
|
||||
vdata->quality = 1.0 - *((double *) data) ;
|
||||
|
||||
Reference in New Issue
Block a user