1 #ifndef _library__ogg__hpp__included__
2 #define _library__ogg__hpp__included__
10 * A packet in Ogg bitstream.
22 ogg_packet(uint64_t granule
, bool first
, bool last
, bool spans
, bool eos
, const std::vector
<uint8_t>& d
);
24 * Is the packet first within its page?
26 bool get_first_page() const throw() { return first_page
; }
28 * Is the packet last within its page?
30 bool get_last_page() const throw() { return last_page
; }
32 * Is the packet spanning multiple pages?
34 bool get_spans_page() const throw() { return spans_page
; }
36 * Is atomic (first, last and on one page)?
38 bool get_atomic() const throw() { return first_page
&& last_page
&& !spans_page
; }
40 * Get the granule position within page the packet finished at.
42 uint64_t get_granulepos() const throw() { return granulepos
; }
44 * Does the page this ends on have EOS set?
46 bool get_on_eos_page() const throw() { return eos_page
; }
48 * Get the packet data.
50 const std::vector
<uint8_t>& get_vector() const throw() { return data
; }
52 * Get length of packet data.
54 size_t get_length() const throw() { return data
.size(); }
58 const uint8_t* get_data() const throw() { return &data
[0]; }
65 std::vector
<uint8_t> data
;
69 * A page in Ogg bitstream.
75 * Create a new blank page.
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
);
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();
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
; }
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);
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
;
209 bool last_incomplete
;
213 uint8_t segment_count
;
214 uint8_t packet_count
;
217 uint8_t segments
[255];
218 uint16_t packets
[256];
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
); }
242 bool page_in(const ogg_page
& p
);
246 void packet_out(ogg_packet
& pkt
);
250 void discard_packet();
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
,
258 std::ostream
& errors_to
;
259 std::vector
<uint8_t> partial
;
262 uint32_t imprint_stream
;
268 uint64_t last_granulepos
;
281 ogg_muxer(uint32_t streamid
, uint64_t _seq
= 0);
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();
297 void packet_in(const std::vector
<uint8_t>& data
, uint64_t granule
);
299 * Signal end of stream.
305 void page_out(ogg_page
& p
);
309 std::vector
<uint8_t> buffered
;
319 class ogg_stream_reader
325 ogg_stream_reader() throw();
329 virtual ~ogg_stream_reader() throw();
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
; }
356 ogg_stream_reader(const ogg_stream_reader
&);
357 ogg_stream_reader
& operator=(const ogg_stream_reader
&);
359 void discard_buffer(size_t amount
);
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
377 * Parameter stream: The stream to read the data from.
379 ogg_stream_reader_iostreams(std::istream
& stream
);
383 ~ogg_stream_reader_iostreams() throw();
385 size_t read(char* buffer
, size_t size
) throw(std::exception
);
393 class ogg_stream_writer
399 ogg_stream_writer() throw();
403 virtual ~ogg_stream_writer() throw();
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
);
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
431 * Parameter stream: The stream to read the data from.
433 ogg_stream_writer_iostreams(std::ostream
& stream
);
437 ~ogg_stream_writer_iostreams() throw();
439 void write(const char* buffer
, size_t size
) throw(std::exception
);
445 * OggOpus header structure.
447 struct oggopus_header
457 uint8_t chanmap
[255];
461 * OggOpus tags structure
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
);