測試環境設定:
- MAC OS X EI Capitan -- version 10.11.6
- live555 -- version 2016/10/12
- ffmpeg -- version 3.2
1. 下載並編譯 live555
$ git clone https://github.com/xanview/live555
$ cd live555
$ ./genMakefiles macosx
$ make
2. 下載 h.265 測試檔案,並使用 FFmpeg 將資料封裝成 MP4
a. download surfing.265 from http://www.live555.com/liveMedia/public/265/
b. copy surfing.265 to the testProgs directory, rename the file to test.265
c. download the latest ffmpeg and ffplay from http://evermeet.cx/ffmpeg/
d. run ffmpeg, and make sure it was built with "--enable-libx265" flag
LiaotekiMacBook-Pro:testProgs liaokuohsun$ ./ffmpeg ffmpeg version 3.2-tessus Copyright (c) 2000-2016 the FFmpeg developers built with Apple LLVM version 8.0.0 (clang-800.0.38) configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libass --enable-libbluray --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzmq --enable-version3 --disable-ffplay --disable-indev=qtkit --disable-indev=x11grab_xcb libavutil 55. 34.100 / 55. 34.100 libavcodec 57. 64.100 / 57. 64.100 libavformat 57. 56.100 / 57. 56.100 libavdevice 57. 1.100 / 57. 1.100 libavfilter 6. 65.100 / 6. 65.100 libswscale 4. 2.100 / 4. 2.100 libswresample 2. 3.100 / 2. 3.100 libpostproc 54. 1.100 / 54. 1.100
e. check test.265 media information
$ ./ffmpeg -i test.265 Input #0, hevc, from 'test.265': Duration: N/A, bitrate: N/A Stream #0:0: Video: hevc, yuv420p(tv), 1280x720, 25 fps, 25 tbr, 1200k tbn, 25 tbc
f. play test.265 media information
$ ./ffplay test.265
g. use ffmpeg to put hevc data into mp4 container
$ ./ffmpeg -i test.265 -acodec copy -vcodec copy test_h265.mp4
h. use ffmpeg to put hevc data into mp4 container
$ ./ffmpeg -i test.265 -acodec copy -vcodec copy test_h265.mp4
Note
- The data in test.265 is NAL units (start code prefixes). We can search "00 00 00 01" to find the start code
- The data in test_h265.mp4 will replace the start code with 4-byt size fields.
- Both test.265 and test_h265.mp4 can play by ffplay
3. 觀察 mp4 封裝資訊
若要觀察網路封包格式,可以使用 live555 的測試程式,啟動 RTSP server,並透過 ffmpeg 將檔案儲存為 mp4 格式。
$ ./testOnDemandRTSPServer $ ./ffmpeg -i rtsp://172.19.19.50:8554/h265ESVideoTest -vcodec copy h265_ex3.mp4
此 mp4 檔可以使用 VLC 與 FFMPEG 進行播放,檔案封裝方式是沒問題的。
註1:testH265VideoStreamer 預設採用 multicast 進行播放,不適合進行此項測試。
註2:openRTSP 能夠將某些媒體封裝成 mp4 檔案,但並無法將 h.265 封裝成 mp4,因此若要自行實作 H265 to MP4,還是應該要參考 FFmpeg 。
我們可由 SDP 得知 h.265 的 SPS/PPS/VPS 如下:
sprop-vps=QAEMAf//AIAAAAMAAAMAAAMAAAMAALUCQA==; sprop-sps=QgEBAIAAAAMAAAMAAAMAAAMAAKACgIAtH+W1kkbQzkkktySqSfKSyA==; sprop-pps=RAHBpVgeSA==
至 gpac 取得最新版本 mp4box,設定 alias MP4Box="/Applications/Osmo4.app/Contents/MacOS/MP4Box" 以方便存取,接著執行 MP4Box h265_ex3.mp4 -diso,將所有資訊都輸至 h265_ex3_info.xml。
此時可以看到 SPS/PPS/VPS 被封裝在 hvcC box 之內,並且其 NALU type 分別是 32,33,34。
比較 xml 與 SDP 內的 SPS/PPS/VPS 內容,可以發現內容一致。
(可透過 http://tomeko.net/online_tools/base64.php?lang=en 進行 Base64轉換)
4. 自行撰寫程式,將 H.265 封裝成 mp4
此處作法與之前 H.264 封裝類似,差異處只在於 H.265 多了一個 VPS,ffmpeg 的封裝實作可以參考 hevc_mp4toannexb_bsf.c。作法原理是使用 FFmpeg API,將 SPS/PPS/VPS 都設定到 extradata 即可。以上述資料為例,封裝之後,extradata 內容應該如下:
VPS = 40010C01FFFF00800000030000030000030000030000B50240,SPS=42010100800000030000030000030000030000A00280802D1FE5B59246D0CE4924B724AA49F292C8,
PPS=4401C1A5581E48
此處作法與之前 H.264 封裝類似,差異處只在於 H.265 多了一個 VPS,ffmpeg 的封裝實作可以參考 hevc_mp4toannexb_bsf.c。作法原理是使用 FFmpeg API,將 SPS/PPS/VPS 都設定到 extradata 即可。以上述資料為例,封裝之後,extradata 內容應該如下:
VPS = 40010C01FFFF00800000030000030000030000030000B50240,SPS=42010100800000030000030000030000030000A00280802D1FE5B59246D0CE4924B724AA49F292C8,
PPS=4401C1A5581E48
實際程式範例可以參考 https://github.com/alb423/iFrameExtractor,此範例可在 iOS simulator 上正常運行。
參考資料: