mirror of
https://github.com/fmang/opustags.git
synced 2025-07-14 21:15:27 +02:00
implement most of ogg::Encoder
This commit is contained in:
@ -38,7 +38,7 @@ void opustags::edit_tags(ogg::Decoder &in, ogg::Encoder &out, TagsHandler &handl
|
||||
s->downgrade();
|
||||
out.write_raw_page(in.current_page);
|
||||
} else {
|
||||
out.write_page(in.current_page);
|
||||
out.forward(*s);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -48,7 +48,7 @@ void opustags::edit_tags(ogg::Decoder &in, ogg::Encoder &out, TagsHandler &handl
|
||||
break;
|
||||
|
||||
case ogg::DATA_READY:
|
||||
out.write_page(in.current_page);
|
||||
out.forward(*s);
|
||||
break;
|
||||
|
||||
case ogg::RAW_READY:
|
||||
|
71
src/ogg.cc
71
src/ogg.cc
@ -42,7 +42,7 @@ bool ogg::Stream::page_in(ogg_page &og)
|
||||
bool ogg::Stream::handle_page()
|
||||
{
|
||||
ogg_packet op;
|
||||
int rc = ogg_stream_packetout(&stream, &op);
|
||||
int rc = ogg_stream_packetpeek(&stream, &op);
|
||||
if (rc < 0)
|
||||
throw std::runtime_error("ogg_stream_packetout failed");
|
||||
else if (rc == 0) // insufficient data
|
||||
@ -143,3 +143,72 @@ bool ogg::Decoder::buff()
|
||||
ogg_sync_wrote(&sync, input->gcount());
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ogg::Encoder
|
||||
|
||||
ogg::Encoder::Encoder(std::ostream *out)
|
||||
: output(out)
|
||||
{
|
||||
output->exceptions(std::ifstream::badbit);
|
||||
}
|
||||
|
||||
ogg::Stream& ogg::Encoder::get_stream(int streamno)
|
||||
{
|
||||
auto i = streams.find(streamno);
|
||||
if (i == streams.end())
|
||||
i = streams.emplace(streamno, Stream(streamno)).first;
|
||||
return i->second;
|
||||
}
|
||||
|
||||
void ogg::Encoder::forward(ogg::Stream &in)
|
||||
{
|
||||
ogg::Stream *out = &get_stream(in.stream.serialno);
|
||||
forward_stream(in, *out);
|
||||
flush_stream(*out);
|
||||
}
|
||||
|
||||
void ogg::Encoder::forward_stream(ogg::Stream &in, ogg::Stream &out)
|
||||
{
|
||||
int rc;
|
||||
ogg_packet op;
|
||||
for (;;) {
|
||||
rc = ogg_stream_packetout(&in.stream, &op);
|
||||
if (rc < 0) {
|
||||
throw std::runtime_error("ogg_stream_packetout failed");
|
||||
} else if (rc == 0) {
|
||||
break;
|
||||
} else {
|
||||
if (ogg_stream_packetin(&out.stream, &op) != 0)
|
||||
throw std::runtime_error("ogg_stream_packetin failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
void ogg::Encoder::flush_stream(ogg::Stream &out)
|
||||
{
|
||||
ogg_page og;
|
||||
if (ogg_stream_flush(&out.stream, &og))
|
||||
write_raw_page(og);
|
||||
}
|
||||
|
||||
void ogg::Encoder::write_raw_page(const ogg_page &og)
|
||||
{
|
||||
output->write((const char*) og.header, og.header_len);
|
||||
output->write((const char*) og.body, og.body_len);
|
||||
}
|
||||
|
||||
void ogg::Encoder::write_tags(int streamno, const Tags&)
|
||||
{
|
||||
ogg_packet op;
|
||||
op.b_o_s = 0;
|
||||
op.e_o_s = 0;
|
||||
op.granulepos = 0;
|
||||
op.packetno = 1; // TODO ensure it's not 2
|
||||
// craft the tags
|
||||
op.bytes = 0;
|
||||
|
||||
ogg::Stream *s = &streams.at(streamno); // assume it exists
|
||||
if (ogg_stream_packetin(&s->stream, &op) != 0)
|
||||
throw std::runtime_error("ogg_stream_packetin failed");
|
||||
flush_stream(*s);
|
||||
}
|
||||
|
11
src/ogg.h
11
src/ogg.h
@ -93,9 +93,9 @@ namespace ogg
|
||||
struct Encoder
|
||||
{
|
||||
Encoder(std::ostream*);
|
||||
~Encoder();
|
||||
|
||||
void write_page(const ogg_page&);
|
||||
// Copy the input stream's current page.
|
||||
void forward(Stream &in);
|
||||
|
||||
// Write the page without even ensuring its page number is correct.
|
||||
// It would be an efficient way to copy a stream identically, and also
|
||||
@ -108,7 +108,12 @@ namespace ogg
|
||||
|
||||
// We're gonna need some ogg_stream_state for adjusting the page
|
||||
// numbers and splitting large packets as it's gotta be done.
|
||||
std::map<int, ogg_stream_state> streams;
|
||||
std::map<int, Stream> streams;
|
||||
|
||||
private:
|
||||
Stream& get_stream(int streamno);
|
||||
void forward_stream(Stream &in, Stream &out);
|
||||
void flush_stream(Stream &out);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user