2018年3月8日 星期四

3 進階技術-封裝資料&廣播封包&fast-forward

  • 廣播封包


用 UDP[只能用 UDP,TCP 不行]與標準 IPv4,可以透過一種叫作廣播(broadcasting)的機制達成。IPv6 不支援廣播,所以你必須要採用比較高級的技術-群播(multicasting).

如何指定廣播訊息的目地位址呢?

有兩種常見的方法:

1. 將資料送給子網路(subnet)的廣播位址,就是將 subnet's network(子網路網段)的 host(主機)那部分全部填 1,舉例來說,我家裡的網路是 192.168.1.0,而我的 netmask(網路遮罩)是 255.255.255.0,所以位址的最後一個 byte 就是我的 host number[因為依據 netmask,前三個 bytes 是 network number]。所以我的廣播位址就是 192.168.1.255。

2. 將資料送給 "global(全域的)"廣播位址,255.255.255.255,又稱為 INADDR_BROADCAST,很多機器會自動將它與你的 network number 進行 AND 位元運算,以轉換為網路廣播位址,但是有些機器不會這樣做。Routers 不會將這類的廣播封包轉送(forward)出你的區域網路。


使用廣播封包一定要小心,因為 LAN 上面的每台電腦都會被迫處理這類封包,無論它們有沒有用 recvfrom() 接收,這類封包會造成整個電腦網路相當大的負擔,所以一定要謹慎、適當地使用廣播。


  • 封裝資料

不過如果你想要送一些 "二進制" 的資料,非文字資料, 下面常用三種方法:

1. 將數字轉換為文字,使用如 sprintf() 的函式,接著傳送文字。接收者會使用如 strtol() 函式解析文字,並轉換為數字。

2. 直接以原始資料傳送,將指向資料的指標傳遞給 send()

3. 將數字編碼(encode)為可移植的二進制格式,接收者會將它解碼(decode)。


第二個方法:傳送原始資料(raw data),這個方法相當簡單[但是危險!]:只要將資料指標提供給 send(),不具可移植性
第三種方法為封裝資料,




  • socket struct 傳送(struct 用指標指向開始位址 傳送)(公司header)



c++ struct 中如果有 char 變數: 4 表示4bit
socket 在傳送時,如果非1byte 送出, 透過上述的struct 有猜4bit 4 bit 

則可能會因為little ending 掉換過來

例如v3 header

typedef struct Image_header_V3 

 unsigned int nStartCode;   //FFFFFFAA
 time_t      tSec;            //時間
 unsigned int tuSec;
 unsigned int nLen;    //Frame 的資料長度
 unsigned long long nRec_ch;   //紀錄錄影當時的頻道
 unsigned short  nChA;          //Channel number
 unsigned short  nChB:4;          // For Video:Reaolution, For Audio:Audio Type
 unsigned short  nFrameType:2;   // 0: MPEG4 , 1: H264 , 2: ALL_AUDIO , 3: MJPEG
 unsigned short  nKeyframe:1;     // 0: P-Frame , 1: I-Frame
 unsigned short  nVideosystem:1; // 0: NTSC , 1: PAL

 unsigned short  Capture:1;   // 0: Analog , 1: IPCAM
 unsigned short  nRes:1;           // 不使用,預設為 0
 unsigned short  field:2;   // 不使用,預設為 3
 unsigned short  Reserver:4;

}__attribute__((packed)) Image_header_V3;

------------------------------------------------

int time_t int int (long long) short short
4      4        4      4         8            2        2     //占的位子大小(單位btye)

最後那個short為2byte,包含
 nchB , nFrameType,nKeyframe,nVideosystem, //總和1byte
Capture,nRes,field,Reserver   //總和1byte

以上是送
---------------------------------------
以下是收

如到因為little ending  所以會反過來,
如果為getshort(26)//26為起始位置

收到順序Reserver,field,nRes,Capture,
nVideosystem,nKeyframe,nFrameType:2,nchB:4

所以: nFrameType 取為& 00 30 
//30表示 0011(nVideosystem,nKeyframe,nFrameType:2
0000(nchB)


----------------------------------------------
-----------------------------------------------
typedef struct Image_Header_V2 {
    unsigned int  nStartCode;        //FFFFFFAA
    /*time_t*/ unsigned int  tSec;   //時間 unsigned int for 64-bit issue
    //unsigned long long tSec;     //時間 unsigned int for 64-bit issue
    unsigned int    tuSec;
    unsigned int    nLen;            //Frame 的資料長度
    unsigned int    nRec_ch;         //
    unsigned short  nChA;            //Channel number
    unsigned short  nChB:4;          // For Video:Reaolution, For Audio:Audio Type
    unsigned short  nFrameType:2;    // 0: MPEG4 , 1: H264 , 2: ALL_AUDIO , 3: MJPEG
    unsigned short  nKeyframe:1;     // 0: P-Frame , 1: I-Frame
    unsigned short  nVideosystem:1;  // 0: NTSC , 1: PAL
    
    unsigned short  Capture:1;       // 0: Analog , 1: IPCAM
    unsigned short  nRes:1;          // 
    unsigned short  field:2;         //
    unsigned short  Reserver:4;
    
} Image_Header_V2;


  • H264 decode fast-forward



屬於多媒體播放,已知有兩種方法
1.  尋找 I frame  decode (影像不順, cpu不耗效能)

2.  1秒鐘內decode 多張不同timestamp (cpu耗效能,影像順)

注意聲音&影像同步問題