⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsmcc_biop.cpp

📁 数字电视中间件小型库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include  <stdio.h>
#include "../libavcodec/common.h"
#include "dsmcc_biop.h"

template<class T> uint32_t BIOP::add_flat_size(int sum, T flat_object) {
    return sum + flat_object.flat_size();
}

bool BIOP::parse(ObjectLocationComponent& component, uint8_t* buffer) {
    component.id_tag = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];

#ifdef BIOP_STRICT
    if(component.id_tag != BIOP_COMPONENT_ID_OBJECTLOC) {
        return false;
    }
#endif

    component.data_length = buffer[4];
    component.carousel_id = (buffer[5] << 24) | (buffer[6] << 16) | (buffer[7] << 8) | buffer[8];
    component.module_id   = (buffer[9] << 8) | buffer[10];
    component.version_major = buffer[11];
    component.version_minor = buffer[12];
    component.object_key_length = buffer[13];

    #ifdef BIOP_STRICT
        if(component.version_major != 1 || component.version_minor != 0) {
            return false;
        }
    #endif

    buffer += 14;

    // Hand-crafted for loop; I couldn't bring myself to loop for this triviality
    component.object_key = (buffer[0] << 24);    if(component.object_key_length > 1) component.object_key |= (buffer[1] << 16);    if(component.object_key_length > 2) component.object_key |= (buffer[2] << 8);    if(component.object_key_length > 3) component.object_key |= buffer[3];

    #ifdef BIOP_TRACE_OBJECTLOCATIONCOMPONENT
        BIOP_TRACE_NUM("ObjectLocationComponent", "id_tag", component.id_tag, "8");
        BIOP_TRACE_NUM("ObjectLocationComponent", "data_length", component.data_length, "2");
        BIOP_TRACE_NUM("ObjectLocationComponent", "carousel_id", component.carousel_id, "8");
        BIOP_TRACE_NUM("ObjectLocationComponent", "module_id", component.module_id, "4");
        BIOP_TRACE_NUM("ObjectLocationComponent", "version_major", component.version_major, "2");
        BIOP_TRACE_NUM("ObjectLocationComponent", "version_minor", component.version_minor, "2");
        BIOP_TRACE_NUM("ObjectLocationComponent", "object_key_length", component.object_key_length, "2");
        BIOP_TRACE_NUM("ObjectLocationComponent", "object_key", component.object_key, "8");
    #endif

    return true;
}

