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

📄 oggvorbistagreader.java

📁 YOYOPlayer MP3播放器 java+JMF实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Entagged Audio Tag library
 * Copyright (c) 2003-2005 Rapha�l Slinckx <raphael@slinckx.net>
 * Copyright (c) 2004-2005 Christian Laireiter <liree@web.de>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package com.hadeslee.audiotag.audio.ogg;

import com.hadeslee.audiotag.audio.exceptions.CannotReadException;
import com.hadeslee.audiotag.tag.vorbiscomment.VorbisCommentReader;
import com.hadeslee.audiotag.tag.vorbiscomment.VorbisCommentTag;
import com.hadeslee.audiotag.audio.ogg.util.OggPageHeader;
import com.hadeslee.audiotag.audio.ogg.util.VorbisHeader;
import com.hadeslee.audiotag.audio.ogg.util.VorbisPacketType;
import com.hadeslee.audiotag.audio.generic.Utils;
import com.hadeslee.audiotag.tag.Tag;

import java.io.*;
import java.util.List;
import java.util.logging.Logger;

/**
 * Read Vorbis Comment Tag within ogg
 *
 * Vorbis is the audiostream within an ogg file, Vorbis uses VorbisComments as its tag
 */
public class OggVorbisTagReader
{
    // Logger Object
    public static Logger logger = Logger.getLogger("com.hadeslee.jaudiotagger.audio.ogg");

    private VorbisCommentReader vorbisCommentReader = new VorbisCommentReader();

    /**
     * Read the Logical VorbisComment Tag from the file
     *
     * <p>Read the CommenyTag, within an OggVorbis file the VorbisCommentTag is mandatory 
     * @param raf
     * @return
     * @throws CannotReadException
     * @throws IOException
     */
    public Tag read(RandomAccessFile raf) throws CannotReadException, IOException
    {
        logger.info("Starting to read ogg vorbis tag from file:");
        byte[] rawVorbisCommentData = readRawPacketData(raf);

        //Begin tag reading
        VorbisCommentTag tag = vorbisCommentReader.read(rawVorbisCommentData,true);
        logger.fine("CompletedReadCommentTag");
        return tag;
    }

    /**
     * Retrieve the Size of the VorbisComment packet including the oggvorbis header
     *
     * @param raf
     * @return
     * @throws CannotReadException
     * @throws IOException
     */
    public int readOggVorbisRawSize(RandomAccessFile raf) throws CannotReadException, IOException
    {
         byte[] rawVorbisCommentData = readRawPacketData(raf);
         return rawVorbisCommentData.length
             + VorbisHeader.FIELD_PACKET_TYPE_LENGTH
             + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH;
    }

    /**
     * Retrieve the raw VorbisComment packet data, does not include the OggVorbis header
     *
     * @param raf
     * @return
     * @throws CannotReadException if unable to find vorbiscomment header
     * @throws IOException
     */
    public byte[] readRawPacketData(RandomAccessFile raf) throws CannotReadException, IOException
    {
        logger.fine("Read 1st page");
        //1st page = codec infos
        OggPageHeader pageHeader = OggPageHeader.read (raf);
        //Skip over data to end of page header 1
        raf.seek(raf.getFilePointer() + pageHeader.getPageLength());

        logger.fine("Read 2nd page");
        //2nd page = comment, may extend to additional pages or not , may also have setup header
        pageHeader = OggPageHeader.read (raf);

        //Now at start of packets on page 2 , check this is the vorbis comment header 
        byte [] b = new byte[VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH];
        raf.read(b);
        if(!isVorbisCommentHeader (b))
        {
            throw new CannotReadException("Cannot find comment block (no vorbiscomment header)");
        }


        //Convert the comment raw data which maybe over many pages back into raw packet
        byte[] rawVorbisCommentData = convertToVorbisCommentPacket(pageHeader,raf);
        return rawVorbisCommentData;
    }



