use of androidx.media3.common.Metadata.Entry in project media by androidx.
the class VorbisUtil method parseVorbisComments.
/**
* Builds a {@link Metadata} instance from a list of Vorbis Comments.
*
* <p>METADATA_BLOCK_PICTURE comments will be transformed into {@link PictureFrame} entries. All
* others will be transformed into {@link VorbisComment} entries.
*
* @param vorbisComments The raw input of comments, as a key-value pair KEY=VAL.
* @return The fully parsed Metadata instance. Null if no vorbis comments could be parsed.
*/
@Nullable
public static Metadata parseVorbisComments(List<String> vorbisComments) {
List<Entry> metadataEntries = new ArrayList<>();
for (int i = 0; i < vorbisComments.size(); i++) {
String vorbisComment = vorbisComments.get(i);
String[] keyAndValue = Util.splitAtFirst(vorbisComment, "=");
if (keyAndValue.length != 2) {
Log.w(TAG, "Failed to parse Vorbis comment: " + vorbisComment);
continue;
}
if (keyAndValue[0].equals("METADATA_BLOCK_PICTURE")) {
// Decode it from Base64 and transform it into a PictureFrame.
try {
byte[] decoded = Base64.decode(keyAndValue[1], Base64.DEFAULT);
metadataEntries.add(PictureFrame.fromPictureBlock(new ParsableByteArray(decoded)));
} catch (RuntimeException e) {
Log.w(TAG, "Failed to parse vorbis picture", e);
}
} else {
VorbisComment entry = new VorbisComment(keyAndValue[0], keyAndValue[1]);
metadataEntries.add(entry);
}
}
return metadataEntries.isEmpty() ? null : new Metadata(metadataEntries);
}
use of androidx.media3.common.Metadata.Entry in project media by androidx.
the class FragmentedMp4Extractor method parseSampleGroups.
private static void parseSampleGroups(ContainerAtom traf, @Nullable String schemeType, TrackFragment out) throws ParserException {
// Find sbgp and sgpd boxes with grouping_type == seig.
@Nullable ParsableByteArray sbgp = null;
@Nullable ParsableByteArray sgpd = null;
for (int i = 0; i < traf.leafChildren.size(); i++) {
LeafAtom leafAtom = traf.leafChildren.get(i);
ParsableByteArray leafAtomData = leafAtom.data;
if (leafAtom.type == Atom.TYPE_sbgp) {
leafAtomData.setPosition(Atom.FULL_HEADER_SIZE);
if (leafAtomData.readInt() == SAMPLE_GROUP_TYPE_seig) {
sbgp = leafAtomData;
}
} else if (leafAtom.type == Atom.TYPE_sgpd) {
leafAtomData.setPosition(Atom.FULL_HEADER_SIZE);
if (leafAtomData.readInt() == SAMPLE_GROUP_TYPE_seig) {
sgpd = leafAtomData;
}
}
}
if (sbgp == null || sgpd == null) {
return;
}
sbgp.setPosition(Atom.HEADER_SIZE);
int sbgpVersion = Atom.parseFullAtomVersion(sbgp.readInt());
// grouping_type == seig.
sbgp.skipBytes(4);
if (sbgpVersion == 1) {
// grouping_type_parameter.
sbgp.skipBytes(4);
}
if (sbgp.readInt() != 1) {
// entry_count.
throw ParserException.createForUnsupportedContainerFeature("Entry count in sbgp != 1 (unsupported).");
}
sgpd.setPosition(Atom.HEADER_SIZE);
int sgpdVersion = Atom.parseFullAtomVersion(sgpd.readInt());
// grouping_type == seig.
sgpd.skipBytes(4);
if (sgpdVersion == 1) {
if (sgpd.readUnsignedInt() == 0) {
throw ParserException.createForUnsupportedContainerFeature("Variable length description in sgpd found (unsupported)");
}
} else if (sgpdVersion >= 2) {
// default_sample_description_index.
sgpd.skipBytes(4);
}
if (sgpd.readUnsignedInt() != 1) {
// entry_count.
throw ParserException.createForUnsupportedContainerFeature("Entry count in sgpd != 1 (unsupported).");
}
// CencSampleEncryptionInformationGroupEntry
// reserved = 0.
sgpd.skipBytes(1);
int patternByte = sgpd.readUnsignedByte();
int cryptByteBlock = (patternByte & 0xF0) >> 4;
int skipByteBlock = patternByte & 0x0F;
boolean isProtected = sgpd.readUnsignedByte() == 1;
if (!isProtected) {
return;
}
int perSampleIvSize = sgpd.readUnsignedByte();
byte[] keyId = new byte[16];
sgpd.readBytes(keyId, 0, keyId.length);
@Nullable byte[] constantIv = null;
if (perSampleIvSize == 0) {
int constantIvSize = sgpd.readUnsignedByte();
constantIv = new byte[constantIvSize];
sgpd.readBytes(constantIv, 0, constantIvSize);
}
out.definesEncryptionData = true;
out.trackEncryptionBox = new TrackEncryptionBox(isProtected, schemeType, perSampleIvSize, keyId, cryptByteBlock, skipByteBlock, constantIv);
}
use of androidx.media3.common.Metadata.Entry in project media by androidx.
the class AtomParsers method parseIlst.
@Nullable
private static Metadata parseIlst(ParsableByteArray ilst, int limit) {
ilst.skipBytes(Atom.HEADER_SIZE);
ArrayList<Metadata.Entry> entries = new ArrayList<>();
while (ilst.getPosition() < limit) {
@Nullable Metadata.Entry entry = MetadataUtil.parseIlstElement(ilst);
if (entry != null) {
entries.add(entry);
}
}
return entries.isEmpty() ? null : new Metadata(entries);
}
use of androidx.media3.common.Metadata.Entry in project media by androidx.
the class PictureFrameTest method populateMediaMetadata_setsBuilderValues.
@Test
public void populateMediaMetadata_setsBuilderValues() {
byte[] pictureData = new byte[] { -12, 52, 33, 85, 34, 22, 1, -55 };
Metadata.Entry entry = new PictureFrame(/* pictureType= */
MediaMetadata.PICTURE_TYPE_FRONT_COVER, /* mimeType= */
MimeTypes.IMAGE_JPEG, /* description= */
"an image", /* width= */
4, /* height= */
2, /* depth= */
1, /* colors= */
1, pictureData);
MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon();
entry.populateMediaMetadata(builder);
MediaMetadata mediaMetadata = builder.build();
assertThat(mediaMetadata.artworkData).isEqualTo(pictureData);
assertThat(mediaMetadata.artworkDataType).isEqualTo(MediaMetadata.PICTURE_TYPE_FRONT_COVER);
}
use of androidx.media3.common.Metadata.Entry in project media by androidx.
the class ApicFrameTest method populateMediaMetadata_setsBuilderValues.
@Test
public void populateMediaMetadata_setsBuilderValues() {
byte[] pictureData = new byte[] { -12, 52, 33, 85, 34, 22, 1, -55 };
@MediaMetadata.PictureType int pictureType = MediaMetadata.PICTURE_TYPE_LEAFLET_PAGE;
Metadata.Entry entry = new ApicFrame(/* mimeType= */
MimeTypes.BASE_TYPE_IMAGE, /* description= */
"an image", pictureType, pictureData);
MediaMetadata.Builder builder = MediaMetadata.EMPTY.buildUpon();
entry.populateMediaMetadata(builder);
MediaMetadata mediaMetadata = builder.build();
assertThat(mediaMetadata.artworkData).isEqualTo(pictureData);
assertThat(mediaMetadata.artworkDataType).isEqualTo(pictureType);
}
Aggregations