[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