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

📄 oggvorbistagwriter.java

📁 YOYOPlayer MP3播放器 java+JMF实现
💻 JAVA
📖 第 1 页 / 共 3 页
字号:


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

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

            //Add last bit of Setup header should match remaining buffer size
            logger.finest(setupHeaderData.length - copyAmount + ":"+ lastSetupHeaderBuffer.position() + ":"+ lastSetupHeaderBuffer.capacity() );

            //Copy remainder of setupheader
            lastSetupHeaderBuffer.put(setupHeaderData,copyAmount,setupHeaderData.length - copyAmount);

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

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


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

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

            //Transfer the second page bytebuffer content and write to temp file
            lastSetupHeaderBuffer.rewind();
            rafTemp.getChannel().write(lastSetupHeaderBuffer);
        }
        //End of Comment and SetupHeader can fit on one page
        else
        {
            logger.fine("Setupheader fits on comment page");
            byte[] segmentTable = createSegmentTable(lastPageCommentPacketSize, originalHeaderSizes.getSetupHeaderSize());
            int lastHeaderLength = OggPageHeader.OGG_PAGE_HEADER_FIXED_LENGTH + segmentTable.length;
            ByteBuffer lastCommentHeaderBuffer = ByteBuffer.allocate(lastHeaderLength
                + lastPageCommentPacketSize
                + originalHeaderSizes.getSetupHeaderSize());

            //Build the last comment page header base on original secondpageheader
            //OggS capture
            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
            raf.seek(originalHeaderSizes.getSetupHeaderStartPosition());
            OggPageHeader setupPageHeader;




            //Add setup Header (although it will fit in this page, it may be over multiple pages in its original form
            //so need to use this function to convert to raw data 
            byte[] setupHeaderData = reader.convertToVorbisSetupHeaderPacket(originalHeaderSizes.getSetupHeaderStartPosition(),raf);
            lastCommentHeaderBuffer.put(setupHeaderData);

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

            //Set Header Flag to indicate continuous (except for first flag)
            lastCommentHeaderBuffer.put(OggPageHeader.FIELD_HEADER_TYPE_FLAG_POS,OggPageHeader.HeaderTypeFlag.CONTINUED_PACKET.getFileValue());

            //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);
        }

        //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();
        long startAudioWritten = rafTemp.getFilePointer();
        logger.fine("Writing audio, audio starts in original file at :"+startAudio+":Written to:"+startAudioWritten);
        while(raf.getFilePointer()<raf.length())
        {
            logger.fine("Reading Ogg Page");
            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
            byte[] 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 macth, file not written");
        }
    }

    /**
     * This method creates a new segment table for the second page (header).
     *
     * @param newCommentLength Of this value the start of the segment table
     *                         will be created.
     * @param setupHeaderLength The length of setup table, zero if comment String extends
     * over multiple pages and this is not the last page.
     * @return new segment table.
     */
    private byte[] createSegmentTable(int newCommentLength, int setupHeaderLength)
    {

        byte[] newStart;

        if( setupHeaderLength==0)
        {
            //Comment Stream continues onto next page so last lacing value can be 255
            newStart=createSegments(newCommentLength, false);
            return newStart;
        }
        else
        {
             //Comment Stream finishes on this page so if is a multiple of 255
             //have to add an extra entry.
             newStart=createSegments(newCommentLength, true);
        }

        //TODO Why false, what about is header length fixed, cvant seto to true because may go onto
        //next page.
        byte[] restShouldBe = createSegments(setupHeaderLength, false);
        byte[] result = new byte[newStart.length + restShouldBe.length];

        System.arraycopy(newStart, 0, result, 0, newStart.length);
        System.arraycopy(restShouldBe, 0, result, newStart.length, restShouldBe.length);
        return result;

    }

    /**
     * This method creates a byte array of values whose sum should
     * be the value of <code>length</code>.<br>
     *
     * @param length     Size of the page which should be
     *                   represented as 255 byte packets.
     * @param quitStream If true and a length is a multiple of 255 we need another
     *                   segment table entry with the value of 0. Else it's the last stream of the
     *                   table which is already ended.
     * @return Array of packet sizes. However only the last packet will
     *         differ from 255.
     *
     * TODO if pass is data of max length (65025 bytes) and have quitStream==true
     * this will return 256 segments which is illegal, should be checked somewhere
     */
    private byte[] createSegments(int length, boolean quitStream)
    {
        byte[] result = new byte[length / OggPageHeader.MAXIMUM_SEGMENT_SIZE
            + ((length %  OggPageHeader.MAXIMUM_SEGMENT_SIZE == 0 && !quitStream) ? 0 : 1)];
        int i = 0;
        for (; i < result.length - 1; i++)
        {
            result[i] = (byte) 0xFF;
        }
        result[result.length - 1] = (byte) (length - (i *  OggPageHeader.MAXIMUM_SEGMENT_SIZE));
        return result;
    }

    /**
     *
     * @param commentLength
     * @param setupHeaderLength
     * @return true if there is enough room to fit the comment and the setup headers on one page taking into
     * account the maximum no of segment s allowed per page and zero lacing values.
     */
    private boolean isCommentAndSetupHeaderFitsOnASinglePage(int commentLength,int setupHeaderLength)
    {
        int additionalZeroLacingRequiredForComment=0;
        int additionalZeroLacingRequiredForHeader=0;

        if((commentLength % OggPageHeader.MAXIMUM_SEGMENT_SIZE == 0))
        {
            additionalZeroLacingRequiredForComment=1;
        }
        if(setupHeaderLength % OggPageHeader.MAXIMUM_SEGMENT_SIZE == 0)
        {
            additionalZeroLacingRequiredForHeader=1;
        }

        if( ((commentLength / OggPageHeader.MAXIMUM_SEGMENT_SIZE)
            +
            (setupHeaderLength / OggPageHeader.MAXIMUM_SEGMENT_SIZE)
            + additionalZeroLacingRequiredForComment
            + additionalZeroLacingRequiredForHeader
        )
            <=OggPageHeader.MAXIMUM_NO_OF_SEGMENT_SIZE
        )
        {
            return true;
        }
        return false;
    }

}

⌨️ 快捷键说明

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