bool OggVorbisEncoder::open(std::function<void(UINT8*, UINT32)> writeCallback, UINT32 sampleRate, UINT32 bitDepth, UINT32 numChannels) { mNumChannels = numChannels; mBitDepth = bitDepth; mWriteCallback = writeCallback; mClosed = false; ogg_stream_init(&mOggState, std::rand()); vorbis_info_init(&mVorbisInfo); // Automatic bitrate management with quality 0.4 (~128 kbps for 44 KHz stereo sound) INT32 status = vorbis_encode_init_vbr(&mVorbisInfo, numChannels, sampleRate, 0.4f); if (status != 0) { LOGERR("Failed to write Ogg Vorbis file."); close(); return false; } vorbis_analysis_init(&mVorbisState, &mVorbisInfo); vorbis_block_init(&mVorbisState, &mVorbisBlock); // Generate header vorbis_comment comment; vorbis_comment_init(&comment); ogg_packet headerPacket, commentPacket, codePacket; status = vorbis_analysis_headerout(&mVorbisState, &comment, &headerPacket, &commentPacket, &codePacket); vorbis_comment_clear(&comment); if (status != 0) { LOGERR("Failed to write Ogg Vorbis file."); close(); return false; } // Write header ogg_stream_packetin(&mOggState, &headerPacket); ogg_stream_packetin(&mOggState, &commentPacket); ogg_stream_packetin(&mOggState, &codePacket); ogg_page page; while (ogg_stream_flush(&mOggState, &page) > 0) { WRITE_TO_BUFFER(page.header, page.header_len); WRITE_TO_BUFFER(page.body, page.body_len); } return true; }
void OggVorbisEncoder::writeBlocks() { while (vorbis_analysis_blockout(&mVorbisState, &mVorbisBlock) == 1) { // Analyze and determine optimal bitrate vorbis_analysis(&mVorbisBlock, nullptr); vorbis_bitrate_addblock(&mVorbisBlock); // Write block into ogg packets ogg_packet packet; while (vorbis_bitrate_flushpacket(&mVorbisState, &packet)) { ogg_stream_packetin(&mOggState, &packet); // If new page, write it to the internal buffer ogg_page page; while (ogg_stream_flush(&mOggState, &page) > 0) { WRITE_TO_BUFFER(page.header, page.header_len); WRITE_TO_BUFFER(page.body, page.body_len); } } } }
bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) { int writeRow = 0; int writeCol = left; int litPos = 0; int rlePos = 0; while (rlePos < rleSize) { int op = rleData[rlePos++]; if ((op & 0xc0) == 0xc0) { op &= 0x3f; if (op == 0) { // Go to next line in target buffer writeRow++; writeCol = left; } else { // Skip bytes on current line writeCol += op; } } else if (op & 0x80) { op &= 0x3f; if (op == 0) { // Copy remainder of current line int rem = width - (writeCol - left); WRITE_TO_BUFFER(rem); writeRow++; writeCol = left; litPos += rem; } else { // Copy bytes WRITE_TO_BUFFER(op); writeCol += op; litPos += op; } } else { uint16 count = ((op & 7) << 8) | rleData[rlePos++]; switch (op >> 3) { case 2: // Skip bytes writeCol += count; break; case 3: // Copy bytes WRITE_TO_BUFFER(count); writeCol += count; litPos += count; break; case 6: { // Copy rows if (count == 0) count = height - writeRow; for (int i = 0; i < count; i++) { WRITE_TO_BUFFER(width); litPos += width; writeRow++; } break; } case 7: // Skip rows if (count == 0) count = height - writeRow; writeRow += count; break; default: warning("Unsupported operation %i encountered", op >> 3); return false; } } } return true; }