Closed mushahidh closed 8 years ago
I don't use Windows much, so I haven't really tested it under Visual Studio. It is heavily tested under Clang and GNU compilers, with full warnings.
Are you sure that you have enabled C++11 compatibility mode for the compiler?
@pjkundert This was the underlying problem . Thanks for the info. Could you please tell me how to see recovered data after decoding? It only shows how much errors are corrected. Secondly, Is ezpwd rs codes are good to use with video data when transmitted over unreliable network? Need your kind opinion on this too.
If it returns a 0 or other positive number, the data were corrected -- and the number of errors corrected is reported. A -'ve value (or exception) indicates that the data were unrecoverable; a valid Reed-Solomon Codeword could not be recovered.
If you are sending data over an unreliable network -- I presume an IP network, probably UDP/IP protocol -- it will be delivered in chunks of whatever IP message size you send. The message itself is unlikely to have errors, due to the IP packet CRC.
So, you must recover missing packets. Thus, any code must cover multiple packets of data. For example, for every 15 packets , you could send a parity packet, allowing you to recover any one missing packet.
Of course, this means that you may need to delay your video stream on the receiving side by up to 14 packets, in order to recover the missing one and play them in order. It is often better just to drop the missing frame, rather than implement a "jitter" buffer, and delay your video by the required number of packets to implement your loss recovery system.
Anyway, that's one idea.
@pjkundert Thanks again. You said it returns number of corrected errors. But How to see corrected data after-that?
You are very much true about decoding delay. But that's the mystery i want to solve i.e increasing the block size would enhance error correcting performance on the other hand it causes a decoding delay which is not tolerable by real time applications.
Could you advice me about how Ezpwd RS codes could be implemented on frame packet levels. So for instance i have one frame consist of 7 RTP packets and i want to use RS(7,5) so that after every 5 packets 2 parity packets will be added. I want to cope with packet loss problem. So out of 5 packet if 1 or 2 packet get lost it could be recovered on receiver end.
But for my understanding RS codes get number of bytes. So if one packet consist of 500 bytes how it would be represented on packet level. This thing is confusing me too much.
Also I can use RS(7,5) to recover lost packet at earliest to avoid any delay but optimal parameters would be decided after applying some experiments.
So in the simplest possible example the output of data variable remains the same after applying decoding. Even though it shows me number of errors corrected 2.
int main(int argc, char** argv) {
ezpwd::RS<255,251> rs;
std::string data="Hel00000";
rs.encode( data );
cout<<data<<endl;
data+="na";
int fixed = rs.decode( data );
cout<< data ;
;
cout<<fixed ;
cout<<data;
return 0;
}
Here is a basic example:
int failures= 0;
ezpwd::RS<255,253> rs; // 255 symbol codeword, up to 253 data == 2 symbols parity
std::string orig = "Hello, world!";
// Most basic use of API to correct an error
std::string data = orig; // working data, copy of orig
std::cout << "Original: " << std::vector<uint8_t>( data.begin(), data.end() ) << std::endl;
rs.encode( data ); // 13 symbols data + 2 symbols R-S parity added
std::cout << "Encoded: " << std::vector<uint8_t>( data.begin(), data.end() ) << std::endl;
data[3] = 'x'; // Corrupt one symbol
std::cout << "Corrupted: " << std::vector<uint8_t>( data.begin(), data.end() ) << std::endl;
int count = rs.decode( data ); // Correct any symbols possible
std::cout << "Corrected: " << std::vector<uint8_t>( data.begin(), data.end() ) << " : " << count << " errors fixed" << std::endl;
data.resize( data.size() - rs.nroots() ); // Discard added R-S parity symbols
std::cout << "Restored: " << std::vector<uint8_t>( data.begin(), data.end() ) << std::endl;
if ( data != orig ) { // Ensure original data is recovered
failures += 1;
std::cout << "Failed to restore origin data." << std::endl;
}
When you call rs.encode(), it will take your original data (up to the payload capacity 'rs.load()' of the Reed-Solomon codeword), and add 'rs.nroots()' R-S parity symbols.
When you call rs.decode(), it will correct any symbols in-place, if possible.
After, it is your responsibility to remove the added R-S parity symbols from the end.
The term RS(255,253) indicates the R-S codeword size, 255. For 8-bit symbols, the codeword size is always 255 symbols. 2^N-1, for N-bit symbols. The maximum codeword data capacity is the second number, 253. This means that there are 2 R-S parity symbols: 255-253 == 2. This means that you can correct up to 1 error (symbols that are incorrect, but not indicated as missing), or up to 2 erasures (symbols marked missing).
@pjkundert That is great.Sorry to bother you again but if i replace data[3] = 'x';
with data.erase(1,1);
The result is -1. Even though it should be able to correct up to 2 erasures and 1 error. So how to cater with completely lost symbol like in this case ?i have tried to enable erasure correction capability in decoder but unable to do that. Actually, in my scenario there will be a erasure correction i.e complete packet loss but i do know the position of packet.
Thanks in advance.
Nope, you have to encode your data in such a way that you can identify the start/end of a block, and can identify the position of each symbol in your block.
Normally, using Ethernet IP communications, you deal in sending/receiving blocks of data. Thus, you know which blocks you've received and which you have not. Any symbols from a "missing" block of data will be designated as an "erasure". The spot for the symbol there -- you pass a separate std::vector
This is somewhat confusing, I know. To add Reed-Solomon encoding to a single block of Ethernet UDP/IP is not normally useful -- you are going to receive the whole block, almost certainly correct.
What you are trying to do is: receive multiple blocks, each one identifying its ordering in your sequence of data blocks. You want to generate Reed-Solomon codewords that contain symbols from each of N blocks (say, 10 symbols from 24 separate blocks), for a total of (say) 240 symbols. Then, if you add another 10 symbols of Reed-Solomon parity data (for a total of 250 symbols), and send the extra parity packet, you can now recover from one missing block out of every 25. You just collect up the 24 incoming blocks, mark all of the symbols from the 1 missing block as "erasures" in each codeword, and then call rs.decode() on each block.
Hope that makes sense.
@pjkundert Very very much thanks for your kind help. You cleared many misconceptions i have. Based on your suggestion i am now starting my implementation. I saw you updated Read me too and you answered my next expected question there.
Again Thanks for your kind attention.
I've updated the README.org a bit, with more description of the C++ API, including a bit about passing erasures and positions std::vector
I've always found that this is the best way to really understand an API. Documentation is, necessarily, less valuable than the code, because it always contains less information, and less reliable information (otherwise, it would be the code!) There are a bunch of tests and examples.
Basically, as you collect up the symbols for a codeword, and you find that a symbol is missing (eg. comes from a packet you didn't receive), then just put a 0 (or whatever) in the codeword at that position -- and append the index of that position onto the end of a std::vector
Then, when you finally want to try the R-S decode, you pass the codeword and the erasures vector:
int corrections = rs.decode( codeword, erasures );
@pjkundert That's my bad. I have read code thoroughly and it is well written and understandable. Could you please let me know what is the best way of determining N , K values for RS encoder? In my scenario let say i have one encoded video frame with 34 RTP packets in it and each packet contains not more than 400 bytes. But it could be some times 24 bytes per packet as well.And let say i apply random packet loss on it and packet no 4 get lost. In this case how can i make 2 parity packets after every 7 packet so that it can recover missing packet no 4? How will you cater this scenario ?
I want to use ezpwd RS code to protect video stream from packet loss. However, using the library in Visual studio and even in Qt gives me lot of undeclared identifier errors when i just call ezpwd::RS<255,251> rs; in my code.like```