[xiph-commits] r8253 - in experimental/dholth/oggpy: . tests

dholth at motherfish-iii.xiph.org dholth at motherfish-iii.xiph.org
Mon Nov 22 17:58:20 PST 2004


Author: dholth
Date: 2004-11-22 17:58:20 -0800 (Mon, 22 Nov 2004)
New Revision: 8253

Added:
   experimental/dholth/oggpy/MANIFEST.in
   experimental/dholth/oggpy/README
   experimental/dholth/oggpy/oggpy_wrappers.cc
   experimental/dholth/oggpy/oggpy_wrappers.h
   experimental/dholth/oggpy/tests/
   experimental/dholth/oggpy/tests/decode.py
   experimental/dholth/oggpy/tests/oggtext.py
   experimental/dholth/oggpy/tests/test.py
   experimental/dholth/oggpy/tests/theoratest.py
   experimental/dholth/oggpy/theora_wrappers.h
   experimental/dholth/oggpy/theoracc.h
   experimental/dholth/oggpy/theorapy.pyste
   experimental/dholth/oggpy/vorbispy.pyste
   experimental/dholth/oggpy/vorbispy_wrappers.cc
   experimental/dholth/oggpy/vorbispy_wrappers.h
Modified:
   experimental/dholth/oggpy/Makefile
   experimental/dholth/oggpy/makeclass.py
   experimental/dholth/oggpy/oggcc.h
   experimental/dholth/oggpy/oggpy.pyste
   experimental/dholth/oggpy/setup.py
Log:
jump to patch-20


Added: experimental/dholth/oggpy/MANIFEST.in
===================================================================
--- experimental/dholth/oggpy/MANIFEST.in	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/MANIFEST.in	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,6 @@
+include Doxyfile MANIFEST.in CHANGELOG COPYING
+include *.pyste *.h
+include tests/*.py
+include tests/encode.py
+include tests/oggtext.py
+include tests/test.py

Modified: experimental/dholth/oggpy/Makefile
===================================================================
--- experimental/dholth/oggpy/Makefile	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/Makefile	2004-11-23 01:58:20 UTC (rev 8253)
@@ -1,6 +1,29 @@
-all:
-	touch oggcc.cc
+PYTHON_HEADER_DIR=/usr/include/python2.3
+BOOST_HEADER_DIR=/home/dholth/opt/include/boost-1_31
+
+all: module
+
+multiple: oggpy.pyste vorbispy.pyste theorapy.pyste
+	pyste --multiple --module=oggpy --out=oggpy -I. -I$(PYTHON_HEADER_DIR) -I$(BOOST_HEADER_DIR) -I$(HOME)/include/theora \
+	oggpy.pyste vorbispy.pyste theorapy.pyste
+
+oggpy.cpp: oggpy_wrappers.h oggcc.cc oggcc.h oggpy.pyste
+	pyste --module=oggpy --out=oggpy.cpp -I. -I$(PYTHON_HEADER_DIR) -I$(BOOST_HEADER_DIR) oggpy.pyste
+
+vorbispy.cpp: vorbispy_wrappers.h oggcc.h vorbiscc.h vorbispy.pyste
+	pyste --module=vorbispy --out=vorbispy.cpp -I. -I$(PYTHON_HEADER_DIR) -I$(BOOST_HEADER_DIR) vorbispy.pyste
+
+theorapy.cpp: oggcc.cc oggcc.h theoracc.h theorapy.pyste
+	pyste --module=theorapy --out=theorapy.cpp -I. \
+	-I$(PYTHON_HEADER_DIR) -I$(BOOST_HEADER_DIR) -I$(HOME)/include/theora  theorapy.pyste
+
+module: oggpy.cpp vorbispy.cpp theorapy.cpp oggcc.cc oggcc.h vorbispy_wrappers.cc vorbispy_wrappers.h
 	python ./setup.py build
 
-doc:
+webcode: tests/*.py
+
+.py .html:
+	code2html $< $@
+
+doc: oggcc.h vorbiscc.h theoracc.h
 	doxygen

Added: experimental/dholth/oggpy/README
===================================================================
--- experimental/dholth/oggpy/README	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/README	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,47 @@
+What's this?
+============
+
+If you've downloaded this, you're probably wondering two things - what's
+it for, and why doesn't it compile?
+
+I wrote this wrapper because I was frustrated with the official ogg/vorbis
+wrapper and to teach myself about Boost.Python.  When encoding the
+official ogg/vorbis Python wrapper could only write its output to a file.
+No tostring() method.  Well, mine has a tostring() method, and it's
+written in a more concise and understandable way thanks to the magic
+of Boost.Python.  Ideally, by combining this wrapper and shoutpy, it will
+be possible to write a program like ices (re-encode and stream ogg/vorbis)
+in Python.
+
+Incidentally, there's a separately usable C++ wrapper here too.
+
+This is a very early release.  By downloading this software, you're
+participating in the receiving end of the 'release early, release often'
+open source philosophy.
+
+Send your feedback to dholth at fastmail.fm.
+
+Thanks,
+
+Daniel Holth
+
+Compiling
+=========
+
+To compile this software, use setup.py.
+	
+Edit the setup:
+	vim setup.py
+
+Compile:
+	python setup.py build
+
+(Possibly):
+	python setup.py install
+
+Basic necessities will include editing setup.py to point to your
+Boost.Python include directory, and possibly removing theora
+support.
+
+Boost.Python 1.31 or CVS is necessary; 1.30 won't work because it lacks
+a str:: constructor used in vorbispy_wrappers.cc

Modified: experimental/dholth/oggpy/makeclass.py
===================================================================
--- experimental/dholth/oggpy/makeclass.py	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/makeclass.py	2004-11-23 01:58:20 UTC (rev 8253)
@@ -42,9 +42,60 @@
 extern int      ogg_page_packets(ogg_page *og);
 
 extern void     ogg_packet_clear(ogg_packet *op);
+
+extern const char *theora_version_string    (void);
+extern ogg_uint32_t theora_version_number   (void);
+
+extern int theora_encode_init       (theora_state *th, theora_info *c);
+
+extern int theora_encode_YUVin      (theora_state *t, yuv_buffer *yuv);
+extern int theora_encode_packetout  (theora_state *t, int last_p, ogg_packet *op);
+
+extern int theora_encode_header     (theora_state *t, ogg_packet *op);
+extern int theora_encode_comment    (theora_comment *tc, ogg_packet *op);
+extern int theora_encode_tables     (theora_state *t, ogg_packet *op);
+
+extern int theora_decode_header     (theora_info  *ci, theora_comment *cc, ogg_packet *op);
+
+extern int theora_decode_init       (theora_state *th, theora_info *c);
+
+extern int theora_decode_packetin   (theora_state *th, ogg_packet *op);
+extern int theora_decode_YUVout     (theora_state *th, yuv_buffer *yuv);
+
+extern double theora_granule_time   (theora_state *th, ogg_int64_t granulepos);
+
+extern void theora_info_init        (theora_info *c);
+extern void theora_info_clear       (theora_info *c);
+extern void theora_clear            (theora_state *t);
+
+extern void theora_comment_init     (theora_comment *tc);
+extern void theora_comment_add      (theora_comment *tc, char *comment);
+extern void theora_comment_add_tag  (theora_comment *tc, char *tag, char *value);
+
+extern char *theora_comment_query       (theora_comment *tc, char *tag, int count);
+extern int   theora_comment_query_count (theora_comment *tc, char *tag);
+extern void  theora_comment_clear       (theora_comment *tc);
+
+extern void  oggpack_writeinit(oggpack_buffer *b);
+extern void  oggpack_writetrunc(oggpack_buffer *b,long bits);
+extern void  oggpack_writealign(oggpack_buffer *b);
+extern void  oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
+extern void  oggpack_reset(oggpack_buffer *b);
+extern void  oggpack_writeclear(oggpack_buffer *b);
+extern void  oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
+extern void  oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
+extern long  oggpack_look(oggpack_buffer *b,int bits);
+extern long  oggpack_look1(oggpack_buffer *b);
+extern void  oggpack_adv(oggpack_buffer *b,int bits);
+extern void  oggpack_adv1(oggpack_buffer *b);
+extern long  oggpack_read(oggpack_buffer *b,int bits);
+extern long  oggpack_read1(oggpack_buffer *b);
+extern long  oggpack_bytes(oggpack_buffer *b);
+extern long  oggpack_bits(oggpack_buffer *b);
+extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
 """
 
-declarations = vorbies.vorbis
+# declarations = vorbies.vorbis
 
 if __name__ == "__main__":
     pre = sre.compile("\s+|(\()|(,)|;|(\))")

Modified: experimental/dholth/oggpy/oggcc.h
===================================================================
--- experimental/dholth/oggpy/oggcc.h	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/oggcc.h	2004-11-23 01:58:20 UTC (rev 8253)
@@ -1,202 +1,257 @@
-/* oggcc.h
+/** oggcc.h
  *
  * A straightforward C++ wrapper for libogg.
  *
- * Daniel Holth <dholth at fastmail.fm>
- * 19 Jan. 2004
+ * @author Daniel Holth <dholth at fastmail.fm>
  */
 
 #ifndef OGGCC_H
 #define OGGCC_H
 
 #include <ogg/ogg.h>
