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

📄 dsmcc_biop.h

📁 数字电视中间件小型库
💻 H
字号:
#ifndef DSMCC_BIOP_H#define DSMCC_BIOP_H

#include "../libavcodec/common.h"

#define BIOP_STRICT

// Master switch
// #define BIOP_TRACE_ON

// Granular tracing
//#define BIOP_TRACE_DIIMODULELOOPITEM
//#define BIOP_TRACE_DIRECTORYMESSAGE
#define BIOP_TRACE_STREAMMESSAGE
#define BIOP_TRACE_STREAMEVENTMESSAGE
#define BIOP_TRACE_MESSAGEHEADER
//#define BIOP_TRACE_BINDING
//#define BIOP_TRACE_SERVICECONTEXT
#define BIOP_TRACE_NAME
//#define BIOP_TRACE_IOR
//#define BIOP_TRACE_TAP
//#define BIOP_TRACE_BIOPPROFILE
//#define BIOP_TRACE_OBJECTLOCATIONCOMPONENT
//#define BIOP_TRACE_CONNBINDERCOMPONENT
//#define BIOP_TRACE_SERVICEGATEWAYINFO

// Making it work all together
#ifdef BIOP_TRACE_ON
#   define BIOP_TRACE_INDENT(num)                               if(BIOP::Private::traceindent + num >= 0) BIOP::Private::traceindent += num
#   define BIOP_TRACE_THRESHOLD(num)                            BIOP::Private::tracethreshold = num
#   define BIOP_TRACE_NUM(context, message, value, padto)       if(BIOP::Private::traceindent <= BIOP::Private::tracethreshold) { \
                                                                    for(int indt = 0; indt < BIOP::Private::traceindent; ++indt) printf("  "); printf("[BIOP::" context "] " message " = %d (0x%0" padto "x)\n", (value), (value)); \
                                                                }
#   define BIOP_TRACE_STR(context, message, value)              if(BIOP::Private::traceindent <= BIOP::Private::tracethreshold) { \
                                                                    for(int indt = 0; indt < BIOP::Private::traceindent; ++indt) printf("  "); printf("[BIOP::" context "] " message " = \"%s\"\n", (value)); \
                                                                }
#   define BIOP_TRACE_DUMP(context, message, buffer, length)    if(BIOP::Private::traceindent <= BIOP::Private::tracethreshold) { \
                                                                    for(int indt = 0; indt < BIOP::Private::traceindent; ++indt) printf("  "); if(length) printf("[BIOP::" context "] " message " dump follows:\n"); DSM_CC::Private::hexdump(buffer, length); \
                                                                }
#   define BIOP_TRACE_GENERAL(context, message)                 if(BIOP::Private::traceindent <= BIOP::Private::tracethreshold) { \
                                                                    for(int indt = 0; indt < BIOP::Private::traceindent; ++indt) printf("  "); printf("[BIOP::" context "] " message "\n"); \
                                                                }
#else
#   define BIOP_TRACE_INDENT(num)
#   define BIOP_TRACE_THRESHOLD(num) 
#   define BIOP_TRACE_NUM(context, message, value, padto)
#   define BIOP_TRACE_STR(context, message, value)
#   define BIOP_TRACE_DUMP(context, message, buffer, length)
#   define BIOP_TRACE_GENERAL(context, message)
#   undef BIOP_TRACE_DIIMODULELOOPITEM
#   undef BIOP_TRACE_DIRECTORYMESSAGE
#   undef BIOP_TRACE_STREAMMESSAGE
#   undef BIOP_TRACE_STREAMEVENTMESSAGE
#   undef BIOP_TRACE_MESSAGEHEADER
#   undef BIOP_TRACE_BINDING
#   undef BIOP_TRACE_SERVICECONTEXT
#   undef BIOP_TRACE_NAME
#   undef BIOP_TRACE_IOR
#   undef BIOP_TRACE_TAP
#   undef BIOP_TRACE_BIOPPROFILE
#   undef BIOP_TRACE_OBJECTLOCATIONCOMPONENT
#   undef BIOP_TRACE_CONNBINDERCOMPONENT
#   undef BIOP_TRACE_SERVICEGATEWAYINFO
#endif

#define BIOP_DELIVERY_PARA_USE  0x0016
#define BIOP_OBJECT_USE         0x0017
#define BIOP_PROGRAM_USE        0x0019
#define BIOP_MAGIC_BIOP         0x42494f50
#define BIOP_ALIAS_TYPE_ID_SRG  0x73726700
#define BIOP_ALIAS_TYPE_ID_DIR  0x64697200
#define BIOP_ALIAS_TYPE_ID_FIL  0x66696c00
#define BIOP_ALIAS_TYPE_ID_STR  0x73747200
#define BIOP_ALIAS_TYPE_ID_STE  0x73746500

#define BIOP_PROFILE_ID_BIOP        0x49534f06
#define BIOP_PROFILE_ID_LITEOPTIONS 0x49534f05

#define BIOP_COMPONENT_ID_CONNBIND  0x49534f40
#define BIOP_COMPONENT_ID_OBJECTLOC 0x49534f50

#include <exception>
#include <numeric>      // for flat_size magic tricks with std::accumulate
#include <vector>

namespace BIOP {

    // Used for tracing
    namespace Private {
        // To keep track of trace output indentation
        static int traceindent    = 0;
        static int tracethreshold = 100;
    }

    template<class T> uint32_t add_flat_size(int sum, T flat_object);

    typedef struct {
        uint16_t type;
        uint32_t transaction_id;
        uint32_t timeout;
    } TapSelector;

    typedef struct {
        uint16_t    use;
        uint16_t    assoc_tag;
        uint8_t     selector_length;
        TapSelector selector; // At most one selector allowed and a very specific at that (TR 101 202 p32)
        uint32_t    flat_size() {return 7 + selector_length;} // Consequence of the above
    } Tap;

    typedef struct {
        uint32_t id_tag;
        uint8_t  data_length;
        uint32_t carousel_id;
        uint16_t module_id;
        uint8_t  version_major;
        uint8_t  version_minor;

        // About object_key:
        // TR 101 202 repeatedly states that object_key will not exceed 4 bytes. Therefore, it is
        // fast and ultra convenient to keep this as a length and a 32-bit integer key.
        uint8_t  object_key_length;
        uint32_t object_key;
    } ObjectLocationComponent;

    typedef struct {
        uint32_t   id_tag;
        uint8_t    data_length;

        // Altough theoretically there can be more taps than one, the standard does not clearly define
        // what the presence of these taps means. Therefore, it's perfectly justified to only retain the
        // first tap and a count of the total number of taps in this general-purpose decoder. It's faster
        // than involving a std::vector<Tap> which would contain at most one element.
        uint8_t    network_taps_count;
        Tap        network_tap;
    } ConnBinderComponent;

    typedef struct {
        uint32_t data_length;
        uint8_t small_endian;
        uint8_t component_count;
        ObjectLocationComponent object_location;
        ConnBinderComponent     conn_binder;

        uint32_t flat_size() {
            return 8 + data_length;
        }
    } BIOPProfile;
    
    typedef struct {
        /*
        uint32_t data_length;
        uint8_t small_endian;
        uint8_t component_count;
        ObjectLocationComponent object_location;
        ConnBinderComponent     conn_binder;
        */
        uint32_t flat_size() {
            return 0;
            //return 8 + data_length;
        }
    } LiteOptionsProfile;

    typedef struct {
        uint32_t id_tag;
        union {
            BIOPProfile biop;
            LiteOptionsProfile lite;
        };

        uint32_t flat_size() {
            switch(id_tag) {
                case BIOP_PROFILE_ID_BIOP:
                    return biop.flat_size();
                case BIOP_PROFILE_ID_LITEOPTIONS:
                    return lite.flat_size();
                default:
                    return 0;
            }
        }
    } Profile;

    typedef struct {
        // TR 101 202 p31 states that only alias_type_id values will be used for the type_id field
        // here. These values are all null-terminated strings of length 3 (plus the term character).
        // It's therefore both faster and more convenient here to hold the value in a straight
        // array rather than a std::vector<uint8_t>.
        uint8_t type_id[4];
        std::vector<Profile> profiles;
            
        uint32_t flat_size() {
            // With the type_id optimization, this is:
            return std::accumulate(profiles.begin(), profiles.end(), 12, add_flat_size<Profile>);

            // If we used a vector for the type_id, and consequently had to deal with CDR alignment:
            //uint8_t  padding = (type_id.size() % 4 ? 4 - (type_id.size() % 4) : 0);
            //return std::accumulate(profiles.begin(), profiles.end(), 8 + type_id.size() + padding, add_flat_size<Profile>);
        }
    } IOR;

    typedef struct {
        IOR ior;

        // The semantics of the Taps field in IOP::IOR is not defined (TR 101 202 p44), therefore
        // we a) don't expect to find any in a general-public broadcast scenario and b) wouldn't
        // know what to do if we did find one. Thus we save the number of taps found, and totally
        // skip the taps themselves.
        uint8_t download_taps_count;

        // Same goes for the ServiceContextList, so just save the number here.
        uint8_t service_context_list_count;

        // Finally: the standard says that the user_info field shall be a descriptor loop, but it
        // does NOT say what these descriptors mean (if present). Go with the above approach again.
        uint8_t user_info_length;
    } ServiceGatewayInfo;

    typedef struct {
        uint32_t module_timeout;
        uint32_t block_timeout;
        uint32_t min_block_time;
        uint8_t  taps_count;
        Tap      tap; // one expected
        uint8_t  user_info_length;

        // Support for compressed module descriptor, demanded by the MHP profile
        uint8_t  z_compression_method;
        uint32_t z_original_size;
    } ModuleInfo;

