Skip to content

Commit

Permalink
Support multiple-page OpusTags packets
Browse files Browse the repository at this point in the history
  • Loading branch information
fmang committed Feb 2, 2023
1 parent d88498e commit 7eea196
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 19 deletions.
38 changes: 20 additions & 18 deletions src/ogg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,28 @@ void ot::ogg_reader::process_header_packet(const std::function<void(ogg_packet&)
{
if (ogg_page_continued(&page))
throw status {ot::st::error, "Unexpected continued header page."};

ogg_packet packet;
ogg_logical_stream stream(ogg_page_serialno(&page));
stream.pageno = ogg_page_pageno(&page);
if (ogg_stream_pagein(&stream, &page) != 0)
throw status {st::libogg_error, "ogg_stream_pagein failed."};

ogg_packet packet;
int rc = ogg_stream_packetout(&stream, &packet);
if (ogg_stream_check(&stream) != 0 || rc == -1)
throw status {ot::st::libogg_error, "ogg_stream_packetout failed."};
else if (rc == 0)
throw status {ot::st::error,
"Reading header packets spanning multiple pages are not yet supported. "
"Please file an issue to make your wish known."};
for (;;) {
if (ogg_stream_pagein(&stream, &page) != 0)
throw status {st::libogg_error, "ogg_stream_pagein failed."};

int rc = ogg_stream_packetout(&stream, &packet);
if (ogg_stream_check(&stream) != 0 || rc == -1) {
throw status {ot::st::libogg_error, "ogg_stream_packetout failed."};
} else if (rc == 0) {
// Not enough data: read the next page.
if (!next_page())
throw status {ot::st::error, "Unterminated header packet."};
continue;
} else {
// The packet was successfully read.
break;
}
}

f(packet);

Expand Down Expand Up @@ -109,15 +118,8 @@ void ot::ogg_writer::write_header_packet(int serialno, int pageno, ogg_packet& p
throw status {ot::st::libogg_error, "ogg_stream_packetin failed"};

ogg_page page;
if (ogg_stream_flush(&stream, &page) != 0)
while (ogg_stream_flush(&stream, &page) != 0)
write_page(page);
else
throw status {ot::st::libogg_error, "ogg_stream_flush failed"};

if (ogg_stream_flush(&stream, &page) != 0)
throw status {ot::st::error,
"Writing header packets spanning multiple pages are not yet supported. "
"Please file an issue to make your wish known."};

if (ogg_stream_check(&stream) != 0)
throw status {st::libogg_error, "ogg_stream_check failed"};
Expand Down
12 changes: 11 additions & 1 deletion t/opustags.t
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use strict;
use warnings;
use utf8;

use Test::More tests => 50;
use Test::More tests => 54;

use Digest::MD5;
use File::Basename;
Expand Down Expand Up @@ -311,3 +311,13 @@ U=\xFE
END_OUT

unlink('out.opus');

####################################################################################################
# Multiple-page tags

my $big_tags = "DATA=x\n" x 15000; # > 90K, which is over the max page size of 64KiB.
is_deeply(opustags(qw(-S gobble.opus -o out.opus), {in => $big_tags}), ['', '', 0], 'write multi-page header');
is_deeply(opustags('out.opus'), [$big_tags, '', 0], 'read multi-page header');
is_deeply(opustags(qw(out.opus -i -D -a), 'encoder=Lavc58.18.100 libopus'), ['', '', 0], 'shrink the header');
is(md5('out.opus'), '111a483596ac32352fbce4d14d16abd2', 'the result is identical to the original file');
unlink('out.opus');

0 comments on commit 7eea196

Please sign in to comment.