📄 dsmcc_biop.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 + -