📄 oggvorbistagwriter.java
字号:
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 + -