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

📄 dsmcc.h

📁 数字电视中间件小型库
💻 H
📖 第 1 页 / 共 3 页
字号:
                if(!download_trackers.contains(profile.object_location.carousel_id)) {

                    #ifdef DSM_CC_TRACE_CAROUSELTRACKER
                        DSM_CC_TRACE_NUM("CarouselTracker", "DSI received for previously unknown download_id", profile.object_location.carousel_id, "8");
                    #endif

                    #ifdef DSM_CC_STRICT
                        if(profile.conn_binder.network_tap.selector_length == 0) {
                            DSM_CC_TRACE_GENERAL("CarouselTracker", "ERROR: IOR pointing to SRG: tap does not define a transaction_id!");
                            return false;
                        }
                    #endif

                    // Start tracking this download                
                    if(!Track(profile.object_location.carousel_id, table_id_ext)) {
                        return false;
                    }

                    // Now, start tracking the module which contains the service gateway
                    if(!download_trackers[profile.object_location.carousel_id]->TrackModule(profile.object_location.module_id)) {
                        return false;
                    }

                    #ifdef DSM_CC_TRACE_CAROUSELTRACKER
                        DSM_CC_TRACE_NUM("CarouselTracker", "Signalling we 're interested in the SRG, transaction_id", profile.conn_binder.network_tap.selector.transaction_id, "8");
                    #endif

                    // Note down that we want to receive the download control messages containing the DII
                    RequestDownloadControl(component_tag, profile.conn_binder.network_tap.selector.transaction_id);

                    // Note down that when the DII has been received, enabling us to get the data blocks, and
                    // the data blocks are received and examined, we are interested in the service gateway object
                    MarkObject(profile.object_location.carousel_id,
                               profile.object_location.module_id,
                               profile.object_location.object_key,
                               profile.object_location.object_key_length,
                               true);

                    return true;        
                }

