• 沒有找到結果。

整合式多媒體串流平台的發展與實作

N/A
N/A
Protected

Academic year: 2021

Share "整合式多媒體串流平台的發展與實作"

Copied!
92
0
0

加載中.... (立即查看全文)

全文

(1)

國 立 交 通 大 學

電信工程學系

碩 士 論 文

整合式多媒體串流平台的發展與實作

Development and Implementation of

Integrated Multimedia Streaming

Platform

研究生:張為棟

指導教授:張文鐘 博士

(2)

整合式多媒體串流平台的發展與實做

Development and Implementation of Integrated Multimedia

Streaming Platform

研 究 生:張為棟 Student:Wei-Tung Chang 指導教授:張文鐘 Advisor:Wen-Thong Chang 國 立 交 通 大 學 電信工程學系 碩 士 論 文 A Thesis

Submitted to Department of Communication Engineering College of Electrical and Computer Engineering

National Chiao Tung University in partial Fulfillment of the Requirements

for the Degree of Master in

Communication Engineering August 2006

Hsinchu, Taiwan, Republic of China

(3)

整合式多媒體串流平台的發展與實做

研究生:張為棟 指導教授:張文鐘 博士 國立交通大學電信工程學系碩士班 摘要

多媒體串流技術,使消費者在下載多媒體檔案的同時可以觀賞到已收到的 部份,此項技術使得使用者不需要花費下載時間與硬體空間來儲存多媒體檔案。 多媒體串流技術,包括三個部份:1、檔案包裝格式,舉例來說*.avi 、*.mp4、 *.wmv、*.mpg,這些都是包裝格式的一種,包裝格式的檔頭會說明如何從這些 檔案格式中拆解出解碼器所需要的聲音流與影像流。2 影音壓縮解壓縮技術,舉 例來說 mpeg-4、mp3、AAC 等都是影音壓縮解壓縮的一種,藉由這些影音壓縮 技術可以把原始影音檔案大小壓縮成原來的數十分之ㄧ,3、網路串流技術,利 用網路讓遠端接收到多媒體檔案並播放,所要求的為檔案播放的及時性與平順 性。因此,一個完美的多媒體串流平台,基本上必須看得懂所有的檔案包裝格式 與網路串流格式,同時必須準備各種影音壓縮技術來對影像流與聲音流進行編碼 及解碼,這種看似複雜的串流平台在自由軟體基金會及全球軟體工程師的努力下 正逐漸的建構當中,本論文的第三章將探討一個開放原碼的自由軟體 FFmpeg。 多媒體串流的一項重要應用為安全監控,本論文將建構一套雙攝影機模組的 即時遠端安全監控系統,利用 VFW SDK 擷取雙攝影機影像並將其壓縮成 mpeg-4 simple profile,再利用串流平台串流播放之,由於將即時影像來源壓縮成 mpeg-4 simple profile 將會消耗大量 cpu 資源,本論文嘗試使用硬體代替軟體進行 mpeg-4 simple profile 的壓縮,至於解壓縮部份由於銷耗 cpu 資源有限因此仍以軟體進行 解壓縮,而研究中也發現雖然軟、硬體皆是使用 mpeg-4 simple profile 但會因為 codec tool 的差異而造成解碼錯誤,本論文將解決差異所造成的解碼錯誤,並成 功的串流由硬體所壓縮出來的影音檔案。

(4)

Development and Implementation of Multimedia

Streaming Platform

Student : Wei-tung Chang Advisor : Dr. Wen-Thong Chang

Department of Communication Engineering National Chiao Tung University

Abstract

Streaming technology allows people to enjoy the multimedia contents while downloading them. With the advantages of this technology, users don’t need to spend extra hours on downloading multimedia contents or spare memory space to save them.

Streaming technology consists of three components. 1. File Format, for example, *.avi, *.mp4, *.wmv, and *.mpg. Decoder can parse video stream and audio stream via analyzing the header of a file format. 2. Codec, for example, mpeg-4, mp3, and AAC. By using Codec, users can compress original file several folds. 3. Network Streaming Technology. User can present smooth and real-time multimedia contents via network. In order to develop a perfect multimedia streaming platform, one have to realize all kinds of file formats and network streaming technology. In addition, the perfect platform has to possess all kinds of Codec to decode or encode multimedia contents. This complex perfect multimedia streaming platform is being built gradually by global software engineers. We will introduce an open source software which is produced by free software foundation in chapter 3.

Surveillance system is an important application in streaming technology, we will build a real-time two camera model multimedia streaming surveillance system in this thesis, we use VFW SDK to capture this two camera image and encode image to mpeg-4 simple profile, and stream the mpeg-4 video stream via internet.

In order to decrease the cpu loading, we try to use hardware mpeg-4 simple profile encoder to replace the software one. Although both hardware encoder and software decoder are mpeg-4 simple profile codec, the difference of codec tool will cause decoder error, we will resolve this problem in this thesis and successfully streaming multimedia contents which is made by hardware encoder,

(5)

致謝

首先,我要感謝我的指導教授:張文鐘老師,感謝老師兩年來辛 苦的指導,不管在課業或是日常生活當中,老師的指導使我們獲益良 多。 接者我要感謝我的實驗室夥伴,兩年多來認識了很多一起鑽研多 媒體通訊領域的好朋友,不管是建華、其瑩、心賢、智維、義皓或是 同屆的同學、陳博、小林、邱董、飄髮哥,以及新進來的學弟準 leader、 阿修等,感謝這些夥伴的照顧與幫忙。 當然,還要感謝我的大學朋友們,在我最難過的時候安慰我鼓勵 我,讓我能繼續完成該完成的目標,尤其是書安,幫了我許多忙,還 有還有 Selena,讓我度過很多快樂的日子。 最後我要感謝我的家人,讓我這兩年可以沒有後顧之憂的唸書和 做研究。 祝福我所有的朋友,老師,家人,身體健康、萬事順利。

(6)

目錄 中文摘要 ………. I 英文摘要 ………. II 致謝 ………. III 目錄 ... IV 圖列 ... VI 表列 ... VIII 第一章 Introduction... 1 1.1 背景介紹... 1 1.2 研究動機... 2

第二章 Mpeg-2 System And M4v Header Syntax…………... 4

2.1 Mpeg-2 System Introduction………. 4

2.2 Mpeg-2 Program Stream………... 9

2.2.1 Pack And System Header……… 10

2.3 Mpeg-2 Transport Stream………. 12

2.4 M4v Header Syntax………... 15

2.5 Parsing Video Stream from Mpeg-2 System………. 20

第三章 多媒體串流之自由軟體介紹及使用………. 24

3.1 FFmpeg……….. 24

3.1.1 應用程式的編譯及使用………. 25

3.1.2 av_regist_all 各種影音格式模板建立……….. 28

(7)

3.1.4 av_find_stream_info 獲得 codec 資訊……….. 37

3.2 OpenCV 與串流平台結合……… 41

3.2.1 串流平台簡介……… 41

3.2.2 一個 OpenCV 與串流平台結合的例子……… 47

第四章 Rtp Payload Format for M4v And Mpeg-2 System... 51

4.1 RTP……… 52

4.1.1 RTP 檔頭資訊………... 52

4.1.2 RTP Payload Format For M4V……….. 54

4.2 Live555………. 62

4.2.1 Rtsp Command In Live555………. 62

4.2.2 M4V RTP Payload In Live555………... 65

4.3 Rtp Payload Format For Mpeg-2 System………….. 68

4.3.1 Mpeg-2 Video Stream………. 68

4.3.2 Live555 包裝 Mpeg-2 System 方式……… 69

第五章 多媒體串流環境建構………. 72 5.1 軟硬體多媒體串流平台整合……….. 72 5.2 雙攝影機串流平台整合……….. 75 5.2.1 雙攝影機影像擷取……… 75 5.2.3 雙攝影機串流平台建構……… 76 第六章 結論………. 79 第七章 參考文獻………. 81

(8)

圖列

圖 1 Model Of Mpeg-2 System... 5

圖 2 PES Packet……… 6

圖 3 Relationship Between PES Packet and Program Stream…… 10

圖 4 Relationship Between PES and Transport Stream………….. 12

圖 5 Visual Information – Logical Structure……….. 16

圖 6 Structure of M4V……… 16

圖 7 Display M4V by Hex……….. 17

圖 8 ESDS data example………. 17

圖 9 Vop_start_code and Vop_coding_type……… 19

圖 10 實際拆解 program stream 的結果………. 21

圖 11 實際拆解 transport stream 的結果……… 23

圖 12 ./configure –help 列出支援的參數配置………. 27

圖 13 ffplay 播放畫面………. 28

圖 14 Member of AVInputFormat………. 29

圖 15 Mpeg-2 Program Stream 的結構成員……… 30

圖 16 av_register_all()之水平關係圖………. 31 圖 17 av_register_input_format()程式碼……….. 32 圖 18 各種影音格式的鏈節串列………. 32 圖 19 av_open_input_file()水平關係圖……….. 33 圖 20 av_probe_input_format()的原始碼……… 34 圖 21 mpegps_probe()程式碼………. 35 圖 22 mpegts_probe()與 analyze()關係………. 36 圖 23 analyze()原始碼……….. 37 圖 24 av_find_stream_info()水平關係圖……….. 38

(9)

圖 25 mpegps_read_packet()水平關係圖……….. 39

圖 26 mpegps_psm_parse()原始碼……… 40

圖 27 Thread of Server System……….. 42

圖 28 RTSP State Machine………. 43

圖 29 Thread of Client System……… 44

圖 30 配置 codec 所需的 input data 與 output data……… 46

圖 31 將 header 檔加入 Project 中………. 47 圖 32 IplImage 的成員………. 48 圖 33 於 IDE 介面中加入 Library……… 49 圖 34 結合影像處理與串流平台的結果……….. 50 圖 35 RTP 封包格式……….. 52 圖 36 RTP Header Format……… 53

圖 37 一個有 video packet 的 mpeg-4 video stream………. 55

圖 38 Video Packet Structure……….. 55

圖 39 Macroblock number = 25……….. 57

圖 40 RTP Timestamp………. 59

圖 41 RTP Packet 的例子………... 61

圖 42 buildAndSendPacket……… 65

圖 43 Mpeg-4 Video Stream in RTP Payload………. 66

圖 44 A Mpeg-2 Video Stream Example……….. 69

圖 45 Frame 中 Slice 的分布示意圖………. 69

圖 46 Mpeg-2 Video Stream In RTP Payload……… 73

圖 47 串流平台伺服端接收端介面……… 74

圖 48 雙攝影機伺服端介面……… 77

(10)

表列

表 1 Mpeg2 Standards………. 5

表 2 Stream_id assignments……… 7 表 3 Program Stream Map………. 8 表 4 Pack Header Syntax……… 9

表 5 System Header Syntax……… 11

表 6 Stream Type assignments……… 11

表 7 Transport Stream Header………... 13

表 8 PID Table………. 13

表 9 Program Association Section………. 14

表 10 Transport Stream Program Map Table………. 15

表 11 Meaning Of Vop Coding Type……… 20

(11)

第一章 簡介

1.1 背景介紹

隨著網路傳輸頻寬的不斷成長,網際網路的應用已經從原本的文 字或圖片傳輸,轉變成結合聲音、影像的互動式多媒體網路,這些多 媒體資訊藉由稱為串流技術的新傳輸科技在網際網路上迅速擴張。 串流是一種具有即時〈Real-time〉特性的多媒體傳輸技術,其特 色為客戶端不需要完整下載多媒體檔案,只需要先下載極小一部份資 料即可開始播放,其優點除了減少使用者下載所需的時間外,更可節 省磁碟儲存空間,達到智慧財產權的保護等。 目前串流媒體在網際網路上的傳輸方式主要有兩種方式,一種是 以HTTP/TCP 為基礎,利用 HTTP 協定可以讓串流媒體通過防火牆的 阻礙,但缺點是TCP 通訊協定將會導致傳輸速度的減緩,進而增加 串流媒體所需要的頻寬,另一種方式則是使用RTP/UDP,Real Time

Protocol (RTP),是由 Internet Engineering Task Force (IETF)所制定,

並定義於RFC-3550 ,根據[1],RTP 提供點對點的傳輸服務,包括

payload type identification、sequence numbering、timestamping,利用 sequence number 來進行封包重建,而 timestamp 則記錄著各影像、聲 音封包所應播放的時間,如此即可增進即時傳輸的品質。

(12)

一個權威性標準產生,以至於各家廠商紛紛推出以自己的標準或是特 有通訊協定所開發的串流媒體伺服器,導致一套串流伺服器只能對應 一套編碼/解碼格式,綜觀市場目前串流媒體的三大主流分別是 RealNetworks.com 的 RealSystemR[2] 、 Microsoft 的 Media ServicesR[3]以及頻果電腦主推的 Quick Time ServerR[4]。也由於沒有 一套標準的編碼解碼器(Codec)及串流媒體,Open Source 將在整合出 重量級串流媒體伺服器上面扮演重要的角色。

1.2 研究動機

一個多媒體串流平台,包括 server 與 client,client 向 server 要求某 種多媒體影音檔案,server 則對 client 所要求的多媒體影音檔案進行 Parse 並包裝成特殊網路封包格式--RTP Packet 進行網路傳送,所謂的 Parse 即是將多媒體影音檔案中的影像流與聲音流抽取出來,同時 client 必須對這影像流與聲音流進行解碼與播放,由上述的過程我們

可以知道client 與 server 存在某種默契,即 server 必須有能力抽取出

client 所要求的多媒體影音檔案中影像流與聲音流並包裝成 RTP Packet,而 client 必須有從 RTP Packet 中找出影音資料同時解碼這個

影音資料的能力,現在的問題為當client 所要求的多媒體影音檔案,

server 沒有能力 Parse,或是當 Server 抽取出某種多媒體影音檔案的 聲音流與影像流後,client 沒有相對應的解碼器對這些聲音流與影像

(13)

流進行解碼,此外,目前我們是使用RTSP 當作 client 與 server 的溝

通橋樑,不管是client 要求暫停、快轉、倒轉甚至是要求某種影音檔

案,都是藉由RTSP Command 來進行溝通,server 也藉由 RTSP

Command 來回應 client 的要求,當 server 看不懂 client 的 RTSP 指令

或是server 回應的 RTSP Command client 看不懂,這些都將造成串

流的失敗,這些相容性問題,常常發生於不同串流平台之間的溝通,

例如蘋果的QuickTime Server 沒有辦法與 RealPlayer 互通。

要解決此相容性的問題,我們必須讓 server 有能力看得懂各種影 音資料,任何多媒體影音資料都是由0101…..這些 bitstreams 所組成, 藉由讓sever 看得懂這些 bitstreams 的物理意義,我們可以對多媒體 影音資料進行Parse,server 抽取出影像流與聲音流後必需包裝成適當 的RTP Packet,適當的 RTP Packet 可以幫助我們在錯誤發生時進行錯 誤回復,client 則從這些 RTP Packet 中取得影音資料,再根據影音資 料的種類給予適當的解碼器進行解碼與播放,因此我們必須在 Client 與Server 端建立影音格式與解碼編碼的資料庫,在研究中也發現,光 是建立一種影音資料庫是是不夠的,藉由建立各種多媒體影音資料庫 的Link List,可以處理各式多媒體影音資料。同時我們也必須試著建 立一個符合標準的RTSP 指令,使 client 與 server 可通用於目前流通 於市面上的各種多媒體串流平台。

(14)

第二章 MPEG-2 System and M4v header syntax

MPEG-2 system 定義 DVD 與數位廣播電視的包裝格式,但為了增

加壓縮比,在許多多媒體的應用上,藉由mpeg-4 codec 取代 mpeg-2

codec,本章將介紹由 ISO 13818-1[5]定義的 mpeg-2system,包括現在 DVD 所使用的 mpeg-2 program stream 與數位廣播電視所使用的 mpeg-2 transport stream,在了解 mpeg-2 system 後我們便可以從中抽

取出影像流與聲音流,抽取出來的影像流是mpeg-4 simple profile,接

下來為了找出這個影像流中各個frame 的起始及結束位置,我們將研

究mpeg-4 simple profile 中各個語法的意義,在本章的最後將拆解實

際的例子。

2.1 MPEG-2 System Introduction

MPEG-2 Standards 制訂於 Motion Picture Experts Group(MPEG)並 由International Standards Organisation(ISO)所出版,目前共分為九個

部份列於表1,其中的 ISO 13818-1[5]定義了兩種 Multiplexing 的格

式,Program stream 以及 Transport stream,參考圖 1[5],所謂的 Multiplexing 是指將壓縮好的影像流、聲音流、控制資料、使用者資 料等結合成單一數據流,使此單一數據流能適用於儲存或者是傳輸, 以下將就此兩種格式分別討論。

(15)

表1 MPEG-2 Standards

圖 1 Model of MPEG-2 System[5]

從圖1,我們可以看到 MPEG-2 System Multiplexing 的過程,首先影

像來源與聲音來源藉由Viedo and Audio Encoder 壓縮成 viedo and audio elementary stream 而 Packetizer 則將這些 elementary stream 加上

(16)

適當的PES Header 形成 PES Packet,同時 Packetizer 也會建立說明這

些elementary stream 位於檔案何處與種類的說明文件,把這些說明文

件加上適當的PES Header 也形成 PES Packet,所謂適當的 PES Header

如圖2 所示,PES Header 開始於 3bytes 的 pes_start_code(00 00 01), 1byte 的 Stream_ID 及兩 bytes 的 PES Packet length,適當的 PES Header 即Packtizer 會根據 payload 的種類給予適當的 stream_id,根據表 2[5] 可知,當 Stream ID 介於 0xC0~0xDF 之間則此 Payload 為 audio stream,當 Stream ID 介於 0xE0~0xEF 之間則此 Payload 為 video stream。

