⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 id3v24frame.java

📁 java+eclipse做的TTPlayer
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
     *
     * @return int frame size
     */
    public int getSize()
    {
        return frameBody.getSize() + ID3v24Frame.FRAME_HEADER_SIZE;
    }


    /**
     * Read the frame from the specified file.
     * Read the frame header then delegate reading of data to frame body.
     *
     * @param byteBuffer to read the frame from
     */
    public void read(ByteBuffer byteBuffer)
        throws InvalidFrameException
    {
        byte[] buffer = new byte[FRAME_ID_SIZE];

        if (byteBuffer.position() + FRAME_HEADER_SIZE >= byteBuffer.limit())
        {
            logger.warning(getLoggingFilename()+":"+"No space to find another frame:");
            throw new InvalidFrameException(getLoggingFilename()+":"+"No space to find another frame");
        }

        //Read the Frame Identifier
        byteBuffer.get(buffer, 0, FRAME_ID_SIZE);
        identifier = new String(buffer);
        logger.fine(getLoggingFilename()+":"+"Identifier is" + identifier);

        //Is this a valid identifier?
        if (isValidID3v2FrameIdentifier(identifier) == false)
        {
            //If not valid move file pointer back to one byte after
            //the original check so can try again.
            logger.info(getLoggingFilename()+":"+"Invalid identifier:" + identifier);
            byteBuffer.position(byteBuffer.position() - (FRAME_ID_SIZE - 1));
            throw new InvalidFrameIdentifierException(identifier + " is not a valid ID3v2.40 frame");
        }


        //Read frame size as syncsafe integer
        frameSize = ID3SyncSafeInteger.bufferToValue(byteBuffer);

        if (frameSize < 0)
        {
            logger.warning(getLoggingFilename()+":"+"Invalid Frame size:" + identifier);
            throw new InvalidFrameException(identifier + " is invalid frame");
        }
        else if (frameSize == 0)
        {
            logger.warning(getLoggingFilename()+":"+"Empty Frame:" + identifier);
            throw new EmptyFrameException(identifier + " is empty frame");
        }
        else if (frameSize > (byteBuffer.remaining() - FRAME_FLAGS_SIZE))
        {
            logger.warning(getLoggingFilename()+":"+"Invalid Frame size larger than size before mp3 audio:" + identifier);
            throw new InvalidFrameException(identifier + " is invalid frame");
        }

        if(frameSize>ID3SyncSafeInteger.MAX_SAFE_SIZE)
        {
            //Set Just after size field this is where we want to be when we leave this if statement
            int currentPosition     = byteBuffer.position();

            //Read as nonsync safe integer
            byteBuffer.position(currentPosition  - FRAME_ID_SIZE);
            int nonSyncSafeFrameSize = byteBuffer.getInt();

            //Is the frame size syncsafe, should always be BUT some encoders such as Itunes do not do it properly
            //so do an easy check now.
            byteBuffer.position(currentPosition  - FRAME_ID_SIZE);
            boolean isNotSyncSafe = ID3SyncSafeInteger.isBufferNotSyncSafe(byteBuffer);
                        
            //not relative so need to move position
            byteBuffer.position(currentPosition);

            if(isNotSyncSafe)
            {
                logger.warning(getLoggingFilename()+":"+"Frame size is NOT stored as a sync safe integer:" + identifier);

                //This will return a larger frame size so need to check against buffer size if too large then we are
                //buggered , give up
                if (nonSyncSafeFrameSize > (byteBuffer.remaining() - - FRAME_FLAGS_SIZE))
                {
                    logger.warning(getLoggingFilename()+":"+"Invalid Frame size larger than size before mp3 audio:" + identifier);
                    throw new InvalidFrameException(identifier + " is invalid frame");
                }
                else
                {
                    frameSize =  nonSyncSafeFrameSize;
                }
            }
            else
            {
                //appears to be sync safe but lets look at the bytes just after the reported end of this
                //frame to see if find a valid frame header

                //Read the Frame Identifier
                byte[] readAheadbuffer  = new byte[FRAME_ID_SIZE];
                byteBuffer.position(currentPosition + frameSize + FRAME_FLAGS_SIZE);

                if(byteBuffer.remaining()<FRAME_ID_SIZE)
                {
                    //There is no padding or framedata we are at end so assume syncsafe
                    //reset position to just after framesize
                    byteBuffer.position(currentPosition);
                }
                else
                {
                    byteBuffer.get(readAheadbuffer, 0, FRAME_ID_SIZE);

                    //reset position to just after framesize
                    byteBuffer.position(currentPosition);

                    String readAheadIdentifier = new String(readAheadbuffer);
                    if(isValidID3v2FrameIdentifier(readAheadIdentifier))
                    {
                        //Everything ok, so continue
                    }
                    else if(ID3SyncSafeInteger.isBufferEmpty(readAheadbuffer))
                    {
                        //no data found so assume entered padding in which case assume it is last
                        //frame and we are ok
                    }
                    //havent found identifier so maybe not syncsafe or maybe there are no more frames, just padding
                    else
                    {
                        //Ok lets try using a non-syncsafe integer

                        //size returned will be larger so is it valid
                        if (nonSyncSafeFrameSize > byteBuffer.remaining() - FRAME_FLAGS_SIZE)
                        {
                            //invalid so assume syncsafe
                            byteBuffer.position(currentPosition);
                        }
                        else
                        {
                            readAheadbuffer  = new byte[FRAME_ID_SIZE];
                            byteBuffer.position(currentPosition + nonSyncSafeFrameSize + FRAME_FLAGS_SIZE);

                            if(byteBuffer.remaining() >= FRAME_ID_SIZE)
                            {
                                byteBuffer.get(readAheadbuffer, 0, FRAME_ID_SIZE);
                                readAheadIdentifier = new String(readAheadbuffer);                                                                  

                                //reset position to just after framesize
                                byteBuffer.position(currentPosition);

                                //ok found a valid identifier using non-syncsafe so assume non-syncsafe size
                                //and continue
                                if(isValidID3v2FrameIdentifier(readAheadIdentifier))
                                {
                                    frameSize =  nonSyncSafeFrameSize;
                                    logger.warning(getLoggingFilename()+":"+"Assuming frame size is NOT stored as a sync safe integer:" + identifier);
                                }
                                //no data found so assume entered padding in which case assume it is last
                                //frame and we are ok whereas we didnt hit padding when using syncsafe integer
                                //or we wouldnt have got to this point. So assume syncsafe ineteger ended within
                                //the frame data whereas this has reached end of frames.
                                else if(ID3SyncSafeInteger.isBufferEmpty(readAheadbuffer))
                                {
                                    frameSize =  nonSyncSafeFrameSize;
                                    logger.warning(getLoggingFilename()+":"+"Assuming frame size is NOT stored as a sync safe integer:" + identifier);
                                }
                                //invalid so assume syncsafe as that is is the standard
                                else
                                {
                                    ;
                                }
                            }
                            else
                            {
                                //reset position to just after framesize
                                byteBuffer.position(currentPosition);

                                //If the unsync framesize matches exactly the remaining bytes then assume it has the
                                //correct size for the last frame
                                if(byteBuffer.remaining() == 0)
                                {
                                    frameSize =  nonSyncSafeFrameSize;
                                }
                                //Inconclusive stick with syncsafe
                                else
                                {
                                    ;
                                }

                            }
                        }
                    }
                }
            }
        }

        //Read the flag bytes
        statusFlags = new StatusFlags(byteBuffer.get());
        encodingFlags = new EncodingFlags(byteBuffer.get());

        //Read extra bits appended to frame header for various encodings
        //These are not included in header size but are included in frame size but wont be read when we actually
        //try to read the frame body data
        int extraHeaderBytesCount = 0;
        boolean isDataLengthindicatorRead = false;
        if(((EncodingFlags)encodingFlags).isGrouping())
        {
            extraHeaderBytesCount = ID3v24Frame.FRAME_GROUPING_INDICATOR_SIZE;
            byteBuffer.get();
        }

        if(((EncodingFlags)encodingFlags).isCompression())
        {
            //Read the sync safe size field
            int datalengthSize = ID3SyncSafeInteger.bufferToValue(byteBuffer);
            logger.info(getLoggingFilename()+":"+"Frame Size Is:"+ frameSize + "Data Length Size:"+datalengthSize);
            extraHeaderBytesCount += ID3v24Frame.FRAME_DATA_LENGTH_SIZE;
            isDataLengthindicatorRead=true;
        }

        if(((EncodingFlags)encodingFlags).isEncryption())
        {
            //Read the Encryption byte, but do nothing with it
            extraHeaderBytesCount += ID3v24Frame.FRAME_ENCRYPTION_INDICATOR_SIZE;
            byteBuffer.get();
        }

        if(((EncodingFlags)encodingFlags).isDataLengthIndicator())
        {
            //There is only data length indicator it may have already been read depending on what flags
            //are set
            if(!isDataLengthindicatorRead)
            {
                //Read the sync safe size field
                int datalengthSize = ID3SyncSafeInteger.bufferToValue(byteBuffer);
                //Read the Grouping byte, but do nothing with it
                extraHeaderBytesCount += FRAME_DATA_LENGTH_SIZE;
                logger.info(getLoggingFilename()+":"+"Frame Size Is:"+ frameSize + "Data Length Size:"+datalengthSize);
            }
        }

        //Work out the real size of the framebody data
        int realFrameSize = frameSize - extraHeaderBytesCount;

        //Create Buffer that only contains the body of this frame rather than the remainder of tag
        ByteBuffer frameBodyBuffer = byteBuffer.slice();
        frameBodyBuffer.limit(realFrameSize);

        //Do we need to synchronize the frame body
        int syncSize=realFrameSize;
        if(((EncodingFlags)encodingFlags).isUnsynchronised())
        {
            //We only want to synchronize the buffer upto the end of this frame (remember this
            //buffer contains the remainder of this tag not just this frame), and we cant just
            //create a new buffer because when this method returns the position of the buffer is used
            //to look for the next frame, so we need to modify the buffer. The action of synchronizing causes
            //bytes to be dropped so the existing buffer is large enough to hold the modifications
            frameBodyBuffer=ID3Unsynchronization.synchronize(frameBodyBuffer);
            syncSize = frameBodyBuffer.limit();
            logger.info(getLoggingFilename()+":"+"Frame Size After Syncing is:"+ syncSize);
        }

        //Read the body data
        try
        {
            frameBody = readBody(identifier,  frameBodyBuffer, syncSize);
            if (!(frameBody instanceof ID3v24FrameBody))
            {
                logger.info(getLoggingFilename()+":"+"Converted frame body with:" + identifier + " to deprecated framebody");
                frameBody = new FrameBodyDeprecated((AbstractID3v2FrameBody) frameBody);
            }
        }
        finally
        {
            //Update position of main buffer, so no attempt is made to reread  these bytes
            byteBuffer.position(byteBuffer.position()+realFrameSize);
        }
    }

    /**
     * Write the frame. Writes the frame header but writing the data is delegated to the
     * frame body.
     *
     * @throws IOException
     */
    public void write(ByteArrayOutputStream tagBuffer)
    {
        boolean unsynchronization;

        logger.info("Writing frame to file:" + getIdentifier());

        //This is where we will write header, move position to where we can
        //write bodybuffer
        ByteBuffer headerBuffer = ByteBuffer.allocate(FRAME_HEADER_SIZE);

        //Write Frame Body Data to a new stream
        ByteArrayOutputStream bodyOutputStream = new ByteArrayOutputStream();
        ((AbstractID3v2FrameBody) frameBody).write(bodyOutputStream);

        //Does it need unsynchronizing, and are we allowing unsychronizing
        byte[] bodyBuffer = bodyOutputStream.toByteArray();
        if(TagOptionSingleton.getInstance().isUnsyncTags())
        {
            unsynchronization = ID3Unsynchronization.requiresUnsynchronization(bodyBuffer);
        }
        else
        {
            unsynchronization=false;
        }
        if(unsynchronization)
        {
            bodyBuffer=ID3Unsynchronization.unsynchronize(bodyBuffer);
            logger.info("bodybytebuffer:sizeafterunsynchronisation:"+bodyBuffer.length);
        }

        //Write Frame Header
        //Write Frame ID, the identifier must be 4 bytes bytes long it may not be
        //because converted an unknown v2.2 id (only 3 bytes long)
        if (getIdentifier().length() == 3)
        {
            identifier = identifier + ' ';
        }
        headerBuffer.put(Utils.getDefaultBytes(getIdentifier(),"ISO-8859-1"), 0, FRAME_ID_SIZE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -