Allow on_input to veto/force system controls (including reset line)
[lsnes.git] / include / library / ogg.hpp
blob81ab8fe283f066c2e9308bff76acb39ca9ea8f5c
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, const std::vector<uint8_t>& d);
23 /**
24 * Is the packet first within its page?
26 bool get_first_page() const throw() { return first_page; }
27 /**
28 * Is the packet last within its page?
30 bool get_last_page() const throw() { return last_page; }
31 /**
32 * Is the packet spanning multiple pages?
34 bool get_spans_page() const throw() { return spans_page; }
35 /**
36 * Is atomic (first, last and on one page)?
38 bool get_atomic() const throw() { return first_page && last_page && !spans_page; }
39 /**
40 * Get the granule position within page the packet finished at.
42 uint64_t get_granulepos() const throw() { return granulepos; }
43 /**
44 * Does the page this ends on have EOS set?
46 bool get_on_eos_page() const throw() { return eos_page; }
47 /**
48 * Get the packet data.
50 const std::vector<uint8_t>& get_vector() const throw() { return data; }
51 /**
52 * Get length of packet data.
54 size_t get_length() const throw() { return data.size(); }
55 /**
56 * Get packet data.
58 const uint8_t* get_data() const throw() { return &data[0]; }
59 private:
60 bool first_page;
61 bool last_page;
62 bool spans_page;
63 bool eos_page;
64 uint64_t granulepos;
65 std::vector<uint8_t> data;
68 /**
69 * A page in Ogg bitstream.
71 class ogg_page
73 public:
74 /**
75 * Create a new blank page.
77 ogg_page() throw();
78 /**
79 * Create a page, reading a buffer.
81 * Parameter buffer: The buffer to read.
82 * Parameter advance: The number of bytes in packet is stored here.
83 * Throws std::runtime_error: Bad packet.
85 ogg_page(const char* buffer, size_t& advance) throw(std::runtime_error);
86 /**
87 * Scan a buffer for pages.
89 * Parameter buffer: The buffer to scan.
90 * Parameter bufferlen: The length of buffer. Should be at least 65307, unless there's not that much available.
91 * Parameter eof: If set, assume physical stream ends after this buffer.
92 * Parameter advance: Amount to advance the pointer is stored here.
93 * Returns: True if packet was found, false if not.
95 static bool scan(const char* buffer, size_t bufferlen, bool eof, size_t& advance) throw();
96 /**
97 * Get the continue flag of packet.
99 bool get_continue() const throw() { return flag_continue; }
101 * Set the continue flag of packet.
103 void set_continue(bool c) throw() { flag_continue = c; }
105 * Get the BOS flag of packet.
107 bool get_bos() const throw() { return flag_bos; }
109 * Set the BOS flag of packet.
111 void set_bos(bool b) throw() { flag_bos = b; }
113 * Get the EOS flag of packet.
115 bool get_eos() const throw() { return flag_eos; }
117 * Set the EOS flag of packet.
119 void set_eos(bool e) throw() { flag_eos = e; }
121 * Get the granulepos of packet.
123 uint64_t get_granulepos() const throw() { return granulepos; }
125 * Set the granulepos of packet.
127 void set_granulepos(uint64_t g) throw() { granulepos = g; }
129 * Get stream identifier.
131 uint32_t get_stream() const throw() { return stream; }
133 * Set stream identifier.
135 void set_stream(uint32_t s) throw() { stream = s; }
137 * Get stream identifier.
139 uint32_t get_sequence() const throw() { return sequence; }
141 * Set stream identifier.
143 void set_sequence(uint32_t s) throw() { sequence = s; }
145 * Get number of packets.
147 uint8_t get_packet_count() const throw() { return packet_count; }
149 * Get the packet.
151 std::pair<const uint8_t*, size_t> get_packet(size_t packetno) const throw()
153 if(packetno >= packet_count)
154 return std::make_pair(reinterpret_cast<const uint8_t*>(NULL), 0);
155 else
156 return std::make_pair(data + packets[packetno], packets[packetno + 1] - packets[packetno]);
159 * Get the last packet incomplete flag.
161 bool get_last_packet_incomplete() const throw() { return last_incomplete; }
163 * Get amount of data that can be written as a complete packet.
165 size_t get_max_complete_packet() const throw();
167 * Append a complete packet to page.
169 * Parameter d: The data to append.
170 * Parameter dlen: The length of data to append.
171 * Returns: True on success, false on failure.
173 bool append_packet(const uint8_t* d, size_t dlen) throw();
175 * Append a possibly incomplete packet to page.
177 * Parameter d: The data to append. Adjusted.
178 * Parameter dlen: The length of data to append. Adjusted
179 * Returns: True if write was complete, false if incomplete.
181 bool append_packet_incomplete(const uint8_t*& d, size_t& dlen) throw();
183 * Get number of octets it takes to serialize this.
185 size_t serialize_size() const throw() { return 27 + segment_count + data_count; }
187 * Serialize this packet.
189 * Parameter buffer: Buffer to serialize to (use serialize_size() to find the size).
191 void serialize(char* buffer) const throw();
193 * Get debugging info for stream this page is from.
195 std::string stream_debug_id() const throw(std::bad_alloc);
197 * Get debugging info for this page.
199 std::string page_debug_id() const throw(std::bad_alloc);
201 * The special granule pos for nothing.
203 const static uint64_t granulepos_none;
204 private:
205 uint8_t version;
206 bool flag_continue;
207 bool flag_bos;
208 bool flag_eos;
209 bool last_incomplete;
210 uint64_t granulepos;
211 uint32_t stream;
212 uint32_t sequence;
213 uint8_t segment_count;
214 uint8_t packet_count;
215 uint16_t data_count;
216 uint8_t data[65025];
217 uint8_t segments[255];
218 uint16_t packets[256];
222 * Ogg demuxer.
224 class ogg_demuxer
226 public:
228 * Create a new demuxer.
230 ogg_demuxer(std::ostream& _errors_to);
232 * Demuxer wants a page in?
234 bool wants_page_in() const throw() { return (packet == packets && !ended); }
236 * Demuxer wants a packet out?
238 bool wants_packet_out() const throw() { return (packet < packets); }
240 * Input a page.
242 bool page_in(const ogg_page& p);
244 * Output a packet.
246 void packet_out(ogg_packet& pkt);
248 * Discard a packet.
250 void discard_packet();
251 private:
252 uint32_t inc1(uint32_t x) { return x + 1; }
253 uint64_t page_fullseq(uint32_t seq);
254 void update_pageseq(uint32_t new_seq);
255 bool complain_lost_page(uint32_t new_seq, uint32_t stream);
256 void complain_continue_errors(unsigned flags, uint32_t seqno, uint32_t stream, uint32_t pkts,
257 uint64_t granule);
258 std::ostream& errors_to;
259 std::vector<uint8_t> partial;
260 bool seen_page;
261 bool damaged_packet;
262 uint32_t imprint_stream;
263 uint32_t page_seq;
264 uint32_t page_era;
265 ogg_page last_page;
266 uint32_t packet;
267 uint32_t packets;
268 uint64_t last_granulepos;
269 bool ended;
273 * Ogg muxer.
275 class ogg_muxer
277 public:
279 * Create a muxer.
281 ogg_muxer(uint32_t streamid, uint64_t _seq = 0);
283 * Wants a packet?
285 bool wants_packet_in() const throw();
287 * Packet of this size fits on current page?
289 bool packet_fits(size_t pktsize) const throw();
291 * Has a page to output?
293 bool has_page_out() const throw();
295 * Input a packet.
297 void packet_in(const std::vector<uint8_t>& data, uint64_t granule);
299 * Signal end of stream.
301 void signal_eos();
303 * Output a page.
305 void page_out(ogg_page& p);
306 private:
307 uint32_t strmid;
308 ogg_page buffer;
309 std::vector<uint8_t> buffered;
310 size_t written;
311 uint64_t seq;
312 bool eos_asserted;
313 uint64_t granulepos;
317 * Ogg stream reader.
319 class ogg_stream_reader
321 public:
323 * Constructor.
325 ogg_stream_reader() throw();
327 * Destructor.
329 virtual ~ogg_stream_reader() throw();
331 * Read some data.
333 * Parameter buffer: The buffer to store the data to.
334 * Parameter size: The maximum size to read.
335 * Returns: The number of bytes actually read.
337 virtual size_t read(char* buffer, size_t size) throw(std::exception) = 0;
339 * Read a page from stream.
341 * Parameter page: The page is assigned here if successful.
342 * Returns: True if page was obtained, false if not.
344 bool get_page(ogg_page& page) throw(std::exception);
346 * Set stream to report errors to.
348 * Parameter strm: The stream.
350 void set_errors_to(std::ostream& os);
352 * Starting offset of last packet returned.
354 uint64_t get_last_offset() { return last_offset; }
355 private:
356 ogg_stream_reader(const ogg_stream_reader&);
357 ogg_stream_reader& operator=(const ogg_stream_reader&);
358 void fill_buffer();
359 void discard_buffer(size_t amount);
360 bool eof;
361 char buffer[65536];
362 size_t left;
363 uint64_t last_offset;
364 uint64_t start_offset;
365 std::ostream* errors_to;
369 * Ogg stream reader based on std::istream.
371 class ogg_stream_reader_iostreams : public ogg_stream_reader
373 public:
375 * Constructor.
377 * Parameter stream: The stream to read the data from.
379 ogg_stream_reader_iostreams(std::istream& stream);
381 * Destructor.
383 ~ogg_stream_reader_iostreams() throw();
385 size_t read(char* buffer, size_t size) throw(std::exception);
386 private:
387 std::istream& is;
391 * Ogg stream writer.
393 class ogg_stream_writer
395 public:
397 * Constructor.
399 ogg_stream_writer() throw();
401 * Destructor.
403 virtual ~ogg_stream_writer() throw();
405 * Write data.
407 * Parameter data: The data to write.
408 * Parameter size: The size to write.
410 virtual void write(const char* buffer, size_t size) throw(std::exception) = 0;
412 * Write a page to stream.
414 * Parameter page: The page to write.
416 void put_page(const ogg_page& page) throw(std::exception);
417 private:
418 ogg_stream_writer(const ogg_stream_writer&);
419 ogg_stream_writer& operator=(const ogg_stream_writer&);
423 * Ogg stream writer based on std::istream.
425 class ogg_stream_writer_iostreams : public ogg_stream_writer
427 public:
429 * Constructor.
431 * Parameter stream: The stream to read the data from.
433 ogg_stream_writer_iostreams(std::ostream& stream);
435 * Destructor.
437 ~ogg_stream_writer_iostreams() throw();
439 void write(const char* buffer, size_t size) throw(std::exception);
440 private:
441 std::ostream& os;
445 * OggOpus header structure.
447 struct oggopus_header
449 uint8_t version;
450 uint8_t channels;
451 uint16_t preskip;
452 uint32_t rate;
453 int16_t gain;
454 uint8_t map_family;
455 uint8_t streams;
456 uint8_t coupled;
457 uint8_t chanmap[255];
461 * OggOpus tags structure
463 struct oggopus_tags
465 std::string vendor;
466 std::vector<std::string> comments;
470 * Parse Ogg page as OggOpus header.
472 * Parameter page: The page to parse.
473 * Returns: Parsed data.
474 * Throws std::runtime_error: Not valid OggOpus header page.
476 struct oggopus_header parse_oggopus_header(struct ogg_page& page) throw(std::runtime_error);
479 * Serialize OggOpus header as an Ogg page.
481 * Parameter header: The header.
482 * Returns: The serialized page.
483 * Throws std::runtime_error: Not valid OggOpus header.
485 struct ogg_page serialize_oggopus_header(struct oggopus_header& header) throw(std::runtime_error);
488 * Parse Ogg page as OggOpus comment.
490 * Parameter page: The page to parse.
491 * Returns: Parsed data.
492 * Throws std::runtime_error: Not valid OggOpus comment page.
494 struct oggopus_tags parse_oggopus_tags(struct ogg_page& page) throw(std::bad_alloc, std::runtime_error);
497 * Serialize OggOpus comments as an Ogg page.
499 * Parameter tags: The comments.
500 * Returns: The serialized page.
501 * Throws std::runtime_error: Not valid OggOpus comments.
503 struct ogg_page serialize_oggopus_tags(struct oggopus_tags& tags) throw(std::runtime_error);
506 * Get tick (2.5ms) count from opus packet.
508 * Parameter packet: The packet data.
509 * Parameter packetsize: The size of packet.
511 * Note: Guaranteed not to read more than 2 bytes from the packet.
513 uint8_t opus_packet_tick_count(const uint8_t* packet, size_t packetsize);
515 #endif