[xiph-commits] r17333 - in experimental/derf/theora-ptalarbvorm: include/theora lib
tterribe at svn.xiph.org
tterribe at svn.xiph.org
Fri Jul 16 09:47:23 PDT 2010
Author: tterribe
Date: 2010-07-16 09:47:23 -0700 (Fri, 16 Jul 2010)
New Revision: 17333
Modified:
experimental/derf/theora-ptalarbvorm/include/theora/theoraenc.h
experimental/derf/theora-ptalarbvorm/lib/Makefile.am
experimental/derf/theora-ptalarbvorm/lib/encode.c
experimental/derf/theora-ptalarbvorm/lib/enquant.c
experimental/derf/theora-ptalarbvorm/lib/enquant.h
experimental/derf/theora-ptalarbvorm/lib/huffenc.c
experimental/derf/theora-ptalarbvorm/lib/huffenc.h
Log:
Add encoder support for copying the configuration of an existing setup header.
This allows an application to re-encode portions of or splice additional frames
into an existing stream without resorting to chaining.
Modified: experimental/derf/theora-ptalarbvorm/include/theora/theoraenc.h
===================================================================
--- experimental/derf/theora-ptalarbvorm/include/theora/theoraenc.h 2010-07-14 21:42:37 UTC (rev 17332)
+++ experimental/derf/theora-ptalarbvorm/include/theora/theoraenc.h 2010-07-16 16:47:23 UTC (rev 17333)
@@ -43,7 +43,7 @@
* <tt>NULL</tt> may be specified to revert to the default tables.
*
* \param[in] _buf <tt>#th_huff_code[#TH_NHUFFMAN_TABLES][#TH_NDCT_TOKENS]</tt>
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
* \retval TH_EINVAL Encoding has already begun or one or more of the given
* tables is not full or prefix-free, \a _buf is
* <tt>NULL</tt> and \a _buf_sz is not zero, or \a _buf is
@@ -57,7 +57,7 @@
* <tt>NULL</tt> may be specified to revert to the default parameters.
*
* \param[in] _buf #th_quant_info
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
* \retval TH_EINVAL Encoding has already begun, \a _buf is
* <tt>NULL</tt> and \a _buf_sz is not zero,
* or \a _buf is non-<tt>NULL</tt> and
@@ -73,7 +73,7 @@
* \param[in] _buf <tt>ogg_uint32_t</tt>: The maximum distance between key
* frames.
* \param[out] _buf <tt>ogg_uint32_t</tt>: The actual maximum distance set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(ogg_uint32_t)</tt>.
* \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE (4)
@@ -101,7 +101,7 @@
* 4:2:0, the picture region is smaller than the full frame,
* or if encoding has begun, preventing the quantization
* tables and codebooks from being set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_VP3_COMPATIBLE (10)
@@ -114,7 +114,7 @@
* the current encoding mode (VBR vs. constant quality, etc.).
*
* \param[out] _buf <tt>int</tt>: The maximum encoding speed level.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation in the current
* encoding mode.*/
@@ -124,7 +124,7 @@
*
* \param[in] _buf <tt>int</tt>: The new encoding speed level.
* 0 is slowest, larger values use less CPU.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or the
* encoding speed level is out of bounds.
* The maximum encoding speed level may be
@@ -142,7 +142,7 @@
*
* \param[out] _buf <tt>int</tt>: The current encoding speed level.
* 0 is slowest, larger values use less CPU.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
* \retval TH_EIMPL Not supported by this implementation in the current
* encoding mode.*/
@@ -162,7 +162,7 @@
*
* \param[in] _buf <tt>int</tt>: The number of duplicates to produce.
* If this is negative or zero, no duplicates will be produced.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or the
* number of duplicates is greater than or equal to the
* maximum keyframe interval.
@@ -187,7 +187,7 @@
* use.
* - #TH_RATECTL_CAP_UNDERFLOW: Don't try to make up shortfalls
* later.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt> or rate control
* is not enabled.
* \retval TH_EIMPL Not supported by this implementation in the current
@@ -211,7 +211,7 @@
* \param[in] _buf <tt>int</tt>: Requested size of the reservoir measured in
* frames.
* \param[out] _buf <tt>int</tt>: The actual size of the reservoir set.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or rate control
* is not enabled. The buffer has an implementation
* defined minimum and maximum size and the value in _buf
@@ -243,7 +243,7 @@
* application.
* \retval >=0 The number of bytes of metric data available in the
* returned buffer.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL \a _buf_sz is not <tt>sizeof(char *)</tt>, no target
* bitrate has been set, or the first call was made after
* the first frame was submitted for encoding.
@@ -283,7 +283,7 @@
* of bytes consumed.
* \retval >0 The number of bytes of metric data required/consumed.
* \retval 0 No more data is required before the next frame.
- * \retval TH_EFAULT \a _enc_ctx is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc is <tt>NULL</tt>.
* \retval TH_EINVAL No target bitrate has been set, or the first call was
* made after the first frame was submitted for
* encoding.
@@ -306,7 +306,7 @@
* \param[in] _buf <tt>int</tt>: The new target quality, in the range 0...63,
* inclusive.
* \retval 0 Success.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL A target bitrate has already been specified, or the
* quality index was not in the range 0...63.
* \retval TH_EIMPL Not supported by this implementation.*/
@@ -328,10 +328,50 @@
*
* \param[in] _buf <tt>long</tt>: The new target bitrate, in bits per second.
* \retval 0 Success.
- * \retval TH_EFAULT \a _enc_ctx or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
* \retval TH_EINVAL The target bitrate was not positive.
* \retval TH_EIMPL Not supported by this implementation.*/
#define TH_ENCCTL_SET_BITRATE (30)
+/**Sets the configuration to be compatible with that from the given setup
+ * header.
+ * This sets the Huffman codebooks and quantization parameters to match those
+ * found in the given setup header.
+ * This guarantees that packets encoded by this encoder will be decodable using
+ * a decoder configured with the passed-in setup header.
+ * It does <em>not</em> guarantee that th_encode_flushheader() will produce a
+ * bit-identical setup header, only that they will be compatible.
+ * If you need a bit-identical setup header, then use the one you passed into
+ * this command, and not the one returned by th_encode_flushheader().
+ *
+ * This also does <em>not</em> enable or disable VP3 compatibility; that is not
+ * signaled in the setup header (or anywhere else in the encoded stream), and
+ * is controlled independently by the #TH_ENCCTL_SET_VP3_COMPATIBLE function.
+ * If you wish to enable VP3 compatibility mode <em>and</em> want the codebooks
+ * and quantization parameters to match the given setup header, you should
+ * enable VP3 compatibility before invoking this command, otherwise the
+ * codebooks and quantization parameters will be reset to the VP3 defaults.
+ *
+ * The current encoder does not support Huffman codebooks which do not contain
+ * codewords for all 32 tokens.
+ * Such codebooks are legal, according to the specification, but cannot be
+ * configured with this function.
+ *
+ * \param[in] _buf <tt>unsigned char[]</tt>: The encoded setup header to copy
+ * the configuration from.
+ * This should be the original,
+ * undecoded setup header packet,
+ * and <em>not</em> a #th_setup_info
+ * structure filled in by
+ * th_decode_headerin().
+ * \retval TH_EFAULT \a _enc or \a _buf is <tt>NULL</tt>.
+ * \retval TH_EINVAL Encoding has already begun, so the codebooks and
+ * quantization parameters cannot be changed, or the
+ * data in the setup header was not supported by this
+ * encoder.
+ * \retval TH_EBADHEADER \a _buf did not contain a valid setup header packet.
+ * \retval TH_ENOTFORMAT \a _buf did not contain a Theora header at all.
+ * \retval TH_EIMPL Not supported by this implementation.*/
+#define TH_ENCCTL_SET_COMPAT_CONFIG (32)
/*@}*/
Modified: experimental/derf/theora-ptalarbvorm/lib/Makefile.am
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/Makefile.am 2010-07-14 21:42:37 UTC (rev 17332)
+++ experimental/derf/theora-ptalarbvorm/lib/Makefile.am 2010-07-16 16:47:23 UTC (rev 17333)
@@ -84,6 +84,8 @@
encoder_sources = \
apiwrapper.c \
+ bitpack.c \
+ dequant.c \
fragment.c \
idct.c \
internal.c \
Modified: experimental/derf/theora-ptalarbvorm/lib/encode.c
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/encode.c 2010-07-14 21:42:37 UTC (rev 17332)
+++ experimental/derf/theora-ptalarbvorm/lib/encode.c 2010-07-16 16:47:23 UTC (rev 17333)
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <string.h>
#include "encint.h"
+#include "dequant.h"
#if defined(OC_X86_ASM)
# include "x86/x86enc.h"
#endif
@@ -1093,6 +1094,17 @@
}
}
+/*Updates the encoder state after the quantization parameters have been
+ changed.*/
+static void oc_enc_quant_params_updated(oc_enc_ctx *_enc,
+ const th_quant_info *_qinfo){
+ oc_enc_enquant_tables_init(_enc,_qinfo);
+ memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits,
+ sizeof(_enc->state.loop_filter_limits));
+ oc_enquant_qavg_init(_enc->log_qavg,_enc->log_plq,_enc->chroma_rd_scale,
+ _enc->state.dequant_tables,_enc->state.info.pixel_fmt);
+}
+
/*Sets the quantization parameters to use.
This may only be called before the setup header is written.
If it is called multiple times, only the last call has any effect.
@@ -1102,16 +1114,20 @@
will be used.*/
static int oc_enc_set_quant_params(oc_enc_ctx *_enc,
const th_quant_info *_qinfo){
+ th_quant_info old_qinfo;
+ int ret;
if(_enc==NULL)return TH_EFAULT;
if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
if(_qinfo==NULL)_qinfo=&TH_DEF_QUANT_INFO;
- /*TODO: Analyze for packing purposes instead of just doing a shallow copy.*/
- memcpy(&_enc->qinfo,_qinfo,sizeof(_enc->qinfo));
- oc_enc_enquant_tables_init(_enc,_qinfo);
- memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits,
- sizeof(_enc->state.loop_filter_limits));
- oc_enquant_qavg_init(_enc->log_qavg,_enc->log_plq,_enc->chroma_rd_scale,
- _enc->state.dequant_tables,_enc->state.info.pixel_fmt);
+ memcpy(&old_qinfo,&_enc->qinfo,sizeof(old_qinfo));
+ ret=oc_quant_params_clone(&_enc->qinfo,_qinfo);
+ if(ret<0){
+ oc_quant_params_clear(&_enc->qinfo);
+ memcpy(&_enc->qinfo,&old_qinfo,sizeof(old_qinfo));
+ return ret;
+ }
+ else oc_quant_params_clear(&old_qinfo);
+ oc_enc_quant_params_updated(_enc,_qinfo);
return 0;
}
@@ -1180,21 +1196,8 @@
_enc->luma_avg=128<<8;
oc_rc_state_init(&_enc->rc,_enc);
oggpackB_writeinit(&_enc->opb);
- if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL||
- _enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL||
- _enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL||
- _enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL||
- _enc->extra_bits[2]==NULL
-#if defined(OC_COLLECT_METRICS)
- ||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
-#endif
- ){
- oc_enc_clear(_enc);
- return TH_EFAULT;
- }
- oc_mode_scheme_chooser_init(&_enc->chooser);
- oc_enc_mb_info_init(_enc);
- memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs));
+ memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes));
+ memset(_enc->qinfo.qi_ranges,0,sizeof(_enc->qinfo.qi_ranges));
/*Reset the packet-out state machine.*/
_enc->packet_state=OC_PACKET_INFO_HDR;
_enc->dup_count=0;
@@ -1206,8 +1209,21 @@
_enc->vp3_compatible=0;
/*No INTER frames coded yet.*/
_enc->coded_inter_frame=0;
- memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes));
- oc_enc_set_quant_params(_enc,NULL);
+ if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL
+ ||_enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL
+ ||_enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL
+ ||_enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL
+ ||_enc->extra_bits[2]==NULL
+#if defined(OC_COLLECT_METRICS)
+ ||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
+#endif
+ ||oc_enc_set_quant_params(_enc,NULL)<0){
+ oc_enc_clear(_enc);
+ return TH_EFAULT;
+ }
+ oc_mode_scheme_chooser_init(&_enc->chooser);
+ oc_enc_mb_info_init(_enc);
+ memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs));
return 0;
}
@@ -1215,6 +1231,7 @@
int pli;
oc_rc_state_clear(&_enc->rc);
oggpackB_writeclear(&_enc->opb);
+ oc_quant_params_clear(&_enc->qinfo);
_ogg_free(_enc->enquant_table_data);
#if defined(OC_COLLECT_METRICS)
/*Save the collected metrics from this run.
@@ -1370,12 +1387,17 @@
}break;
case TH_ENCCTL_SET_VP3_COMPATIBLE:{
int vp3_compatible;
+ int ret;
if(_enc==NULL||_buf==NULL)return TH_EFAULT;
if(_buf_sz!=sizeof(vp3_compatible))return TH_EINVAL;
+ /*Try this before we change anything else, because it can fail.*/
+ ret=oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO);
+ /*If we can't allocate enough memory, don't change any of the state.*/
+ if(ret==TH_EFAULT)return ret;
vp3_compatible=*(int *)_buf;
_enc->vp3_compatible=vp3_compatible;
if(oc_enc_set_huffman_codes(_enc,TH_VP31_HUFF_CODES)<0)vp3_compatible=0;
- if(oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO)<0)vp3_compatible=0;
+ if(ret<0)vp3_compatible=0;
if(_enc->state.info.pixel_fmt!=TH_PF_420||
_enc->state.info.pic_width<_enc->state.info.frame_width||
_enc->state.info.pic_height<_enc->state.info.frame_height||
@@ -1484,6 +1506,38 @@
}
return oc_enc_rc_2pass_in(_enc,_buf,_buf_sz);
}break;
+ case TH_ENCCTL_SET_COMPAT_CONFIG:{
+ unsigned char buf[7];
+ oc_pack_buf opb;
+ th_quant_info qinfo;
+ th_huff_code huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
+ int ret;
+ int i;
+ if(_enc==NULL||_buf==NULL)return TH_EFAULT;
+ if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
+ oc_pack_readinit(&opb,_buf,_buf_sz);
+ /*Validate the setup packet header.*/
+ for(i=0;i<7;i++)buf[i]=(unsigned char)oc_pack_read(&opb,8);
+ if(!(buf[0]&0x80)||memcmp(buf+1,"theora",6)!=0)return TH_ENOTFORMAT;
+ if(buf[0]!=0x82)return TH_EBADHEADER;
+ /*Reads its contents.*/
+ ret=oc_quant_params_unpack(&opb,&qinfo);
+ if(ret<0){
+ oc_quant_params_clear(&qinfo);
+ return ret;
+ }
+ ret=oc_huff_codes_unpack(&opb,huff_codes);
+ if(ret<0){
+ oc_quant_params_clear(&qinfo);
+ return ret;
+ }
+ /*Install the new state.*/
+ oc_quant_params_clear(&_enc->qinfo);
+ memcpy(&_enc->qinfo,&qinfo,sizeof(qinfo));
+ oc_enc_quant_params_updated(_enc,&qinfo);
+ memcpy(_enc->huff_codes,huff_codes,sizeof(_enc->huff_codes));
+ return 0;
+ }
#if defined(OC_COLLECT_METRICS)
case TH_ENCCTL_SET_METRICS_FILE:{
OC_MODE_METRICS_FILENAME=(const char *)_buf;
Modified: experimental/derf/theora-ptalarbvorm/lib/enquant.c
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/enquant.c 2010-07-14 21:42:37 UTC (rev 17332)
+++ experimental/derf/theora-ptalarbvorm/lib/enquant.c 2010-07-16 16:47:23 UTC (rev 17333)
@@ -20,6 +20,69 @@
+int oc_quant_params_clone(th_quant_info *_dst,const th_quant_info *_src){
+ int i;
+ memcpy(_dst,_src,sizeof(*_dst));
+ memset(_dst->qi_ranges,0,sizeof(_dst->qi_ranges));
+ for(i=0;i<6;i++){
+ int nranges;
+ int qti;
+ int pli;
+ int qtj;
+ int plj;
+ int pdup;
+ int qdup;
+ qti=i/3;
+ pli=i%3;
+ qtj=(i-1)/3;
+ plj=(i-1)%3;
+ nranges=_src->qi_ranges[qti][pli].nranges;
+ /*Check for those duplicates that can be cleanly handled by
+ oc_quant_params_clear().*/
+ pdup=i>0&&nranges<=_src->qi_ranges[qtj][plj].nranges;
+ qdup=qti>0&&nranges<=_src->qi_ranges[0][pli].nranges;
+ _dst->qi_ranges[qti][pli].nranges=nranges;
+ if(pdup&&_src->qi_ranges[qti][pli].sizes==_src->qi_ranges[qtj][plj].sizes){
+ _dst->qi_ranges[qti][pli].sizes=_dst->qi_ranges[qtj][plj].sizes;
+ }
+ else if(qdup&&_src->qi_ranges[1][pli].sizes==_src->qi_ranges[0][pli].sizes){
+ _dst->qi_ranges[1][pli].sizes=_dst->qi_ranges[0][pli].sizes;
+ }
+ else{
+ int *sizes;
+ sizes=(int *)_ogg_malloc(nranges*sizeof(*sizes));
+ /*Note: The caller is responsible for cleaning up any partially
+ constructed qinfo.*/
+ if(sizes==NULL)return TH_EFAULT;
+ memcpy(sizes,_src->qi_ranges[qti][pli].sizes,nranges*sizeof(*sizes));
+ _dst->qi_ranges[qti][pli].sizes=sizes;
+ }
+ if(pdup&&_src->qi_ranges[qti][pli].base_matrices==
+ _src->qi_ranges[qtj][plj].base_matrices){
+ _dst->qi_ranges[qti][pli].base_matrices=
+ _dst->qi_ranges[qtj][plj].base_matrices;
+ }
+ else if(qdup&&_src->qi_ranges[1][pli].base_matrices==
+ _src->qi_ranges[0][pli].base_matrices){
+ _dst->qi_ranges[1][pli].base_matrices=
+ _dst->qi_ranges[0][pli].base_matrices;
+ }
+ else{
+ th_quant_base *base_matrices;
+ base_matrices=(th_quant_base *)_ogg_malloc(
+ (nranges+1)*sizeof(*base_matrices));
+ /*Note: The caller is responsible for cleaning up any partially
+ constructed qinfo.*/
+ if(base_matrices==NULL)return TH_EFAULT;
+ memcpy(base_matrices,_src->qi_ranges[qti][pli].base_matrices,
+ (nranges+1)*sizeof(*base_matrices));
+ _dst->qi_ranges[qti][pli].base_matrices=
+ (const th_quant_base *)base_matrices;
+ }
+ }
+ return 0;
+}
+
void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo){
const th_quant_ranges *qranges;
const th_quant_base *base_mats[2*3*64];
Modified: experimental/derf/theora-ptalarbvorm/lib/enquant.h
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/enquant.h 2010-07-14 21:42:37 UTC (rev 17332)
+++ experimental/derf/theora-ptalarbvorm/lib/enquant.h 2010-07-16 16:47:23 UTC (rev 17333)
@@ -16,6 +16,7 @@
+int oc_quant_params_clone(th_quant_info *_dst,const th_quant_info *_src);
void oc_quant_params_pack(oggpack_buffer *_opb,const th_quant_info *_qinfo);
void oc_iquant_init(oc_iquant *_this,ogg_uint16_t _d);
void oc_enquant_qavg_init(ogg_int64_t _log_qavg[2][64],
Modified: experimental/derf/theora-ptalarbvorm/lib/huffenc.c
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/huffenc.c 2010-07-14 21:42:37 UTC (rev 17332)
+++ experimental/derf/theora-ptalarbvorm/lib/huffenc.c 2010-07-16 16:47:23 UTC (rev 17333)
@@ -859,9 +859,10 @@
/*First, find the maximum code length so we can align all the bit
patterns.*/
maxlen=_codes[i][0].nbits;
- for(j=1;j<TH_NDCT_TOKENS;j++){
- maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
- }
+ for(j=1;j<TH_NDCT_TOKENS;j++)maxlen=OC_MAXI(_codes[i][j].nbits,maxlen);
+ /*It's improbable that a code with more than 32 bits could pass the
+ validation below, but abort early in any case.*/
+ if(maxlen>32)return TH_EINVAL;
mask=(1<<(maxlen>>1)<<(maxlen+1>>1))-1;
/*Copy over the codes into our temporary workspace.
The bit patterns are aligned, and the original entry each code is from
@@ -877,34 +878,92 @@
/*For each leaf of the tree:*/
bpos=maxlen;
for(j=0;j<TH_NDCT_TOKENS;j++){
- int bit;
- /*If this code has any bits at all.*/
- if(entries[j].shift<maxlen){
- /*Descend into the tree, writing a bit for each branch.*/
- for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
- /*Mark this as a leaf node, and write its value.*/
- oggpackB_write(_opb,1,1);
- oggpackB_write(_opb,entries[j].token,5);
- /*For each 1 branch we've descended, back up the tree until we reach a
- 0 branch.*/
- bit=1<<bpos;
- for(;entries[j].pattern&bit;bpos++)bit<<=1;
- /*Validate the code.*/
- if(j+1<TH_NDCT_TOKENS){
- mask=~(bit-1)<<1;
- /*The next entry should have a 1 bit where we had a 0, and should
- match our code above that bit.
- This verifies both fullness and prefix-freeness simultaneously.*/
- if(!(entries[j+1].pattern&bit)||
- (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
- return TH_EINVAL;
- }
+ ogg_uint32_t bit;
+ /*Fail if this code has no bits at all.
+ Technically a codebook with a single 0-bit entry is legal, but the
+ encoder currently does not support codebooks which do not contain all
+ the tokens.*/
+ if(entries[j].shift>=maxlen)return TH_EINVAL;
+ /*Descend into the tree, writing a bit for each branch.*/
+ for(;bpos>entries[j].shift;bpos--)oggpackB_write(_opb,0,1);
+ /*Mark this as a leaf node, and write its value.*/
+ oggpackB_write(_opb,1,1);
+ oggpackB_write(_opb,entries[j].token,5);
+ /*For each 1 branch we've descended, back up the tree until we reach a
+ 0 branch.*/
+ bit=(ogg_uint32_t)1<<bpos;
+ for(;entries[j].pattern&bit;bpos++)bit<<=1;
+ /*Validate the code.*/
+ if(j+1<TH_NDCT_TOKENS){
+ mask=~(bit-1)<<1;
+ /*The next entry should have a 1 bit where we had a 0, and should
+ match our code above that bit.
+ This verifies both fullness and prefix-freeness simultaneously.*/
+ if(!(entries[j+1].pattern&bit)||
+ (entries[j].pattern&mask)!=(entries[j+1].pattern&mask)){
+ return TH_EINVAL;
}
- /*If there are no more codes, we should have ascended back to the top
- of the tree.*/
- else if(bpos<maxlen)return TH_EINVAL;
}
+ /*If there are no more codes, we should have ascended back to the top
+ of the tree.*/
+ else if(bpos<maxlen)return TH_EINVAL;
}
}
return 0;
}
+
+/*This is used to copy the configuration of an existing setup header for use by
+ the encoder.
+ The decoder uses a completely different data structure for the Huffman
+ codebooks.*/
+int oc_huff_codes_unpack(oc_pack_buf *_opb,
+ th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){
+ int ret;
+ int i;
+ ret=0;
+ for(i=0;i<TH_NHUFFMAN_TABLES;i++){
+ ogg_uint32_t code;
+ int len;
+ int ntokens;
+ int nleaves;
+ code=0;
+ len=ntokens=nleaves=0;
+ memset(_codes[i],0,TH_NDCT_TOKENS*sizeof(*_codes[i]));
+ for(;;){
+ long bits;
+ bits=oc_pack_read1(_opb);
+ /*Only process nodes so long as there's more bits in the buffer.*/
+ if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
+ /*Read an internal node:*/
+ if(!bits){
+ len++;
+ /*Don't allow codewords longer than 32 bits.*/
+ if(len>32)return TH_EBADHEADER;
+ }
+ /*Read a leaf node:*/
+ else{
+ ogg_uint32_t code_bit;
+ /*Don't allow more than 32 tokens per codebook.*/
+ if(++nleaves>32)return TH_EBADHEADER;
+ bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
+ /*The current encoder does not support codebooks that do not contain
+ all of the tokens.*/
+ if(_codes[i][bits].nbits>0)return TH_EINVAL;
+ _codes[i][bits].pattern=code>>32-len;
+ _codes[i][bits].nbits=len;
+ code_bit=0x80000000U>>len-1;
+ while(len>0&&(code&code_bit)){
+ code^=code_bit;
+ code_bit<<=1;
+ len--;
+ }
+ if(len<=0)break;
+ code|=code_bit;
+ }
+ }
+ /*The current encoder does not support codebooks that do not contain all of
+ the tokens.*/
+ if(nleaves<32)return TH_EINVAL;
+ }
+ return 0;
+}
Modified: experimental/derf/theora-ptalarbvorm/lib/huffenc.h
===================================================================
--- experimental/derf/theora-ptalarbvorm/lib/huffenc.h 2010-07-14 21:42:37 UTC (rev 17332)
+++ experimental/derf/theora-ptalarbvorm/lib/huffenc.h 2010-07-16 16:47:23 UTC (rev 17333)
@@ -1,6 +1,7 @@
#if !defined(_huffenc_H)
# define _huffenc_H (1)
# include "huffman.h"
+# include "bitpack.h"
@@ -15,5 +16,7 @@
int oc_huff_codes_pack(oggpack_buffer *_opb,
const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]);
+int oc_huff_codes_unpack(oc_pack_buf *_opb,
+ th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]);
#endif
More information about the commits
mailing list