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

📄 dsmcc.h

📁 数字电视中间件小型库
💻 H
📖 第 1 页 / 共 3 页
字号:
#ifndef DSMCC_H#define DSMCC_H

#include <qmap.h>
#include "config.h"
#include "dsmcc_storage.h"
#include "dsmcc_biop.h"

#define DSM_CC_STRICT

// Master switch
//#define DSM_CC_TRACE_ON

// Granular tracing
#define DSM_CC_TRACE_CAROUSELTRACKER
#define DSM_CC_TRACE_DOWNLOADTRACKER
#define DSM_CC_TRACE_MODULETRACKER
#define DSM_CC_TRACE_STORAGE

// Making it work all together
#ifdef DSM_CC_TRACE_ON
#   include  <stdio.h>
#   define dsmcc_trace printf
#   define DSM_CC_TRACE_NUM(context, message, value, padto)       printf("[DSMCC::" context "] " message " = %d (0x%0" padto "x)\n", (value), (value))
#   define DSM_CC_TRACE_STR(context, message, value)              printf("[DSMCC::" context "] " message " = \"%s\"\n", (value))
#   define DSM_CC_TRACE_DUMP(context, message, buffer, length)    if(length) printf("[DSMCC::" context "] " message " dump follows:\n"); DSM_CC::Private::hexdump(buffer, length)
#   define DSM_CC_TRACE_GENERAL(context, message)                 printf("[DSMCC::" context "] " message "\n");
#else
#   define dsmcc_trace DSM_CC::sink
#   define DSM_CC_TRACE_NUM(context, message, value, padto)
#   define DSM_CC_TRACE_STR(context, message, value)
#   define DSM_CC_TRACE_DUMP(context, message, buffer, length)
#   define DSM_CC_TRACE_GENERAL(context, message)
#   undef  DSM_CC_TRACE_CAROUSELTRACKER
#   undef  DSM_CC_TRACE_DOWNLOADTRACKER
#   undef  DSM_CC_TRACE_MODULETRACKER
#   undef  DSM_CC_TRACE_STORAGE
#endif

// From the MHEG profile
#define DSM_CC_MAX_BLOCK_SIZE 4066

#ifdef CONFIG_ZLIB#include <zlib.h>#endif

namespace DSM_CC {

    namespace Private {
        void hexdump(uint8_t* buffer, uint32_t length);
    }

    // The headers for DII and DDB messages are identical,
    // but the semantics of one field changes. Luckily, the
    // data type is the same in both cases, so we can make
    // it all a union and treat it the same way everywhere.
    typedef struct {
        uint8_t protocol_discriminator;
        uint8_t dsmcc_type;
        uint16_t message_id;
        union {
            uint32_t download_id;
            uint32_t transaction_id;
        };
        uint8_t adaptation_length;
        uint16_t message_length;
        uint32_t flat_size() {
            return 12; // 11 + 1 for the reserved field which isn't shown here
        }
    } MessageHeader;

    typedef struct {
        MessageHeader header;
        uint8_t* payload_pointer;
        uint16_t module_id;
        uint8_t  module_version;
        uint16_t block_number;
        uint16_t payload_size;
    } DownloadDataBlock;

    typedef struct {
        MessageHeader header;
        uint32_t download_id;
        uint16_t block_size;
        uint16_t num_modules;
        uint32_t flat_size() {
            return header.flat_size() + 20;
        }
    } DownloadInfoIndication;

    typedef struct {
        uint16_t module_id;
        uint8_t  module_version;
        uint32_t module_size;
        uint32_t num_blocks;
        uint16_t block_size;
        uint8_t  z_compression_method;
        uint32_t z_original_size;
    } tracked_module_t;

    class ModuleTracker {
        public:
            ModuleTracker();
            ~ModuleTracker();

            bool InterestedInObject(uint32_t object_key, uint8_t object_key_length);
            void MarkObject(uint32_t object_key, uint8_t object_key_length, bool mark);

            void SetParameters(const tracked_module_t& module);
            bool HaveParameters() const {return have_module_info;}
            tracked_module_t GetParameters() const {return tracked_module;}

            bool ProcessDDB(const DownloadDataBlock& block);
            bool Completed() const {return have_module_info && (received_blocks_count == tracked_module.num_blocks);}
            
            uint8_t* Buffer() {return contents;}

        private:
            // Disabled
            ModuleTracker(const ModuleTracker&);
            ModuleTracker& operator = (const ModuleTracker&);

            // Data
            bool             have_module_info;
            tracked_module_t tracked_module;
            uint32_t         received_blocks_count;
            uint32_t*        received_blocks;
            uint8_t*         contents;
            std::vector<uint64_t> interesting_objects;
    };

    class DownloadTracker {
        public:
            DownloadTracker(uint32_t id);
            ~DownloadTracker();

            bool TrackModule(uint16_t module_id);
            bool UntrackModule(uint16_t module_id);

            bool ProcessDDB(const DownloadDataBlock& block);
            bool ProcessDII(const DownloadInfoIndication& indication, const BIOP::DIIModuleLoopItem& mitem);

            bool Completed() const {return num_modules_tracked == num_modules_completed;}
            bool CompletedModule(uint16_t module_id) const {return module_trackers.contains(module_id) && module_trackers[module_id]->Completed();}