圖 2 PES Packet Stream_id Stream codind 1011 1100 1011 1101 1011 1110 1011 1111 110x xxxx 1110 xxxx 1111 0000 Program_stream_map Private_stream_1 Padding_stream Private_stream_2

ISO/IEC 13818-3 or ISO/IEC 11172-3 audio stream

ITU-T Rec H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 video stream

(17)

1111 0001 1111 0010 1111 0011 1111 0100 1111 0101 1111 0110 1111 0111 1111 1000 1111 1001 1111(1010-1110) 1111 1111 EMM stream

ITU-T Rec.H.222.0 | ISO/IEC 13818-1 Annex A or ISO/IEC 13818-6 DSMCC stream

ISO/IEC_13522_stream ITU-T Rec H.222 | type A ITU-T Rec H.222 | type B ITU-T Rec H.222 | type C ITU-T Rec H.222 | type D ITU-T Rec H.222 | type E ancillary_stream

reserved data stream program_stream_directory

表 2 [5]Stream_id assignments

PES header 除了告訴 decorder 其 Payload data 為影像流或者是聲音流

外,他還必須告知decorder 此影像流或聲音流的格式。當 stream_id =

1011 1100 從表 2 可知此 PES 為 Program_stream_map,從表3、表4 中可以得知Program stream map 藉由 stream_type、

elementary_stream_id 來告知某一 stream_id 其 stream_type 為何。舉例 來說,一個mpeg-4 simple profile 的 mpeg-2 program stream,我們可

以找到很多PES header 中的 stream_id =0xE0 從表 2[5]可得知這代表

這些PES 的 Payload data 為影像流,也可以找到 stream_id = 0xBC 的 PES 根據表 2[5] 這代表這個 PES 為 Program Stream map,從這個 Program Stream map 的 Payload data 中我們將找到 stream_type = 16、 elementary_stream_id = 0xE0,根據表 4[5],stream_type = 16 為保留 的型別,其定義為mpeg-4 video codec。因此 stream_type =16、

(18)

elementary_stream_id =0xE0 代表只要影像流其 PES header 中的 stream id 為 0xE0 則此影像流為 mpeg-4 video codec。

(19)

表4[5] Stream type assignments

2.2 MPEG-2 Program Stream

MPEG-2 Program Stream 就是 DVD 儲存的格式,根據 ISO13818-1[5] Program Stream 具有以下幾點特性 1 適用於儲存檔案格式,不適合用於傳輸檔案格式。 2 所有的 elementary streams(video、audio、data 等)皆具有相同的時間 基準(time base)。 3 每一個 Program Stream 只能包含一個節目。 4 由於 Packet Size 比較大而沒有固定大小,因此適用於較少發生錯誤 的環境,因為decorder 很難去預測封包的開始及結束點。

(20)

由圖 1、圖 3 可以知道,要形成一個完整的 Program Stream 必須

先將各種不同的elementary stream 加上其應該有的檔頭,形成 PES

(Packetized Elementary Stream),再將許多 PES 集合起來並藉由加上 Pack header 形成一個 Pack,最後再將數個 Pack 集合成 Programe Streams,我們的目的是要拆解出藏在 PES payload 中的 mpeg-4 elementary stream 。

圖 3 Relationship between PES packets and Program Stream

2.2.1 MPEG-2 Program Stream—PACK and System header

根據ISO 13818-1[6]以及圖 3,PES 在結合成 Program Stream 之 前必須再加上PACK header,PACK header 由 pack_start_code

0x000001BA 開始,表 5 為 PACK Header 的 syntax,此外當ㄧ個 program stream 的 PACK 中包涵 frame 的起始位置,則此 PACK 將會 在PACK Header 之後再加上 System Header 此 System Header 將描述

(21)

表5 PACK Header Syntax

(22)

2.3 MPEG-2 Transport Stream

MPEG-2 Transport Stream 就是 HDTV 的傳輸格式,根據 ISO13818-1 Transport Stream 具有以下幾點特性:

1 一個 Transport Stream 可以擁有多個節目(program) 2 不同的節目可以擁有不同的時間基準(time base)]

3 擁有固定長度的封包大小,使解碼器能夠很容易的找出每一張照片 的開始和結束,同時也比較容易在掉封包後進行補救

參考圖 4,與 Program Stream 不同,Transport Stream 藉由將 PES

以每184bytes 為一個單位,再加上 4bytes 的 TS header 所組成的,參

考表7[5],TS header 由 8bits 的 sync_byte 0x47 開始,另外還有一個 13bits 的 PID,PID 的目的是告訴解碼器這個 Transport Stream packet

的payload 是什麼種類,由表 8[5]可以知道,我們有興趣的影像流與

聲音流其PID 將會介於 0x0010 與 0x1FFE 之間。

(23)

表 7[5] Transport Stream header

表 8 [5]PID Table

Transport Stream 與 Program Stream 一樣,必須要告訴解碼器此 Transport Stream 所攜帶的聲音流與影像流的格式,當 Transport Stream header 中的 PID = 0x0000 時,根據表 8[5],這個 Transport Stream 的 性質為Program Association Table,表 9[5]指出 Program Association Table 有哪些成員,其中解碼器會參照表 9[5]中的 program_map_PID,

(24)

也就是當之後解碼器遇到Transport Stream header 中的 PID 等於 program_map_PID 他就知道這個 packet 有 program_map 的資訊, program_map 會告知解碼器某一個 PID 其影像流與聲音流是用何種壓

縮格式,表10[5]指出 program_map_table 有哪些成員,從表 10[5]可

以知道Transport Stream 與 Program Stream 的 map table 相似,都是利

用stream_type 以及 elementary_PID 來告訴解碼器某一個 PID 其影像

流與聲音流的壓縮格式,至於stream_type 所代表的壓縮格式則與表

4[5]相同。

(25)

表 10 [5]Transport Stream program map table

2.4 M4v header syntax

從 2.2、2.3 中,目前我們已經知道 Program Stream 以及 Transport Stream 分別將影像流資料與聲音流資料藏在哪裡,但對串流來說,我

們還必須知道每張frame 的開始以及結束,那是因為只要是同一張

frame 的資料我們都要分配給他相同的 RTP timestamp,(關於 RTP 我 們將再第四章進行討論),因此本章將描述壓縮好的 mpeg-4

(26)

圖 5 Visual Informaton-Logical Structure[6]

圖5[ 6]指出了一個完整的 M4v,是由 Visual Object Sequence Header、Visual Object Header、Video Object Header、Video Object Layer Header 所組成,這些 header 將會夾帶解碼器所需要的一些訊息,例如

照片的尺寸、量化矩陣的參數等資料,我們稱這些資料為Elementary

Stream Descriptors(ESDS data),根據 ISO 14496-2[6],ESDS data 結束

後將進入Video Object Plane,也就是每張 frame 的起始位置,我們就

是藉由Video Object Plane 的 header 來判斷這張照片是 I 或 P frame 以

及每張frame 的起始位置。圖 6 顯示一個完整 m4v 檔是由 ESDS data

以及I frame 與 P frame 組合而成。

圖 6 Structure Of M4V

圖7 則是利用 UltraEdit 以 16 進位的方式顯示某一 m4v 檔,雖然

(27)

Header .

圖 7 Display*.m4v by Hex

及Visual Object Header 但事實上為了因應個別需求所開發出來的

mpeg-4 codec 其格式會有些許的差別,從圖 7 可以發現,這個 M4v 開始於32bits 的 video_object_start_code 00 00 01 00,而非

Visual_object_sequence_start_code。圖 8 列出了這個檔案的 ESDS data,

其大小為18bytes。

(28)

圖 8-b byte 4 ~byte 7

圖 8-c byte 8 ~ byte 10

圖 8-d byte 10 ~ byte 12

圖 8-e byte 12~byte15

圖 8-f byte 16~byte17

從圖8-c 中,可以發現 ESDS data 定義了 2bits 的 vol_shape,在

(29)

現有兩個13bytes 的值分別代表 vol_width 以及 vol_height,在這裡 width = 176,height = 144,因此解碼器可以從 ESDS data 中得到如何 解碼I frame 與 P frame 的資訊。

在ESDS data 中,也會因為 profile 選擇上的差異,造成 codec tool

使用上的不同,以圖8-c 來看,其 vol_control_parameters 設定為 0,

若此bit 設定為 1,則會增加 2bits 的 chroma_format,與 1bits 的 low_delay、vbv_parameters,當 vbv_parameters 設定為 1,則之後將 設定一些VBV 參數,包括 15bits 的 first_half_bit_rate、

latter_half_bit_rate、first_balf_vbv_buffer_size、

latter_half_vbv_occupancy 以及 3bits 的 latter_half_vbv_occupancy,此

