Skip to content

Commit f816d2c

Browse files
committed
More docs and constants
1 parent 3a17881 commit f816d2c

File tree

1 file changed

+52
-20
lines changed

1 file changed

+52
-20
lines changed

app/src/main/java/org/schabi/newpipe/streams/OggFromWebMWriter.java

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
* The following specifications are used for the implementation:
3939
* </p>
4040
* <ul>
41+
* <li>FLAC: <a href="https://www.rfc-editor.org/rfc/rfc9639">RFC 9639</a></li>
4142
* <li>Opus: All specs can be found at <a href="https://opus-codec.org/docs/">
4243
* https://opus-codec.org/docs/</a>.
4344
* <a href="https://datatracker.ietf.org/doc/html/rfc7845.html">RFC7845</a>
@@ -50,10 +51,24 @@
5051
* @author tobigr
5152
*/
5253
public class OggFromWebMWriter implements Closeable {
54+
private static final String TAG = OggFromWebMWriter.class.getSimpleName();
55+
56+
/**
57+
* No flags set.
58+
*/
5359
private static final byte FLAG_UNSET = 0x00;
54-
//private static final byte FLAG_CONTINUED = 0x01;
60+
/**
61+
* The packet is continued from previous the previous page.
62+
*/
63+
private static final byte FLAG_CONTINUED = 0x01;
64+
/**
65+
* BOS (beginning of stream).
66+
*/
5567
private static final byte FLAG_FIRST = 0x02;
56-
private static final byte FLAG_LAST = 0x04;
68+
/**
69+
* EOS (end of stream).
70+
*/
71+
private static final byte FLAG_LAST = 0x04;;
5772

5873
private static final byte HEADER_CHECKSUM_OFFSET = 22;
5974
private static final byte HEADER_SIZE = 27;
@@ -66,6 +81,12 @@ public class OggFromWebMWriter implements Closeable {
6681
*/
6782
private static final int OGG_SEGMENT_SIZE = 255;
6883

84+
/**
85+
* The maximum size of the Opus packet in bytes, to be included in the Ogg page.
86+
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7845.html#section-6">
87+
* RFC7845 6. Packet Size Limits</a>
88+
*/
89+
private static final int OPUS_MAX_PACKETS_PAGE_SIZE = 61_440;
6990

7091
private boolean done = false;
7192
private boolean parsed = false;
@@ -330,12 +351,13 @@ private int makePacketHeader(final long granPos, @NonNull final ByteBuffer buffe
330351
* @ImplNote See <a href="https://datatracker.ietf.org/doc/html/rfc7845.html#section-5.2">
331352
* RFC7845 5.2</a>
332353
*
333-
* @return
354+
* @return the metadata header as a byte array, or null if the codec is not supported
355+
* for metadata generation
334356
*/
335357
@Nullable
336358
private byte[] makeMetadata() {
337359
if (DEBUG) {
338-
Log.d("OggFromWebMWriter", "Downloading media with codec ID " + webmTrack.codecId);
360+
Log.d(TAG, "Downloading media with codec ID " + webmTrack.codecId);
339361
}
340362

341363
if ("A_OPUS".equals(webmTrack.codecId)) {
@@ -355,18 +377,17 @@ private byte[] makeMetadata() {
355377
}
356378

357379
if (DEBUG) {
358-
Log.d("OggFromWebMWriter", "Creating metadata header with this data:");
359-
metadata.forEach(p -> Log.d("OggFromWebMWriter", p.first + "=" + p.second));
380+
Log.d(TAG, "Creating metadata header with this data:");
381+
metadata.forEach(p -> Log.d(TAG, p.first + "=" + p.second));
360382
}
361383

362384
return makeOpusTagsHeader(metadata);
363385
} else if ("A_VORBIS".equals(webmTrack.codecId)) {
364-
/**
365-
* See <a href="https://datatracker.ietf.org/doc/html/rfc7845.html#section-5.2">
366-
* RFC7845 5.2</a>
367-
*/
386+
// See https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-620004.2.1
387+
// for the Vorbis comment header format
388+
// TODO: add Vorbis metadata: same as Opus, but with the Vorbis comment header format
368389
return new byte[]{
369-
0x03, // ???
390+
0x03, // packet type for Vorbis comment header
370391
0x76, 0x6f, 0x72, 0x62, 0x69, 0x73, // "vorbis" binary string
371392
0x00, 0x00, 0x00, 0x00, // writing application string size (not present)
372393
0x00, 0x00, 0x00, 0x00 // additional tags count (zero means no tags)
@@ -401,23 +422,31 @@ private static byte[] makeOpusMetadataTag(final Pair<String, String> pair) {
401422
* containing the provided bitmap as cover art.
402423
*
403424
* <p>
404-
* One could also use the COVERART tag instead, but it is not as widely supported
405-
* as METADATA_BLOCK_PICTURE.
425+
* The {@code METADATA_BLOCK_PICTURE} tag is defined in the FLAC specification (RFC 9639)
426+
* and is supported by Opus metadata headers.
427+
* One could also use the {@code COVERART} tag instead, but it is not as widely supported
428+
* as {@code METADATA_BLOCK_PICTURE}.
406429
* </p>
407430
*
431+
* @see <a href="https://www.rfc-editor.org/rfc/rfc9639.html#section-8.8">
432+
* RFC 9639 8.8 Picture</a>
433+
*
408434
* @param bitmap The bitmap to use as cover art
409435
* @return The key-value pair representing the tag
410436
*/
411437
private static Pair<String, String> makeOpusPictureTag(final Bitmap bitmap) {
412438
// FLAC picture block format (big-endian):
413439
// uint32 picture_type
414-
// uint32 mime_length, mime_string
415-
// uint32 desc_length, desc_string
440+
// uint32 mime_length,
441+
// mime_string
442+
// uint32 desc_length,
443+
// desc_string
416444
// uint32 width
417445
// uint32 height
418446
// uint32 color_depth
419447
// uint32 colors_indexed
420-
// uint32 data_length, data_bytes
448+
// uint32 data_length,
449+
// data_bytes
421450

422451
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
423452
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
@@ -428,7 +457,8 @@ private static Pair<String, String> makeOpusPictureTag(final Bitmap bitmap) {
428457
// fixed ints + mime + desc
429458
final int headerSize = 4 * 8 + mimeBytes.length + descBytes.length;
430459
final ByteBuffer buf = ByteBuffer.allocate(headerSize + imageData.length);
431-
// See https://id3.org/id3v2.3.0#Attached_picture for a full list of picture types
460+
// See https://www.rfc-editor.org/rfc/rfc9639.html#table-13 for the complete list
461+
// of picture types
432462
// TODO: allow specifying other picture types, i.e. cover (front) for music albums;
433463
// but this info needs to be provided by the extractor first.
434464
buf.putInt(3); // picture type: 0 = Other, 2 = Cover (front)
@@ -476,6 +506,7 @@ private static byte[] makeOpusTagsHeader(final List<Pair<String, String>> keyVal
476506

477507
final var head = ByteBuffer.allocate(byteCount);
478508
head.order(ByteOrder.LITTLE_ENDIAN);
509+
// See RFC7845 5.2: https://datatracker.ietf.org/doc/html/rfc7845.html#section-5.2
479510
head.put(new byte[]{
480511
0x4F, 0x70, 0x75, 0x73, 0x54, 0x61, 0x67, 0x73, // "OpusTags" binary string
481512
0x00, 0x00, 0x00, 0x00, // vendor (aka. Encoder) string of length 0
@@ -559,9 +590,10 @@ private boolean addPacketSegment(final SimpleBlock block) {
559590
}
560591

561592
private boolean addPacketSegment(final int size) {
562-
if (size > 65025) {
563-
throw new UnsupportedOperationException(
564-
String.format("page size is %s but cannot be larger than 65025", size));
593+
if (size > OPUS_MAX_PACKETS_PAGE_SIZE) {
594+
throw new UnsupportedOperationException(String.format(
595+
"page size is %s but cannot be larger than %s",
596+
size, OPUS_MAX_PACKETS_PAGE_SIZE));
565597
}
566598

567599
int available = (segmentTable.length - segmentTableSize) * OGG_SEGMENT_SIZE;

0 commit comments

Comments
 (0)