Support multiple-page OpusTags packets

This commit is contained in:
Frédéric Mangano 2023-01-27 15:19:59 +09:00
parent d88498e4fd
commit 7eea19633c
2 changed files with 32 additions and 20 deletions

View File

@ -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_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."};
ogg_logical_stream stream(ogg_page_serialno(&page));
stream.pageno = ogg_page_pageno(&page);
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);
@ -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"};

View File

@ -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;
@ -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');