外,也可以在ESDS Data 中設定量化矩陣參數,圖 8-f 中 quant_type

設定為0,當此值設定 1 為則我們可以設定 64bytes 的

intra_quant_mat,與 64bytes 的 non_intra_quant_mat。

根據圖6,ESDS data 結束後會進入 I frame,frame 由

vop_start_code 開始,圖 9 則表示出這個 m4v 檔的 I frame 開始於 32bits 的 vop_start_code 00 00 01 B6,以及 2bits 的 vop_coding_type,從表 11 可以知道當 vop_coding_type = 00 時代表此 frame 為 I frame 。

(30)

圖 9 byte 18 ~ byte 22

表 11 Meaning of vop_coding_type

2.5 Parsing video stream from Mpeg-2 System

從前面三小節中,我們可以知道如何從Program Stream 以及

Transport Stream 中拆解出 elementary stream,同時也知道每一張 frame 的開始與結束點為何。

以Program Stream 來說,首先,要先拿掉 PACK header 以及

SYSTEM header,接下來找出藏有 program_map 的 PES,這個 PES

的stream_id 根據表 2 會等於 0xBC,而且這個 PES 根據表 3 會有

stream_type 以及 elementary_stream_id 等資訊,從 elementary_stream_id

我們可以知道接下來要找的PES 其 header 中的 stream_id 若是等於

elementary_stream_id 則這個 PES 的 payload data 中就有我們要的訊 息,而從payload data 中可以藉由 vop_start_code 00 00 01 B6 找到每

張frame 的開頭與結尾,在這邊要注意的地方是在 I frame 之前還會

有ESDS data 必須將其保留下來,作為解碼器解碼的依據。接下來將

(31)

file 並將結果顯示於圖 10。

(32)

從圖10 中我們可以發現,pack 0 與 pack 92 分別是一張 frame 的

開始,所以這兩個pack 將會包含比其他 pack 更多的資訊,例如這兩

個pack 都有 program stream map,從這個 program stream map 可以知 道video stream 為 mpeg 4,因為 stream_type = 16,而且其 PES 的 payload data 中更包含有 PTS(presentation time stamp)及 DTS(

decoding time stamp)等幫助播放及解碼的資訊。

Transport stream 的拆解過程與 Program stream 相似,首先我們要 找出transport stream header 中的 PID = 0x0000 的 packet,因為根據表 8 這代表這個 packet 的 payload data 為 program association table,而 根據表9 我們可以從 program association table 中找到一個

program_map_PID,接下來我們要找出某一個 Transport stream header 中的PID = program_map_PID,因為這個 Transport stream 的 payload data 中根據表 8 會告訴我們 elementary_PID 及其 stream_type,之後只

要PID = elementary_PID 我們就保留其 payload data,在這裡要注意的

是根據圖3 假如這個 tansport stream packet 剛好包含 PES header,則

我們必須在保留其payload data 前先拿掉 PES header。圖 11 為分析一

個Transport stream 檔案的結果其壓縮格式為 mpeg-2。

從圖 11 的 pack 2 中我們可以找到 elementary_PID 接下來只要將 Transport stream header 中 PID = elementary_PID 的 payload data 保留

(33)

起來即可。

(34)

第三章 多媒體串流之自由軟體介紹及使用

在第二章中,我們建立了一種多媒體檔案格式的資料庫MPEG-2

System 以及 mpeg-4 simple profile,但世界上的多媒體檔案格式太多, 要建立各種多媒體檔案格式的資料庫所需耗費的工程可以預期將會 相當巨大,所幸這些問題藉由自由軟體的發布可以獲得解決,藉由自 由軟體我們可以建立各種影音格式的資料庫,以這個資料庫來處理各 種影音檔案。

自由軟體基金會(Free Software Foundation)[7]提供的免費且能自 由流通的軟體,開發者除了能擁有軟體的完整程式碼,同時也被允許 能對此程式碼進行修改及開發,那是因為由自由軟體基金會所發布的

軟體都擁有GNU 通用公共許可證(GNU Lesser General Public

License),這個許可證讓程式接收人可以擁有運行、修改、發行及公 開的自由。本章將介紹及使用由自由軟體基金會所發布與多媒體串流 有關的軟體,FFmpeg[8],另外也將介紹一套由 Intel 所開發的

OpenCV(Open Source Computer Vision Library)[9]這是一套與影像處 理相關的自由函式庫。

3.1 FFmpeg

(35)

聲音流的分離、轉換、編碼、解碼,主要是由三個應用程式ffmpeg、 ffserver、ffplay 以及兩個函式庫 libavcodec、libavformat 組成:

1 ffmpeg,是個轉碼工具,也就是將某一個影音格式轉碼成另一個影 音格式,例如ffmpeg –i inputfile.mpg outputfile.mp4 就是將一個.mpg 檔轉換成.mp4 檔。 2 ffserver,是個串流伺服器,藉由 HTTP 進行即時串流。 3 ffplay,是一個用 FFmpeg 函式庫所開發出來的多媒體播放器。 4 libavcodec 是 FFmpeg 所提供的函式庫,幾乎涵蓋了所有影音格式 的編碼及解碼功能,程式開發者只要將此函式庫引入project 即可使 用其所提供的編碼/解碼功能。 5 libavformat 是 FFmpeg 所提供的函式庫,利用這個函式庫將聲音流 與影像流從檔案中抽取出來或是將壓縮過的聲音流與影像流結合成 某種格式的檔案。

3.1.1 應用程式的的編譯及使用

本節將介紹如何在Windows 底下連結應用程式與 FFmpeg 所提供

的兩個library,藉由連結這兩個函式庫 libavcodec 與 libavformat 應用

程式將可以使用這兩個函式庫所提供的各種影音檔案的編碼、解碼等 功能。

(36)

用的語法無法在VC++底下編譯通過,因此若希望在 WinXP 底下編

譯FFmpeg 就必須使用 MINGW 加上 MSYS,MSYS 是 Windows 底

下的一個虛擬linux shell 環境,此環境提供了標準的 C 編譯器,我們

藉由他來執行configure、make 等指令,在這邊需要注意的是 MSYS

必須安裝在MINGW 底下的 bin 資料夾下。

接下來就是下載FFmpeg 的 source code,下載的方式是使用

CVS(Concurrent Versions System)協作/併發版本系統,CVS 是一種版 本控制系統,它可以很方便的讓開發者將最新版本上傳,也可以讓使

用者能隨時下載最新版本,下載到最新的 FFmpeg 後我們必須執行裡

面的configure,執行 configure 的目的是將必要的參數傳給 Makefile,

我們可以使用最簡單的參數配置方式,也就是打開MSYS,將所在目

錄切換到剛剛下載的FFmepg 底下,執行以下的指

令”./configure –enable-memalign-hack”,至於其他的配置方式例如希望 得到.lib 檔或是.dll 檔則可藉由執行”./configure --help”得到說明,

(37)

圖 12 ./configure –help 列出支援的參數配置

執行完./configure -- enable-memalign-hack 後,接下來就是執行 make 以及 make install,在 linux 環境下,我們是藉由 Makefile 將

各種library 的連接與輸出輸入的關係設定好,根據上面的步驟我

們可以成功的編譯出ffmpeg.exe 這個執行檔。但若是想要編譯出

ffplay.exe 檔則必須連結 SDL(Simple DirectMedia Layer),基本上 SDL 就如同 Windows 所提供的 DirectDraw 一般,不同之處在於 SDL 需在 Linux 的作業系統上使用,其主要目的是為了讓使用者 能夠藉由直接存取記憶體的方式,達到快速顯示、播放多媒體的

(38)

功能。安裝的方法是將下載下來的SDL 的 bin、include、lib、share 等四個目錄拷貝到mingw 的目錄底下,接著修改 i386-mingw32msvc-sdl-config 的第一行指令為 prefix=/mingw,之 後重新編譯ffmpeg 即可得到 ffplay.exe 這個執行檔,圖 13 是使用 ffplay 播放影片的畫面。 圖13 ffplay 播放畫面

3.1.2 av_register_all( )—各種影音格式模板的建立

為了使用FFmpeg 所提供的函式庫,必須要試著了解 FFmpeg 提

供哪些API(Application Program Interface)以及這些應用程式開發介面

具有哪些功能。

首先,FFmpeg 幾乎可以看的懂目前大部分的影音包裝格式,那是因

為函式庫libavformat 支援了大部分的影音包裝格式例如

mpg(mpeg1/2)、mp4、mp3、avi、wav、rm、quick time 等,FFmpeg 的做法為在應用程式的一開始先建立好一個鏈結串列,這個鏈結串列

(39)

的單位為一種影音格式模板而每個模版都是一個Structure

AVInputFormat,圖 14 則列出 AVInputFormat 包含哪些成員。不同的

影音格式模板其成員的內容將不盡相同,例如mpeg-2 program stream

這個影音模版其成員long name 會定義成 MPEG PS format 而 mpeg-2

