Search in sources :

Example 1 with Mp4Tag

use of org.jaudiotagger.tag.mp4.Mp4Tag in project MusicDNA by harjot-oberai.

the class Mp4TagReader method createMp4Field.

/**
 * Process the field and add to the tag
 *
 * Note:In the case of coverart MP4 holds all the coverart within individual dataitems all within
 * a single covr atom, we will add separate mp4field for each image.
 *
 * @param tag
 * @param header
 * @param raw
 * @return
 * @throws UnsupportedEncodingException
 */
private void createMp4Field(Mp4Tag tag, Mp4BoxHeader header, ByteBuffer raw) throws UnsupportedEncodingException {
    // Header with no data #JAUDIOTAGGER-463
    if (header.getDataLength() == 0) {
    // Just Ignore
    } else // Reverse Dns Atom
    if (header.getId().equals(Mp4TagReverseDnsField.IDENTIFIER)) {
        // 
        try {
            TagField field = new Mp4TagReverseDnsField(header, raw);
            tag.addField(field);
        } catch (Exception e) {
            logger.warning(ErrorMessage.MP4_UNABLE_READ_REVERSE_DNS_FIELD.getMsg(e.getMessage()));
            TagField field = new Mp4TagRawBinaryField(header, raw);
            tag.addField(field);
        }
    } else // Normal Parent with Data atom
    {
        int currentPos = raw.position();
        boolean isDataIdentifier = Utils.getString(raw, Mp4BoxHeader.IDENTIFIER_POS, Mp4BoxHeader.IDENTIFIER_LENGTH, "ISO-8859-1").equals(Mp4DataBox.IDENTIFIER);
        raw.position(currentPos);
        if (isDataIdentifier) {
            // Need this to decide what type of Field to create
            int type = Utils.getIntBE(raw, Mp4DataBox.TYPE_POS_INCLUDING_HEADER, Mp4DataBox.TYPE_POS_INCLUDING_HEADER + Mp4DataBox.TYPE_LENGTH - 1);
            Mp4FieldType fieldType = Mp4FieldType.getFieldType(type);
            logger.config("Box Type id:" + header.getId() + ":type:" + fieldType);
            // Special handling for some specific identifiers otherwise just base on class id
            if (header.getId().equals(Mp4FieldKey.TRACK.getFieldName())) {
                TagField field = new Mp4TrackField(header.getId(), raw);
                tag.addField(field);
            } else if (header.getId().equals(Mp4FieldKey.DISCNUMBER.getFieldName())) {
                TagField field = new Mp4DiscNoField(header.getId(), raw);
                tag.addField(field);
            } else if (header.getId().equals(Mp4FieldKey.GENRE.getFieldName())) {
                TagField field = new Mp4GenreField(header.getId(), raw);
                tag.addField(field);
            } else if (header.getId().equals(Mp4FieldKey.ARTWORK.getFieldName()) || Mp4FieldType.isCoverArtType(fieldType)) {
                int processedDataSize = 0;
                int imageCount = 0;
                // The loop should run for each image (each data atom)
                while (processedDataSize < header.getDataLength()) {
                    // for each subimage (if there are more than one image)
                    if (imageCount > 0) {
                        type = Utils.getIntBE(raw, processedDataSize + Mp4DataBox.TYPE_POS_INCLUDING_HEADER, processedDataSize + Mp4DataBox.TYPE_POS_INCLUDING_HEADER + Mp4DataBox.TYPE_LENGTH - 1);
                        fieldType = Mp4FieldType.getFieldType(type);
                    }
                    Mp4TagCoverField field = new Mp4TagCoverField(raw, fieldType);
                    tag.addField(field);
                    processedDataSize += field.getDataAndHeaderSize();
                    imageCount++;
                }
            } else if (fieldType == Mp4FieldType.TEXT) {
                TagField field = new Mp4TagTextField(header.getId(), raw);
                tag.addField(field);
            } else if (fieldType == Mp4FieldType.IMPLICIT) {
                TagField field = new Mp4TagTextNumberField(header.getId(), raw);
                tag.addField(field);
            } else if (fieldType == Mp4FieldType.INTEGER) {
                TagField field = new Mp4TagByteField(header.getId(), raw);
                tag.addField(field);
            } else {
                boolean existingId = false;
                for (Mp4FieldKey key : Mp4FieldKey.values()) {
                    if (key.getFieldName().equals(header.getId())) {
                        // The parentHeader is a known id but its field type is not one of the expected types so
                        // this field is invalid. i.e I received a file with the TMPO set to 15 (Oxf) when it should
                        // be 21 (ox15) so looks like somebody got their decimal and hex numbering confused
                        // So in this case best to ignore this field and just write a warning
                        existingId = true;
                        logger.warning("Known Field:" + header.getId() + " with invalid field type of:" + type + " is ignored");
                        break;
                    }
                }
                // Unknown field id with unknown type so just create as binary
                if (!existingId) {
                    logger.warning("UnKnown Field:" + header.getId() + " with invalid field type of:" + type + " created as binary");
                    TagField field = new Mp4TagBinaryField(header.getId(), raw);
                    tag.addField(field);
                }
            }
        } else // Special Cases
        {
            // copy parent and child as is without modification
            if (header.getId().equals(Mp4NonStandardFieldKey.AAPR.getFieldName())) {
                TagField field = new Mp4TagRawBinaryField(header, raw);
                tag.addField(field);
            } else // Default case
            {
                TagField field = new Mp4TagRawBinaryField(header, raw);
                tag.addField(field);
            }
        }
    }
}
Also used : TagField(org.jaudiotagger.tag.TagField) CannotReadException(org.jaudiotagger.audio.exceptions.CannotReadException) IOException(java.io.IOException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) Mp4FieldKey(org.jaudiotagger.tag.mp4.Mp4FieldKey)

