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

📄 oggvorbistagwriter.java

📁 YOYOPlayer MP3播放器 java+JMF实现
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
                                                      OggPageHeader secondPageHeader,
                                                      ByteBuffer newComment,
                                                      RandomAccessFile raf,
                                                      RandomAccessFile rafTemp) throws IOException,CannotReadException,CannotWriteException
    {
        byte[] segmentTable = createSegmentTable(newCommentLength, originalHeaderSizes.getSetupHeaderSize());
        int newSecondPageHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length;

        ByteBuffer secondPageBuffer = ByteBuffer.allocate(newSecondPageLength + newSecondPageHeaderLength);

        //Build the new 2nd page header, can mostly be taken from the original upto the segment length
        //OggS capture
        secondPageBuffer.put(secondPageHeader.getRawHeaderData(), 0, OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH - 1);
        secondPageBuffer.order(ByteOrder.LITTLE_ENDIAN);

        //Number of page Segments
        secondPageBuffer.put((byte) segmentTable.length);
        //Page segment table
        for (int i = 0; i < segmentTable.length; i++)
        {
            secondPageBuffer.put(segmentTable[i]);
        }
        //Add New VorbisComment
        secondPageBuffer.put(newComment);



        int pageSequence = secondPageHeader.getPageSequence();

        //Now find the setupheader which is on a different page (or extends over pages) and get it with
        //page header stripped out (it has already been worked it will all fir in so should be no buffer overflow)
        byte[] setupHeaderData = reader.convertToVorbisSetupHeaderPacket(originalHeaderSizes.getSetupHeaderStartPosition(),raf);
        logger.finest(setupHeaderData.length + ":"+ secondPageBuffer.position() + ":"+ secondPageBuffer.capacity() );
        secondPageBuffer.put(setupHeaderData);

        //CRC should be zero before calculating it
        secondPageBuffer.putInt(OggPageHeader.FIELD_PAGE_CHECKSUM_POS, 0);

        //Compute CRC over the new second page
        byte[] crc = OggCRCFactory.computeCRC(secondPageBuffer.array());
        for (int i = 0; i < crc.length; i++)
        {
            secondPageBuffer.put(OggPageHeader.FIELD_PAGE_CHECKSUM_POS + i, crc[i]);
        }

        //Transfer the second page bytebuffer content and write to temp file
        secondPageBuffer.rewind();
        rafTemp.getChannel().write(secondPageBuffer);

        //Write the rest of the original file

        //Now the Page Sequence Number for all the subsequent pages (containing audio frames) are out because there are
        //less pages before then there used to be, so need to adjust

        long startAudio = raf.getFilePointer();
        logger.finest("About to read Audio starting from:"+startAudio);
        long startAudioWritten = rafTemp.getFilePointer();
        while(raf.getFilePointer()<raf.length())
        {
            OggPageHeader nextPage = OggPageHeader.read (raf);

            //Create buffer large enough foor next page (header and data) and set byte order to LE so we can use
            //putInt method
            ByteBuffer nextPageHeaderBuffer = ByteBuffer.allocate(
                nextPage.getRawHeaderData().length + nextPage.getPageLength());
            nextPageHeaderBuffer.order(ByteOrder.LITTLE_ENDIAN);

            nextPageHeaderBuffer.put(nextPage.getRawHeaderData());
            raf.getChannel().read(nextPageHeaderBuffer);

            //Recalculate Page Sequence Number
            nextPageHeaderBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS,++pageSequence);

            //CRC should be zero before calculating it
            nextPageHeaderBuffer.putInt(OggPageHeader.FIELD_PAGE_CHECKSUM_POS, 0);

            //Compute CRC over the modified page
            crc = OggCRCFactory.computeCRC(nextPageHeaderBuffer.array());
            for (int i = 0; i < crc.length; i++)
            {
                nextPageHeaderBuffer.put(OggPageHeader.FIELD_PAGE_CHECKSUM_POS + i, crc[i]);
            }

            nextPageHeaderBuffer.rewind();
            rafTemp.getChannel().write(nextPageHeaderBuffer);
        }
        if((raf.length() - startAudio)!=(rafTemp.length() - startAudioWritten))
        {
            throw new CannotWriteException("File written counts dont match, file not written");
        }
    }

    /**
     * CommentHeader extends over multiple pages
     *
     * @param originalHeaderSizes
     * @param newCommentLength
     * @param secondPageHeader
     * @param newComment
     * @param raf
     * @param rafTemp
     *
     * @throws IOException
     * @throws CannotReadException
     * @throws CannotWriteException
     */
    private void replacePagesAndRenumberPageSeqs(OggVorbisTagReader.OggVorbisHeaderSizes originalHeaderSizes,
                                                 int newCommentLength,
                                                 OggPageHeader secondPageHeader,
                                                 ByteBuffer newComment,
                                                 RandomAccessFile raf,
                                                 RandomAccessFile rafTemp) throws IOException,CannotReadException,CannotWriteException
    {
        int pageSequence = secondPageHeader.getPageSequence();

        //We need to work out how to split the newcommentlength over the pages
        int noOfPagesNeededForComment = newCommentLength / OggPageHeader.MAXIMUM_PAGE_DATA_SIZE;
        logger.info("Comment requires:"+noOfPagesNeededForComment+" complete pages");
        //Create the Pages
        int newCommentOffset=0;
        for(int i=0;i< noOfPagesNeededForComment;i++)
        {
            //Create ByteBuffer for the New page
            byte[] segmentTable   = this.createSegments(OggPageHeader.MAXIMUM_PAGE_DATA_SIZE,false);
            int pageHeaderLength  = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length;
            ByteBuffer pageBuffer = ByteBuffer.allocate(pageHeaderLength + OggPageHeader.MAXIMUM_PAGE_DATA_SIZE);
            pageBuffer.order(ByteOrder.LITTLE_ENDIAN);

            //Now create the page basing it on the existing 2ndpageheader
            pageBuffer.put(secondPageHeader.getRawHeaderData(), 0, OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH - 1);
            //Number of page Segments
            pageBuffer.put((byte) segmentTable.length);
            //Page segment table
            for (int j = 0; j < segmentTable.length; j++)
            {
               pageBuffer.put(segmentTable[j]);
            }
            //Put in first bit of Comment
            pageBuffer.put(newComment.array(),newCommentOffset,OggPageHeader.MAXIMUM_PAGE_DATA_SIZE);
            //Recalculate Page Sequence Number
            pageBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS,pageSequence);
            pageSequence++;


            //Set Header Flag to indicate continous (except for first flag)
            if(i!=0)
            {
                pageBuffer.put(OggPageHeader.FIELD_HEADER_TYPE_FLAG_POS,OggPageHeader.HeaderTypeFlag.CONTINUED_PACKET.getFileValue());
            }

            //CRC should be zero before calculating it
            pageBuffer.putInt(OggPageHeader.FIELD_PAGE_CHECKSUM_POS, 0);

            //Compute CRC over the page
            byte[] crc = OggCRCFactory.computeCRC(pageBuffer.array());
            for (int j = 0; j < crc.length; j++)
            {
                pageBuffer.put(OggPageHeader.FIELD_PAGE_CHECKSUM_POS + j, crc[j]);
            }

            pageBuffer.rewind();
            rafTemp.getChannel().write(pageBuffer);
            newCommentOffset+=OggPageHeader.MAXIMUM_PAGE_DATA_SIZE;
        }


        int lastPageCommentPacketSize = newCommentLength % OggPageHeader.MAXIMUM_PAGE_DATA_SIZE;
        logger.fine("Last comment packet size:"+lastPageCommentPacketSize );
        if(!isCommentAndSetupHeaderFitsOnASinglePage(lastPageCommentPacketSize,originalHeaderSizes.getSetupHeaderSize()))
        {
            logger.fine("Spread over two pages");
            //We need to spread over two pages

            //This page contains last bit of comment header and part of setup header
            byte[] commentSegmentTable = createSegments(lastPageCommentPacketSize, true);

            //Cant just add minus the packet data from the max packet size because space available to header affected
            //by size of last comment segment. i.e if it is 1 then 254 is not avilable from the max size
            int remainingSegmentSlots = OggPageHeader.MAXIMUM_NO_OF_SEGMENT_SIZE  - commentSegmentTable.length;
            int firstHalfOfHeaderSize = remainingSegmentSlots * OggPageHeader.MAXIMUM_SEGMENT_SIZE;
            byte[] firstHalfofSegmentHeaderTable = createSegments(firstHalfOfHeaderSize,false);

            byte[] segmentTable = createSegmentTable(lastPageCommentPacketSize,firstHalfOfHeaderSize);
            int lastCommentHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH
                + commentSegmentTable.length
                + firstHalfofSegmentHeaderTable.length;

            ByteBuffer lastCommentHeaderBuffer = ByteBuffer.allocate(lastCommentHeaderLength
                + lastPageCommentPacketSize
                + firstHalfOfHeaderSize);

            //Build the last comment page header
            lastCommentHeaderBuffer.put(secondPageHeader.getRawHeaderData(), 0, OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH - 1);
            lastCommentHeaderBuffer.order(ByteOrder.LITTLE_ENDIAN);

            //Number of page Segments
            lastCommentHeaderBuffer.put((byte) segmentTable.length);
            //Page segment table
            for (int i = 0; i < segmentTable.length; i++)
            {
                lastCommentHeaderBuffer.put(segmentTable[i]);
            }
            //Add last bit of Comment
            lastCommentHeaderBuffer.put(newComment.array(),newCommentOffset,lastPageCommentPacketSize);

            //Now find the setupheader which is on a different page (or extends over pages) and get it with
            //page header stripped out
            byte[] setupHeaderData = reader.convertToVorbisSetupHeaderPacket(originalHeaderSizes.getSetupHeaderStartPosition(),raf);
            logger.finest(setupHeaderData.length + ":"+ lastCommentHeaderBuffer.position() + ":"+ lastCommentHeaderBuffer.capacity() );
            int copyAmount = setupHeaderData.length;
            if( setupHeaderData.length>lastCommentHeaderBuffer.remaining())
            {
                copyAmount = lastCommentHeaderBuffer.remaining();
                logger.finest("Copying :"+ copyAmount);
            }
            lastCommentHeaderBuffer.put(setupHeaderData,0,copyAmount);

            //Page Sequence No
            lastCommentHeaderBuffer.putInt(OggPageHeader.FIELD_PAGE_SEQUENCE_NO_POS,pageSequence);

            //Continuous
            lastCommentHeaderBuffer.put(OggPageHeader.FIELD_HEADER_TYPE_FLAG_POS,OggPageHeader.HeaderTypeFlag.CONTINUED_PACKET.getFileValue());

            pageSequence++;

            //CRC should be zero before calculating it
            lastCommentHeaderBuffer.putInt(OggPageHeader.FIELD_PAGE_CHECKSUM_POS, 0);

            //Compute CRC over the new second page
            byte[] crc = OggCRCFactory.computeCRC(lastCommentHeaderBuffer.array());
            for (int i = 0; i < crc.length; i++)
            {
                lastCommentHeaderBuffer.put(OggPageHeader.FIELD_PAGE_CHECKSUM_POS + i, crc[i]);
            }

            //Transfer the second page bytebuffer content and write to temp file
            lastCommentHeaderBuffer.rewind();
            rafTemp.getChannel().write(lastCommentHeaderBuffer);

            //This page contains the remainder of the setup header -----------------------------------------------
            int secondHalfOfHeaderSize =
                originalHeaderSizes.getSetupHeaderSize() - firstHalfOfHeaderSize;
            segmentTable = createSegmentTable(secondHalfOfHeaderSize,0);
            int lastSetupHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length;
            ByteBuffer lastSetupHeaderBuffer = ByteBuffer.allocate(lastSetupHeaderLength
                + secondHalfOfHeaderSize);

⌨️ 快捷键说明

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