transport stream 這個影音模版其成員 long name 則會定義成 MPEG TS format。

typedef struct AVInputFormat {

const char *name;

const char *long_name;

int priv_data_size;

int (*read_probe)(AVProbeData *);

int (*read_header)(struct AVFormatContext *, AVFormatParameters *ap);

int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);

int (*read_close)(struct AVFormatContext *);

int (*read_seek)(struct AVFormatContext *,

int stream_index, int64_t timestamp, int flags);

int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit);

int flags;

const char *extensions;

int value;

int (*read_play)(struct AVFormatContext *);

int (*read_pause)(struct AVFormatContext *);

struct AVInputFormat *next;

圖 14 member of AVInputFormat

鏈結串列會將所有的影音格式模板串接其來,在這裡的影音格式模板

是指一個屬於AVInputFormat 的結構,例如圖 15 就是 FFmpeg 所定義

(40)

AVInputFormat 這個結構,而輸入的檔案只要對這個鏈結串列進行循 序搜尋,當搜尋到某一個影音格式模版時,我們必須將輸入檔案的檔

頭餵給這個影音格式的成員函式read_probe( ),舉例來說,若是搜尋

到的影音格式是mpeg-2 program stream 則根據圖 15 我們必須把輸入

檔案的檔頭餵給mpegps_probe( ),read_probe( )這個成員函式會去判 斷輸入檔案的檔頭符不符合這個影音格式,若是符合則read_probe( ) 會回傳非零整數,代表輸入檔案即為此一影音格式,反之若是回傳值 為零則代表還沒有找到符合的影音格式,程式必須繼續搜尋下去。 AVInputFormat mpegps_demux = { "mpeg", "MPEG PS format", sizeof(MpegDemuxContext), mpegps_probe, mpegps_read_header, mpegps_read_packet, mpegps_read_close, NULL, mpegps_read_dts, .flags = AVFMT_SHOW_IDS, };

圖15 mpeg-2 program stream 的結構成員

上面建立鏈結串列與搜尋檔案格式的過程看似複雜,但 FFmpeg

的API 能幫助我們完成大部分的工作,由 libavformat 這個函式庫所

提供的API av_register_all( )其目的就是建立起有所有檔案格式的鏈

(41)

以發現av_register_all( )呼叫了很多影音格式的初始化函式,例如 mp3_init( )、mpegps_init( )、mpegts_init( )等,這些初始化函式分別都 會呼叫av_register_input_format( ),程式就用 av_register_input_format( )

建立起所有影音格式的鏈節串列,圖 17 則 av_register_input_format( )

的原始程式碼,從圖16、17 我們可以知道 av_register_all( )呼叫了所

圖 16 av_register_all( )之水平關係圖

AVInputFormat *first_iformat = NULL;

void av_register_input_format(AVInputFormat *format) {

(42)

p = &first_iformat;

while (*p != NULL) p = &(*p)->next; *p = format; format->next = NULL; } 圖17 av_register_input_format( )程式碼 有影音格式的初始化函式例如mp3_init( )、mpegps_init( ),而這些初 始化函式會將它們所代表的影音包裝格式以Structure AVInputFormat 傳給av_register_input_format( ),舉例來說,mpegps_init( )會將圖 15 的mpegps_demux 傳給 av_register_input_format( ),而 av_register_input_format( )則會將 mpegps_demux 與前面的影音格式串 接起來,因此我們只要很呼叫av_register_all( )這個 api,就可以建立 如圖18 所示的鏈結串列,將各種模版串接起來。而 first_iformat 則會 指向這個鏈結串列的起始位置。 圖18 各種影音格式的鏈結串列

3.1.3 av_open_input_file( )—確認輸入檔案包裝格式

在建立好各種影音格式的鏈結串列後,接下來就要判斷輸入檔案 為何種影音格式,判斷的方式如上一節所述,輸入檔案會跟每種影音

(43)

格式模板進行比對,每個影音格式模板的成員函式read_probe( )會試 著判斷輸入檔案的檔頭符不符合這種影音格式的檔頭標準,一旦符合 則會回傳一個非零整數,這個判斷的過程libavformat 這個函式庫也 提供一個api 供程式開發者使用,那就是 av_open_input_file( ),圖 19 則列出av_open_input_file( )的水平關係圖。av_open_input_file( )藉由 呼叫av_probe_input_format( )來進行搜尋鏈結串列的過程。 圖19 av_open_input_file( )水平關係圖 圖20 則是 av_probe_input_format( )的原始碼,根據圖 18,first_iformat 會指向這個鏈結串列的開頭,因此av_probe_input_format( )利用一個 for 迴圈從鏈結串列的開頭 first_iformat 一直搜尋到鏈結串列的結 尾,而for 迴圈每執行一次就代表搜尋到某一個影音格式,同時每執 行一次都會呼叫一次fmt1->read_probe(pd),這裡的 fmt1 是代表某一 個影音格式,pd 則是輸入檔案的檔頭,read_probe( )在輸入檔案的檔 頭與這個影像格式所定義的檔頭相符時,會回傳一個大於零的整數 值,並將fmt 設定為 fmt1,而 fmt 則為最後確定好的影音格式。

(44)

圖20 av_probe_input_format( )的原始碼

至於read_probe( )的函式內容則根據影音格式的不同而有不同的

定義,在這邊我們將以第二章出現過的mpeg-2 program stream 與

transport stream 為例子分別說明在 FFmpeg 中 read_probe( )如何成功 的判斷出檔案格式為program stream 與 transport stream,從圖 20 我們

可以知道當搜尋到某一個影音格式時程式會呼叫fmt1->read_probe( )

(45)

為mpeg-2 program stream 也就是當圖 20 的 fmt1 等於圖 14 的 mpegps_demux 時,呼叫 fmt1->read_probe( )事實上就等同於呼叫圖 20 的 mpegps_probe( ),圖 21 則為 mpegps_probe( )的程式碼,首先 mpegps_probe( )會先讀進這個 program stream 的前面 2048bytes 的資

料,事實上以第二章的圖10 來看,讀進 2048bytes 就是讀進 PACK 0

與PACK 1,而判斷的規則則是這 2048bytes 至少要有一個

system_header_start_code 0x000001BB,而且 system header 的個數必

需小於或等於PACK header。只要符合這兩項,mpegps_probe( )就會

回傳一個大於零的整數,也就確定此輸入檔案為program stream。

圖21 mpegps_probe( )程式碼

(46)

transport stream 時,呼叫 ftm1->read_probe( )等同於呼叫

mpegts_probe( ),圖 22 則是 mpegts_probe( )的水平關係圖以及

mpegts_probe( )呼叫 analyze( )的程式碼,不同於 mpegps_probe( )直接

圖22 mpegts_probe( )與 analyze( )關係

判斷輸入檔案的檔頭有幾個system_header 與 pack_header,

mpegts_probe( )則是在副函式 analyze( )中進行判斷,其判斷的方式是 讀入輸入檔案(就是圖 22 的 p->buf)的前 1880bytes,接下來判斷這 1880bytes 中有幾個 bytes 是 Transport stream header 中的 sync_byte 0x47,每讀進一個 sync_byte 則圖 22 中的 score 會加一,從第二章的 圖11 我們可以知道 Transport stream 中每個 packet 其大小為 188bytes 且其開頭會有4 bytes 的 header,sync_byte 0x47 就包含在這 4bytes

中,因此我們可以預期讀進這1880bytes 並判斷 sync_byte 後 score 的

值將為10,程式就是藉由這個方法判斷出輸入檔案為 mpeg-2

(47)

圖 23 analyze( )原始碼

3.1.4 av_find_stream_info( )—獲得 codec 資訊

從3.1.2 與 3.1.3 中我們可以知道,FFmpeg 如何建立起鏈節串列, 以及如何獲知輸入檔案其影音格式為何,在這邊要注意的是,影音格 式只是個包裝,舉例來說,一個*.mp4 的檔案,mp4 只是他的包裝格 式,但其裡面包裝的聲音流與影像流其codec 可能有很多種可能,聲

音流可能使用MP3(MPEG-1 Audio Layer 3),也有可能使用

AAC(Advanced Audio Coding),影像流則有可能是 mpeg-4,

(48)

裝格式其聲音流與影像流到底是用何種codec,圖 24 是 av_find_stream_info( )的水平關係圖,從圖 24 我們可以知道

av_find_stream_info( )最後將會呼叫 iformat->read_packet( ),在這邊 iformat 是屬於如圖 14 的 Structure AVInputformat,因此假若輸入檔 案是mpeg-2 program stream 則 iformat 會因為 3.1.3 介紹的 API

av_open_input_file( )而被設定成如圖 15 的 mpegps_demux,因此在這 邊呼叫iformat->read_packet( )事實上就等於呼叫圖 15 的

mpegps_read_packet( )。

圖 24 av_find_stream_info( )之水平關係圖

接下來我們將介紹FFmepg 如何利用 mpegps_read_packet( )找出