bool BIOP::parse(ConnBinderComponent& component, uint8_t* buffer) {
    component.id_tag = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];

    #ifdef BIOP_STRICT
        if(component.id_tag != BIOP_COMPONENT_ID_CONNBIND) {
            return false;
        }
    #endif

    component.data_length = buffer[4];
    component.network_taps_count = buffer[5];

    #ifdef BIOP_TRACE_CONNBINDERCOMPONENT
        BIOP_TRACE_NUM("ConnBinderComponent", "id_tag", component.id_tag, "8");
        BIOP_TRACE_NUM("ConnBinderComponent", "data_length", component.data_length, "2");
        BIOP_TRACE_NUM("ConnBinderComponent", "network_taps_count", component.network_taps_count, "2");
    #endif

    if(component.network_taps_count < 1) {
        return false;
    }

    // Shift the buffer and read the one mandatory tap
    buffer += 6;
    BIOP_TRACE_INDENT(1);
    if(!parse(component.network_tap, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    // Now shift are loop over all other taps to tell us what we 're missing out on
    buffer += component.network_tap.flat_size();

    BIOP_TRACE_INDENT(1);
    for(int i = 1; i < component.network_taps_count; ++i) {
        Tap dummy_tap;
        if(!parse(dummy_tap, buffer)) {
            return false;
        }
        buffer += dummy_tap.flat_size();
        BIOP_TRACE_GENERAL("ConnBinderComponent", "Skipped one network tap beyond the first");
    }
    BIOP_TRACE_INDENT(-1);

    return true;
}

bool BIOP::parse(Tap& tap, uint8_t* buffer) {

    // Skip first two bytes (tap.id), it's checked only if BIOP_STRICT
    tap.use       = (buffer[2] << 8) | buffer[3];
    tap.assoc_tag = (buffer[4] << 8) | buffer[5];
    tap.selector_length = buffer[6];

    #ifdef BIOP_TRACE_TAP
        BIOP_TRACE_NUM("Tap", "id", ((buffer[0] << 8) | buffer[1]), "4");
        BIOP_TRACE_NUM("Tap", "use", tap.use, "4");
        BIOP_TRACE_NUM("Tap", "association_tag", tap.assoc_tag, "4");
        BIOP_TRACE_NUM("Tap", "selector_length", tap.selector_length, "2");
    #endif

    #ifdef BIOP_STRICT
        if(((buffer[0] << 8) | buffer[1]) != 0x00) {  // mandatory per ETSI TR 101 202
            return false;
        }
    
        switch(tap.use) { // all this mandatory per ETSI TR 101 202
            case BIOP_DELIVERY_PARA_USE:
                if(tap.selector_length != 0x0a) {
                    return false;
                }
                break;
    
            case BIOP_PROGRAM_USE:
            case BIOP_OBJECT_USE:
                if(tap.selector_length != 0) {
                    return false;
                }
                break;

            default:
                return true;
        }
    #endif

    if(tap.selector_length) {
        tap.selector.type           = (buffer[7] << 8) | buffer[8];
        tap.selector.transaction_id = (buffer[9] << 24) | (buffer[10] << 16) | (buffer[11] << 8) | buffer[12];
        tap.selector.timeout        = (buffer[13] << 24) | (buffer[14] << 16) | (buffer[15] << 8) | buffer[16];

        #ifdef BIOP_TRACE_TAP
            BIOP_TRACE_NUM("Tap", "selector.type", tap.selector.type, "4");
            BIOP_TRACE_NUM("Tap", "selector.transaction_id", tap.selector.transaction_id, "8");
            BIOP_TRACE_NUM("Tap", "selector.timeout", tap.selector.timeout, "8");
        #endif
        
        #ifdef BIOP_STRICT
            if(tap.selector.type != 0x0001) { // guess what?
                return false;
            }
        #endif
    }

    return true;
}

bool BIOP::parse(ServiceGatewayInfo& sgi, uint8_t* buffer) {

    BIOP_TRACE_THRESHOLD(-1);

    BIOP_TRACE_INDENT(1);
    if(!parse(sgi.ior, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    #ifdef BIOP_STRICT
        if(((sgi.ior.type_id[0] << 24) | (sgi.ior.type_id[1] << 16) | (sgi.ior.type_id[2] << 8) | sgi.ior.type_id[3]) != BIOP_ALIAS_TYPE_ID_SRG) {
            return false;
        }
    #endif

    buffer += sgi.ior.flat_size();
    sgi.download_taps_count = buffer[0];

    ++buffer;
    BIOP_TRACE_INDENT(1);
    for(int i = 0; i < sgi.download_taps_count; ++i) {
        Tap dummy_tap;
        if(!parse(dummy_tap, buffer)) {
            return false;
        }
        buffer += dummy_tap.flat_size();
        BIOP_TRACE_GENERAL("ServiceGatewayInfo", "Skipped one network tap");
    }
    BIOP_TRACE_INDENT(-1);

    sgi.service_context_list_count = buffer[0];
    ++buffer;
    BIOP_TRACE_INDENT(1);
    for(int i = 0; i < sgi.service_context_list_count; ++i) {
        ServiceContext dummy_context;
        if(!parse(dummy_context, buffer)) {
            return false;
        }
        buffer += dummy_context.flat_size();
        BIOP_TRACE_GENERAL("ServiceGatewayInfo", "Skipped one service context");
    }
    BIOP_TRACE_INDENT(-1);
    sgi.user_info_length = (buffer[0] << 8) | buffer[1];

    #ifdef BIOP_TRACE_SERVICEGATEWAYINFO
        BIOP_TRACE_NUM("ServiceGatewayInfo", "download_taps_count", sgi.download_taps_count, "2");
        BIOP_TRACE_NUM("ServiceGatewayInfo", "service_context_list_count", sgi.service_context_list_count, "2");
        BIOP_TRACE_NUM("ServiceGatewayInfo", "user_info_length", sgi.user_info_length, "2");
    #endif

    BIOP_TRACE_THRESHOLD(10);

    return true;
}

bool BIOP::parse(ModuleInfo& mi, uint8_t* buffer) {
    mi.z_compression_method = mi.z_original_size = 0;
    mi.module_timeout = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
    mi.block_timeout  = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
    mi.min_block_time = (buffer[8] << 24) | (buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
    mi.taps_count     = buffer[12];

    if(mi.taps_count != 1) {
        return false;
    }

    BIOP_TRACE_INDENT(1);
    if(!parse(mi.tap, buffer + 13)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    mi.user_info_length = buffer[20];
    buffer += 21;
    int i = 0;

    while(i < mi.user_info_length) {
        uint8_t descriptor_tag = buffer[i++];
        uint8_t descriptor_len = buffer[i++];
        switch(descriptor_tag) {
            case 0x09:  // compressed module descriptor
                mi.z_compression_method = buffer[i];
                mi.z_original_size = (buffer[i+1] << 24) | (buffer[i+2] << 16) | (buffer[i+3] << 8) | buffer[i+4];
                break;
            default:
                printf(">> descriptor_tag: %02x\n", descriptor_tag);
                return false;
                break;
        }
        i += descriptor_len;
    }

    return true;
}

bool BIOP::parse(DIIModuleLoopItem& module, uint8_t* buffer) {
    module.module_id      = (buffer[0] << 8) | buffer[1];    module.module_size    = (buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | buffer[5];    module.module_version = buffer[6];    module.module_info_length = buffer[7];
    #ifdef BIOP_TRACE_DIIMODULELOOPITEM
        BIOP_TRACE_NUM("DIIModuleLoopItem", "module_id", module.module_id, "4");
        BIOP_TRACE_NUM("DIIModuleLoopItem", "module_size", module.module_size, "8");
        BIOP_TRACE_NUM("DIIModuleLoopItem", "module_version", module.module_version, "2");
        BIOP_TRACE_NUM("DIIModuleLoopItem", "module_info_length", module.module_info_length, "2");
    #endif

    BIOP_TRACE_INDENT(1);
    if(!parse(module.module_info, buffer + 8)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    return true;
}

bool BIOP::parse(DirectoryMessage& dm, uint8_t* buffer) {

    BIOP_TRACE_INDENT(1);
    if(!parse(dm.header, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    #ifdef BIOP_STRICT
        if(dm.header.object_kind != BIOP_ALIAS_TYPE_ID_DIR) {
            return false;
        }
    #endif

    buffer += dm.header.flat_size();
    uint16_t bindings_count = (buffer[0] << 8) | buffer[1];
    dm.bindings.resize(bindings_count);

    #ifdef BIOP_TRACE_DIRECTORYMESSAGE
        BIOP_TRACE_NUM("DirectoryMessage", "bindings_count", bindings_count, "4");
    #endif

    // Reposition the buffer to start reading bindings
    buffer += 2;
    BIOP_TRACE_INDENT(1);
    for(uint16_t i = 0; i < bindings_count; ++i) {
        BIOP::Binding bind;
        if(!parse(bind, buffer)) {
            return false;
        }
        dm.bindings[i] = bind;
        buffer += bind.flat_size();
    }
    BIOP_TRACE_INDENT(-1);

    return true;

}

bool BIOP::parse(FileMessage& fm, uint8_t* buffer) {

    BIOP_TRACE_INDENT(1);
    if(!parse(fm.header, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    #ifdef BIOP_STRICT
        if(fm.header.object_kind != BIOP_ALIAS_TYPE_ID_FIL) {
            return false;
        }
    #endif

    fm.contents = buffer + fm.header.flat_size() + 4;

    return true;

}

bool BIOP::parse(ServiceGateway& srg, uint8_t* buffer) {

    BIOP_TRACE_INDENT(1);
    if(!parse(srg.header, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    #ifdef BIOP_STRICT
        if(srg.header.object_kind != BIOP_ALIAS_TYPE_ID_SRG) {
            return false;
        }
    #endif

    buffer += srg.header.flat_size();
    uint16_t bindings_count = (buffer[0] << 8) | buffer[1];
    srg.bindings.resize(bindings_count);

    #ifdef BIOP_TRACE_SERVICEGATEWAY
        BIOP_TRACE_NUM("ServiceGateway", "bindings_count", bindings_count, "4");
    #endif

    // Reposition the buffer to start reading bindings
    buffer += 2;
    BIOP_TRACE_INDENT(1);
    for(uint16_t i = 0; i < bindings_count; ++i) {
        BIOP::Binding bind;
        if(!parse(bind, buffer)) {
            return false;
        }
        srg.bindings[i] = bind;
        buffer += bind.flat_size();
    }
    BIOP_TRACE_INDENT(-1);

    return true;

}

bool BIOP::parse(StreamMessage& str, uint8_t* buffer) {

    BIOP_TRACE_INDENT(1);
    if(!parse(str.header, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    #ifdef BIOP_STRICT
        if(str.header.object_kind != BIOP_ALIAS_TYPE_ID_STR) {
            return false;
        }
    #endif

    buffer += str.header.flat_size();

    uint8_t taps_count = buffer[0];

    #ifdef BIOP_TRACE_STREAMMESSAGE
        BIOP_TRACE_NUM("StreamMessage", "taps_count", taps_count, "2");
    #endif

    if(taps_count < 1) {
        return false;
    }

    // Shift the buffer and read the one mandatory tap
    ++buffer;
    BIOP_TRACE_INDENT(1);
    if(!parse(str.tap, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

    #ifdef BIOP_STRICT
        if(str.tap.use != BIOP_PROGRAM_USE) {
            return false;
        }
    #endif    

    // Now shift are loop over all other taps to tell us what we 're missing out on
    buffer += str.tap.flat_size();

    BIOP_TRACE_INDENT(1);
    for(uint8_t i = 1; i < taps_count; ++i) {
        Tap dummy_tap;
        if(!parse(dummy_tap, buffer)) {
            return false;
        }
        buffer += dummy_tap.flat_size();
        BIOP_TRACE_GENERAL("StreamMessage", "Skipped one tap beyond the first");
    }
    BIOP_TRACE_INDENT(-1);

    return true;
}

bool BIOP::parse(StreamEventMessage& ste, uint8_t* buffer) {

    BIOP_TRACE_INDENT(1);
    if(!parse(ste.header, buffer)) {
        return false;
    }
    BIOP_TRACE_INDENT(-1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -