I have simulated the grainy effect as shown below:
For this I firstly generate a random integer between 1000 to 2000 in C called "rand_seed" and pass it into the GLSL fragment shader as a uniform variable. In GLSL I used the sin function as the pseudo number generator.
int rand = int(abs(sin(rand_seed * fs_Texcoords.x * fs_Texcoords.y)) * 10000);
rand = rand & 63;
out_Color *= max( 1.0f, (float(rand) / 64.0f + 0.5f));
The first line generate an integer according to the fs_Texcoords.
This process uses the third and fourth digit after the decimal point by doing bitwise and operation with 0x3F.
Then the result is divided by 64.0 to get the grainy weight of the current pixel. Since the color of each pixel should be mostly determined by the original picture, I decrease the influence of grainy effect by half using the max( 1.0f, (float(rand) / 64.0f + 0.5f)) and multiply the result to out_Color.
Because the rand_seed is updated every frame, this method could easily create dynamic distributed grainy effects over time.