(49)

mpegps_read_packet( )的水平關係圖,其中 mpegps_read_pes_header( )

圖 25 mpegps_read_packet( )水平關係圖

會藉由呼叫find_next_start_code( )找到下一個 PES header 中的 start code,第二章表 2 則列出所有 PES 的 start code,一旦

find_next_start_code( )找到的 start code 等於 0xBC 根據表 2 這個 PES 所代表的意義為Program Stream map,則 mpegps_read_pes_header( ) 就會呼叫函式mpegps_psm_parse( )來進行 Program Stream map 的分

解動作,根據表 3 我們可以得知對 Program Stream map 的分解動作其

最終的目的為找到各為1byte 的 stream_type 與

elementary_stream_id,我們就是藉由 stream_type 與

elementary_stream_id 來判斷出影像流與聲音流的 codec,圖 26 則為 mpegps_psm_parse( )的原始碼,對照表 3 與圖 26,type 與 es_id 分別 等同於stream_type 與 elementary_stream_id,至於 stream_type 與 codec

(50)
(51)

3.2 OpenCV 與串流平台結合

目前應用於多媒體串流的例子很多,安全監控是其中之一,安全 監控的應用很多,例如人臉追蹤與辨識,移動物偵測等,結合各種影 像處理與壓縮串流是目前多媒體串流的一個重要應用,本節將實際結 合影像處理與壓縮串流,驗證影像處理與壓縮串流結合。

OpenCV(Open Source Computer Vision Library)是 Intel 開放原碼

電腦視覺函式庫,由一系列c 函式和少量 c++類別所構成,實現了影

像處理方面許多的應用,其特色為擁有 300 多個 c 函式 API,而且對

商業與非商業的應用都是免費的,要使用OpenCV 的函式庫,首先要

先編譯出我們所需要的函式庫(Library)與靜態聯結函式庫(dll),從下

載下來的OpenCV 原始程式中的 make 資料夾我們可以找到

opencv.dsw 這個 workspace,只要編譯這個 workspace 就可以得到我

們想要的函式庫,當然我們也可以在這個workspace 進行程式修改以

得到更符合我們需要的影像處理函式庫。

3.2.1 串流平台簡介[11]

串流平台可以分為兩個部份,Server 以及 Client,Server 端將影

像來源進行mpeg-4 壓縮,也就是將不含 bmp header 的 bmp raw data

(52)

elementary stream 則包裝成 rtp packet 進行網路傳送,而 Client 端則接

收rtp packet 並且進行 mpeg-4 的解壓縮,也就是將 mpeg-4 video

elementary stream 解壓縮成 bmp raw data,由於 client/server 系統必須

在同一個時間處理不同的工作,例如server 必須一邊進行 mpeg-4 壓 縮一邊進行網路傳輸的工作,因此整個系統是建構成多執行緒系統 (multi-thread system),作業系統分配資源給各個執行緒,讓系統能同 時間的進行多項工作。圖27 是同一個時間 server 端會執行的執行緒 StatusTimeFunc() GUI Thread TunnelMain() PacketScheduler() OverallL iste nerTh read () RTSPProcessor Thread() Bandwidth Smoother() StreamerletIs() Streaming Data ... LeakyBucket Token IP Network ... TCP UDP Transcoder() ... ...

Raw Audiovisual Data MPEG4

MPEG4 RTP Packets

圖 27 Threads of server system

.● GUI thread

作為使用者與server 端溝通的介面

● Transcoder( )

將各種攝影機擷取而來的raw data 壓縮成 mpeg-4 elementary stream,

(53)

● StatusTineFunc( ) 收集並且顯示client 的資訊於 GUI 上 ● OverallListenerThread( ) 負責接收新的client 連線,並且每次當成功的建立起新的連線會創造 另外一個執行緒RTSPProcessorThread( )來管理這個新的連線 ● PacketScheduler( )

將已經包裝好的RTP pacets 藉由 UDP sockets 送入網際網路中

下面這些執行緒,在每次有新的client 連線進來時就會被建立起來

● RTSPProcessorThread( )

負責接收、分析、抽取以及回應 RTSP messages,並且改變目前 server

的狀態,圖28 是 RTSP State Machine,舉例來說,當 Server 端目前

在Ready state,而且收到來自 client 端的 ”PLAY” message,

RTSPProcessorThread( )會將 state 改變成 Play state 並且做出對應的動 作 Init Ready Play TEARDOWN TEARDOWN SETUP TEARDOWN PLAY SETUP PAUSE PLAY SETUP 圖 28 RTSP State Machine

(54)

● StreamerletIs( )

如果是採用UDP,則此執行緒負責將剛剛 Transcoder( )壓縮好的

mpeg-4 video elementary stream 包裝成 RTP packets,並將這些 packets

放在PacketScheduler( )能夠存取的 buffer 上,另一方面如果是採用

TCP 當做傳送協定,則此執行緒便不做包裝的動作,直接將壓縮好 的elementary stream 放在 TunnelMain( )能夠存取的 buffer 上

● TunnelMain( )

藉由TCP Sockets 將 elementary stream 送入網際網路中

圖29 則是當 client 啟動時,同時間會執行的執行緒

圖29 Threads of client system

● GUI thread

作為使用者與server 端溝通的介面

●VideoStatusTimeFunc( )

負責在GUI 上面顯示目前接收封包的情況,同時把接收的 mpeg-4

(55)

出來 ● RTSPProcessorThread( ) 與server 端相同,負責 RTSP 指令分析以及改變 client 的 RTSP 狀態 ● TunnelMain( ) 藉由TCP 接收串流封包,並且把這些串流封包放在 VideoStatusTime Func( )能夠存取的地方 ● RecvThreadIsK( )

藉由UDP 接收 RTP packets,並且把這些封包放在 DepktThreadIsK( )

能夠存取的地方 ● DePktThreadIsK( )

拆解RTP packets 取得裡面的 elementary streams,並將這些資料放在

VideoStatusTimeFunc( )能存取的地方 從以上這些介紹,我們可以在server 端或是 client 端加上影像處 理,在server 端我們可以加在 Transcoder( )這個執行緒裡,因為這個 執行緒將從各種攝影機抓取資料,抓到的資料必須轉成bmp 檔接著 我們可以在這邊進行影像處理以及串流處理,在client 端我們可以加 在VideoStatusTimeFunc( )這個執行緒之上,因為這個執行緒能將

elementary stream 解碼成 bmp 的 raw data,我們可以再建立另外一個

執行緒來存取這個raw data 並做影像處理。

在server 端我們將透過以下幾個 API 以及一些參數配置將影像處

(56)

配置好mpeg-4 壓縮輸入資料與輸出資料的位置,在這邊輸入資料是

指每一張進行過影像處理的bmp raw data 而輸出資料是指壓縮過後

的mpeg-4 video elementary stream,有可能是 ESDS data +I frame 也有

可能是P frame 其配置方式如圖 30 所示,其中 imageData 是經過影像

處理後的bmp raw data 的起始位置,而 TargetBuffer 則是壓縮過後的

mpeg-4 frame 的起始位置。接下來我們就要對此 bmp raw data 進行

圖30 配置 codec input data 與 output data

mpeg-4 壓縮,使用 API encore( ),此 API 會將壓縮好的 mpeg-4 elementary stream 放到 TargetBuffer 裡。

● encore((HANDLE*)(&handle),ENC_OPT_ENCODE, &ENC_FRAME,NULL)

(57)

這個執行緒送到與StreamerletIs( )共享的 share memory 中,這個動作 則是藉由CapturToServer( )這個 API 來完成。

● CaptureToServer(void** StreamServer,int stream_type,int

input_channel,int real_time_capture,Medialtem *mediabuffer ) ;

至於client 端則只要再建立一個執行緒,跟圖 29 的

VideoStatusTimeFunc( )這個執行緒共同分享 raw audiovisual data 即 可,圖29 的 raw audiovisual data 是放在 global_a->Display_bmp 中。

3.2.2 一個 OpenCV 與串流平台結合的例子

在這裡我們利用OpenCV 提供的影像處理函式,與串流平台進行整

合,首先必須先將OpenCV 所提供的 header 檔加入我們的 Project,

如圖31 所示,如此我們就可以使用這些 header 檔所提供給我們的

Structure,OpenCV 提供了一個 Structure IplImage 專門用來處理 bmp 的 raw data,因此不管是再 server 端從攝影機得到的 raw data 或是

(58)

Client 端經過解碼而得的 bmp raw data 我們都必須將這些 raw data 的

資料填進這個Structure 中以便後續影像處理的程序,圖 32 則是

IplImage 的成員,我們必須將這個結構裡面的 imageData 指向想要進

行影像處理的bmp raw data,同時還必須設定好 width,height 等資料

圖 32 IplImage 的成員

接下來,為了使用 OpenCV 所提供的 API,我們必須將之前編譯出來

的library 加入到我們的 Project 中,加入的方法如圖 33 所示,在 IDE

