[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