Example 2 with Mp4Tag

use of org.jaudiotagger.tag.mp4.Mp4Tag in project MusicDNA by harjot-oberai.

the class Mp4TagReader method read.

/*
     * The metadata is stored in the box under the hierachy moov.udta.meta.ilst
     *
     * There are gaps between these boxes

     */
public Mp4Tag read(RandomAccessFile raf) throws CannotReadException, IOException {
    Mp4Tag tag = new Mp4Tag();
    // Get to the facts everything we are interested in is within the moov box, so just load data from file
    // once so no more file I/O needed
    Mp4BoxHeader moovHeader = Mp4BoxHeader.seekWithinLevel(raf, Mp4AtomIdentifier.MOOV.getFieldName());
    if (moovHeader == null) {
        throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_CONTAINER.getMsg());
    }
    ByteBuffer moovBuffer = ByteBuffer.allocate(moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH);
    raf.getChannel().read(moovBuffer);
    moovBuffer.rewind();
    // Level 2-Searching for "udta" within "moov"
    Mp4BoxHeader boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.UDTA.getFieldName());
    if (boxHeader != null) {
        // Level 3-Searching for "meta" within udta
        boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.META.getFieldName());
        if (boxHeader == null) {
            logger.warning(ErrorMessage.MP4_FILE_HAS_NO_METADATA.getMsg());
            return tag;
        }
        Mp4MetaBox meta = new Mp4MetaBox(boxHeader, moovBuffer);
        meta.processData();
        // Level 4- Search for "ilst" within meta
        boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.ILST.getFieldName());
        // This file does not actually contain a tag
        if (boxHeader == null) {
            logger.warning(ErrorMessage.MP4_FILE_HAS_NO_METADATA.getMsg());
            return tag;
        }
    } else {
        // Level 2-Searching for "meta" not within udta
        boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.META.getFieldName());
        if (boxHeader == null) {
            logger.warning(ErrorMessage.MP4_FILE_HAS_NO_METADATA.getMsg());
            return tag;
        }
        Mp4MetaBox meta = new Mp4MetaBox(boxHeader, moovBuffer);
        meta.processData();
        // Level 3- Search for "ilst" within meta
        boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.ILST.getFieldName());
        // This file does not actually contain a tag
        if (boxHeader == null) {
            logger.warning(ErrorMessage.MP4_FILE_HAS_NO_METADATA.getMsg());
            return tag;
        }
    }
    // Size of metadata (exclude the size of the ilst parentHeader), take a slice starting at
    // metadata children to make things safer
    int length = boxHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH;
    ByteBuffer metadataBuffer = moovBuffer.slice();
    // Datalength is longer are there boxes after ilst at this level?
    logger.config("headerlengthsays:" + length + "datalength:" + metadataBuffer.limit());
    int read = 0;
    logger.config("Started to read metadata fields at position is in metadata buffer:" + metadataBuffer.position());
    while (read < length) {
        // Read the boxHeader
        boxHeader.update(metadataBuffer);
        // Create the corresponding datafield from the id, and slice the buffer so position of main buffer
        // wont get affected
        logger.config("Next position is at:" + metadataBuffer.position());
        createMp4Field(tag, boxHeader, metadataBuffer.slice());
        // Move position in buffer to the start of the next parentHeader
        metadataBuffer.position(metadataBuffer.position() + boxHeader.getDataLength());
        read += boxHeader.getLength();
    }
    return tag;
}
Also used : Mp4Tag(org.jaudiotagger.tag.mp4.Mp4Tag) Mp4BoxHeader(org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader) CannotReadException(org.jaudiotagger.audio.exceptions.CannotReadException) Mp4MetaBox(org.jaudiotagger.audio.mp4.atom.Mp4MetaBox) ByteBuffer(java.nio.ByteBuffer)

Aggregations

CannotReadException (org.jaudiotagger.audio.exceptions.CannotReadException)2 IOException (java.io.IOException)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 ByteBuffer (java.nio.ByteBuffer)1 Mp4BoxHeader (org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader)1 Mp4MetaBox (org.jaudiotagger.audio.mp4.atom.Mp4MetaBox)1 TagField (org.jaudiotagger.tag.TagField)1 Mp4FieldKey (org.jaudiotagger.tag.mp4.Mp4FieldKey)1 Mp4Tag (org.jaudiotagger.tag.mp4.Mp4Tag)1