(59)

加進來,這樣就可以使用OpenCV 的 API。在這邊我們將列出幾個

圖 33 於 IDE 介面中加入 Library OpenCV 與人臉追蹤有關的函式。

● CvHaarClassifierCascade* cvLoadHaarClassifierCascade(const char* directory,

CvSize orig_window_size );

此函式會載入利用海爾特徵的級聯分類器,OpenCV 已經幫我們訓練

了幾個級聯分類器都是以xml 的格式儲存,例如

haarcascade_frontalface_alt.xml 就是一個以正臉為目標樣本的分類器 ● CvSeq* cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade*

cascade, CvMemStorage* storage, double scale_factor=1.1,int min_neighbors=3, int flags=0,CvSize min_size=cvSize(0,0) );

在這邊image 是待檢驗的影像來源,cascade 則是

cvLoadHaarClassifierCascade( )的回傳值,cvHaarDetectObjects( )會回 傳待檢驗的影像來源有幾個我們有興趣的目標例如”人臉”。

(60)

● void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,

int thickness=1, int line_type=8, int shift=0 );

繪制簡單、指定粗細或帶填充的矩形,藉由cvHarrDetectObjects( )我

們可以得到目標在影像來源的位置,使用cvRectangle( )將目標以矩

形標記。

圖34 是結合臉部追蹤於 client 端的結果。

(61)

第四章 RTP Payload Format for MPEG-4 Video

Stream and MPEG-2 System

在本章我們將介紹一套標準的網路串流Open Source Live555,

Live555 實做了 RTP/RTSP 等標準網路串流協定,此套標準協定將幫

助我們建立一套標準的RTSP 串流平台。

在多媒體串流的應用中,為了達到即時傳輸的特性,我們捨棄了 TCP(Transmission control protocol)傳輸控制協議,因為 TCP 给與每個 封包序號,這個序號除了保證接收端能夠按照順序處理封包外,同時 也保證當封包遺失後,傳送端能夠重傳遺失的封包,但這個重傳的動 作將會影響到我們所要求的即時傳輸特性,因此,在要求即時傳輸的 多媒體串流應用中,我們捨棄了TCP 而改採用 UDP(User datagram protocol)用戶數據報協議,UDP 只提供資料的不可靠交付,也就是當 封包遺失後,UDP 將不採取任何動作,但同時我們也失去了當封包 順序錯誤時的回復能力,為了解決這個問題,我們再UDP 之上再加

上了RTP(Real-time transport protocol),RTP 在其檔頭裡面加了 16bits

的sequence number,利用此 sequence number 我們可以訂正封包順序

錯誤的情形。本章將敘述RTP 如何包裹 mpeg-4 video stream 及 mpeg-2

system,並藉由 live555[11]這套支援 RTP 串流格式平台驗證實際串流 情形。

(62)

4.1 RTP(Real-Time Transport Protocol)

RTP 提供點對點的網路傳輸功能,適用於各種即時傳輸的應用程 式當中,例如各種多媒體資料的傳輸,這些多媒體資料被包裝成特定 格式的RTP 封包,然後藉由 UDP 等網路協定傳送到網際網路上。圖 35 則為 RTP 封包的格式,從圖 35 我們可以知道 RTP 封包包含一個 檔頭以及在檔頭後面的負載資料,RTP 封包的檔頭格式在 RFC 3550 中有明確定義,而負載資料格式的切割方式,則根據負載資料不同而 有不同的定義,例如,RFC 3016[12]定義了 MPEG-4 影像流與聲音 流在RTP 封包的負載資料格式。 圖35 RTP 封包格式

4.1.1 RTP 檔頭資訊

參考圖36,RTP 檔頭有以下訊息 ● Version (V) : 2bits 指出RTP 的版本為何,RFC3550 把此值設定為 2。 ● Padding (P) : 1bits

此bit 指出封包的結尾有無 padding data,padding data 可以用於各種

加密演算法,padding 的最後一個 byte 則指出有幾個 padding bytes 是 可以忽略的。

(63)

● Extension(X) : 1bits

當此bit 設定為 1 時,代表這個 RTP 封包除了固定大小的檔頭外,還

放了額外的檔頭資訊。 ● CSRC count(CC) : 4bits

一個RTP Packet 可能是由兩個以上的來源藉由 Mixer 所組合而成的,

CSRC(Contributing source)則是來源串流的 ID,因此 CSRC count 會說

明這個RTP packet 是由幾個來源組成的。

圖 36 RTP Header Format[12] ● Marker (M) : 1 bit

用來說明這個封包是否有重要的事件,例如這個RTP 封包的 Payload

data 中有無 frame 的分界。 ● Payload type(PT) : 7 bits 指出payload data 的類型。 ● Sequence number : 16 bits

每增加一個RTP packet 這個數字就會線性增加,起始值是隨機的,藉

(64)

行重新排列。

● Timestamp : 32 bits

在即時擷取的影音資料時,這個值代表payload data 中第一個 byte 的

取樣時間。當我們要傳送的資料是已經儲存好的多媒體資料時,這個

值則是代表payload data 的播放時間點,因此只要 payload data 的影像

資料是屬於同一個VOP 則這些 RTP packets 的 Timestamp 的值都會是

一樣的,初始值則是隨機選擇。 ● SSRC : 32 bits

Synchronization source(SSRC)代表這個 RTP packet 的 ID,也就是當這

個RTP packet 藉由 Mixer 組合成其他 RTP 封包時,其他 RTP 封包的

CCRC 值就是這個 RTP 封包的 SSRC 值。

● CSRC list : 0 到 15 個項目,每個項目 32bits

列出這個RTP 封包是由哪些來源所組成的,列出那些來源的 SSRC

值。

4.1.2 RTP Payload Format for MPEG-4 Audio/Visual Streams

RFC3016 中定義了如何切割 MPEG-4 video stream 於 RTP payload

當中,但首先我們要先介紹mpeg4 video stream 中 video packet 的觀

念,在mpeg4 video 的壓縮中,使用 video packet 的目的是為了幫助

解碼器進行錯誤回復,一個vop 當中可能會包含很多個 video packet,

(65)

失的情形發生,不幸的是,當遺失的封包包含VOP header 資料時,

將會造成屬於這個VOP 的所有 Macorblock 都無法解碼,藉由 video

packet 將可以解決這個問題,根據 ISO 14496-2,一個擁有 video packet 的mpeg-4 simpel profile 將會如圖 37 所示,video packet 由許多

Macroblock 所組成,當解碼端讀取到 video packet 時,會開始讀取 Macroblock,每讀取完一個 Macroblock 解碼端會判斷接下來是否出現 video packet header 或 VOP header 若是沒出現這兩個 header 解碼端

就判斷接下來仍然是Macroblock,圖 38 則是 video packet 的細部結構

圖 37 一個有 video packet 的 mpeg-4 video stream

參考圖38,video packet 首先由連續 16 個 0 形成 resync_marker,在 resync_marker 之後會有 Macroblock number,

圖 38 video packet structure

Macroblock number 的 bit 數可以從 1bit 到 14bits,這個 bit 數是跟 VOP 的大小有關,舉例來說,一個vop_width = 320 而 vop_height = 240 參

(66)

考表12[6],則這個 Macroblock number 需要 9bits 來表示所有 VOP 的 Macroblock。每一個 VOP 其 Macroblock 都有特定的 Macroblock number 最左上角的 Macroblock 其 Macroblock number 為 0,最右下 角的Macroblock 其 Macroblock number 最大,每增加一個 Macroblock

表 12 Length of macroblock_number code[6]

則Macroblock number 會增加 1,以剛剛那個例子來說,若一個 video

packet 其 Macroblock number = 000011001,則代表這個 video packet

(67)

圖 39 Macroblock number = 25

Macroblock number 之後就是 1 個 bit 的 HEC(header_extension_code) flag,若是這個 flag 被設定成”1”,則在 HEC 之後會列出這個 video packet 所屬的 VOP 其檔頭資訊,例如 vop_width、vop_height、 vop_time_increment 等資訊,因此藉由 video packet 所攜帶的資訊,就

算之前的rtp 封包遺失,解碼器還是能找到目前這個 rtp 封包其

Macroblock 位於 VOP 何處,同時也可以藉由重複出現的 VOP 檔頭 資訊得到如何解碼的方式。

RFC3016 基本上建議一個 RTP Packet 裡面只放一個 VOP,這是

因為每個RTP Packet 檔頭的 Timestamp 會隨著不同 VOP 而不同,但

是在實際的應用上,這種作法會造成頻寬的浪費,因為有時候VOP

(68)

狀的VOP 其 coding block 很小也就是 video packet 很小,這種情形下

若是仍舊讓一個RTP packet 只包含一個 VOP 將會造成 OVERHEAD

的效應,因此RFC3016 允許串聯多個 VOP 於一個 RTP packet 中,有

鑑於此 RFC3016 對於 Timestamp 的設定有額外定義如下

