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>
143 lines
4.3 KiB
Diff
143 lines
4.3 KiB
Diff
--- 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) ;
|
|
|