    /**
     * Is this a Vorbis Comment header, check
     *
     * Note this check only applies to Vorbis Comments embedded within an OggVorbis File which is why within here
     *
     * @param headerData
     *
     * @return true if the headerData matches a VorbisComment header i.e is a Vorbis header of type COMMENT_HEADER
     */
    public boolean isVorbisCommentHeader (byte[] headerData)
    {
        String vorbis = Utils.getString(headerData, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH,"ISO-8859-1");
        if (headerData[VorbisHeader.FIELD_PACKET_TYPE_POS] != VorbisPacketType.COMMENT_HEADER.getType()
            || !vorbis.equals(VorbisHeader.CAPTURE_PATTERN))
        {
            return false;
        }
        return true;
    }

    /**
     * Is this a Vorbis SetupHeader check
     *
     * @param headerData
     * @return true if matches vorbis setupheader
     */
    public boolean isVorbisSetupHeader (byte[] headerData)
    {
        String vorbis = Utils.getString(headerData, VorbisHeader.FIELD_CAPTURE_PATTERN_POS, VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH,"ISO-8859-1");
        if (headerData[VorbisHeader.FIELD_PACKET_TYPE_POS] != VorbisPacketType.SETUP_HEADER.getType()
            || !vorbis.equals(VorbisHeader.CAPTURE_PATTERN))
        {
            return false;
        }
        return true;
    }

    /**
     * The Vorbis Comment may span multiple pages so we we need to identify the pages they contain and then
     * extract the packet data from the pages
     */
    private byte[] convertToVorbisCommentPacket(OggPageHeader startVorbisCommentPage,RandomAccessFile raf)
        throws IOException,CannotReadException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte [] b = new byte[startVorbisCommentPage.getPacketList().get(0).getLength()
            - (VorbisHeader.FIELD_PACKET_TYPE_LENGTH + VorbisHeader.FIELD_CAPTURE_PATTERN_LENGTH) ];
        raf.read(b);
        baos.write(b);

        //Because there is at least one other packet (SetupHeaderPacket) this means the Comment Packet has finished
        //on this page so thats all we need and we can return
        if(startVorbisCommentPage.getPacketList().size()>1)
        {
            logger.info("Comments finish on 2nd Page because there is another packet on this page");
            return baos.toByteArray();
        }

        //There is only the VorbisComment packet on page if it has completed on this page we can return
        if(!startVorbisCommentPage.isLastPacketIncomplete())
        {
            logger.info("Comments finish on 2nd Page because this packet is complete");
            return baos.toByteArray();
        }

        //The VorbisComment extends to the next page, so should be at end of page already
        //so carry on reading pages until we get to the end of comment
        while(true)
        {
            logger.info("Reading next page");
            OggPageHeader nextPageHeader = OggPageHeader.read (raf);
            b = new byte[ nextPageHeader.getPacketList().get(0).getLength()];
            raf.read(b);
            baos.write(b);

            //Because there is at least one other packet (SetupHeaderPacket) this means the Comment Packet has finished
            //on this page so thats all we need and we can return
            if(nextPageHeader.getPacketList().size()>1)
            {
                logger.info("Comments finish on Page because there is another packet on this page");
                return baos.toByteArray();
            }

            //There is only the VorbisComment packet on page if it has completed on this page we can return
            if(!nextPageHeader.isLastPacketIncomplete())
            {
                logger.info("Comments finish on Page because this packet is complete");
                return baos.toByteArray();
            }
        }
    }

       /**
         * The Vorbis Seup Header may span multiple(2) pages, athough it doesnt normally. We pass the start of the
         * file offset of the OggPage it belongs on, it probably wont be first packet.
         */
        public byte[] convertToVorbisSetupHeaderPacket(long fileOffsetOfStartingOggPage,RandomAccessFile raf)
            throws IOException,CannotReadException
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            //Seek to specified offset
            raf.seek(fileOffsetOfStartingOggPage);

            //Read Page
            OggPageHeader setupPageHeader = OggPageHeader.read (raf);

            //Assume that if multiple packets first packet is VorbisComment and second packet
            //is setupheader
            if(setupPageHeader.getPacketList().size()>1)
            {
                raf.skipBytes(setupPageHeader.getPacketList().get(0).getLength());

⌨️ 快捷键说明

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