quiet / libcorrect

C library for Convolutional codes and Reed-Solomon
BSD 3-Clause "New" or "Revised" License
379 stars 94 forks source link

Error With RS Decode (return all zeros) #47

Open Zijian-Zhou opened 4 months ago

Zijian-Zhou commented 4 months ago

Firstly, thank you for your library, which has been very helpful for my project. I have been using it to encode and decode files, and it works well when repairing some erasures in data blocks. However, I encounter an issue where it returns all zeros when trying to repair parity blocks. While re-encoding to recover the parity blocks is a feasible workaround, I am curious to understand why I am getting all zeros in my current approach. Thank you again for your time and attention!

Here are my code context:


long long getfsize(const char *filename){
    FILE *file = fopen(filename, "rb");
    if (file == NULL) {
        return -1;
    }
    fseek(file, 0, SEEK_END);
    long long size = ftell(file);
    fclose(file);
    return size;
}

long long max(long long a, long long b){
    if(a>b) return a;
    return b;
}

int encode_file(char* filelist[], int n, int k){

    size_t message_length = (size_t)k;
    size_t min_distance = (size_t)(n - k);
    size_t block_length = (size_t)n;

    correct_reed_solomon *rs = correct_reed_solomon_create(
            correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
    rs_testbench *testbench = rs_testbench_create(block_length, min_distance);

    rs_test test;
    test.encode = rs_correct_encode;
    test.decode = rs_correct_decode;
    test.encoder = rs;
    test.decoder = rs;

    FILE *FilePointers[n];
    long long max_filesize =  -1;

    for(int i = 0; i < n; i++){
        if(i < k){
            FilePointers[i] = fopen(filelist[i], "rb");
            max_filesize = max(max_filesize, getfsize(filelist[i]));
        }else{
            FilePointers[i] = fopen(filelist[i], "wb");
        }

        if(FilePointers[i] == NULL){
            printf("File Open Failed AT IDX: %d", i);
            for(int j = 0; j < i; j++){
                fclose(FilePointers[j]);
            }
            return -1;
        }
    }

    int cnt = 0;

    while(cnt < max_filesize){
        cnt++;
        for(int i = 0;i < n; i++){
            if(i < k){
                if(fread(testbench->msg + i, 1, 1, FilePointers[i]) == 0){
                    testbench->msg[i] = (unsigned char)0x00;
                }
            }else testbench->msg[i] = (unsigned char)0x00;
        }
        test.encode(test.encoder, testbench->msg, message_length, testbench->encoded);
        for(int i = k; i < n;i++){
            fwrite(testbench->encoded + i, 1, 1, FilePointers[i]);
        }
    }

    for(int i = 0; i < n;i++) fclose(FilePointers[i]);

    return 0;
}

bool check_loss(int i, int loss_idx[], int loss_num){
    bool flag = 0;
    for(int j = 0;j < loss_num;j++){
        if(i == loss_idx[j]){
            flag = 1;
            break;
        }
    }
    return flag;
}

int decode_file(char* filelist[], int n, int k, int loss_idx[], int loss_num){
    size_t message_length = (size_t)k;
    size_t min_distance = (size_t)(n - k);
    size_t block_length = (size_t)n;

    correct_reed_solomon *rs = correct_reed_solomon_create(
            correct_rs_primitive_polynomial_ccsds, 1, 1, min_distance);
    rs_testbench *testbench = rs_testbench_create(block_length, min_distance);

    rs_test test;
    test.encode = rs_correct_encode;
    test.decode = rs_correct_decode;
    test.encoder = rs;
    test.decoder = rs;

    FILE *FilePointers[n];
    long long max_filesize =  -1;

    for(int i = 0; i < n; i++){
        bool flag = check_loss(i, loss_idx, loss_num);
        if(flag){
            FilePointers[i] = fopen(filelist[i], "wb");
        }else{
            FilePointers[i] = fopen(filelist[i], "rb");
            max_filesize = max(max_filesize, getfsize(filelist[i]));
        }

        if(FilePointers[i] == NULL){
            printf("File Open Failed AT IDX: %d", i);
            for(int j = 0; j < i; j++){
                fclose(FilePointers[j]);
            }
            return -1;
        }
    }

    int cnt=0;

    while(cnt < max_filesize){

        cnt++;
        int detected = 0;
        unsigned char* c = (unsigned char*)malloc(sizeof(unsigned char));
        memset(testbench->corrupted_encoded, 0, sizeof(testbench->corrupted_encoded));

        for(int i = 0; i < n; i++){
            bool flag = check_loss(i, loss_idx, loss_num);
            if(flag){
                testbench->erasure_locations[detected] = i;
                detected++; 
            }else{
                if(fread(testbench->corrupted_encoded + i, 1, 1, FilePointers[i]) == 0){
                    testbench->corrupted_encoded[i] = 0x00;
                }
            }
        }

        test.decode(test.decoder, testbench->corrupted_encoded, block_length,
                    testbench->erasure_locations, loss_num,
                    testbench->recvmsg, testbench->message_length - message_length, testbench->min_distance);

        for(int i = 0;i < loss_num;i++){
            *c = testbench->recvmsg[loss_idx[i]];
            fwrite(c, 1, 1, FilePointers[loss_idx[i]]);
        }
    }

    for(int i = 0;i < n;i++) fclose(FilePointers[i]);

    return 0;
}

int main() {

    /*char* filelist[] = {
        "test/block_0.dat",
        "test/block_1.dat",
        "test/block_2.dat",
        "test/block_3.dat",
        "test/block_4.dat",
        "test/block_5.dat",
        "parity/parity_0.dat",
        "parity/parity_1.dat",
        "parity/parity_2.dat",
    };*/

    char* filelist[] = {
        "test/block_0.dat",
        "test/block_1_.dat",
        "test/block_2_.dat",
        "test/block_3.dat",
        "test/block_4.dat",
        "test/block_5.dat",
        "parity/parity_0_.dat",
        "parity/parity_1.dat",
        "parity/parity_2.dat",
    };

    //encode_file(filelist, 9, 6);
    int losses[] = {1, 2, 6};
    decode_file(filelist, 9, 6, losses, 3);

    return 0;
}