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