将位字段转换为字节数组 [英] Converting bit field to byte array

查看:43
本文介绍了将位字段转换为字节数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些mpeg ts位字段,例如传输流包:

I have some mpeg ts bitfields, for example transport stream package:

struct ts_package_header_s {
    unsigned int continuity_counter :4;
    unsigned int adaptation_field_control :2;
    unsigned int transport_scrambling_control :2;
    unsigned int PID :13;
    unsigned int transport_priority :1;
    unsigned int payload_unit_start_indicator :1;
    unsigned int transport_error_indicator :1;
    unsigned int sync_byte :8;
};

struct ts_package_s {
    struct ts_package_header_s ts_header;
    unsigned char ts_body[TS_BODY];
};

union ts_package_u {
    struct ts_package_s ts_package;
    unsigned char bytes[TS_PACKAGE];
};

在我的源代码中,我初始化标头struct:

In my source code I initialize header struct:

pat_package_header.sync_byte = 0x47;
pat_package_header.transport_error_indicator = 0;
pat_package_header.payload_unit_start_indicator = 1;
pat_package_header.transport_priority = 0;
pat_package_header.PID = PAT_PID;
pat_package_header.transport_scrambling_control = 0;
pat_package_header.adaptation_field_control = 1;
pat_package_header.continuity_counter = 0;

然后我会创建ts_packag联合

And than I make ts_packag union

union ts_package_u package;
package.ts_package.ts_header = pat_package_header;

比我填写ts_body数组.当我将此包写入文件时.我得到了向后数组:

Than I fill ts_body array. When I write this package to file. I get backwards array:

10 00 40 47 XX XX XX.. instead of 47 40 10 00 XX XX XX.. 

我尝试将结构强制转换为char *而不是使用union,但是得到了相同的结果.

I tried to cast my struct to char* instead of using union, but got same result.

哪里出毛病?谢谢.

推荐答案

使用尝试将这样的结构直接序列化到磁盘上是很危险的,在磁盘上必须在不同的体系结构中知道该格式,或者使用不同的编译器.

It's dangerous to use try and serialise structs like this directly to disk where the format must be known across different architectures, or use different compilers.

编译器在存储位域的方式上有所不同,并且体系结构的底层耐久性也改变了数据的存储方式

Compilers differ in how they store bitfields and the underlying endianess of your architecture also changes how the data is stored

例如,可能是编译器选择在字节,字或其他边界上对齐位域.这是编译器的决定.它还可以选择以任何顺序保存位,这通常取决于计算机的耐久性.

For example, it could be that a compiler chooses to align bitfields on byte, word or some other boundary. It's a compiler decision. It may also choose to save the bits in any order, which usually depends on the endianess of your machine.

为了安全地将此标头写入磁盘,您需要自己对数据进行序列化.根据维基百科,标头是32位和Big Endian.

In order to safely write this header to disk, you need to serialise the data yourself. The header is 32-bit and Big Endian according to Wikipedia.

例如:

#include <stdio.h>

#define TS_BODY 1024
#define PAT_PID 0x40

struct ts_package_header_s {
    unsigned int continuity_counter :4;
    unsigned int adaptation_field_control :2;
    unsigned int transport_scrambling_control :2;
    unsigned int PID :13;
    unsigned int transport_priority :1;
    unsigned int payload_unit_start_indicator :1;
    unsigned int transport_error_indicator :1;
    unsigned int sync_byte :8;
};

struct ts_package_s {
    struct ts_package_header_s ts_header;
    unsigned char ts_body[TS_BODY];
};

static void write_ts( struct ts_package_s pat_package )
{
    FILE* f = fopen( "test.ts", "wb+" );
    unsigned int header = 0;

    if( f == NULL )
        return;

    header = pat_package.ts_header.sync_byte << 24;
    header |= ( pat_package.ts_header.transport_error_indicator << 23 );
    header |= ( pat_package.ts_header.payload_unit_start_indicator << 22 );
    header |= ( pat_package.ts_header.transport_priority << 21 );
    header |= ( pat_package.ts_header.PID << 8 );
    header |= ( pat_package.ts_header.transport_scrambling_control << 6 );
    header |= ( pat_package.ts_header.adaptation_field_control << 4 );
    header |= ( pat_package.ts_header.continuity_counter );

    /* Write the 32-bit header as big-endian */
    unsigned char byte = header >> 24;
    fwrite( &byte, 1, 1, f );

    byte = ( header >> 16 ) & 0xFF;
    fwrite( &byte, 1, 1, f );

    byte = ( header >> 8 ) & 0xFF;
    fwrite( &byte, 1, 1, f );

    byte = header & 0xFF;
    fwrite( &byte, 1, 1, f );

    fclose( f );
}

int main( int argc, char* argv[] )
{
    struct ts_package_s pat_package;
    pat_package.ts_header.sync_byte = 0x47;
    pat_package.ts_header.transport_error_indicator = 0;
    pat_package.ts_header.payload_unit_start_indicator = 1;
    pat_package.ts_header.transport_priority = 0;
    pat_package.ts_header.PID = PAT_PID;
    pat_package.ts_header.transport_scrambling_control = 0;
    pat_package.ts_header.adaptation_field_control = 1;
    pat_package.ts_header.continuity_counter = 0;

    write_ts( pat_package );

    return 0;
}

写入具有以下标头的文件:

Writes a file with the following header:

0x47 0x40 0x01 0x10

根据您使用的值看来是正确的.

which appears to be correct according to the values you're using.

这篇关于将位字段转换为字节数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