-#include <vorbis/codec.h>
+#include <string>
 
+
+/// enclosure for all oggcc memberse
 namespace ogg {
 
-  class packet {
-    public:
-      ogg_packet data;
-      
-      void clear ()               { ogg_packet_clear(&this->data); }
-  };
+    /// Codec-level packet.
+    class packet {
+        /// packet points to internal data structures.  not sure how memory management works.
+        /// zero packet and free internal storage (NOT SAFE: packet points to internal oggvorbis stuff)
+        /// this method is not called in the ogg, vorbis, or ices source.
+        protected:
+            void clear ( )              { ogg_packet_clear(&this->data); }
 
-  class page {
-    public:
-      ogg_page data;
-      
-      int bos ( )                 { return ogg_page_bos(&this->data); }
-      int continued ( )           { return ogg_page_continued(&this->data); }
-      int eos ( )                 { return ogg_page_eos(&this->data); }
-      int packets ( )             { return ogg_page_packets(&this->data); }
-      int serialno ( )            { return ogg_page_serialno(&this->data); }
-      int version ( )             { return ogg_page_version(&this->data); }
-      long pageno ( )             { return ogg_page_pageno(&this->data); }
-      ogg_int64_t granulepos ( )  { return ogg_page_granulepos(&this->data); }
-      void checksum_set ( )       { return ogg_page_checksum_set(&this->data); }
-  };
+        private:
+            ogg_packet data;
 
-  class stream {
-    public:
-      ogg_stream_state data;
-      
-      int clear ( )                       { return ogg_stream_clear(&this->data); }
-      int destroy ( )	                    { return ogg_stream_destroy(&this->data); }
-      int eos ( )	                        { return ogg_stream_eos(&this->data); }
-      int flush ( ogg_page *og )  	      { return ogg_stream_flush(&this->data, og); }
-      int init ( int serialno )	          { return ogg_stream_init(&this->data, serialno); }
-      int packetin ( ogg_packet *op )	    { return ogg_stream_packetin(&this->data, op); }
-      int packetout ( ogg_packet *op )	  { return ogg_stream_packetout(&this->data, op); }
-      int packetpeek ( ogg_packet *op )	  { return ogg_stream_packetpeek(&this->data, op); }
-      int pagein  ( ogg_page *og )	      { return ogg_stream_pagein(&this->data, og); }
-      int pageout ( ogg_page *og )	      { return ogg_stream_pageout(&this->data, og); }
-      int reset   ( )	                    { return ogg_stream_reset(&this->data); }
-      int reset_serialno ( int serialno )	{ return ogg_stream_reset_serialno(&this->data, serialno); }
-  };
+        public:
+            ogg_packet *get_data( )     { return &this->data; }
 
-  class sync {
-    public:
-      ogg_sync_state data;
-      
-      char *buffer    ( long size )	      { return ogg_sync_buffer (&this->data, size); }
-      int   clear     ( )	                { return ogg_sync_clear (&this->data); }
-      int   destroy   ( )	                { return ogg_sync_destroy (&this->data); }
-      int   init      ( )             	  { return ogg_sync_init (&this->data); }
-      int   pageout   ( ogg_page *og )	  { return ogg_sync_pageout (&this->data, og); }
-      int   reset     ( )	                { return ogg_sync_reset (&this->data); }
-      int   wrote     ( long bytes )	    { return ogg_sync_wrote (&this->data, bytes); }
-      long  pageseek  ( ogg_page *og )	  { return ogg_sync_pageseek (&this->data, og); }
-  };
+            packet ( )                  { /* memset(&data, 0, sizeof(this->data)); // may be redundant anyway */ }
+            virtual ~packet ( )         { }
 
-  
-  namespace vorbis {
+            ogg_int64_t packetno( )     { return this->get_data()->packetno; }
+            ogg_int64_t granulepos( )   { return this->get_data()->granulepos; } // may want to expose only page granulepos, or this may be useful for encode only.
+    };
 
-    class block {
-      public:
-        vorbis_block data;
 
-        int analysis ( ogg_packet *op )  {
-          return vorbis_analysis ( &this->data, op );  }
-        
-        int bitrate_addblock ( )  {
-          return vorbis_bitrate_addblock ( &this->data ); }
-        
-        int block_clear ( )  {
-          return vorbis_block_clear ( &this->data ); }
-        
-        int synthesis ( ogg_packet *op )  {
-          return vorbis_synthesis ( &this->data, op ); }
-        
-        int synthesis_trackonly ( ogg_packet *op )  {
-          return vorbis_synthesis_trackonly ( &this->data, op ); }
+    /// For submitting user data to an ogg stream
+    class userpacket : public packet {
+        private:
+            std::string bytes;
+
+        public:
+            virtual ~userpacket ()    { }
+
+            /// granulepos is the last sample (+1?) in this packet. 
+            // libogg framing sets the packetno for us.
+            userpacket(std::string bytes, ogg_int64_t granulepos, bool bos = false, bool eos = false)
+            {
+                this->bytes = bytes;
+                (const char*)(this->get_data()->packet)     = bytes.c_str();
+                this->get_data()->granulepos = granulepos;
+                this->get_data()->bytes      = bytes.size();
+                this->get_data()->b_o_s      = bos;
+                this->get_data()->e_o_s      = eos;
+            }
     };
 
-    
-    class comment {
-      public:
-        vorbis_comment data;
 
-        char *query ( char *tag , int count )  {
-          return vorbis_comment_query ( &this->data, tag, count ); }
+    /// Shared pieces of the bitpacker.
+    class oggpack_base {
+        private:
+            oggpack_buffer data;
 
-        int query_count ( char *tag )  {
-          return vorbis_comment_query_count ( &this->data, tag ); }
+        public:
+            oggpack_buffer *get_data()          { return &this->data; }
+            unsigned char *get_buffer ( )       { return oggpack_get_buffer ( this->get_data() ); }
 
-        int header_out ( ogg_packet *op )  {
-          return vorbis_commentheader_out ( &this->data, op ); }
+            void readinit ( unsigned char *buf, int bytes )  { oggpack_readinit ( this->get_data(), buf, bytes );  }
 
-        void add ( char *comment )  {
-          vorbis_comment_add ( &this->data, comment ); }
+            /** Start reading data from an ogg packet.
+             *
+             * libogg1 holds a reference to the packet; be careful not to
+             * read after you've invalidated the packet.
+             */
+            void readinit ( packet *p )    {
+                ogg_packet *op;
+                op = p->get_data();
+                this->readinit(op->packet, op->bytes);
 
-        void add_tag ( char *tag , char *contents )  {
-          vorbis_comment_add_tag ( &this->data, tag, contents ); }
+                /* LIBOGG2:
+                 * opb = malloc(oggpack_buffersize()):
+                 * // oggpack_buffersize() is implemented as
+                 * // sizeof(oggpack_buffer), but we don't
+                 * // get that size in our main code.
+                 * oggpack_readinit(op->packet);
+                 */
+            }
+            
+            void writeinit ( )                  { oggpack_writeinit ( this->get_data() );  }
+    };
 
-        void clear ( )  {
-          vorbis_comment_clear ( &this->data ); }
 
-        void init ( )  {
-          vorbis_comment_init ( &this->data ); }
+    /// Little-endian bitpacker.
+    class oggpack : public oggpack_base {
+
+            long bits   ( )             { return oggpack_bits   ( this->get_data() );  }
+            long bytes  ( )             { return oggpack_bytes  ( this->get_data() );  }
+            long look   ( int bits )    { return oggpack_look   ( this->get_data(), bits );  }
+            long look1  ( )             { return oggpack_look1  ( this->get_data() ); }
+            long read   ( int bits )    { return oggpack_read   ( this->get_data(), bits );  }
+            long read1  ( )             { return oggpack_read1  ( this->get_data() ); }
+
+            void adv ( int bits )       { oggpack_adv   ( this->get_data(), bits );  }
+            void adv1 ( )               { oggpack_adv1  ( this->get_data() );  }
+            void reset ( )              { oggpack_reset ( this->get_data() );  }
+
+            void write (unsigned long value, int bits )     { oggpack_write ( this->get_data(), value, bits ); }
+
+            void writealign (  )                            { oggpack_writealign ( this->get_data() ); }
+            void writeclear (  )                            { oggpack_writeclear ( this->get_data() ); }
+            void writecopy  ( void *source, long bits )     { oggpack_writecopy ( this->get_data(), source, bits );  }
+            void writetrunc ( long bits )                   { oggpack_writetrunc ( this->get_data(), bits );  }
     };
 
     
-    class dsp {
-      public:
-        vorbis_dsp_state data;
+    /// Big-endian bitpacker
+    class oggpackB : public oggpack_base {
 
-        double granule_time ( ogg_int64_t granulepos )  {
-          return vorbis_granule_time ( &this->data, granulepos ); }
+            long bits   ( )             { return oggpackB_bits   ( this->get_data() );  }
+            long bytes  ( )             { return oggpackB_bytes  ( this->get_data() );  }
+            long look   ( int bits )    { return oggpackB_look   ( this->get_data(), bits );  }
+            long look1  ( )             { return oggpackB_look1  ( this->get_data() ); }
+            long read   ( int bits )    { return oggpackB_read   ( this->get_data(), bits );  }
+            long read1  ( )             { return oggpackB_read1  ( this->get_data() ); }
 
-        float **analysis_buffer ( int vals )  {
-          return vorbis_analysis_buffer ( &this->data, vals ); }
+            void adv ( int bits )       { oggpackB_adv   ( this->get_data(), bits );  }
+            void adv1 ( )               { oggpackB_adv1  ( this->get_data() );  }
+            void reset ( )              { oggpackB_reset ( this->get_data() );  }
 
-        int analysis_blockout ( vorbis_block *vb )  {
-          return vorbis_analysis_blockout ( &this->data, vb ); }
+            void write (unsigned long value, int bits )     { oggpackB_write ( this->get_data(), value, bits ); }
 
-        int analysis_headerout ( vorbis_comment *vc , ogg_packet *op , ogg_packet *op_comm , ogg_packet *op_code )  {
-          return vorbis_analysis_headerout ( &this->data, vc , op , op_comm , op_code ); }
+            void writealign (  )                            { oggpackB_writealign ( this->get_data() ); }
+            void writeclear (  )                            { oggpackB_writeclear ( this->get_data() ); }
+            void writecopy  ( void *source, long bits )     { oggpackB_writecopy ( this->get_data(), source, bits );  }
+            void writetrunc ( long bits )                   { oggpackB_writetrunc ( this->get_data(), bits );  }
+    };
 
-        int analysis_init ( vorbis_info *vi )  {
-          return vorbis_analysis_init ( &this->data, vi ); }
+    
+    /// Basic unit of ogg bitstream format.
+    class page {
+        private:
 
-        int analysis_wrote ( int vals )  {
-          return vorbis_analysis_wrote ( &this->data, vals ); }
+        public:
+            ogg_page data;  // soon to be privatized, take that social security!
+            ogg_page *get_data()        { return &this->data; }
 
-        int bitrate_flushpacket ( ogg_packet *op )  {
-          return vorbis_bitrate_flushpacket ( &this->data, op ); }
+            /// first page in stream?
+            bool bos ( )                { return (ogg_page_bos(this->get_data())); }
+            bool continued ( )          { return (ogg_page_continued(this->get_data())); }
+            /// last page in stream?
+            bool eos ( )                { return ogg_page_eos(this->get_data()); }
+            /// x.packets() -> number of packets completed on this page
+            int packets ( )             { return ogg_page_packets(this->get_data()); }
+            int serialno ( )            { return ogg_page_serialno(this->get_data()); }
+            int version ( )             { return ogg_page_version(this->get_data()); }
+            long pageno ( )             { return ogg_page_pageno(this->get_data()); }
+            ogg_int64_t granulepos ( )  { return ogg_page_granulepos(this->get_data()); }
+            /// Compute the page's checksum.
+            void checksum_set ( )       { ogg_page_checksum_set(this->get_data()); }
 
-        int block_init ( vorbis_block *vb )  {
-          return vorbis_block_init ( &this->data, vb ); }
+            /// for encoding. concatenate header and body to form a page, pages to form ogg streams.
+            std::string header ( )      { return std::string((char*)this->data.header, (size_t)this->data.header_len); }
+            std::string body ( )        { return std::string((char*)this->data.body, (size_t)this->data.body_len); }
+    };
 
-        int synthesis_blockin ( vorbis_block *vb )  {
-          return vorbis_synthesis_blockin ( &this->data, vb ); }
+    
+    /// Separate raw bitstream into ogg pages.
+    class sync {
+        protected:
+            int   clear     ( )               { return ogg_sync_clear (&this->data); }
+            int   destroy   ( )               { return ogg_sync_destroy (&this->data); }
+            int   init      ( )               { return ogg_sync_init (&this->data); }
+            int   pageout   ( ogg_page *og )  { return ogg_sync_pageout (&this->data, og); }
 
-        int synthesis_init ( vorbis_info *vi )  {
-          return vorbis_synthesis_init ( &this->data, vi ); }
+            /** Skip ahead to beginning of next page.
+             * -n means that we skipped n bytes within the bitstream.
+             *  0 means that the page isn't ready and we need more data. No bytes have been skipped.
+             *  n means that the page was synced at the current location, with a page length of n bytes. 
+             */
+            long  pageseek  ( ogg_page *og )  { return ogg_sync_pageseek (&this->data, og); }
 
-        int synthesis_lapout ( float ***pcm )  {
-          return vorbis_synthesis_lapout ( &this->data, pcm ); }
+        public:
+            ogg_sync_state data;
 
-        int synthesis_pcmout ( float ***pcm )  {
-          return vorbis_synthesis_pcmout ( &this->data, pcm ); }
+            sync ()   { this->init();  }
+            ~sync ()  { this->clear(); }
 
-        int synthesis_read ( int samples )  {
-          return vorbis_synthesis_read ( &this->data, samples ); }
+            /// expose a buffer of at least \c size bytes
+            char *buffer    ( long size )     { return ogg_sync_buffer (&this->data, size); }
+            int   wrote     ( long bytes )    { return ogg_sync_wrote (&this->data, bytes); }
 
-        int synthesis_restart ( )  {
-          return vorbis_synthesis_restart ( &this->data ); }
+            int   pageout   ( page *og )      { return this->pageout(&og->data);  }
+            long  pageseek  ( page *og )      { return this->pageseek(&og->data); }
 
-        void dsp_clear ( )  {
-          vorbis_dsp_clear ( &this->data ); }
+            /// good to call before seeking
+            int   reset     ( )               { return ogg_sync_reset (&this->data); }
     };
 
+    
+    /// Stream
+    class stream {
+        public:
+            ogg_stream_state data;
 
-    class info {
-      public:
-        vorbis_info data;
+        protected:
+            /// allocate non-flat storage for stream
+            int init ( int serialno )             { return ogg_stream_init(&this->data, serialno); }
+            /// dealloc non-flat storage within
+            int clear ( )                         { return ogg_stream_clear(&this->data); }
+            /// delete oggvorbis allocated ogg_stream_state structure (would try to _ogg_free this->data)
+            int destroy ( )                       { return ogg_stream_destroy(&this->data); }
 
-        int info_blocksize ( int zo )  {
-          return vorbis_info_blocksize ( &this->data, zo );  }
+            int flush ( ogg_page *og )            { return ogg_stream_flush(&this->data, og); }
 
-        int synthesis_halfrate ( int flag )  {
-          return vorbis_synthesis_halfrate ( &this->data, flag );  }
+            int packetin ( ogg_packet *op )       { return ogg_stream_packetin(&this->data, op); }
+            int packetout ( ogg_packet *op )      { return ogg_stream_packetout(&this->data, op); }
+            int packetpeek ( ogg_packet *op )     { return ogg_stream_packetpeek(&this->data, op); }
 
-        int synthesis_halfrate_p ( )  {
-          return vorbis_synthesis_halfrate_p ( &this->data );  }
+            int pagein  ( ogg_page *og )          { return ogg_stream_pagein(&this->data, og); }
+            int pageout ( ogg_page *og )          { return ogg_stream_pageout(&this->data, og); }
 
-        int synthesis_headerin ( vorbis_comment *vc, ogg_packet *op )  {
-          return vorbis_synthesis_headerin ( &this->data, vc, op );  }
+        public:
+            stream(int serialno)                  { this->init(serialno); }
+            ~stream()                             { this->clear(); }
 
-        long packet_blocksize ( ogg_packet *op )  {
-          return vorbis_packet_blocksize ( &this->data, op );  }
+            int eos ( )                           { return ogg_stream_eos(&this->data); }
 
-        void info_clear ( )  {
-          return vorbis_info_clear ( &this->data );  }
+            /// use to flush a packet regardles of its size
+            int flush ( page *og )                { return this->flush(&og->data); }
 
-        void info_init ( )  {
-          return vorbis_info_init ( &this->data );  }
+            // decode.  copies page in?
+            int pagein  ( page *og )              { return this->pagein(&og->data); }
+            /// decode.  points a packet at an internal data buffer.
+            int packetout   ( packet *op )        { return this->packetout(op->get_data()); }
+            /** Attempt to assemble a raw data packet and return it without advancing decoding.
+             * 
+             * Before this method is called, an ogg_page should be submitted to the
+             * stream using stream::pagein(). op Pointer to the next packet available
+             * in the bitstream, if any. A NULL value may be passed in the case of
+             * a simple "is there a packet?" check.
+             */
+            int packetpeek  ( packet *op )        { return this->packetpeek(op->get_data()); }
 
+            // encode. copies submitted packet. always returns zero.
+            int packetin ( packet *op )           { return this->packetin(op->get_data()); }
+            int pageout ( page *og )              { return this->pageout(&og->data); }
+
+            /// good to call before seeking
+            int reset   ( )                       { return ogg_stream_reset(&this->data); }
+            int reset_serialno ( int serialno )   { return ogg_stream_reset_serialno(&this->data, serialno); }
     };
-  };
 };
 
 #endif

Modified: experimental/dholth/oggpy/oggpy.pyste
===================================================================
--- experimental/dholth/oggpy/oggpy.pyste	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/oggpy.pyste	2004-11-23 01:58:20 UTC (rev 8253)
@@ -1,11 +1,32 @@
-declaration_code('#include "oggcc.h"')
+def document(element, blurb):
+	"""Add a docstring to a definition"""
+	element._Attribute('doc', blurb)
 
-oggpy = AllFromHeader("oggcc.h")
+Include("oggpy_wrappers.h")
 
-exclude(oggpy.sync.data)
-exclude(oggpy.sync.buffer)
+oggpy    = AllFromHeader("oggcc.h")
+
+# exclude(oggpy.oggpack_base)
+exclude(oggpy.oggpack_base.get_data)
+exclude(oggpy.oggpack_base.get_buffer)
+exclude(oggpy.oggpack.get_buffer)
+exclude(oggpy.oggpack.get_data)
+exclude(oggpy.oggpackB.get_buffer)
+exclude(oggpy.oggpackB.get_data)
 exclude(oggpy.packet.data)
+exclude(oggpy.packet.get_data)
 exclude(oggpy.page.data)
+exclude(oggpy.page.get_data)
 exclude(oggpy.stream.data)
-exclude(oggpy.dsp.analysis_buffer)
-exclude(oggpy.comment.comment_query)
+exclude(oggpy.sync.buffer)
+exclude(oggpy.sync.data)
+exclude(oggpy.sync.wrote)
+exclude(oggpy.userpacket.get_data)
+
+syncwrite = Function("ogg::sync_write", "oggpy_wrappers.h")
+oggpy.syncwrite = syncwrite
+
+document(oggpy.sync, "Separate streams into ogg pages")
+document(oggpy.sync.pageout, "Produce a page.")
+
+# add_method(oggpy.sync, "sync_write")

Added: experimental/dholth/oggpy/oggpy_wrappers.cc
===================================================================
--- experimental/dholth/oggpy/oggpy_wrappers.cc	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/oggpy_wrappers.cc	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,27 @@
+/* Wrappers for oggpy.
+ *
+ * Daniel Holth <dholth at fastmail.fm>, 2004
+ */
+
+#include "oggpy_wrappers.h"
+#include <string.h>
+
+using namespace ogg;
+using namespace boost::python;
+
+// should return zero.  -1 means we overflowed a buffer.
+int ogg::sync_write(ogg::sync &s, str &data)
+{
+  int len;
+  char const* c_str;
+  char *buffer;
+
+  len = extract<int>(data.attr("__len__")());
+  c_str = extract<char const*>(data);
+
+  buffer = s.buffer(len);
+  memcpy((void*)buffer, (void*)c_str, len);
+
+  return s.wrote(len);
+}
+

Added: experimental/dholth/oggpy/oggpy_wrappers.h
===================================================================
--- experimental/dholth/oggpy/oggpy_wrappers.h	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/oggpy_wrappers.h	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,16 @@
+/* Some wrappers for oggpy.
+ *
+ * Daniel Holth <dholth at fastmail.fm>, 2004
+ */
+
+#ifndef VORBISPY_WRAPPERS_H
+#define VORBISPY_WRAPPERS_H
+
+#include "oggcc.h"
+#include <boost/python.hpp>
+
+namespace ogg {
+    int sync_write(ogg::sync &s, boost::python::str &data);
+}
+
+#endif

Modified: experimental/dholth/oggpy/setup.py
===================================================================
--- experimental/dholth/oggpy/setup.py	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/setup.py	2004-11-23 01:58:20 UTC (rev 8253)
@@ -3,15 +3,26 @@
 
 from distutils.core import setup
 from distutils.extension import Extension
+import os.path
+import sys
 
-# edit to point to your boost::python installation
-boost = "/home/dholth/opt/include/boost-1_31"
+extra_include_dirs = [".", "/home/dholth/include/theora"]
 
-description = """oggpy provides alternative python bindings for ogg."""
+if sys.version[0:3] == "2.3":
+    boost = "/home/dholth/opt/include/boost-1_31" # boost.python include path
+    boostlib = "boost_python-gcc-1_31"            # boost.python library name
+else:
+    boost  = "/usr/include/boost"
+    boostlib = "boost_python"
 
+if(os.path.exists(boost)):
+    extra_include_dirs.append(boost)
+
+description = """oggpy provides alternative python bindings to ogg, vorbis and theora."""
+
 classifiers="""\
-Development Status :: 3 - Alpha
-License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+Development Status :: 2 - Pre-Alpha
+License :: OSI Approved :: MIT License
 Operating System :: POSIX :: Linux
 Programming Language :: C++
 Programming Language :: Python
@@ -20,15 +31,36 @@
 """
 
 setup(name="oggpy",
-      version="0.0",
-      description="Boost.Python interface for ogg",
+      version="0.3",
+      description="Boost.Python and C++ wrappers of ogg, vorbis and theora",
       long_description=description,
       author="Daniel Holth",
       author_email="dholth at fastmail.fm",
-      url="http://dingoskidneys.com/shoutpy/",
+      url="http://dingoskidneys.com/oggpy/",
       platforms="linux",
-      license="GNU LGPL",
+      license="MIT",
       classifiers=filter(None, classifiers.splitlines()),
-      ext_modules=[Extension("oggpy", ["oggcc.cc", "oggpy.cpp"],
-                             libraries=["ogg", "vorbis", "boost_python-gcc"],
-                             include_dirs=[boost])])
+
+      ext_modules=[
+                    Extension("oggpy", ["oggcc.cc", "oggpy.cpp", "oggpy_wrappers.cc"],
+                              libraries=["ogg", boostlib],
+                              include_dirs=extra_include_dirs, depends=["oggcc.h"]),
+      
+                    Extension("vorbispy", ["oggcc.cc", "vorbispy.cpp", "vorbispy_wrappers.cc"],
+                              libraries=["ogg", "vorbis", "vorbisenc", boostlib],  
+                              include_dirs=extra_include_dirs, depends=["oggcc.h", "vorbiscc.h", "vorbispy_wrappers.h"]),
+                   
+                    Extension("theorapy", ["oggcc.cc", "theorapy.cpp"],
+                              libraries=["ogg", "theora", boostlib],
+                              include_dirs=extra_include_dirs, depends=["oggcc.h", "theoracc.h"])                    
+# If we want to statically link libboost_python we would have to put
+# everything in one file; this doesn't work right away due to name
+# collisions.
+#                    , Extension("panogg", 
+#                              ["panogg.cc", "oggpy/_oggpy.cpp", "oggpy/_theorapy.cpp", 
+#                              "oggpy/_vorbispy.cpp", "vorbispy_wrappers.cc", "oggpy_wrappers.cc"],
+#                              libraries=["ogg", "theora", "vorbis", "vorbisenc", boostlib],
+#                              include_dirs=extra_include_dirs, depends=["oggcc.h", "theoracc.h"])
+                  ]
+     )
+

Added: experimental/dholth/oggpy/tests/decode.py
===================================================================
--- experimental/dholth/oggpy/tests/decode.py	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/tests/decode.py	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+#
+# Partial port of decoder_example.c from the vorbis library.
+# Decodes an ogg/vorbis file from stdin, writing the first channel to disk.
+#
+# Daniel Holth <dholth at fastmail.fm>, 2004
+
+import oggpy
+import sys
+import numarray
+
+BUFSIZE=8192
+
+def test(ogg, outfile=file("decode.raw", "w")):
+    numarray.Error.setMode(all="ignore")
+    
+    oy = oggpy.sync()
+    og = oggpy.page()
+    op = oggpy.packet()
+    vi = oggpy.info()
+    vd = oggpy.dsp()
+    vb = oggpy.block()
+    vc = oggpy.comment()
+
+    while 1:
+        buffer = ogg.read(BUFSIZE)
+        oggpy.sync_write(oy, buffer)
+
+        if oy.pageout(og) != 1:
+            if len(buffer) < BUFSIZE: break
+            print >> sys.stderr, "Input does not appear to be an Ogg bitstream."
+            sys.exit(1)
+
+        os = oggpy.stream(og.serialno())
+
+        if os.pagein(og) < 0:
+            print >> sys.stderr, "Error reading first Ogg bitstream page"
+            sys.exit(1)
+
+        if os.packetout(op) != 1:
+            print >> sys.stderr, "Error reading initial header packet"
+            sys.exit(1)
+
+        if vi.synthesis_headerin(vc, op) < 0:
+            print >> sys.stderr, "Not an ogg/vorbis bitstream."
+            sys.exit(1)
+
+        i = 0
+        while i < 2:
+            while i < 2:
+                result = oy.pageout(og)
+                if result == 0: break
+                if result == 1:
+                    os.pagein(og)
+                    while i < 2:
+                        result = os.packetout(op)
+                        if result == 0: break
+                        if result < 0:
+                            print >> sys.stderr, "corrupt second header."
+                            sys.exit(1)
+                        vi.synthesis_headerin(vc, op)
+                        i += 1
+        
+            buffer = ogg.read(BUFSIZE)
+            if len(buffer) == 0 and i < 2:
+                print >> sys.stderr, "EOF before finding all vorbis headers!"
+                sys.exit(1)
+
+            oggpy.sync_write(oy, buffer)
+
+        print >> sys.stderr, oggpy.get_comments(vc)
+
+        vd.synthesis_init(vi)
+        vd.block_init(vb)
+
+        eos = False
+        while not eos:
+            while not eos:
+                result = oy.pageout(og)
+                if result == 0: break           # need more data
+                if result < 0:
+                    print >> sys.stderr, "Yikes, corruption! continue..."
+                else:
+                    os.pagein(og)
+                    p = 0
+                    while 1:
+                        result = os.packetout(op)
+                        if result == 0: break   # need more data
+                        if result > 0:          # we have a packet. decode it.
+                            p += 1
+                            if vb.synthesis(op) == 0:
+                                vd.synthesis_blockin(vb)
+                                                        
+                            samples = oggpy.oggpy_synthesis_pcmout(vd)
+                            while samples != None:
+                                samples *= 32767;
+                                wav = samples.astype('Int16')
+                                
+                                interleaved = numarray.zeros(samples.shape[1]*2, numarray.Int16)
+                                interleaved[0::2] = wav[0]
+                                interleaved[1::2] = wav[1]
+                                interleaved.tofile(outfile)
+                                        
+                                samples = oggpy.oggpy_synthesis_pcmout(vd)
+                                
+                if og.eos(): eos = True
+            if not eos:
+                buffer = ogg.read(BUFSIZE)
+                oggpy.sync_write(oy, buffer)
+                if len(buffer) == 0: eos = True
+        
+
+if __name__ == "__main__":
+    # test(sys.stdin)
+    test(file("music.ogg", "r"))


Property changes on: experimental/dholth/oggpy/tests/decode.py
___________________________________________________________________
Name: svn:executable
   + *

Added: experimental/dholth/oggpy/tests/oggtext.py
===================================================================
--- experimental/dholth/oggpy/tests/oggtext.py	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/tests/oggtext.py	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+#
+# The new line-based text format, oggtext!
+#
+# Puts lines of text into a new ogg-format stream.
+#
+# Daniel Holth <dholth at fastmail.fm>, 2004
+
+import oggpy
+import sys
+
+granule  = 0
+
+os = oggpy.stream(0x00FF00FF)
+page = oggpy.page()
+
+pack = oggpy.userpacket("OGGText", granule, True, False)
+os.packetin(pack)
+
+os.pageout(page)
+sys.stdout.write(page.header())
+sys.stdout.write(page.body())
+
+for data in sys.stdin.readlines():
+    if(os.pageout(page) != 0):
+        sys.stdout.write(page.header())
+        sys.stdout.write(page.body())
+    granule += len(data)
+    pack = oggpy.userpacket(data, granule, False, False)
+    os.packetin(pack)
+
+pack = oggpy.userpacket("END", granule, False, True)
+os.packetin(pack)
+os.pageout(page)
+sys.stdout.write(page.header())
+sys.stdout.write(page.body())


Property changes on: experimental/dholth/oggpy/tests/oggtext.py
___________________________________________________________________
Name: svn:executable
   + *

Added: experimental/dholth/oggpy/tests/test.py
===================================================================
--- experimental/dholth/oggpy/tests/test.py	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/tests/test.py	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+#
+# Grab comments from an ogg/vorbis file.
+#
+# Daniel Holth <dholth at fastmail.fm>
+# 20 Jan. 2004
+
+import oggpy
+import sys
+
+oggpy.sync.write = oggpy.sync_write
+
+def test(ogg = open("test.ogg", "rb")):
+    sync = oggpy.sync()
+    page = oggpy.page()
+    pkt  = oggpy.packet()
+
+    sync.write(ogg.read(4096))
+
+    if sync.pageout(page) != 1:
+        raise "Input doesn't seem to be an ogg bitstream."
+
+    strm = oggpy.stream(page.serialno())
+    info = oggpy.info()
+    cmt  = oggpy.comment()
+
+    print "pagein",     strm.pagein(page)
+    print "packetout",  strm.packetout(pkt)
+    print "headerin",   info.synthesis_headerin(cmt, pkt)
+
+    i = 0
+
+    while i<2:
+        while i<2:
+            result = sync.pageout(page)
+            if result == 0: break   # get more yummy data
+            strm.pagein(page)
+            while i<2:
+                result = strm.packetout(pkt)
+                if result == 0: break # mmm... data
+                if result < 0:
+                    raise "can't handle ogg/vorbis corruption this early."
+                info.synthesis_headerin(cmt, pkt)
+                i = i + 1
+        sync.write(ogg.read(4096))
+
+    print cmt.query_count("artist")
+    print oggpy.get_comments(cmt)
+
+
+if __name__ == "__main__":
+    if len(sys.argv) == 2:
+        test(open(sys.argv[1]))
+    else:
+        test()


Property changes on: experimental/dholth/oggpy/tests/test.py
___________________________________________________________________
Name: svn:executable
   + *

Added: experimental/dholth/oggpy/tests/theoratest.py
===================================================================
--- experimental/dholth/oggpy/tests/theoratest.py	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/tests/theoratest.py	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,106 @@
+#!/usr/bin/python
+#
+# Display some basic information about ogg/theora files.
+#
+# Daniel Holth <dholth at fastmail.fm>, 2004
+
+import oggpy
+import vorbispy
+import theorapy
+import sys
+import numarray
+import inspect
+
+BUFSIZE=8192
+
+def packetsource(ogg):
+    """Generator to take ogg packets out of a file.  Only returns packets from the first stream."""
+    
+    state = 0
+    
+    oy = oggpy.sync()
+    og = oggpy.page()
+    op = oggpy.packet()
+
+    buffer = True   # prime the pump
+    while buffer:
+        buffer = ogg.read(BUFSIZE)
+        oy.write(buffer)
+        while(oy.pageout(og)):
+            if state == 0:
+                stream = oggpy.stream(og.serialno())
+                state += 1
+            stream.pagein(og)
+            while(stream.packetout(op) == 1):
+                yield op
+
+
+def test(ogg):
+    """Display some basic information about a theora stream."""
+
+    numarray.Error.setMode(all="ignore")
+
+    oggpy.sync.write = oggpy.sync_write # hack until the wrapper can do this itself
+    
+    ti = theorapy.info()
+    tc = theorapy.comment()
+    td = theorapy.state()
+
+    yuv = theorapy.yuv_image()
+
+    theora = 0
+
+    for op in packetsource(ogg):
+        if theora == 0:
+            head = ti.decode_header(tc, op)
+            if head >= 0:
+                print "got theora", head
+                theora += 1
+            else:
+                print "no theora"
+                return
+                
+        elif theora < 3:   # should handle packets that are more than one page long.
+            h = ti.decode_header(tc, op)
+            print "header ", h
+            theora += 1
+
+        elif theora == 3:
+            print "This theora encoded by: ", tc.get_vendor()
+            print "Trying to decode with: ", theorapy.version_string(), theorapy.version_number()
+            for i in dir(ti):
+                if i[0:2] != "__":
+                    try:
+                        value = ti.__getattribute__(i)
+                        if not inspect.ismethod(value):
+                            print i, value
+                    except TypeError:
+                        pass
+            print "decode init returns", td.decode_init(ti)
+
+            print "comments:"
+            for i in range(tc.size()):
+                print tc.query_index(i)
+            print ":end comments"
+
+            theora += 1
+           
+        elif theora > 3 and theora < 10:
+            print theora
+            theora += 1
+            assert(td.decode_packetin(op) == 0)
+            assert(td.decode_YUVout(yuv) == 0)
+            print "yuv info:"
+            print "y\t%d\t%d\t%d" % (yuv.y_width, yuv.y_height, yuv.y_stride)
+            print "uv\t%d\t%d\t%d" % (yuv.uv_width, yuv.uv_height, yuv.uv_stride)
+        else:
+            break
+
+
+if __name__ == "__main__":
+    if len(sys.argv) == 2:
+        filename = sys.argv[1]
+    else:
+        filename = "video.ogg"
+        
+    test(file(filename, "rb"))


Property changes on: experimental/dholth/oggpy/tests/theoratest.py
___________________________________________________________________
Name: svn:executable
   + *

Added: experimental/dholth/oggpy/theora_wrappers.h
===================================================================
--- experimental/dholth/oggpy/theora_wrappers.h	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/theora_wrappers.h	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,18 @@
+/* Functions needed for Python to interface with theoracc
+ *
+ * Daniel Holth <dholth at fastmail.fm>, 2004
+ */
+
+#ifndef VORBISPY_WRAPPERS_H
+#define VORBISPY_WRAPPERS_H
+
+#include "oggcc.h"
+#include "theoracc.h"
+#include <boost/python.hpp>
+
+/// Return a list of all the comments in a theora comment object.
+///
+/// Less important now that we have query_index.
+boost::python::str get_comment(ogg::theora::comment *tco);
+
+#endif

Added: experimental/dholth/oggpy/theoracc.h
===================================================================
--- experimental/dholth/oggpy/theoracc.h	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/theoracc.h	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,179 @@
+#ifndef THEORACC_H
+#define THEORACC_H
+
+#include "oggcc.h"
+#include <string>
+#include <theora/theora.h>
+
+#if 0
+
+typedef struct {
+    int   y_width;
+    int   y_height;
+    int   y_stride;
+
+    int   uv_width;
+    int   uv_height;
+    int   uv_stride;
+    char *y;
+    char *u;
+    char *v;
+
+} yuv_buffer;
+
+typedef enum {
+  OC_CS_UNSPECIFIED,
+  OC_CS_ITU_REC_470M,
+  OC_CS_ITU_REC_470BG,
+} theora_colorspace;
+
+typedef struct {
+  ogg_uint32_t  width;
+  ogg_uint32_t  height;
+  ogg_uint32_t  frame_width;
+  ogg_uint32_t  frame_height;
+  ogg_uint32_t  offset_x;
+  ogg_uint32_t  offset_y;
+  ogg_uint32_t  fps_numerator;
+  ogg_uint32_t  fps_denominator;
+  ogg_uint32_t  aspect_numerator;
+  ogg_uint32_t  aspect_denominator;
+  theora_colorspace colorspace;
+  int           target_bitrate;
+  int           quality;
+  int           quick_p;  /* quick encode/decode */
+
+  /* decode only */
+  unsigned char version_major;
+  unsigned char version_minor;
+  unsigned char version_subminor;
+
+  void *codec_setup;
+
+  /* encode only */
+  int           dropframes_p;
+  int           keyframe_auto_p;
+  ogg_uint32_t  keyframe_frequency;
+  ogg_uint32_t  keyframe_frequency_force;  /* also used for decode init to
+                                              get granpos shift correct */
+  ogg_uint32_t  keyframe_data_target_bitrate;
+  ogg_int32_t   keyframe_auto_threshold;
+  ogg_uint32_t  keyframe_mindistance;
+  ogg_int32_t   noise_sensitivity;
+  ogg_int32_t   sharpness;
+
+} theora_info;
+
+#define OC_FAULT       -1
+#define OC_EINVAL      -10
+#define OC_BADHEADER   -20
+#define OC_NOTFORMAT   -21
+#define OC_VERSION     -22
+#define OC_IMPL        -23
+#define OC_BADPACKET   -24
+#define OC_NEWPACKET   -25
+
+#endif
+
+namespace ogg {
+    /// libtheora
+    namespace theora {
+        /// Annotate theora streams.
+        class comment {
+            private:
+                theora_comment data;
+
+                void init ( )   { theora_comment_init ( this->get_data() ); }
+                void clear ( )  { theora_comment_clear ( this->get_data() ); }
+                
+            public:
+                comment()   { this->init(); }
+                ~comment()  { this->clear(); }
+                
+                theora_comment *get_data() { return &this->data; }
+                
+                const char *query (char *tag , int count) { 
+                    return theora_comment_query (this->get_data(), tag , count ); }
+
+                /// Return the nth comment.
+                std::string query_index(unsigned int index) { 
+                    theora_comment *data = this->get_data();
+                    return (index < (unsigned)(data->comments) ? 
+                            std::string(data->user_comments[index], data->comment_lengths[index]) : ""); };
+                    
+                int query_count (char *tag) { return  theora_comment_query_count ( this->get_data(), tag ); }
+                int encode (packet *op)     { return  theora_encode_comment ( this->get_data(), op->get_data() ); }
+
+                void add ( char *comment )  { return  theora_comment_add ( this->get_data(), comment ); }
+                void add_tag ( char *tag , char *value )  { return  theora_comment_add_tag ( this->get_data(), tag, value ); }
+
+                const char* get_vendor() { return this->get_data()->vendor; }
+
+                int size()  { return this->get_data()->comments; }
+        };
+
+        
+        /// Store stream information such as resolution, framerate, and aspect ratio.
+        class info : public theora_info {
+            private:
+                void init ( )   { return  theora_info_init ( this->get_data() ); }
+                void clear ( )  { return  theora_info_clear ( this->get_data() ); }
+
+            public:
+                info()  { this->init(); }
+                ~info() { this->clear(); }
+
+                theora_info *get_data() { return (theora_info*)this; }
+
+                int decode_header ( theora::comment *cc , ogg::packet *op )  { 
+                    return  theora_decode_header ( this->get_data() , cc->get_data() , op->get_data() ); }
+        };
+        
+
+        /// YUV image data
+        class yuv_image : public yuv_buffer { };
+
+        
+        /// Codec state.
+        class state {
+            private:
+                theora_state data;
+                void clear ( )  { return  theora_clear ( this->get_data() ); }
+
+            public:
+                state() { 
+                    theora_state *ts = this->get_data(); 
+                    ts->i = NULL;
+                    ts->internal_encode = ts->internal_decode = NULL; 
+                    ts->granulepos = 0; }
+
+                ~state() { this->clear(); }
+                
+                theora_state *get_data() { return &this->data; }
+                
+                double granule_time ( ogg_int64_t granulepos ) {
+                    return  theora_granule_time ( this->get_data(), granulepos ); }
+                
+                int decode_init     ( info *c )         { return theora_decode_init     ( this->get_data(), c->get_data() ); }
+                int decode_packetin ( ogg::packet *op ) { return theora_decode_packetin ( this->get_data(), op->get_data() ); }
+                int decode_YUVout   ( yuv_image *yuv )  { return theora_decode_YUVout   ( this->get_data(), yuv ); }
+                
+                int encode_init     ( info *c )         { return theora_encode_init     ( this->get_data(), c->get_data() ); }
+                int encode_header   ( ogg::packet *op ) { return theora_encode_header   ( this->get_data(), op->get_data() ); }
+                int encode_tables   ( ogg::packet *op ) { return theora_encode_tables   ( this->get_data(), op->get_data() ); }
+                int encode_YUVin    ( yuv_image *yuv )  { return theora_encode_YUVin    ( this->get_data(), yuv ); }
+                
+                int encode_packetout ( int last_p, ogg::packet *op )  { 
+                    return  theora_encode_packetout ( this->get_data(), last_p, op->get_data() ); }
+        };
+
+
+        /// Human-readable version of libtheora
+        const char *version_string  ( void )    { return  theora_version_string ( ); }
+
+        /// Computer-convenient numeric version of libtheora
+        ogg_uint32_t version_number ( void )    { return  theora_version_number ( ); }
+    };
+};
+
+#endif

Added: experimental/dholth/oggpy/theorapy.pyste
===================================================================
--- experimental/dholth/oggpy/theorapy.pyste	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/theorapy.pyste	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,8 @@
+
+theorapy = AllFromHeader("theoracc.h")
+
+exclude(theorapy.info.get_data)
+exclude(theorapy.comment.get_data)
+exclude(theorapy.state.get_data)
+
+Enum("theora_colorspace", "theora.h")

Added: experimental/dholth/oggpy/vorbispy.pyste
===================================================================
--- experimental/dholth/oggpy/vorbispy.pyste	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/vorbispy.pyste	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,26 @@
+vorbispy = AllFromHeader("vorbiscc.h")
+
+Include("vorbispy_wrappers.h")
+
+# exclude(vorbispy.comment.query)
+exclude(vorbispy.dsp.analysis_buffer)
+exclude(vorbispy.dsp.get_data)
+exclude(vorbispy.comment.get_data)
+
+# vorbispy.block.synthesis.infos.doc = "Synthesize things."
+# #Function("oggpy_synthesis_pcmout", "oggpy_wrappers.h")
+
+doc = """\
+oggpy_synthesis_pcmout(oggpy.dsp) -> pcm data
+
+Fetches some pcm data from vorbis decode, in a channels by samples numarray object.
+It's so cool, you could keep meat in it."""
+
+pcmout = Function("oggpy_synthesis_pcmout", "vorbispy_wrappers.h", doc = doc)
+Function("oggpy_analysis_write", "vorbispy_wrappers.h")
+Function("get_comments", "vorbispy_wrappers.h")
+
+# #add_method(oggpy.sync, "ogg::sync_write")
+# #rename(oggpy.sync.sync_write, "write")
+
+# module_code("oggpy_wrappers_init();\n")

Added: experimental/dholth/oggpy/vorbispy_wrappers.cc
===================================================================
--- experimental/dholth/oggpy/vorbispy_wrappers.cc	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/vorbispy_wrappers.cc	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,103 @@
+/* Wrappers for oggpy.
+ *
+ * Daniel Holth <dholth at fastmail.fm>
+ * 21 Jan. 2004
+ */
+
+#include "vorbispy_wrappers.h"
+#include <string.h>
+#include <vorbis/codec.h>
+#include <numarray/libnumarray.h>
+#include <boost/version.hpp>
+
+using namespace ogg;
+using namespace boost::python;
+
+void oggpy_wrappers_init()
+{
+  import_libnumarray();
+}
+
+
+// It lives!!!
+// ideas: see if vorbis will let us read zero until samples is a minimum size > 0, to give less units to python
+PyObject *oggpy_synthesis_pcmout(ogg::vorbis::dsp *dsp)
+{
+  PyArrayObject *pcmarray = NULL;
+  float **pcm;
+  float *mono;
+  int samples;
+  int channels;
+
+  samples = dsp->synthesis_pcmout(&pcm);
+  
+  if(samples > 0)
+  {
+    channels  = dsp->get_data()->vi->channels;
+    pcmarray  = NA_NewArray(NULL, tFloat32, 2, channels, samples);
+    for(int i=0; i<channels; i++)
+    {
+      mono = (float*)((char*)NA_OFFSETDATA(pcmarray)+(pcmarray->strides[0])*i);
+      memcpy((void*)mono, (void*)*(pcm+i), samples*sizeof(float));
+    }
+    vorbis_synthesis_read(&dsp->data, samples);
+    return NA_ReturnOutput(NULL, pcmarray);
+  }
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+
+// If *data is None, we write zero bytes.
+// This is important to do because calling analysis_wrote with zero seems to be how libvorbis knows it's the end of the stream.
+int oggpy_analysis_write(ogg::vorbis::dsp *d, PyObject *data)
+{
+  PyArrayObject* input;
+  float **buffer;
+  float *channel;
+  int channels;
+  int len;
+  int wrote;
+
+  len = 0;
+  
+  if(data != Py_None)
+  {
+    channels = d->get_data()->vi->channels;
+    input    = NA_InputArray(data, tFloat32, C_ARRAY);
+    if(input != NULL)
+    {
+      len      = input->dimensions[1];
+      buffer   = d->analysis_buffer(len); // request buffer size in number of 32-bit-float samples.
+
+      for(int i=0; i<channels; i++)
+      {
+        channel = (float*)((char*)NA_OFFSETDATA(input)+(input->strides[0]*i));
+        memcpy((void*)(buffer[i]), (void*)channel, len*sizeof(float));
+      }
+      Py_XDECREF(input);
+    }
+  }
+
+  wrote = d->analysis_wrote(len);
+
+  return wrote; 
+}
+
+
+boost::python::list get_comments(ogg::vorbis::comment *vco)
+{
+  boost::python::list comments;
+  str com;
+  vorbis_comment *vc;
+
+  vc = vco->get_data();
+
+  for(int i=0; i < vc->comments; i++) 
+  {
+    comments.append(str(vc->user_comments[i], vc->comment_lengths[i]));
+  }
+
+  return comments;
+}

Added: experimental/dholth/oggpy/vorbispy_wrappers.h
===================================================================
--- experimental/dholth/oggpy/vorbispy_wrappers.h	2004-11-23 01:39:39 UTC (rev 8252)
+++ experimental/dholth/oggpy/vorbispy_wrappers.h	2004-11-23 01:58:20 UTC (rev 8253)
@@ -0,0 +1,19 @@
+/* vorbiscc wrappers for vorbispy.
+ *
+ * Daniel Holth <dholth at fastmail.fm>, 2004
+ */
+
+#ifndef VORBISPY_WRAPPERS_H
+#define VORBISPY_WRAPPERS_H
+
+#include "oggcc.h"
+#include "vorbiscc.h"
+#include <boost/python.hpp>
+
+int oggpy_analysis_write(ogg::vorbis::dsp *d, PyObject *data);
+boost::python::list get_comments(ogg::vorbis::comment *vc);
+PyObject *oggpy_synthesis_pcmout(ogg::vorbis::dsp *dsp);
+
+void oggpy_wrappers_init();
+
+#endif



More information about the commits mailing list