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