/*
printf("For this carousel, we have requested %d objects. %d total have arrived, %d premature.\n", 
    download_stats[profile.object_location.carousel_id].objects_requested, 
    download_stats[profile.object_location.carousel_id].objects_arrived,
    download_stats[profile.object_location.carousel_id].objects_premature
);
*/

                // OK, we already have this download_id, maybe the carousel has been updated?
                // Remember, every time the carousel is updated, table_id_ext toggles between 0x0000 and 0x0001
                if(download_stats[profile.object_location.carousel_id].last_table_id_ext != table_id_ext) {
                    dsmcc_trace("[CarouselTracker] Updated DSI received for download_id = 0x%08x\n", profile.object_location.carousel_id);
                    return Reset(profile.object_location.carousel_id, table_id_ext);
                }
            
                return true;
            }

            bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::ServiceGateway& srg) {
                if(download_stats.contains(download_id)) {
                    ++download_stats[download_id].objects_arrived;
                }

                if(!InterestedInObject(download_id, module_id, srg.header)) {
                    ++download_stats[download_id].objects_premature;
                    return false;
                }

                tracked_module_t module = ModuleGetParameters(download_id, module_id);

                // Commit to permanent storage
                if(!StoreObject(download_id, module_id, module.module_version, srg)) {
                    return false;
                }

                uint32_t num_bindings = srg.bindings.size();

                for(uint32_t i = 0; i < num_bindings; ++i) {
                    if(srg.bindings[i].ior.profiles[0].id_tag != BIOP_PROFILE_ID_BIOP) {
                        continue;
                    }
                    BIOP::BIOPProfile profile = srg.bindings[i].ior.profiles[0].biop;
                    // We have to:
                    // 1. Signal we want to receive transaction_ids for the messages describing the module containing this object
                    // 2. Start tracking this module, if we aren't already tracking it
                    // 3. Mark the object at the end of the module as interesting
                    
                    RequestDownloadControl(profile.conn_binder.network_tap.assoc_tag, profile.conn_binder.network_tap.selector.transaction_id);
                    download_trackers[profile.object_location.carousel_id]->TrackModule(profile.object_location.module_id);
                    MarkObject(profile.object_location.carousel_id,
                               profile.object_location.module_id,
                               profile.object_location.object_key,
                               profile.object_location.object_key_length,
                               true);
                }

                download_stats[download_id].objects_requested += num_bindings;
                
                return true;
            }

            bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::DirectoryMessage& dm) {
                if(download_stats.contains(download_id)) {
                    ++download_stats[download_id].objects_arrived;
                }

                if(!InterestedInObject(download_id, module_id, dm.header)) {
                    ++download_stats[download_id].objects_premature;
                    return false;
                }

                uint32_t num_bindings = dm.bindings.size();

                tracked_module_t module = ModuleGetParameters(download_id, module_id);

                // Commit to permanent storage
                if(!StoreObject(download_id, module_id, module.module_version, dm)) {
                    return false;
                }

                // Same story as with ServiceGateway
                for(uint32_t i = 0; i < num_bindings; ++i) {
                    if(dm.bindings[i].ior.profiles[0].id_tag != BIOP_PROFILE_ID_BIOP) {
                        continue;
                    }
                    BIOP::BIOPProfile profile = dm.bindings[i].ior.profiles[0].biop;
                    // We have to:
                    // 1. Signal we want to receive transaction_ids for the messages describing the module containing this object
                    // 2. Start tracking this module, if we aren't already tracking it
                    // 3. Mark the object at the end of the module as interesting
                    
                    RequestDownloadControl(profile.conn_binder.network_tap.assoc_tag, profile.conn_binder.network_tap.selector.transaction_id);
                    download_trackers[profile.object_location.carousel_id]->TrackModule(profile.object_location.module_id);
                    MarkObject(profile.object_location.carousel_id,
                               profile.object_location.module_id,
                               profile.object_location.object_key,
                               profile.object_location.object_key_length,
                               true);
                }

                download_stats[download_id].objects_requested += num_bindings;

                return true;
            }

            bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::FileMessage& fm) {
                if(download_stats.contains(download_id)) {
                    ++download_stats[download_id].objects_arrived;
                }

                if(!InterestedInObject(download_id, module_id, fm.header)) {
                    ++download_stats[download_id].objects_premature;
                    return false;
                }

                tracked_module_t module = ModuleGetParameters(download_id, module_id);

                // Commit to permanent storage
                return StoreObject(download_id, module_id, module.module_version, fm);
            }


            bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::StreamMessage& str) {
                return false;
            }

            bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::StreamEventMessage& ste) {
                return false;
            }

            void RequestDownloadControl(uint8_t component_tag, uint32_t tr_id) {
                // We 're going to call MarkDownloadControl, but first cut off
                // the "version" part of the transaction_id. This way, when we
                // receive the first DII message it is guaranteed to have a
                // different version field than 0x0000 and it will be accepted.
                MarkDownloadControl(component_tag, tr_id & 0xffff, BIOP::REQUESTED);
            }

            void MarkObject(uint32_t download_id, uint16_t module_id, uint32_t object_key, uint8_t object_key_length, bool mark) {
                if(!download_trackers.contains(download_id)) {
                    return;
                }
            
                download_trackers[download_id]->MarkObject(module_id, object_key, object_key_length, mark);
            }

            void MarkDownloadControl(uint8_t component_tag, uint32_t tr_id, BIOP::ObjectStatus status) {
                #ifdef DSM_CC_TRACE_CAROUSELTRACKER
                    //printf("[DSMCC::CarouselTracker] Marking download control message: assoc_tag = 0x%02x, transaction_id = 0x%08x, status = %d\n", component_tag, tr_id, status);
                #endif

                control_message_trackers[component_tag].SetStatus(tr_id, status);
            }

            void MarkDownloadData(uint8_t component_tag, BIOP::ObjectStatus status) {
                if(data_message_trackers[component_tag] == BIOP::UNKNOWN && status != BIOP::UNKNOWN) {
                    streams_needed.push_back(component_tag);
                }

                data_message_trackers[component_tag] = status;
                
            }

            bool InterestedInDownloadControl(uint8_t component_tag, uint32_t tr_id) {
                // First off, the two LSBs are the identification. We don't want our
                // identification to be foiled by the value of the very last bit
                // (update flag), so set that to 1 to make the equality checks easier.
                uint16_t id      = (tr_id & 0xffff) | 1;

                // The two MSBs are versioning
                uint16_t version = (tr_id & 0xffff0000) >> 16;

                if(id == 0x0001) {
                    // Always interested in DSI messages to catch carousel updates
                    return true;
                }

                if(!control_message_trackers.contains(component_tag)) {
                    // Nothing wanted with this component tag
                    return false;
                }

                if(control_message_trackers[component_tag].GetVersion(tr_id) == version) {
                    // Old news
                    return false;
                }

                return control_message_trackers[component_tag].GetStatus(tr_id) != BIOP::UNKNOWN;
            }

            bool InterestedInDownloadData(uint8_t component_tag) {
                return data_message_trackers[component_tag] != BIOP::UNKNOWN;
            }

            bool InterestedInObject(uint32_t download_id, uint16_t module_id, uint32_t object_key, uint8_t key_length) {
                if(!download_trackers.contains(download_id)) {
                    return false;
                }
            
                return download_trackers[download_id]->InterestedInObject(module_id, object_key, key_length);
            }

            bool InterestedInObject(uint32_t download_id, uint16_t module_id, const BIOP::MessageHeader& header) {
                uint32_t object_key(0);                uint8_t  key_size(header.object_key.size());                                // Hand-crafted for loop; I couldn't bring myself to loop for this triviality                object_key |= (header.object_key[0] << 24);                if(key_size > 1) object_key |= (header.object_key[1] << 16);                if(key_size > 2) object_key |= (header.object_key[2] << 8);                if(key_size > 3) object_key |= header.object_key[3];
                return InterestedInObject(download_id, module_id, object_key, key_size);
            }

        private:

            typedef struct download_stats {
                uint16_t last_table_id_ext;
                uint32_t objects_requested;
                uint32_t objects_arrived;
                uint32_t objects_premature;
                download_stats() : objects_requested(0), objects_arrived(0), objects_premature(0) {}
            } download_stats_t;

            // This holds the download trackers themselves, indexed by download_id
            typedef QMap<uint32_t, DownloadTracker*>       download_tracker_map;
            download_tracker_map download_trackers;

            // This holds information pertinent to the state of each download tracker,
            // even though we could do without it (it's not necessary for correct
            // operation), indexed by download_id
            typedef QMap<uint32_t, download_stats_t>        download_stats_map;
            download_stats_map download_stats;

            // This holds information about the download control messages (DIIs)
            // that we are interested in receiving (or not). A message won't get
            // forwarded to a download tracker unless the DownloadMessageTracker
            // thinks it's interesting. This is done mainly to avoid the extra
            // overhead of parsing messages that are of no use to us.
            // Indexed by stream component_tag.
            typedef QMap<uint8_t,  DownloadControlTracker> download_control_map;
            download_control_map control_message_trackers;

            // This would do the same for DDB messages, however DDB messages have
            // to be parsed before we can know if we 're interested in them. So
            // this takes the form of an array indexed by component_tag, telling
            // us if we should be bothering with DDBs from that stream at all.
            uint8_t* data_message_trackers;

            // An array to hold identification for the streams we need to start
            // receiving. Presently just component_tag. Not a stack because
            // std::stack is just a container adapter anyway.
            std::vector<uint8_t> streams_needed;
    };

    bool parse(DownloadDataBlock& block, uint8_t* buffer);
    bool parse(DownloadInfoIndication& dii, uint8_t* buffer);
    bool parse(MessageHeader& header, uint8_t* buffer);
    void sink(...); // used to sink printf() args when trace is turned off
}

#endif // DSMCC_H

⌨️ 快捷键说明

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