• 沒有找到結果。

4. 系統架構設計與實作

4.3. DSM-CC

Transport Stream 的 packets 經過 TS Parser 的處理之後,會產生一個個的 sections,然後送給 Section Filter 處理,轉成 blocks 之後,透過 table_id 及 table_id_extension 這兩個欄位來判斷它們是屬於 DSI、DII、DDB 中哪一種類型 的資料並送給相對應的 Decoder 處理。

DDB blocks 的資料,會根據 DII block 當中所記錄的資訊重新組合成為 modules,最後再透過BIOP Decoder轉回原本的資料並儲存到記憶體當中。

DSM-CC的執行流程大致上如Figure 46所示。

Figure 46. Block diagram of DSM-CC

因為所有跟 modules 相關的資訊都記錄在 DII 當中,所以要等到我們處理過 DII section 之後,才能有效率的判斷這一個 DDB 是否已經有效率的處理過。又 因為每一個 service 都只會有一個相對應的 DII section,所以我們只需要處理一次 就可以了。對此,我們特別設置了 diiFlag 以及 ddbFlag 兩個旗幟。

1) diiFlag:因為每一個 service 都只會有一個 DII,所以利用 diiFlag 來判 斷是不是已經處理過 DII section 了,如果 diiFlag = true,則我們可以直 接把之後收到的 DII section 略過,以節省處理時間。

2) ddbFlag:若 ddbFlag = false 的話,代表我們還沒有收到 DII,這時就算 解出了 DDB,也很難去記錄我們已經處理過哪些 modules 的哪些 blocks。所以在處理 DII 之前,我們把 ddbFlag 設為 false,並且略過在 此時收到的所有 DDB sections。

在處理過DII section之後,我們可以取得block size,number of modules,

module ID,跟module size這幾個資訊。利用moduke size

/ block size,我們可以知道每一 個module當中有幾個blocks,並依此建立起moduleTable跟blockCount這兩個table。

1) moduleTable:第一個欄位是moduleId,後面的欄位數則跟block number一樣。當我們收到一個DDB之後,解出它的moduleId跟 blockNumber之後,就可以到moduleTable作比對判斷這個DDB是不 是已經處理過了。如果還沒處理,才儲存起來,並且把它相對應的 欄位設為true,否則就直接略過。moduleTable如Figure 47所示。

2) blockCount:第一個欄位也是 moduleId,第二個欄位則是一個 counter,記錄了這一個 module 所包含的 blocks 的數量,當我們每 收到這個 module 的一個 DDB,比對過它是還沒處理過的,就處理 它,然後把這個 module 相對的 counter - 1,直到 counter = 0 時,

我們就知道這個 module 所有的 block 都已經收到了,就可以送給 下一個 Decoder 處理。

Figure 47. Example of Module Table

每當我們收到一個block,就把它的moduleId、blockNumber、data這三項存 到我們自己的資料結構DataRecord當中,如Figure 48所示,並且把blockCount中 相對應的counter – 1。

當counter = 0 時,我們知道這個欄位相對應的module已經全部收到了,這時

我們會再呼叫另外一個我們自己的資料結構MDSComparator,如Figure 49所示,

它會對相同moduleId的所有bolck的blockNumber作排序,然後我們再依序從陣列 當中,把屬於我們需要的module的每一筆資料抓出來儲存,就可以得到一個完整 的module了。

Figure 48. My Data Structure:DataRecord

Figure 49. My Data Structure:MDSComparator

每當我們收到一個完整的 module 之後,就可以把它送給 BIOP Decoder 處 理,而 BIOP Decoder 再根據收到的是哪一種類型的資料,分別呼叫不同的 decoder 作處理。

如果收到的是Srg的話,那就把旗標isSrg設為true,然後呼叫BIOP DirMessage Decoder,如果是dir的話,那就把旗標isSrg設為false,然後呼叫BIOP DirMessage Decoder 。 而 BIOP DirMessage Decoder 會 處 理 整 個 資 料 的 內 容 , 並 且 把

objectKeyDataByte的內容,還有這個資料結構中所包含的所有資料的name、

type、profileObjectKeyDataByte存進我們自己的FileNode資料結構當中。FileNode 的結構如Figure 50所示。

如果收到的是 Fil 的話,先把目前已經收到並記錄的 FileNode List(fnList)轉 成陣列(treeArray),再分成兩個步驟。第一步是重新建立目前已經收到的節點的 objectKeyDataBye 比較。如果相同的話,表示 treeArray 中的 這一項就是這個子節點。

2) 如果這個子結點的類型是資料夾的話,那我們就找出由根節點到這 個子結點的路徑,然後把資料夾建立。如果子結點的類型是檔案的 話,就先到去檢查它的資料是不是已經在 missingList 當中,如果 是的話,就建立檔案然後把它的資料從 missingLsit 中搬過來。

以上步驟重覆到 queue 中已經沒有資料為止。

此外,BIOP FileMessage Decoder 在處理一筆資料時,會先去檢查目前 fnList 中所有的檔案結點中,是否有結點的 profileObjectKeyDataBye 和這份資料的 objectKeyDataBye 相同。如果有的話,就把資料存進這個檔案當中;如果沒有的

話,那就用這個結點的 objectKeyDataBye 作為檔名建立 tempFile,然後把檔案丟 進 missingList 當中。

BIOP的執行流程如Figure 51所示。

class FileNode {

protected boolean isSRG;

protected int objectKey;

protected int type;

protected String name;

protected int bindingsCount;

protected String childName[];

protected int childType[];

protected int childKey[];

protected FileNode child[];

protected FileNode parent;

protected String pathname;

protected File file;

protected FileNode(int objectKey , int type, int bindingsCount) {

isSRG = false;

this.objectKey = objectKey;

this.bindingsCount = bindingsCount;

childName = new String[bindingsCount];

childType = new int[bindingsCount];

childKey = new int[bindingsCount];

child = new FileNode[bindingsCount];

parent = null;

pathname = null;

file = null;

} }

Figure 50. My DataStructure:FileNode

Figure 51. Block Diagram of BIOP Decoder

相關文件