mirror of
https://github.com/fmang/opustags.git
synced 2025-07-12 20:15:39 +02:00
implement ogg::Decoder
This commit is contained in:
@ -37,7 +37,8 @@ namespace opustags {
|
||||
// header is read.
|
||||
//
|
||||
// Use:
|
||||
// ogg::Decoder dec(std::ifstream("in.ogg"));
|
||||
// std::ifstream in("in.ogg");
|
||||
// ogg::Decoder dec(&in);
|
||||
// TagsLister lister(options);
|
||||
// list_tags(dec, lister);
|
||||
//
|
||||
@ -47,8 +48,10 @@ namespace opustags {
|
||||
// with the handler's edit method.
|
||||
//
|
||||
// Use:
|
||||
// ogg::Decoder dec(std::ifstream("in.ogg"));
|
||||
// ogg::Encoder enc(std::ofstream("out.ogg"));
|
||||
// std::ifstream in("in.ogg");
|
||||
// ogg::Decoder dec(&in);
|
||||
// std::ofstream out("out.ogg");
|
||||
// std::Encoder enc(&out);
|
||||
// TagsEditor editor(options);
|
||||
// edit_tags(dec, enc, editor);
|
||||
//
|
||||
|
69
src/ogg.cc
69
src/ogg.cc
@ -1,9 +1,13 @@
|
||||
#include "ogg.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
|
||||
using namespace opustags;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ogg::Stream
|
||||
|
||||
ogg::Stream::Stream(int streamno)
|
||||
{
|
||||
state = ogg::BEGIN_OF_STREAM;
|
||||
@ -61,11 +65,14 @@ void ogg::Stream::handle_packet(const ogg_packet &op)
|
||||
void ogg::Stream::parse_header(const ogg_packet &op)
|
||||
{
|
||||
// TODO
|
||||
// set type
|
||||
// set state
|
||||
}
|
||||
|
||||
void ogg::Stream::parse_tags(const ogg_packet &op)
|
||||
{
|
||||
// TODO
|
||||
state = TAGS_READY;
|
||||
}
|
||||
|
||||
void ogg::Stream::downgrade()
|
||||
@ -74,3 +81,65 @@ void ogg::Stream::downgrade()
|
||||
if (state != ogg::BEGIN_OF_STREAM && state != ogg::END_OF_STREAM)
|
||||
state = RAW_READY;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ogg::Decoder
|
||||
|
||||
ogg::Decoder::Decoder(std::istream *in)
|
||||
: input(in)
|
||||
{
|
||||
input->exceptions(std::ifstream::badbit);
|
||||
ogg_sync_init(&sync);
|
||||
}
|
||||
|
||||
ogg::Decoder::~Decoder()
|
||||
{
|
||||
ogg_sync_clear(&sync);
|
||||
}
|
||||
|
||||
ogg::Stream* ogg::Decoder::read_page()
|
||||
{
|
||||
while (page_out()) {
|
||||
int streamno = ogg_page_serialno(¤t_page);
|
||||
auto i = streams.find(streamno);
|
||||
if (i == streams.end()) {
|
||||
// we could check the page number to detect new streams (pageno = 0)
|
||||
i = streams.emplace(streamno, Stream(streamno)).first;
|
||||
}
|
||||
if (i->second.page_in(current_page))
|
||||
return &(i->second);
|
||||
}
|
||||
return NULL; // end of stream
|
||||
}
|
||||
|
||||
// Read the next page and return true on success, false on end of stream.
|
||||
bool ogg::Decoder::page_out()
|
||||
{
|
||||
int rc;
|
||||
for (;;) {
|
||||
rc = ogg_sync_pageout(&sync, ¤t_page);
|
||||
if (rc < 0) {
|
||||
throw std::runtime_error("ogg_sync_pageout failed");
|
||||
} else if (rc == 1) {
|
||||
break; // page complete
|
||||
} else if (!buff()) {
|
||||
// more data required but end of file reached
|
||||
// TODO check sync.unsynced flag in case we've got an incomplete page
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read data from the stream into the sync's buffer.
|
||||
bool ogg::Decoder::buff()
|
||||
{
|
||||
if (input->eof())
|
||||
return false;
|
||||
char *buf = ogg_sync_buffer(&sync, 65536);
|
||||
if (buf == NULL)
|
||||
throw std::runtime_error("ogg_sync_buffer failed");
|
||||
input->read(buf, 65536);
|
||||
ogg_sync_wrote(&sync, input->gcount());
|
||||
return true;
|
||||
}
|
||||
|
12
src/ogg.h
12
src/ogg.h
@ -70,7 +70,7 @@ namespace ogg
|
||||
|
||||
struct Decoder
|
||||
{
|
||||
Decoder(std::istream&&);
|
||||
Decoder(std::istream*);
|
||||
~Decoder();
|
||||
|
||||
// Read a page, dispatch it, and return the stream it belongs to.
|
||||
@ -79,16 +79,20 @@ namespace ogg
|
||||
// After the end of the file is reached, it returns NULL.
|
||||
Stream* read_page();
|
||||
|
||||
std::istream input;
|
||||
std::istream *input;
|
||||
|
||||
ogg_sync_state sync;
|
||||
ogg_page current_page;
|
||||
std::map<int, Stream> streams;
|
||||
|
||||
private:
|
||||
bool page_out();
|
||||
bool buff();
|
||||
};
|
||||
|
||||
struct Encoder
|
||||
{
|
||||
Encoder(std::ostream&&);
|
||||
Encoder(std::ostream*);
|
||||
~Encoder();
|
||||
|
||||
void write_page(const ogg_page&);
|
||||
@ -100,7 +104,7 @@ namespace ogg
|
||||
|
||||
void write_tags(int streamno, const Tags&);
|
||||
|
||||
std::ostream output;
|
||||
std::ostream *output;
|
||||
|
||||
// We're gonna need some ogg_stream_state for adjusting the page
|
||||
// numbers and splitting large packets as it's gotta be done.
|
||||
|
Reference in New Issue
Block a user