            uint8_t* ModuleGetBuffer(uint16_t module_id) const {return CompletedModule(module_id) ? module_trackers[module_id]->Buffer() : 0;}
            bool ModuleHaveParameters(uint16_t module_id) const {return module_trackers.contains(module_id) ? module_trackers[module_id]->HaveParameters() : false;}
            tracked_module_t ModuleGetParameters(uint16_t module_id) const {return module_trackers.contains(module_id) ? module_trackers[module_id]->GetParameters() : tracked_module_t();}
            bool ModuleSetParameters(const tracked_module_t& module);

            void MarkObject(uint16_t module_id, uint32_t object_key, uint8_t object_key_length, bool mark);
            bool InterestedInObject(uint16_t module_id, uint32_t object_key, uint8_t key_length);

        private:
            // Disabled
            DownloadTracker();
            DownloadTracker(const ModuleTracker&);
            DownloadTracker& operator = (const ModuleTracker&);

            typedef QMap<uint16_t, ModuleTracker*> module_tracker_map;

            // Data
            uint32_t download_id;
            uint16_t num_modules_tracked;
            uint16_t num_modules_completed;
            module_tracker_map module_trackers;
            uint32_t allocated_memory;
    };

    class DownloadControlTracker {
        public:
            void SetStatus(uint32_t transaction_id, uint8_t status) {
                uint16_t id      = (transaction_id & 0xffff) | 1;
                uint16_t version = (transaction_id & 0xffff0000) >> 16;
                tr_id_info_t info = {version, status};
                transaction_ids[id] = info;
            }

            uint8_t GetStatus(uint32_t transaction_id) {
                uint16_t id = (transaction_id & 0xffff) | 1;

                if(!transaction_ids.contains(id)) {
                    return BIOP::UNKNOWN;
                }

                return transaction_ids[id].status;
            }

            uint16_t GetVersion(uint32_t transaction_id) {
                uint16_t id = (transaction_id & 0xffff) | 1;

                if(!transaction_ids.contains(id)) {
                    return 0;
                }

                return transaction_ids[id].version;
            }

        private:
            typedef struct tr_id_info {
                uint16_t  version; // 2 MSB of transaction_id
                uint8_t   status;  // are we interested in it or what?
            } tr_id_info_t;

            typedef QMap<uint16_t, tr_id_info_t> tr_id_info_map;

            tr_id_info_map transaction_ids;
    };

    template<class StoragePolicy>
    class CarouselTracker : public StoragePolicy {
        public:
            CarouselTracker() : data_message_trackers(new uint8_t[256]) {
                if(data_message_trackers == 0) throw std::exception(); memset(data_message_trackers, BIOP::UNKNOWN, 256);
            }
            ~CarouselTracker() {
                typename download_tracker_map::const_iterator i;
                for (i = download_trackers.begin(); i != download_trackers.end(); ++i) {
                    delete download_trackers[i.key()];
                }
            
                delete[] data_message_trackers;
            }

            void Clear() {                typename download_tracker_map::const_iterator i;
                for (i = download_trackers.begin(); i != download_trackers.end(); ++i) {
                    delete download_trackers[i.key()];
                }                download_trackers.clear();                download_stats.clear();                memset(data_message_trackers, BIOP::UNKNOWN, 256);            }

            bool CompletedDownload(uint32_t download_id) const {return download_trackers.contains(download_id) && download_trackers[download_id]->Completed();}
            bool CompletedModule(uint32_t download_id, uint16_t module_id) const {return download_trackers.contains(download_id) && download_trackers[download_id]->CompletedModule(module_id);}

            bool ProcessDownloadData(uint8_t component_tag, uint16_t table_id_ext, uint8_t* buffer) {
                (void) table_id_ext;
                // DDB messages are different from download control messages: they carry no transaction_id,                // because only DDB messages from a single carousel may be present on the same stream.                            // Therefore, we shall just check if the stream we are receiving the DDB message from                // contains data from a carousel we are interested in before trying to parse the DDB.                            if(!InterestedInDownloadData(component_tag)) {                    return true;                }                            DownloadDataBlock datablock;                if(!parse(datablock, buffer)) {                    return false;                }                            if(!ProcessDDB(component_tag, datablock)) {                    return false;                }

                return true;
            }
            bool ProcessDownloadControl(uint8_t component_tag, uint16_t table_id_ext, uint8_t* buffer) {

                MessageHeader header;                parse(header, buffer);

                // If this is not an ISO/IEC 13818-6 IS download message, no go
                if(header.dsmcc_type != 0x03) {
                    return false;
                }

                // First of all, check if the transaction_id of this message could contain                // anything we are interested in. Otherwise, no point in processing further.
                if(!InterestedInDownloadControl(component_tag, header.transaction_id)) {                    return true;                }

                switch(header.message_id) {                    case 0x1002:            // DownloadInfoIndication
                        DownloadInfoIndication dii;                        if(!parse(dii, buffer)) {
                            return false;                        }    
                        // Reposition buffer to read groupinfo structures                        buffer += dii.flat_size();                            BIOP::DIIModuleLoopItem mitem;                        for(uint16_t i = 0; i < dii.num_modules; ++i) {                            if(!parse(mitem, buffer)) {
                                return false;                            }                            buffer += (8 + mitem.module_info_length);
                            if(!ProcessDII(component_tag, dii, mitem)) {
                                return false;
                            }                        }                        break;                       case 0x1006:            // DownloadServerInitiate                            // We should do a little parsing here, mainly to decide if this message                        // belongs to a Data Carousel or an Object Carousel. Otherwise, some of                        // this could be moved into BIOP::parse(ServiceGatewayInfo&, uint_8t*)    

⌨️ 快捷键说明

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