Actually call on_reset callback
[lsnes.git] / include / library / ogg.hpp
blob900d33bbebdb0f660e65979b5429577f52ad4603
1 #ifndef _library__ogg__hpp__included__
2 #define _library__ogg__hpp__included__
4 #include <cstdint>
5 #include <stdexcept>
6 #include <vector>
7 #include <map>
9 namespace ogg
11 /**
12 * A packet in Ogg bitstream.
14 class packet
16 public:
17 /**
18 * Constructor.
20 packet() {}
21 /**
22 * Constructor.
24 packet(uint64_t granule, bool first, bool last, bool spans, bool eos, bool bos,
25 const std::vector<uint8_t>& d);
26 /**
27 * Is the packet first within its page?
29 bool get_first_page() const throw() { return first_page; }
30 /**
31 * Is the packet last within its page?
33 bool get_last_page() const throw() { return last_page; }
34 /**
35 * Is the packet spanning multiple pages?
37 bool get_spans_page() const throw() { return spans_page; }
38 /**
39 * Is atomic (first, last and on one page)?
41 bool get_atomic() const throw() { return first_page && last_page && !spans_page; }
42 /**
43 * Get the granule position within page the packet finished at.
45 uint64_t get_granulepos() const throw() { return granulepos; }
46 /**
47 * Does the page this ends on have EOS set?
49 bool get_on_eos_page() const throw() { return eos_page; }
50 /**
51 * Does the page this starts on have BOS set?
53 bool get_on_bos_page() const throw() { return bos_page; }
54 /**
55 * Get the packet data.
57 const std::vector<uint8_t>& get_vector() const throw() { return data; }
58 /**
59 * Get length of packet data.
61 size_t get_length() const throw() { return data.size(); }
62 /**
63 * Get packet data.
65 const uint8_t* get_data() const throw() { return &data[0]; }
66 private:
67 bool first_page;
68 bool last_page;
69 bool spans_page;
70 bool eos_page;
71 bool bos_page;
72 uint64_t granulepos;
73 std::vector<uint8_t> data;
76 /**
77 * A page in Ogg bitstream.
79 class page
81 public:
82 /**
83 * Create a new blank page.
85 page() throw();
86 /**
87 * Create a page, reading a buffer.
89 * Parameter buffer: The buffer to read.
90 * Parameter advance: The number of bytes in packet is stored here.
91 * Throws std::runtime_error: Bad packet.
93 page(const char* buffer, size_t& advance);
94 /**
95 * Scan a buffer for pages.
97 * Parameter buffer: The buffer to scan.
98 * Parameter bufferlen: The length of buffer. Should be at least 65307, unless there's not that much available.
99 * Parameter eof: If set, assume physical stream ends after this buffer.
100 * Parameter advance: Amount to advance the pointer is stored here.
101 * Returns: True if packet was found, false if not.
103 static bool scan(const char* buffer, size_t bufferlen, bool eof, size_t& advance) throw();
105 * Get the continue flag of packet.
107 bool get_continue() const throw() { return flag_continue; }
109 * Set the continue flag of packet.
111 void set_continue(bool c) throw() { flag_continue = c; }
113 * Get the BOS flag of packet.
115 bool get_bos() const throw() { return flag_bos; }
117 * Set the BOS flag of packet.
119 void set_bos(bool b) throw() { flag_bos = b; }
121 * Get the EOS flag of packet.
123 bool get_eos() const throw() { return flag_eos; }
125 * Set the EOS flag of packet.
127 void set_eos(bool e) throw() { flag_eos = e; }
129 * Get the granulepos of packet.
131 uint64_t get_granulepos() const throw() { return granulepos; }
133 * Set the granulepos of packet.
135 void set_granulepos(uint64_t g) throw() { granulepos = g; }
137 * Get stream identifier.
139 uint32_t get_stream() const throw() { return stream; }
141 * Set stream identifier.
143 void set_stream(uint32_t s) throw() { stream = s; }
145 * Get stream identifier.
147 uint32_t get_sequence() const throw() { return sequence; }
149 * Set stream identifier.
151 void set_sequence(uint32_t s) throw() { sequence = s; }
153 * Get number of packets.
155 uint8_t get_packet_count() const throw() { return packet_count; }
157 * Get the packet.
159 std::pair<const uint8_t*, size_t> get_packet(size_t packetno) const throw()
161 if(packetno >= packet_count)
162 return std::make_pair(reinterpret_cast<const uint8_t*>(NULL), 0);
163 else
164 return std::make_pair(data + packets[packetno], packets[packetno + 1] - packets[packetno]);
167 * Get the last packet incomplete flag.
169 bool get_last_packet_incomplete() const throw() { return last_incomplete; }
171 * Get amount of data that can be written as a complete packet.
173 size_t get_max_complete_packet() const throw();
175 * Append a complete packet to page.
177 * Parameter d: The data to append.
178 * Parameter dlen: The length of data to append.
179 * Returns: True on success, false on failure.
181 bool append_packet(const uint8_t* d, size_t dlen) throw();
183 * Append a possibly incomplete packet to page.
185 * Parameter d: The data to append. Adjusted.
186 * Parameter dlen: The length of data to append. Adjusted
187 * Returns: True if write was complete, false if incomplete.
189 bool append_packet_incomplete(const uint8_t*& d, size_t& dlen) throw();
191 * Get number of octets it takes to serialize this.
193 size_t serialize_size() const throw() { return 27 + segment_count + data_count; }
195 * Serialize this packet.
197 * Parameter buffer: Buffer to serialize to (use serialize_size() to find the size).
199 void serialize(char* buffer) const throw();
201 * Get debugging info for stream this page is from.
203 std::string stream_debug_id() const;
205 * Get debugging info for this page.
207 std::string page_debug_id() const;
209 * The special granule pos for nothing.
211 const static uint64_t granulepos_none;
212 private:
213 uint8_t version;
214 bool flag_continue;
215 bool flag_bos;
216 bool flag_eos;
217 bool last_incomplete;
218 uint64_t granulepos;
219 uint32_t stream;
220 uint32_t sequence;
221 uint8_t segment_count;
222 uint8_t packet_count;
223 uint16_t data_count;
224 uint8_t data[65025];
225 uint8_t segments[255];
226 uint16_t packets[256];
230 * Ogg demuxer.
232 class demuxer
234 public:
236 * Create a new demuxer.
238 demuxer(std::ostream& _errors_to);
240 * Demuxer wants a page in?
242 bool wants_page_in() const throw() { return (dpacket == packets && !ended); }
244 * Demuxer wants a packet out?
246 bool wants_packet_out() const throw() { return (dpacket < packets); }
248 * Input a page.
250 bool page_in(const page& p);
252 * Output a packet.
254 void packet_out(packet& pkt);
256 * Discard a packet.
258 void discard_packet();
259 private:
260 uint32_t inc1(uint32_t x) { return x + 1; }
261 uint64_t page_fullseq(uint32_t seq);
262 void update_pageseq(uint32_t new_seq);
263 bool complain_lost_page(uint32_t new_seq, uint32_t stream);
264 void complain_continue_errors(unsigned flags, uint32_t seqno, uint32_t stream, uint32_t pkts,
265 uint64_t granule);
266 std::ostream& errors_to;
267 std::vector<uint8_t> partial;
268 bool started_bos;
269 bool seen_page;
270 bool damaged_packet;
271 uint32_t imprint_stream;
272 uint32_t page_seq;
273 uint32_t page_era;
274 page last_page;
275 uint32_t dpacket;
276 uint32_t packets;
277 uint64_t last_granulepos;
278 bool ended;
282 * Ogg muxer.
284 class muxer
286 public:
288 * Create a muxer.
290 muxer(uint32_t streamid, uint64_t _seq = 0);
292 * Wants a packet?
294 bool wants_packet_in() const throw();
296 * Packet of this size fits on current page?
298 bool packet_fits(size_t pktsize) const throw();
300 * Has a page to output?
302 bool has_page_out() const throw();
304 * Input a packet.
306 void packet_in(const std::vector<uint8_t>& data, uint64_t granule);
308 * Signal end of stream.
310 void signal_eos();
312 * Output a page.
314 void page_out(page& p);
315 private:
316 uint32_t strmid;
317 page buffer;
318 std::vector<uint8_t> buffered;
319 size_t written;
320 uint64_t seq;
321 bool eos_asserted;
322 uint64_t granulepos;
326 * Ogg stream reader.
328 class stream_reader
330 public:
332 * Constructor.
334 stream_reader() throw();
336 * Destructor.
338 virtual ~stream_reader() throw();
340 * Read some data.
342 * Parameter buffer: The buffer to store the data to.
343 * Parameter size: The maximum size to read.
344 * Returns: The number of bytes actually read.
346 virtual size_t read(char* buffer, size_t size) = 0;
348 * Read a page from stream.
350 * Parameter page: The page is assigned here if successful.
351 * Returns: True if page was obtained, false if not.
353 bool get_page(page& page);
355 * Set stream to report errors to.
357 * Parameter strm: The stream.
359 void set_errors_to(std::ostream& os);
361 * Starting offset of last packet returned.
363 uint64_t get_last_offset() { return last_offset; }
364 private:
365 stream_reader(const stream_reader&);
366 stream_reader& operator=(const stream_reader&);
367 void fill_buffer();
368 void discard_buffer(size_t amount);
369 bool eof;
370 char buffer[65536];
371 size_t left;
372 uint64_t last_offset;
373 uint64_t start_offset;
374 std::ostream* errors_to;
378 * Ogg stream reader based on std::istream.
380 class stream_reader_iostreams : public stream_reader
382 public:
384 * Constructor.
386 * Parameter stream: The stream to read the data from.
388 stream_reader_iostreams(std::istream& stream);
390 * Destructor.
392 ~stream_reader_iostreams() throw();
394 size_t read(char* buffer, size_t size);
395 private:
396 std::istream& is;
400 * Ogg stream writer.
402 class stream_writer
404 public:
406 * Constructor.
408 stream_writer() throw();
410 * Destructor.
412 virtual ~stream_writer() throw();
414 * Write data.
416 * Parameter data: The data to write.
417 * Parameter size: The size to write.
419 virtual void write(const char* buffer, size_t size) = 0;
421 * Write a page to stream.
423 * Parameter page: The page to write.
425 void put_page(const page& page);
426 private:
427 stream_writer(const stream_writer&);
428 stream_writer& operator=(const stream_writer&);
432 * Ogg stream writer based on std::istream.
434 class stream_writer_iostreams : public stream_writer
436 public:
438 * Constructor.
440 * Parameter stream: The stream to read the data from.
442 stream_writer_iostreams(std::ostream& stream);
444 * Destructor.
446 ~stream_writer_iostreams() throw();
448 void write(const char* buffer, size_t size);
449 private:
450 std::ostream& os;
454 #endif