cpython-3.xwebsocketctypesbytestream

How do I convert a byte stream to unsigned int 8 in C


I am streaming a video in python via WebSocket, which is a raw bytes stream and appears like this:

b'\x00\x00\x00\x01A\x9a \x02\x04\xe1{=z\xf8FMS\xe6\\\x9eMubH\xa7R.1\xd7]F\xea3}\xa9b\x9f\x14n\x12| ....'

Now, I am passing these bytes to a C function (via ctypes) where I am trying to convert this to a uint8_t [] array (This is needed in order to decode it using a FFmpeg library). Here's my code so far:

This is how I am passing bytes to C:

 import ctypes
 dll = ctypes.CDLL("decode_video.so")
 data = bytearray(b'\x00\x00\x00\x01A\x9a \x02\x04\xe1-{=z\xf8FM....')
 b_array = ctypes.c_char * len(data)
 dll.conversion_test(b_array.from_buffer(data), len(data))

decode_video.c

void conversion_test(unsigned char* buf, int bufSize) {
    char temp[3]; 
    uint8_t vals[bufSize];

    // Iterate over the values
    for (int i = 0; i < bufSize; i++) {
        // Copy two characters into the temporary string
        temp[0] = buf[i * 2];
        temp[1] = buf[i * 2 + 1];

        temp[2] = 0;
        vals[i] = strtol(temp, NULL, 16);
    }

    for(int i=0; i<bufSize; i++){
        printf("%02x ", vals[i] & 0xff);
    }

}

Aside from this, I am simultaneously dumping the stream to a file. In C, I have another function that reads from this file and stores in a uint8_t buffer.

Streaming code in python:

f = open("video.h264", "wb")
def on_message(ws, message):
    # The first 14 characters have irrelevant info to decode the video
    f.write(message[14:])

ws = websocket.WebSocketApp("wss://somewebsite.com/archives",
                                on_open=on_open,
                                on_message=on_message,
                                on_error=on_error,
                                on_close=on_close,
                                header=[protocol_str]
                                )
ws.binaryType = 'arraybuffer'
ws.run_forever(dispatcher=rel)

Reading from the raw file in C:

#include "libavcodec/avcodec.h"
#define INBUF_SIZE 4096
uint8_t *data;
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
f = fopen(input_name, "rb");
data_size = fread(inbuf, 1, INBUF_SIZE, f);

// Printing bytes in hex to debug
for(size_t i=0; i<data_size; i++){
     printf("%02x ", inbuf[i] & 0xff);
}

However the contents of this inbuf and output of the vals buffer are not the same. Basically, I am unsure of my method of passing bytes to C and its corresponding coversion to uint8_t.

Update:

I tried printing the hex values of vals and here's what it looks like: 00 00 0a 00 00 00 00 00 00 00 00 00 00 00 01 00 00 ...

While the output of inbuf looks like this: 00 00 00 01 67 42 00 1e e2 90 14 07 b6 02 dc ...


Solution

  • Fix:

    As suggested by @n. m. and @dreamlax, a simple identity mapping works between unsigned char and uint8_t. Now vals and inbuf output the same values!

    void conversion_test(unsigned char* buf, int bufSize) {
        uint8_t vals[bufSize];
        for(int i = 0; i < bufSize; i++)
            vals[i] = (uint8_t)buf[i];
    }
    

    (OR) A simple type-casting

    uint8_t *vals = (uint8_t *)ubuf;