Example1Tx::Example1Tx(int samplesPerBlock, int nbOriginalBlocks, int nbFecBlocks) { m_params.BlockBytes = samplesPerBlock * sizeof(Sample); m_params.OriginalCount = nbOriginalBlocks; m_params.RecoveryCount = nbFecBlocks; if (cm256_init()) { m_cm256_OK = false; std::cerr << "Example1Tx::Example1Tx: cannot initialize CM256 library" << std::endl; } else { m_cm256_OK = true; } }
SDRdaemonFECBuffer::SDRdaemonFECBuffer() { m_currentMeta.init(); m_outputMeta.init(); m_paramsCM256.BlockBytes = sizeof(ProtectedBlock); m_paramsCM256.OriginalCount = nbOriginalBlocks; m_paramsCM256.RecoveryCount = -1; m_decoderIndexHead = nbDecoderSlots / 2; m_frameHead = -1; m_curNbBlocks = 0; m_curNbRecovery = 0; if (cm256_init()) { m_cm256_OK = false; std::cerr << "SDRdaemonFECBuffer::SDRdaemonFECBuffer: cannot initialize CM256 library" << std::endl; } else { m_cm256_OK = true; } }
Example1Rx::Example1Rx(int samplesPerBlock, int nbOriginalBlocks, int nbFecBlocks) : m_frameCount(0), m_blockCount(0), m_frameHead(0), m_metaReceived(false), m_dataCount(0), m_recoveryCount(0) { m_params.BlockBytes = samplesPerBlock * sizeof(Sample); m_params.OriginalCount = nbOriginalBlocks; m_params.RecoveryCount = nbFecBlocks; m_currentMeta.init(); if (cm256_init()) { m_cm256_OK = false; std::cerr << "Example1Rx::Example1Rx: cannot initialize CM256 library" << std::endl; } else { m_cm256_OK = true; } }
bool ExampleFileUsage() { if (cm256_init()) { return false; } cm256_encoder_params params; // Number of bytes per file block params.BlockBytes = 1296; // Number of blocks params.OriginalCount = 100; // Number of additional recovery blocks generated by encoder params.RecoveryCount = 30; // Size of the original file static const int OriginalFileBytes = params.OriginalCount * params.BlockBytes; // Allocate and fill the original file data uint8_t* originalFileData = new uint8_t[OriginalFileBytes]; for (int i = 0; i < OriginalFileBytes; ++i) { originalFileData[i] = (uint8_t)i; } // Pointers to data cm256_block blocks[256]; for (int i = 0; i < params.OriginalCount; ++i) { blocks[i].Block = originalFileData + i * params.BlockBytes; } // Recovery data uint8_t* recoveryBlocks = new uint8_t[params.RecoveryCount * params.BlockBytes]; // Generate recovery data if (cm256_encode(params, blocks, recoveryBlocks)) { delete[] originalFileData; delete[] recoveryBlocks; return false; } // Initialize the indices for (int i = 0; i < params.OriginalCount; ++i) { blocks[i].Index = cm256_get_original_block_index(params, i); } //// Simulate loss of data, substituting a recovery block in its place //// for (int i = 0; i < params.RecoveryCount && i < params.OriginalCount; ++i) { blocks[i].Block = recoveryBlocks + params.BlockBytes * i; // First recovery block blocks[i].Index = cm256_get_recovery_block_index(params, i); // First recovery block index } //// Simulate loss of data, substituting a recovery block in its place //// if (cm256_decode(params, blocks)) { delete[] originalFileData; delete[] recoveryBlocks; return false; } for (int i = 0; i < params.RecoveryCount && i < params.OriginalCount; ++i) { uint8_t* block = (uint8_t*)blocks[i].Block; int index = blocks[i].Index; for (int j = 0; j < params.BlockBytes; ++j) { const uint8_t expected = (uint8_t)(j + index * params.BlockBytes); if (block[j] != expected) { delete[] originalFileData; delete[] recoveryBlocks; return false; } } } delete[] originalFileData; delete[] recoveryBlocks; return true; }
/** * This is a more realistic example with separation of received data creation (mocking) and its processing */ bool example3() { #pragma pack(push, 1) struct Sample { uint16_t i; uint16_t q; }; struct Header { uint16_t frameIndex; uint8_t blockIndex; uint8_t filler; }; static const int samplesPerBlock = (512 - sizeof(Header)) / sizeof(Sample); struct ProtectedBlock { Sample samples[samplesPerBlock]; }; struct SuperBlock { Header header; ProtectedBlock protectedBlock; }; #pragma pack(pop) if (cm256_init()) { return false; } cm256_encoder_params params; // Number of bytes per file block params.BlockBytes = sizeof(ProtectedBlock); // Number of blocks params.OriginalCount = 128; // Superframe = set of protected frames // Number of additional recovery blocks generated by encoder params.RecoveryCount = 32; SuperBlock* txBuffer = new SuperBlock[params.OriginalCount+params.RecoveryCount]; ProtectedBlock* txRecovery = new ProtectedBlock[params.RecoveryCount]; cm256_block txDescriptorBlocks[params.OriginalCount+params.RecoveryCount]; int frameCount = 0; // Fill original data for (int i = 0; i < params.OriginalCount+params.RecoveryCount; ++i) { txBuffer[i].header.frameIndex = frameCount; txBuffer[i].header.blockIndex = i; if (i < params.OriginalCount) { txBuffer[i].protectedBlock.samples[0].i = i; // marker } else { memset((void *) &txBuffer[i].protectedBlock, 0, sizeof(ProtectedBlock)); } txDescriptorBlocks[i].Block = (void *) &txBuffer[i].protectedBlock; txDescriptorBlocks[i].Index = txBuffer[i].header.blockIndex; } // Generate recovery data long long ts = getUSecs(); if (cm256_encode(params, txDescriptorBlocks, txRecovery)) { std::cerr << "example2: encode failed" << std::endl; delete[] txBuffer; delete[] txRecovery; return false; } long long usecs = getUSecs() - ts; std::cerr << "Encoded in " << usecs << " microseconds" << std::endl; // insert recovery data in sent data for (int i = 0; i < params.RecoveryCount; i++) { txBuffer[params.OriginalCount+i].protectedBlock = txRecovery[i]; } SuperBlock* rxBuffer = new SuperBlock[params.OriginalCount + params.RecoveryCount]; // received blocks int k = 0; for (int i = 0; i < params.OriginalCount+params.RecoveryCount; i++) { if (i % 5 != 4) { rxBuffer[k] = txBuffer[i]; k++; } } Sample *samplesBuffer = new Sample[samplesPerBlock * params.OriginalCount]; ProtectedBlock* retrievedDataBuffer = (ProtectedBlock *) samplesBuffer; ProtectedBlock* recoveryBuffer = new ProtectedBlock[params.OriginalCount]; // recovery blocks with maximum size cm256_block rxDescriptorBlocks[params.OriginalCount]; int recoveryStartIndex; k = 0; for (int i = 0; i < params.OriginalCount; i++) { int blockIndex = rxBuffer[i].header.blockIndex; if (blockIndex < params.OriginalCount) // it's an original block { retrievedDataBuffer[blockIndex] = rxBuffer[i].protectedBlock; rxDescriptorBlocks[i].Block = (void *) &retrievedDataBuffer[blockIndex]; rxDescriptorBlocks[i].Index = blockIndex; } else // it's a recovery block { if (k == 0) { recoveryStartIndex = i; } recoveryBuffer[k] = rxBuffer[i].protectedBlock; rxDescriptorBlocks[i].Block = (void *) &recoveryBuffer[k]; rxDescriptorBlocks[i].Index = blockIndex; k++; } } ts = getUSecs(); if (cm256_decode(params, rxDescriptorBlocks)) { delete[] txBuffer; delete[] txRecovery; delete[] rxBuffer; delete[] samplesBuffer; delete[] recoveryBuffer; return false; } usecs = getUSecs() - ts; for (int i = 0; i < k; i++) // recover missing blocks { int blockIndex = rxDescriptorBlocks[recoveryStartIndex+i].Index; retrievedDataBuffer[blockIndex] = recoveryBuffer[i]; } for (int i = 0; i < params.OriginalCount; i++) { std::cerr << i << ":" << (unsigned int) rxDescriptorBlocks[i].Index << ":" << (unsigned int) retrievedDataBuffer[i].samples[0].i << std::endl; } std::cerr << "Decoded in " << usecs << " microseconds" << std::endl; delete[] txBuffer; delete[] txRecovery; delete[] rxBuffer; delete[] samplesBuffer; delete[] recoveryBuffer; return true; }
bool example2() { static const int payloadSize = 256; // represents 4 subframes of 64 bytes #pragma pack(push, 1) struct ProtectedBlock { uint8_t blockIndex; uint8_t data[payloadSize]; }; struct SuperBlock { uint8_t frameIndex; uint8_t blockIndex; ProtectedBlock protectedBlock; }; #pragma pack(pop) if (cm256_init()) { return false; } cm256_encoder_params params; // Number of bytes per file block params.BlockBytes = sizeof(ProtectedBlock); // Number of blocks params.OriginalCount = 128; // Superframe = set of protected frames // Number of additional recovery blocks generated by encoder params.RecoveryCount = 32; SuperBlock* txBuffer = new SuperBlock[params.OriginalCount+params.RecoveryCount]; ProtectedBlock* txRecovery = new ProtectedBlock[params.RecoveryCount]; cm256_block txDescriptorBlocks[params.OriginalCount+params.RecoveryCount]; int frameCount = 0; // Fill original data for (int i = 0; i < params.OriginalCount+params.RecoveryCount; ++i) { txBuffer[i].frameIndex = frameCount; txBuffer[i].blockIndex = i; if (i < params.OriginalCount) { txBuffer[i].protectedBlock.blockIndex = i; for (int j = 0; j < payloadSize; ++j) { txBuffer[i].protectedBlock.data[j] = i; } txDescriptorBlocks[i].Block = (void *) &txBuffer[i].protectedBlock; txDescriptorBlocks[i].Index = txBuffer[i].blockIndex; } else { memset((void *) &txBuffer[i].protectedBlock, 0, sizeof(ProtectedBlock)); txDescriptorBlocks[i].Block = (void *) &txBuffer[i].protectedBlock; txDescriptorBlocks[i].Index = i; } } // Generate recovery data long long ts = getUSecs(); if (cm256_encode(params, txDescriptorBlocks, txRecovery)) { std::cerr << "example2: encode failed" << std::endl; delete[] txBuffer; delete[] txRecovery; return false; } long long usecs = getUSecs() - ts; std::cerr << "Encoded in " << usecs << " microseconds" << std::endl; // insert recovery data in sent data for (int i = 0; i < params.RecoveryCount; i++) { txBuffer[params.OriginalCount+i].protectedBlock = txRecovery[i]; } SuperBlock* rxBuffer = new SuperBlock[params.OriginalCount]; cm256_block rxDescriptorBlocks[params.OriginalCount]; int k = 0; for (int i = 0; i < params.OriginalCount+params.RecoveryCount; i++) { if (k < params.OriginalCount) { if (i % 5 != 4) { rxBuffer[k] = txBuffer[i]; rxDescriptorBlocks[k].Block = (void *) &rxBuffer[k].protectedBlock; rxDescriptorBlocks[k].Index = rxBuffer[k].blockIndex; k++; } } } ts = getUSecs(); if (cm256_decode(params, rxDescriptorBlocks)) { delete[] txBuffer; delete[] txRecovery; delete[] rxBuffer; return false; } usecs = getUSecs() - ts; for (int i = 0; i < params.OriginalCount; i++) { std::cerr << i << ":" << (unsigned int) rxBuffer[i].blockIndex << ":" << (unsigned int) rxBuffer[i].protectedBlock.blockIndex << ":" << (unsigned int) rxBuffer[i].protectedBlock.data[0] << std::endl; } std::cerr << "Decoded in " << usecs << " microseconds" << std::endl; delete[] txBuffer; delete[] txRecovery; delete[] rxBuffer; return true; }