● 若有多個VOP 包在同一個 RTP 裡,則 RTP 的 Timestamp 定義為

這些VOP 中最早出現的一個,至於其他 VOP 的 Timestamp 則可

由VOP header 的 modulo_time_base 與 vop_time_increment 進行推 算。

● 假如這個RTP packet 只包含 Configuration information(包括 Visual Object Sequence Header、Visual Object Header 和 Video Object Layer Header)則 RTP Timestamp 定義為下一個出現的 VOP。

● 假如RTP packet 只包含 visual object sequence end code 則 Timestamp 會設定為上一個 VOP 的 Timestamp。

RTP Timestamp 在 mpeg4 設定中其解析度為 90kHz,Timestamp 的算

法則如圖40 所示,因此若是每秒出現 25 個 VOP 則每增加一個 VOP

(69)

圖 40 RTP Timestamp

接下來我們要介紹RFC3016 中如何切割 MPEG-4 video stream 於 RTP

payload 中,在那之前我們先定義檔頭的意義

● Configuration information 包括 Visual Object Sequence Header, Visual Object Header 和 Video Object Layer Header。

● visual_object_sequence_end_code

● Group_of_VideoObjectPlane( )或者是 VideoObjectPlane( )、

video_plane_with_short_header( ),MeshObject( )及 FaceObject( )的 檔頭。

● video packet header ● gob_layer( )的檔頭。

知道mpeg-4 video codec 的檔頭定義後,接下來將說明 RFC 3016 對

於MPEG-4 video stream 的切割規則。

(1) Configuration information 和 Group_of_VideoObjectPlane( )應該要

(70)

(2) 若同時有多個 header 存放在 RTP payload 中,則在語法排序上最高 的要放在最前面,visual_object_sequence_end_code 是最低的語法 排序。

(3) 同一個 header 不能拆解到兩個不同的 RTP packet。

(4) 除非 VOP 的 size 太小,否則盡量一個 VOP 放在一個 RTP packet 裡面。

(5) 盡量讓同一個 video packet 放在同一個 RTP packet 中。

根據以上五項規則,RFC3016 列出了幾個 RTP Packet 的例子,如圖 41 所示,圖 41-d 是一個 RTP packet 包裝一個 video packet,這種包 裝方式適用於當網路常有掉封包的情形,因為即使包裝著 VOP header 的 RTP packet 遺失,其他的 RTP packet 也能藉由存放於 video packet header 中的 HEC information 進行解碼,這種作法就不需要額

外的RTP header 來幫助錯誤回復。圖 41-e 則是同時讓多個 video packet

放在一個RTP packet 的例子,這種包裝方式適用於網路頻寬較差的情

形,可以減少因為RTP/IP header 所造成的 overhead 的問題,然而這

也同時減少當RTP packet 遺失後解碼端進行錯誤回復的能力,因為

遺失一個RTP packet 將會損失多個 video packet,至於一個 RTP packet

要放多少個video packet 則是依據網路頻寬與封包遺失率來決定。在

(71)

代表這個mpeg-4 codec 不支援 video packet 的作法,當我們希望每個 RTP packet 都是固定大小時,往往就會形成如圖 41-f 的情形,這種情

形下的RTP packet 不適用於容易掉封包的網路,因為解碼端無法進行

錯誤回復。

(72)

4.2 Live555[11]

Live555 是一套提供 source code 的多媒體串流 c++函式庫,這套

函式庫實做了RTP/RTSP/RTCP/SIP 等標準協定,Live555 的函式庫可

以在Unix、Windows 等平台下進行編譯,同時 Live555 也是 GNU

Lesser General Public License(LGPL)自由軟體。

Live555 包含了 server 以及 client 部份,這套函式庫可以用來傳

送和接收多媒體串流資料,配合各種編碼器可以整合成video on

demand 串流模組,也可以配合相關之解碼器以及應用程式整合成為

串流播放模組,目前已經有 Player 整合 Live555 成為其支援串流視訊

的主要模組,例如VideoLan(VLC Player)以及 MPlayer。Live555 目前

可以支援多種codec 的標準 RTP 封裝及解封裝,如 AC3、AMR、

H.261、JPEG、MP3、MPEG1-2、MPEG-2 TS 、MPEG-4 ES、MPEG-4 Audio、CELP、以及 WAV 等。本節將描述 Live555 如何包裝 MPEG-4 ES 以及抽取出 RTP 封包並對其進行分析。

4.2.1 Rtsp Command in Live555

Live555 提供 RTSP 用於當做遠端連線的控制器,以下將介紹 Live 555 所提供的Command function。在這邊 Client 使用 VideoLanClient(VLC)

而這些Command function 的意義為當 Server 端收到某一個 Command

(73)

例如Server 收到”PLAY”Command 則會利用 handleCmd_PLAY( )做出 對應的動作。

● handleCmd_DESCRIBE( )

Client 以”DESCRIBE”要求 Server 以何種描述方式來描述播放資訊, 描述方式有三種application/sdl、application/rtsl、application/mheg,例 如client 要求 server 以 application/sdp 的方式來描述

rtsp:\\140.113.13.98:554/test.m4v 則 client 的要求將會如下所示

而server 的回應會如下所示,在這邊由於我們傳送的是 mpeg-4 ES 所

以server 的回應訊息會包括這個 test.m4v 檔的 configuration information(包括 visual object sequence header 等資訊)。

● handleCmd_Setup( )

(74)

一個rtsp://140.113.13.98:554/test.m4v 的 RTSP 連線,而 RTP 封包則是 再port 1470 和 1471 進行接收,Server 則回應會從 port 1472 和 1473

丟出RTP 封包。

Client 對 Server 的要求

Server 對 Client 的回應

● handleCmd_OPTIONS( )

Client 利用 OPTIONS 來詢問 Server 支援哪些功能,Server 則將其支 援的功能送出,如下面所示

● handleCmd_PLAY( )

Client 藉由 PLAY 這個指令通知 Server 開始傳送所需的多媒體資料,

如下面所示為Client 對 Server 的 Play 要求,npt = 0 代表要求檔案從

(75)

下面則為Server 收到 PLAY request 所做的回應

4.2.2 M4V RTP payload in live555

從上一小節我們可以知道當Client 送出”PLAY”Command 後,Server

將會開始傳送RTP packet,在 Live555 中藉由 buildAndSendPacket( )

進行RTP packet 的包裝與傳送。如圖 42 所示,packFrame( )會將

(76)

Payload 所需的資料放進去每個 RTP packet 中最後再利用 UDP 將這些

封包傳送出去。圖43 則為實際擷取這些 RTP 封包並對其封包內容進

行分析的結果,從圖43 我們可以看到 PACKET 0 到 PACKET7,因

為其payload data 都包裝同一個 VOP 所以其 RTP header 的 timestamp

.

圖 43 mpeg-4 video stream in RTP payload

(77)

的voprate=29.97/sec 則根據圖 39 其 Timestamp 會增加 90k/29.97 = 3003。至於 seq_num 則一開始會給個隨機的值之後每增加一個封包其 seq_num 會增加 1,Live555 包裝 RTP packet 的方式是藉由讓每個 RTP payload 固定大小為 1436bytes 來減少因為檔頭所造成的 overhead,但

這樣卻失去了mpeg-4 video packet 所提供的錯誤回復能力,以圖 43

為例,當PACKET 2 這個封包遺失,將會影響到 PACKET 1 的 video

packet (2)以及 PACKET 3 的 video packet (4),但若是使用圖 40-d 的包

數據

表 1 MPEG-2 Standards
圖 7 則是利用 UltraEdit 以 16 進位的方式顯示某一 m4v 檔,雖然 根據 ISO-14496-2[6]以及圖 5,m4v 開始於 Visual Object Sequence
圖 7 Display*.m4v by Hex
圖 15 mpeg-2 program stream 的結構成員
+7

參考文獻

相關文件

流感疫苗(包含 aQIV )是根據世界衛生組織建議 (WHO)的病毒株納入疫苗中。故 2014-2015 北半球 季節的流感疫苗是依據 2014 年 2 月中旬 WHO

印順 2

2-1 化學實驗操作程序的認識 探究能力-問題解決 計劃與執行 2-2 化學實驗數據的解釋 探究能力-問題解決 分析與發現 2-3 化學實驗結果的推論與分析

式,都是將終極實在理解為實體性的存在,本文沿用「根源實在論」 [註 2]

„ Start with a STUN header, followed by a STUN payload (which is a series of STUN attributes depending on the message type).

request even if the header is absent), O (optional), T (the header should be included in the request if a stream-based transport is used), C (the presence of the header depends on

n The information contained in the Record-Route: header is used in the subsequent requests related to the same call. n The Route: header is used to record the path that the request

媒體可以說是內容、資訊最大的生產者,但受制於 國際社交媒體及搜尋平台的經營手法,本地主流媒 體在發展網上業務時,面對不公平的競爭。 這些