2 Copyright (C) 2003 Commonwealth Scientific and Industrial Research
3 Organisation (CSIRO) Australia
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 - Neither the name of CSIRO Australia nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #ifndef __OGGZ_WRITE_H__
34 #define __OGGZ_WRITE_H__
37 * Interfaces for writing Ogg files and streams
40 /** \defgroup force_feed Writing by force feeding Oggz
42 * Force feeding involves synchronously:
43 * - Creating an \a ogg_packet structure
44 * - Adding it to the packet queue with oggz_write_feed()
45 * - Calling oggz_write() or oggz_write_output(), repeatedly as necessary,
46 * to generate the Ogg bitstream.
48 * This process is illustrated in the following diagram:
50 * \image html forcefeed.png
51 * \image latex forcefeed.eps "Force Feeding Oggz" width=10cm
53 * The following example code generates a stream of ten packets, each
54 * containing a single byte ('A', 'B', ... , 'J'):
56 * \include write-feed.c
59 /** \defgroup hungry Writing with OggzHungry callbacks
61 * You can add packets to the Oggz packet queue only when it is "hungry"
62 * by providing an OggzHungry callback.
64 * An OggzHungry callback will:
65 * - Create an \a ogg_packet structure
66 * - Add it to the packet queue with oggz_write_feed()
68 * Once you have set such a callback with oggz_write_set_hungry_callback(),
69 * simply call oggz_write() or oggz_write_output() repeatedly, and Oggz
70 * will call your callback to provide packets when it is hungry.
72 * This process is illustrated in the following diagram:
74 * \image html hungry.png
75 * \image latex hungry.eps "Using OggzHungry" width=10cm
77 * The following example code generates a stream of ten packets, each
78 * containing a single byte ('A', 'B', ... , 'J'):
80 * \include write-hungry.c
83 /** \defgroup write_api Oggz Write API
85 * Oggz maintains a packet queue, such that you can independently add
86 * packets to the queue and write an Ogg bitstream.
87 * There are two complementary methods for adding packets to the
90 * - by \link force_feed force feeding Oggz \endlink
91 * - by using \link hungry OggzHungry \endlink callbacks
93 * As each packet is enqueued, its validity is checked against the framing
94 * constraints outlined in the \link basics Ogg basics \endlink section.
95 * If it does not pass these constraints, oggz_write_feed() will fail with
96 * an appropriate error code.
99 * - When writing, you can ensure that a packet starts on a new page
100 * by setting the \a flush parameter of oggz_write_feed() to
101 * \a OGGZ_FLUSH_BEFORE when enqueuing it.
102 * Similarly you can ensure that the last page a packet is written into
103 * won't contain any following packets by setting the \a flush parameter
104 * of oggz_write_feed() to \a OGGZ_FLUSH_AFTER.
105 * - The \a OGGZ_FLUSH_BEFORE and \a OGGZ_FLUSH_AFTER flags can be bitwise
106 * OR'd together to ensure that the packet will not share any pages with
107 * any other packets, either before or after.
113 * This is the signature of a callback which Oggz will call when \a oggz
114 * is \link hungry hungry \endlink.
116 * \param oggz The OGGZ handle
117 * \param empty A value of 1 indicates that the packet queue is currently
118 * empty. A value of 0 indicates that the packet queue is not empty.
119 * \param user_data A generic pointer you have provided earlier
121 * \retval non-zero Instruct Oggz to stop.
123 typedef int (*OggzWriteHungry
) (OGGZ
* oggz
, int empty
, void * user_data
);
126 * Set a callback for Oggz to call when \a oggz
127 * is \link hungry hungry \endlink.
129 * \param oggz An OGGZ handle previously opened for writing
130 * \param hungry Your callback function
131 * \param only_when_empty When to call: a value of 0 indicates that
132 * Oggz should call \a hungry() after each and every packet is written;
133 * a value of 1 indicates that Oggz should call \a hungry() only when
134 * its packet queue is empty
135 * \param user_data Arbitrary data you wish to pass to your callback
137 * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
138 * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
139 * \note Passing a value of 0 for \a only_when_empty allows you to feed
140 * new packets into \a oggz's packet queue on the fly.
142 int oggz_write_set_hungry_callback (OGGZ
* oggz
,
143 OggzWriteHungry hungry
,
147 * Add a packet to \a oggz's packet queue.
148 * \param oggz An OGGZ handle previously opened for writing
149 * \param op An ogg_packet with all fields filled in
150 * \param serialno Identify the logical bitstream in \a oggz to add the
152 * \param flush Bitmask of OGGZ_FLUSH_BEFORE, OGGZ_FLUSH_AFTER
153 * \param guard A guard for nocopy, NULL otherwise
155 * \retval OGGZ_ERR_BAD_GUARD \a guard specified has non-zero initialization
156 * \retval OGGZ_ERR_BOS Packet would be bos packet of a new logical bitstream,
157 * but oggz has already written one or more non-bos packets in
158 * other logical bitstreams,
159 * and \a oggz is not flagged OGGZ_NONSTRICT
160 * \retval OGGZ_ERR_EOS The logical bitstream identified by \a serialno is
162 * and \a oggz is not flagged OGGZ_NONSTRICT
163 * \retval OGGZ_ERR_BAD_BYTES \a op->bytes is invalid,
164 * and \a oggz is not flagged OGGZ_NONSTRICT
165 * \retval OGGZ_ERR_BAD_B_O_S \a op->b_o_s is invalid,
166 * and \a oggz is not flagged OGGZ_NONSTRICT
167 * \retval OGGZ_ERR_BAD_GRANULEPOS \a op->granulepos is less than that of
168 * an earlier packet within this logical bitstream,
169 * and \a oggz is not flagged OGGZ_NONSTRICT
170 * \retval OGGZ_ERR_BAD_PACKETNO \a op->packetno is less than that of an
171 * earlier packet within this logical bitstream,
172 * and \a oggz is not flagged OGGZ_NONSTRICT
173 * \retval OGGZ_ERR_BAD_SERIALNO \a serialno does not identify an existing
174 * logical bitstream in \a oggz,
175 * and \a oggz is not flagged OGGZ_NONSTRICT
176 * or \a serialno is equal to -1, or \a serialno does not fit in
177 * 32 bits, ie. within the range (-(2^31), (2^31)-1)
178 * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
179 * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
181 * \note If \a op->b_o_s is initialized to \a -1 before calling
182 * oggz_write_feed(), Oggz will fill it in with the appropriate
183 * value; ie. 1 for the first packet of a new stream, and 0 otherwise.
185 int oggz_write_feed (OGGZ
* oggz
, ogg_packet
* op
, long serialno
, int flush
,
189 * Output data from an OGGZ handle. Oggz will call your write callback
192 * \param oggz An OGGZ handle previously opened for writing
193 * \param buf A memory buffer
194 * \param n A count of bytes to output
195 * \retval "> 0" The number of bytes successfully output
196 * \retval 0 End of stream
197 * \retval OGGZ_ERR_RECURSIVE_WRITE Attempt to initiate writing from
198 * within an OggzHungry callback
199 * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
200 * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
201 * \retval OGGZ_ERR_STOP_OK Writing was stopped by an OggzHungry callback
202 * returning OGGZ_STOP_OK
203 * \retval OGGZ_ERR_STOP_ERR Reading was stopped by an OggzHungry callback
204 * returning OGGZ_STOP_ERR
206 long oggz_write_output (OGGZ
* oggz
, unsigned char * buf
, long n
);
209 * Write n bytes from an OGGZ handle. Oggz will call your write callback
212 * \param oggz An OGGZ handle previously opened for writing
213 * \param n A count of bytes to be written
214 * \retval "> 0" The number of bytes successfully output
215 * \retval 0 End of stream
216 * \retval OGGZ_ERR_RECURSIVE_WRITE Attempt to initiate writing from
217 * within an OggzHungry callback
218 * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
219 * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
220 * \retval OGGZ_ERR_STOP_OK Writing was stopped by an OggzHungry callback
221 * returning OGGZ_STOP_OK
222 * \retval OGGZ_ERR_STOP_ERR Reading was stopped by an OggzHungry callback
223 * returning OGGZ_STOP_ERR
225 long oggz_write (OGGZ
* oggz
, long n
);
228 * Query the number of bytes in the next page to be written.
230 * \param oggz An OGGZ handle previously opened for writing
231 * \retval ">= 0" The number of bytes in the next page
232 * \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
233 * \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
235 long oggz_write_get_next_page_size (OGGZ
* oggz
);
240 #endif /* __OGGZ_WRITE_H__ */