    typedef struct {
        uint16_t   module_id;        uint32_t   module_size;        uint8_t    module_version;        uint8_t    module_info_length;
        ModuleInfo module_info;
    } DIIModuleLoopItem;
    
    typedef std::vector<uint8_t> uint8_vector;

    typedef struct {
        uint32_t     id;
        uint8_vector data;
        uint32_t flat_size() {return 6 + data.size();}
    } ServiceContext;

    typedef std::vector<ServiceContext> ServiceContext_vector;

    // This would be an std::vector<NameComponent> normally, however TR 101 202
    // states that the number of NameComponents shall always be 1. Therefore
    // some simplification of the implementation is in order.
    typedef struct {
        uint8_vector id;
        uint8_vector kind;
    	uint32_t flat_size() {return 3 + id.size() + kind.size(); }
    } Name;

    typedef struct {
        Name    name;
        uint8_t type;
        IOR     ior;
        uint8_vector object_info;
        uint32_t flat_size() {return name.flat_size() + 1 + ior.flat_size() + 2 + object_info.size();}
    } Binding;

    typedef struct {
        uint32_t     magic;
        uint8_t      biop_version_major;
        uint8_t      biop_version_minor;
        uint8_t      byte_order;
        uint8_t      message_type;
        uint32_t     message_size;
        uint8_vector object_key;
        // Convenience optimization: we know that object_kind is required to be exactly
        // 4 bytes, so store it as a scalar instead of an array for easy access
        uint32_t     object_kind;
        uint8_vector object_info;
        ServiceContext_vector service_context_list;
        uint32_t     message_body_length;
        uint32_t flat_size() {
            return std::accumulate(service_context_list.begin(), service_context_list.end(),
                 28 + object_key.size() + object_info.size() + service_context_list.size(), add_flat_size<ServiceContext>);
        }
    } MessageHeader;

    typedef struct {
        MessageHeader header;
        std::vector<Binding> bindings;
        static const uint32_t type_id_alias = BIOP_ALIAS_TYPE_ID_SRG;
        uint32_t flat_size() { return header.flat_size() + header.message_body_length;}
    } ServiceGateway;

    typedef struct {
        MessageHeader header;
        std::vector<Binding> bindings;
        static const uint32_t type_id_alias = BIOP_ALIAS_TYPE_ID_DIR;
        uint32_t flat_size() { return header.flat_size() + header.message_body_length;}
    } DirectoryMessage;

    typedef struct {
        MessageHeader header;
        // The contents of the file are not stored inside, because
        // that would lead to excessive and unnecessary copying.
        // A simple pointer to a buffer where the contents are placed
        // is sufficient. Of course, this means "handle with care".
        uint8_t*      contents;
        static const uint32_t type_id_alias = BIOP_ALIAS_TYPE_ID_FIL;
        uint32_t flat_size() { return header.flat_size() + header.message_body_length;}
    } FileMessage;

    typedef struct {
        // The DTG MHEG profile says that there will be one tap of use
        // BIOP_PROGRAM_USE, and other types of taps may be skipped.
        MessageHeader header;
        Tap tap;
        uint32_t flat_size() { return header.flat_size() + header.message_body_length;}
    } StreamMessage;

    typedef struct {
        // The DTG MHEG profile says that there will be one tap of use
        // BIOP_PROGRAM_USE, and other types of taps may be skipped.
        MessageHeader header;
        std::vector<uint16_t>    event_ids;
        std::vector<std::string> event_names;
        Tap tap;
        uint32_t flat_size() { return header.flat_size() + header.message_body_length;}
    } StreamEventMessage;

    bool parse(ObjectLocationComponent& object_location, uint8_t* buffer);
    bool parse(ConnBinderComponent& conn_binder, uint8_t* buffer);
    bool parse(ServiceGatewayInfo& sgi, uint8_t* buffer);
    bool parse(DIIModuleLoopItem& module, uint8_t* buffer);
    bool parse(ModuleInfo& mi, uint8_t* buffer);
    bool parse(ServiceContext& sc, uint8_t* buffer);
    bool parse(Binding& bind, uint8_t* buffer);
    bool parse(Name& name, uint8_t* buffer);
    bool parse(IOR& ior, uint8_t* buffer);
    bool parse(BIOPProfile& prof, uint8_t* buffer);
    bool parse(LiteOptionsProfile& prof, uint8_t* buffer);
    bool parse(MessageHeader& header, uint8_t* buffer);
    bool parse(ServiceGateway& srg, uint8_t* buffer);
    bool parse(DirectoryMessage& dir, uint8_t* buffer);
    bool parse(FileMessage& fil, uint8_t* buffer);
    bool parse(StreamMessage& str, uint8_t* buffer);
    bool parse(StreamEventMessage& ste, uint8_t* buffer);
    bool parse(Tap& tap, uint8_t* buffer);

    enum ObjectStatus {
        AVAILABLE = 1,
        REQUESTED,
        UNKNOWN
    };


}

#endif // DSMCC_BIOP_H

⌨️ 快捷键说明

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