Esempio n. 1
0
void Example1Rx::processBlock(SuperBlock& superBlock)
{
    if (superBlock.header.frameIndex != m_frameHead)
    {
        if (m_dataCount != m_params.OriginalCount)
        {
            std::cerr << "Example1Rx::processBlock: incomplete frame" << std::endl;
        }

        m_frameCount++;
        m_blockCount = 0;
        m_metaReceived = false;
        m_dataCount = 0;
        m_recoveryCount = 0;
        m_frameHead = superBlock.header.frameIndex;
    }

    if (m_blockCount < m_params.OriginalCount) // not enough to decode => store data
    {
        int blockIndex = superBlock.header.blockIndex;

        if (blockIndex < m_params.OriginalCount) // data
        {
            m_data[blockIndex] = superBlock.protectedBlock;
            m_descriptorBlocks[m_blockCount].Block = (void *) &m_data[blockIndex];
            m_descriptorBlocks[m_blockCount].Index = blockIndex;
            m_dataCount++;

            if (blockIndex == 0)
            {
                MetaDataFEC *metaData = (MetaDataFEC *) &m_data[blockIndex];

                if (!(*metaData == m_currentMeta))
                {
                    m_currentMeta = *metaData;
                }

                m_metaReceived = true;
            }

//            if (blockIndex == 1)
//            {
//              std::srand(superBlock.header.frameIndex);
//              std::cerr << "Example1Rx::processBlock: " << superBlock.header.frameIndex << ": ";
//
//              for (int k = 0; k < 2; k++)
//              {
//                  uint16_t refI = std::rand();
//                  uint16_t refQ = std::rand();
//
//                  std::cerr  << "[" << k << "] " << m_data[blockIndex].samples[k].i
//                          << "/" << m_data[blockIndex].samples[k].q
//                          << " " << refI
//                          << "/" << refQ
//                          << " ";
//              }
//
//              std::cerr << std::endl;
//            }

        }
        else // recovery data
        {
        	m_recovery[m_recoveryCount] = superBlock.protectedBlock;
            m_descriptorBlocks[m_blockCount].Block = (void *) &m_recovery[m_recoveryCount];
            m_descriptorBlocks[m_blockCount].Index = blockIndex;
            m_recoveryCount++;
        }
    }

    m_blockCount++;

    if (m_blockCount == m_params.OriginalCount) // enough data is received
    {
        if (m_cm256_OK && (m_recoveryCount > 0)) // FEC necessary
        {
            if (cm256_decode(m_params, m_descriptorBlocks)) // failure to decode
            {
                std::cerr << "Example1Rx::processBlock: CM256 decode error" << std::endl;
            }
            else // success to decode
            {
                std::cerr << "Example1Rx::processBlock: CM256 decode success: ";

                int recoveryStart = m_dataCount;

                for (int ir = 0; ir < m_recoveryCount; ir++)
                {
                    int blockIndex = m_descriptorBlocks[recoveryStart + ir].Index;
                    std::cerr << blockIndex << " ";
                    m_data[blockIndex] = *((ProtectedBlock *) m_descriptorBlocks[recoveryStart + ir].Block);
                    m_dataCount++;
                }

                std::cerr << std::endl;
            }
        }

        if (m_dataCount == m_params.OriginalCount)
        {
            checkData();
        }
    }
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
/**
 * 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;
}
Esempio n. 5
0
bool SDRdaemonFECBuffer::writeAndRead(uint8_t *array, std::size_t length, uint8_t *data, std::size_t& dataLength)
{
    assert(length == udpSize);

    bool dataAvailable = false;
    dataLength = 0;
    SuperBlock *superBlock = (SuperBlock *) array;
    int frameIndex = superBlock->header.frameIndex;

//    std::cerr << "SDRdaemonFECBuffer::writeAndRead:"
//            << " frameIndex: " << frameIndex
//            << " decoderIndex: " << decoderIndex
//            << " blockIndex: " << blockIndex
//            << " i.q:";
//
//    for (int i = 0; i < 10; i++)
//    {
//        std::cerr << " " << (int) superBlock->protectedBlock.samples[i].i
//                << "." << (int) superBlock->protectedBlock.samples[i].q;
//    }
//
//    std::cerr << std::endl;

    if ( m_frameHead != frameIndex)
    {
        getSlotData(data, dataLength); // copy slot data to output buffer
        dataAvailable = true;
        initDecodeSlot(); // re-initialize slot
        m_frameHead = frameIndex;
    }

    // decoderIndex should now be correctly set

    if (m_decoderSlot.m_blockCount < nbOriginalBlocks) // not enough blocks to decode -> store data
    {
        int blockCount = m_decoderSlot.m_blockCount;
        int recoveryCount = m_decoderSlot.m_recoveryCount;
        int blockIndex = superBlock->header.blockIndex;
        m_decoderSlot.m_cm256DescriptorBlocks[blockCount].Index = blockIndex;

        if (blockIndex == 0) // first block with meta
        {
            m_decoderSlot.m_metaRetrieved = true;
        }

        if (blockIndex < nbOriginalBlocks) // data block
        {
            m_decoderSlot.m_frame.m_blocks[blockIndex] = superBlock->protectedBlock;
            m_decoderSlot.m_cm256DescriptorBlocks[blockCount].Block = (void *) &m_decoderSlot.m_frame.m_blocks[blockIndex];
        }
        else // redundancy block
        {
            m_decoderSlot.m_recoveryBlocks[recoveryCount] = superBlock->protectedBlock;
            m_decoderSlot.m_cm256DescriptorBlocks[blockCount].Block = (void *) &m_decoderSlot.m_recoveryBlocks[recoveryCount];
            m_decoderSlot.m_recoveryCount++;
        }
    }

    m_decoderSlot.m_blockCount++;

    if (m_decoderSlot.m_blockCount == nbOriginalBlocks) // ready to decode
    {
        m_decoderSlot.m_decoded = true;

        if (m_cm256_OK && (m_decoderSlot.m_recoveryCount > 0)) // recovery data used and CM256 decoder available
        {
            m_paramsCM256.RecoveryCount = m_decoderSlot.m_recoveryCount;
//            // debug print
//            for (int ir = 0; ir < m_decoderSlots[decoderIndex].m_recoveryCount; ir++) // recovery blocks
//            {
//                int blockIndex = m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[nbRxOriginalBlocks+ir].Index;
//                ProtectedBlock *recoveryBlock = (ProtectedBlock *) m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[nbRxOriginalBlocks+ir].Block;
//
//                std::cerr << "SDRdaemonFECBuffer::writeAndRead:"
//                        << " recovery block #" << blockIndex
//                        << " i.q: ";
//
//                for (int i = 0; i < 10; i++)
//                {
//                    std::cerr << " " << recoveryBlock->samples[i].i
//                            << "." << recoveryBlock->samples[i].q;
//                }
//
//                std::cerr << std::endl;
//            }
//            // end debug print

            if (cm256_decode(m_paramsCM256, m_decoderSlot.m_cm256DescriptorBlocks)) // failure to decode
            {
                std::cerr << "SDRdaemonFECBuffer::writeAndRead: CM256 decode error" << std::endl;
            }
            else // success to decode
            {
                int nbRxOriginalBlocks = nbOriginalBlocks - m_decoderSlot.m_recoveryCount;

                std::cerr << "SDRdaemonFECBuffer::writeAndRead: CM256 decode success:"
                        << " nb recovery blocks: " << m_decoderSlot.m_recoveryCount << std::endl;

                for (int ir = 0; ir < m_decoderSlot.m_recoveryCount; ir++) // recover lost blocks
                {
                    int recoveryIndex = nbOriginalBlocks - m_decoderSlot.m_recoveryCount + ir;
                    int blockIndex = m_decoderSlot.m_cm256DescriptorBlocks[recoveryIndex].Index;
                    ProtectedBlock *recoveredBlock = (ProtectedBlock *) m_decoderSlot.m_cm256DescriptorBlocks[recoveryIndex].Block;
                    m_decoderSlot.m_frame.m_blocks[blockIndex] =  *recoveredBlock;

//                    if (blockIndex == 0)
//                    {
//                        m_decoderSlots[decoderIndex].m_metaRetrieved = true;
//                    }

                    // debug print
                    std::cerr << "SDRdaemonFECBuffer::writeAndRead:"
                            << " recovered block #" << blockIndex
                            << " i.q: ";

                    for (int i = 0; i < 10; i++)
                    {
                        std::cerr << " " << recoveredBlock->samples[i].i
                                << "." << recoveredBlock->samples[i].q;
                    }

                    std::cerr << std::endl;
                    // end debug print
                } // recover
            } // success to decode
        } // recovery data used

        if (m_decoderSlot.m_metaRetrieved) // meta data retrieved
        {
            MetaDataFEC *metaData = (MetaDataFEC *) &m_decoderSlot.m_frame.m_blocks[0];

            if (!(*metaData == m_currentMeta))
            {
                m_currentMeta = *metaData;
                printMeta(metaData);
            }
        }
    } // decode frame

    return dataAvailable;
}