1 /*
2    Copyright (C) 2003 Commonwealth Scientific and Industrial Research
3    Organisation (CSIRO) Australia
4 
5    Redistribution and use in source and binary forms, with or without
6    modification, are permitted provided that the following conditions
7    are met:
8 
9    - Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11 
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.
15 
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.
19 
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.
31 */
32 
33 #ifndef __OGGZ_PRIVATE_H__
34 #define __OGGZ_PRIVATE_H__
35 
36 #include <stdio.h>
37 #include <sys/types.h>
38 
39 #include <ogg/ogg.h>
40 #include <oggz/oggz_constants.h>
41 #include <oggz/oggz_off_t.h>
42 
43 #include "oggz/oggz_packet.h"
44 
45 #include "oggz_macros.h"
46 #include "oggz_vector.h"
47 #include "oggz_dlist.h"
48 
49 #define OGGZ_AUTO_MULT 1000Ull
50 
51 typedef struct _OGGZ OGGZ;
52 typedef struct _OggzComment OggzComment;
53 typedef struct _OggzIO OggzIO;
54 typedef struct _OggzReader OggzReader;
55 typedef struct _OggzWriter OggzWriter;
56 
57 
58 typedef int (*OggzReadPacket) (OGGZ * oggz, oggz_packet * op, long serialno,
59 			       void * user_data);
60 typedef int (*OggzReadPage) (OGGZ * oggz, const ogg_page * og, long serialno,
61 			     void * user_data);
62 
63 /* oggz_stream */
64 #include "oggz_stream_private.h"
65 
66 typedef ogg_int64_t (*OggzMetric) (OGGZ * oggz, long serialno,
67 				   ogg_int64_t granulepos,
68 				   void * user_data);
69 
70 typedef int (*OggzOrder) (OGGZ * oggz, ogg_packet * op, void * target,
71 			  void * user_data);
72 
73 typedef int (*OggzWriteHungry) (OGGZ * oggz, int empty, void * user_data);
74 
75 /* oggz_io */
76 typedef size_t (*OggzIORead) (void * user_handle, void * buf, size_t n);
77 typedef size_t (*OggzIOWrite) (void * user_handle, void * buf, size_t n);
78 typedef int (*OggzIOSeek) (void * user_handle, long offset, int whence);
79 typedef long (*OggzIOTell) (void * user_handle);
80 typedef int (*OggzIOFlush) (void * user_handle);
81 
82 struct _oggz_stream_t {
83   ogg_stream_state ogg_stream;
84 
85   /** STATIC INFO */
86   int content;
87   int numheaders;
88   int preroll;
89   ogg_int64_t granulerate_n;
90   ogg_int64_t granulerate_d;
91   ogg_int64_t first_granule;
92   ogg_int64_t basegranule;
93   int granuleshift;
94 
95   /* The comments */
96   char * vendor;
97   OggzVector * comments;
98 
99   /** CURRENT STATE **/
100   /* non b_o_s packet has been written (not just queued) */
101   int delivered_non_b_o_s;
102 
103   int b_o_s; /* beginning of stream */
104   int e_o_s; /* end of stream */
105   ogg_int64_t granulepos;
106   ogg_int64_t packetno;
107 
108   /** CALLBACKS **/
109   OggzMetric metric;
110   void * metric_user_data;
111   int metric_internal;
112 
113   OggzOrder order;
114   void * order_user_data;
115 
116   OggzReadPacket read_packet;
117   void * read_user_data;
118 
119   OggzReadPage read_page;
120   void * read_page_user_data;
121 
122   /* calculated granulepos values, not extracted values */
123   ogg_int64_t last_granulepos;
124   ogg_int64_t page_granulepos;
125   void * calculate_data;
126   ogg_packet * last_packet;
127 };
128 
129 struct _OggzReader {
130   ogg_sync_state ogg_sync;
131 
132   /* XXX: these two can prolly be removed again :) */
133   ogg_stream_state ogg_stream;
134   long current_serialno;
135 
136   OggzReadPacket read_packet;
137   void * read_user_data;
138 
139   OggzReadPage read_page;
140   void * read_page_user_data;
141 
142   ogg_int64_t current_unit;
143   ogg_int64_t current_granulepos;
144 
145   /* Read positioning */
146   long current_page_bytes;
147 
148   /* Calculation of position */
149   oggz_off_t current_packet_begin_page_offset;
150   int current_packet_pages;
151   int current_packet_begin_segment_index;
152 
153 #if 0
154   oggz_off_t offset_page_end; /* offset of end of current page */
155 #endif
156 };
157 
158 /**
159  * Bundle a packet with the stream it is being queued for; used in
160  * the packet_queue vector
161  */
162 typedef struct {
163   ogg_packet op;
164   oggz_stream_t * stream;
165   int flush;
166   int * guard;
167 } oggz_writer_packet_t;
168 
169 enum oggz_writer_state {
170   OGGZ_MAKING_PACKETS = 0,
171   OGGZ_WRITING_PAGES = 1
172 };
173 
174 struct _OggzWriter {
175   oggz_writer_packet_t * next_zpacket; /* stashed in case of FLUSH_BEFORE */
176   OggzVector * packet_queue;
177 
178   OggzWriteHungry hungry;
179   void * hungry_user_data;
180   int hungry_only_when_empty;
181 
182   int writing; /* already mid-write; check for recursive writes */
183   int state; /* OGGZ_MAKING_PACKETS or OGGZ_WRITING_PAGES */
184 
185   int flushing; /* whether current packet is being flushed or just paged out */
186 
187 #if 0
188   int eog; /* end of page */
189   int eop; /* end of packet */
190 #endif
191   int eos; /* end of stream */
192 
193   oggz_writer_packet_t * current_zpacket;
194 
195   int packet_offset; /* n bytes already copied out of current packet */
196   int page_offset; /* n bytes already copied out of current page */
197 
198   ogg_stream_state * current_stream;
199 
200   int no_more_packets; /* used only in the local oggz_write loop to indicate
201                           end of stream */
202 
203 };
204 
205 struct _OggzIO {
206   OggzIORead read;
207   void * read_user_handle;
208 
209   OggzIOWrite write;
210   void * write_user_handle;
211 
212   OggzIOSeek seek;
213   void * seek_user_handle;
214 
215   OggzIOTell tell;
216   void * tell_user_handle;
217 
218   OggzIOFlush flush;
219   void * flush_user_handle;
220 };
221 
222 struct _OggzComment {
223   /** The name of the comment, eg. "AUTHOR" */
224   char * name;
225 
226   /** The value of the comment, as UTF-8 */
227   char * value;
228 };
229 
230 struct _OGGZ {
231   int flags;
232   FILE * file;
233   OggzIO * io;
234 
235   ogg_packet current_packet;
236   ogg_page current_page;
237 
238   oggz_off_t offset; /* offset of current page start */
239   oggz_off_t offset_data_begin; /* offset of unit 0 page start */
240 
241   long run_blocksize; /* blocksize to use for oggz_run() */
242   int cb_next;
243 
244   OggzVector * streams;
245   int all_at_eos; /* all streams are at eos */
246 
247   OggzMetric metric;
248   void * metric_user_data;
249   int metric_internal;
250 
251   OggzOrder order;
252   void * order_user_data;
253 
254   union {
255     OggzReader reader;
256     OggzWriter writer;
257   } x;
258 
259   OggzDList * packet_buffer;
260 };
261 
262 OGGZ * oggz_read_init (OGGZ * oggz);
263 OGGZ * oggz_read_close (OGGZ * oggz);
264 
265 OGGZ * oggz_write_init (OGGZ * oggz);
266 int oggz_write_flush (OGGZ * oggz);
267 OGGZ * oggz_write_close (OGGZ * oggz);
268 
269 int oggz_map_return_value_to_error (int cb_ret);
270 
271 int oggz_get_bos (OGGZ * oggz, long serialno);
272 ogg_int64_t oggz_get_unit (OGGZ * oggz, long serialno, ogg_int64_t granulepos);
273 
274 int oggz_set_metric_internal (OGGZ * oggz, long serialno, OggzMetric metric,
275 			      void * user_data, int internal);
276 int oggz_has_metrics (OGGZ * oggz);
277 
278 int oggz_purge (OGGZ * oggz);
279 
280 /* metric_internal */
281 
282 int
283 oggz_set_granulerate (OGGZ * oggz, long serialno,
284                                     ogg_int64_t granule_rate_numerator,
285                                     ogg_int64_t granule_rate_denominator);
286 
287 int
288 oggz_get_granulerate (OGGZ * oggz, long serialno,
289                                     ogg_int64_t * granulerate_n,
290                                     ogg_int64_t * granulerate_d);
291 
292 int oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift);
293 int oggz_get_granuleshift (OGGZ * oggz, long serialno);
294 
295 int oggz_set_first_granule (OGGZ * oggz, long serialno, ogg_int64_t first_granule);
296 
297 int oggz_set_preroll (OGGZ * oggz, long serialno, int preroll);
298 int oggz_get_preroll (OGGZ * oggz, long serialno);
299 
300 /* oggz_auto */
301 
302 int
303 oggz_auto_read_bos_page (OGGZ * oggz, ogg_page * og, long serialno,
304                          void * user_data);
305 int
306 oggz_auto_read_bos_packet (OGGZ * oggz, ogg_packet * op, long serialno,
307                            void * user_data);
308 
309 int
310 oggz_auto_read_comments (OGGZ * oggz, oggz_stream_t * stream, long serialno,
311                          ogg_packet * op);
312 
313 int oggz_auto_identify_page (OGGZ *oggz, ogg_page *og, long serialno);
314 int oggz_auto_identify_packet (OGGZ * oggz, ogg_packet * op, long serialno);
315 
316 /* comments */
317 int oggz_comments_init (oggz_stream_t * stream);
318 int oggz_comments_free (oggz_stream_t * stream);
319 int oggz_comments_decode (OGGZ * oggz, long serialno,
320                           unsigned char * comments, long length);
321 long oggz_comments_encode (OGGZ * oggz, long serialno,
322                            unsigned char * buf, long length);
323 
324 /* oggz_io */
325 size_t oggz_io_read (OGGZ * oggz, void * buf, size_t n);
326 size_t oggz_io_write (OGGZ * oggz, void * buf, size_t n);
327 int oggz_io_seek (OGGZ * oggz, long offset, int whence);
328 long oggz_io_tell (OGGZ * oggz);
329 int oggz_io_flush (OGGZ * oggz);
330 
331 /* oggz_read */
332 OggzDListIterResponse oggz_read_free_pbuffers(void *elem);
333 
334 #endif /* __OGGZ_PRIVATE_H__ */
335