Compressing a 'char' array using bit packing
Conditional jumps are murder on throughput due to branch-misprediction. Consider simply using a lookup-table instead:
const static uint8_t map[] = { 0, 1, 2, 0, 3 };
*out = (uint8_t)
    ( (map[in[0]] &lt;&lt; 0)
    | (map[in[1]] &lt;&lt; 2)
    | (map[in[2]] &lt;&lt; 4)
    | (map[in[3]] &lt;&lt; 6));

There are many architectures where shifting is more expensive than masking, but I doubt there are any where the reverse holds. Thus, the following code, even though it probably requires one extra machine code instruction (3 shifts vs. 4 masks) is likely to be faster:
const static uint8_t map[] = { 0x00, 0x55, 0xaa, 0x00, 0xff };
*out = (uint8_t)
    ( (map[in[0]] &amp; 0x03)
    | (map[in[1]] &amp; 0x0c)
    | (map[in[2]] &amp; 0x30)
    | (map[in[3]] &amp; 0xc0));

By the way, how do you handle the tail of up to 3 bytes? Or is your data guaranteed to be a multiple of 4 bytes long?
Also, your inner loop currently duplicates the first byte of every 4-byte-chunk four times.
Your comments are blatantly superfluous; at best they repeat the code. Say why you do something, not what you just did.