mirror of
https://github.com/fmang/opustags.git
synced 2024-11-10 07:27:22 +01:00
RAII interface for dynamic ogg packets
This commit is contained in:
parent
82ff7f7751
commit
e41cf918d1
43
src/opus.cc
43
src/opus.cc
@ -86,39 +86,38 @@ ot::status ot::parse_tags(const char *data, long len, opus_tags *tags)
|
||||
return status::ok;
|
||||
}
|
||||
|
||||
int ot::render_tags(opus_tags *tags, ogg_packet *op)
|
||||
ot::dynamic_ogg_packet ot::render_tags(const opus_tags& tags)
|
||||
{
|
||||
// Note: op->packet must be manually freed.
|
||||
op->b_o_s = 0;
|
||||
op->e_o_s = 0;
|
||||
op->granulepos = 0;
|
||||
op->packetno = 1;
|
||||
long len = 8 + 4 + tags->vendor.size() + 4;
|
||||
for (const std::string& comment : tags->comments)
|
||||
len += 4 + comment.size();
|
||||
len += tags->extra_data.size();
|
||||
op->bytes = len;
|
||||
char *data = static_cast<char*>(malloc(len));
|
||||
if (!data)
|
||||
return -1;
|
||||
op->packet = (unsigned char*) data;
|
||||
size_t size = 8 + 4 + tags.vendor.size() + 4;
|
||||
for (const std::string& comment : tags.comments)
|
||||
size += 4 + comment.size();
|
||||
size += tags.extra_data.size();
|
||||
|
||||
dynamic_ogg_packet op(size);
|
||||
op.b_o_s = 0;
|
||||
op.e_o_s = 0;
|
||||
op.granulepos = 0;
|
||||
op.packetno = 1;
|
||||
|
||||
unsigned char* data = op.packet;
|
||||
uint32_t n;
|
||||
memcpy(data, "OpusTags", 8);
|
||||
n = htole32(tags->vendor.size());
|
||||
n = htole32(tags.vendor.size());
|
||||
memcpy(data+8, &n, 4);
|
||||
memcpy(data+12, tags->vendor.data(), tags->vendor.size());
|
||||
data += 12 + tags->vendor.size();
|
||||
n = htole32(tags->comments.size());
|
||||
memcpy(data+12, tags.vendor.data(), tags.vendor.size());
|
||||
data += 12 + tags.vendor.size();
|
||||
n = htole32(tags.comments.size());
|
||||
memcpy(data, &n, 4);
|
||||
data += 4;
|
||||
for (const std::string& comment : tags->comments) {
|
||||
for (const std::string& comment : tags.comments) {
|
||||
n = htole32(comment.size());
|
||||
memcpy(data, &n, 4);
|
||||
memcpy(data+4, comment.data(), comment.size());
|
||||
data += 4 + comment.size();
|
||||
}
|
||||
memcpy(data, tags->extra_data.data(), tags->extra_data.size());
|
||||
return 0;
|
||||
memcpy(data, tags.extra_data.data(), tags.extra_data.size());
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,11 +131,9 @@ static int run(ot::options& opt)
|
||||
for (const std::string& comment : opt.to_add)
|
||||
tags.comments.emplace_back(comment);
|
||||
if(writer.file){
|
||||
ogg_packet packet;
|
||||
ot::render_tags(&tags, &packet);
|
||||
auto packet = ot::render_tags(tags);
|
||||
if(ogg_stream_packetin(&writer.stream, &packet) == -1)
|
||||
error = "ogg_stream_packetin: internal error";
|
||||
free(packet.packet);
|
||||
}
|
||||
else
|
||||
ot::print_comments(tags.comments, stdout);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -158,6 +159,23 @@ struct ogg_writer {
|
||||
|
||||
int write_page(ogg_page *og, FILE *stream);
|
||||
|
||||
/**
|
||||
* Ogg packet with dynamically allocated data.
|
||||
*
|
||||
* Provides a wrapper around libogg's ogg_packet with RAII.
|
||||
*/
|
||||
struct dynamic_ogg_packet : ogg_packet {
|
||||
/** Construct an ogg_packet of the given size. */
|
||||
explicit dynamic_ogg_packet(size_t size) {
|
||||
bytes = size;
|
||||
data = std::make_unique<unsigned char[]>(size);
|
||||
packet = data.get();
|
||||
}
|
||||
private:
|
||||
/** Owning reference to the data. Use the packet field from ogg_packet instead. */
|
||||
std::unique_ptr<unsigned char[]> data;
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/**
|
||||
@ -206,7 +224,7 @@ struct opus_tags {
|
||||
status validate_identification_header(const ogg_packet& packet);
|
||||
|
||||
status parse_tags(const char *data, long len, opus_tags *tags);
|
||||
int render_tags(opus_tags *tags, ogg_packet *op);
|
||||
dynamic_ogg_packet render_tags(const opus_tags& tags);
|
||||
void delete_tags(opus_tags *tags, const char *field);
|
||||
|
||||
/** \} */
|
||||
|
10
t/opus.cc
10
t/opus.cc
@ -110,9 +110,7 @@ static void recode_standard()
|
||||
auto rc = ot::parse_tags(standard_OpusTags, sizeof(standard_OpusTags) - 1, &tags);
|
||||
if (rc != ot::status::ok)
|
||||
throw failure("ot::parse_tags did not return ok");
|
||||
ogg_packet packet;
|
||||
if (ot::render_tags(&tags, &packet) != 0)
|
||||
throw failure("ot::render_tags did not return 0");
|
||||
auto packet = ot::render_tags(tags);
|
||||
if (packet.b_o_s != 0)
|
||||
throw failure("b_o_s should not be set");
|
||||
if (packet.e_o_s != 0)
|
||||
@ -125,7 +123,6 @@ static void recode_standard()
|
||||
throw failure("the packet is not the right size");
|
||||
if (memcmp(packet.packet, standard_OpusTags, packet.bytes) != 0)
|
||||
throw failure("the rendered packet is not what we expected");
|
||||
free(packet.packet);
|
||||
}
|
||||
|
||||
static void recode_padding()
|
||||
@ -140,16 +137,13 @@ static void recode_padding()
|
||||
if (tags.extra_data != "\0hello"s)
|
||||
throw failure("corrupted extra data");
|
||||
// recode the packet and ensure it's exactly the same
|
||||
ogg_packet packet;
|
||||
if (ot::render_tags(&tags, &packet) != 0)
|
||||
throw failure("ot::render_tags did not return 0");
|
||||
auto packet = ot::render_tags(tags);
|
||||
if (static_cast<size_t>(packet.bytes) < padded_OpusTags.size())
|
||||
throw failure("the packet was truncated");
|
||||
if (static_cast<size_t>(packet.bytes) > padded_OpusTags.size())
|
||||
throw failure("the packet got too big");
|
||||
if (memcmp(packet.packet, padded_OpusTags.data(), packet.bytes) != 0)
|
||||
throw failure("the rendered packet is not what we expected");
|
||||
free(packet.packet);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
Loading…
Reference in New Issue
Block a user