作者SocketAM2 (AM2)
看板C_and_CPP
標題Re: [問題] ffmpeg解h264的stream
時間Mon Mar 26 18:55:44 2012
感謝版上各位前輩以及估狗大神的幫忙
研究了一段時間後有了些心得,整理出來給其他有接觸ffmpeg的人參考
1.想要用ffmpeg的API解h264碼,
最主要就是使用avcodec_decode_video2()和sws_scale()
詳細init方法估狗可以找到很多Example Code,請自行估狗上一行的關鍵字
重點就是
AVPacket avpkt.data 先設定好指向存著一段適當影片串流的內容
AVPacket avpkt.size 這好這段內容的長度(byte)
然後把avpkt丟入avcodec_decode_video2()
只要丟入的東西合法就會回傳正數(應該是資料的byte數),
若有解出畫面got_picture就會回傳正數,視avpkt.data內容不一定解出畫面
拿到的畫面丟入sws_scale換成需要的格式、大小
2.要對h264串流內容有一定程度的認識,一些資料提供如下
h264詳細說明:
http://www-ee.uta.edu/dip/courses/ee5356/H264systems.pdf
請特別注意table 7.1,說明各個nalu的定義
中文概述(工研院電通所):
http://goo.gl/gy0I
如果你對h264一點概念都沒有,看這個。 有一定了解就不用看了
其他許多中等程度的說明就請你靠估狗大神了,
小弟有點到的網頁內容正確率都挺高的
3.補充說明剛剛第一點中"應該丟入avpkt.data的東西(需要2的知識)
一個packet的內容,從nalu type = 9的delimiter開始,
一個nalu type = 1 ~ 5的frame內容結束,不包含下一個00 00 00 01
中間可能有nalu type = 6、7、8之類的東西,每個nalu都由00 00 00 01開始。
delimiter的RBSP定義了這個packet的種類,詳細都請看第二點第一個連結
一段包含了type978...5的packet在第一次丟入時並無法解碼出畫面
可以連續執行avcodec_decode_video2()兩次解出這個I-frame。
我推測的理由是第一次丟入的7、8含有的parameter set無法被用在當個packet
這次執行相當於"告知解碼參數"
所以下一次執行才能成功解碼
如果是一段包含type9...1之類的P-frame(一般來說),
需要先解過含有type978...5的最接近的一個I-frame,
並連續解碼這之間的所有type9...1,差一個都不行(這就是p-frame)
4.假如你需要做"同尺寸、只改格式"並像小弟一樣有效率的要求
可以用舊版ffmpeg才有的img_convert()取代sws_scale()
img_convert()不能轉換尺寸,但轉換格式的效率遠高於sws_scale()
一般而言直接把avcodec_decode_video2()的結果拿來用是危險的
ffmpeg官方說法是那裡面的結構希望維持黑盒子,使用者要另外取出
雖然我手邊測試的影片是可以算出padding,但有風險
以上為小弟的一些粗淺心得
詳細的內容網路上真的很多資料我就不費力氣重述了
如有缺漏或觀念錯誤請各位先進不吝指正以造福後來者
最近在學python的GUI和opencv的使用
有相關問題也歡迎來信討論,互相交流一起進步
謝謝收看
※ 引述《SocketAM2 (AM2)》之銘言:
: 標題: Fw: [問題] ffmpeg解h264的stream
: 時間: Fri Mar 23 22:35:47 2012
:
: ※ [本文轉錄自 Programming 看板 #1FR5YjDb ]
:
: 作者: SocketAM2 (AM2) 看板: Programming
: 標題: [問題] ffmpeg解h264的stream
: 時間: Fri Mar 23 19:04:11 2012
:
: 開發環境:VC2008、ffmpeg的SDK
:
: 關於h264的Raw Byte Sequence Payload小弟已經有相當程度的熟悉
: ffmpeg中用到的AVpacket、AVframe等等的初始化也都沒問題
:
: 現在剩下的問題有兩個,
: 都是關於AVPacket avpkt裡面的data要餵進那些nal unit的byte,
: 才能在丟入ffmpeg中用來decode的函數avcodec_decode_video2()後正確解碼
:
: 我嘗試把一段h264 raw stream中一段(HEX)
: 00 00 00 01 09 ......(這是一段delimiter,pic_type: I-frame)
: 00 00 00 01 27 ......(這是一段SPS)
: 00 00 00 01 28 ......(這是一段PPS)
: [00 00 00 01 06 ......] * 3 (連續三段SEI)
: 00 00 00 01 05 ......(這是I-frame的內容)
: 餵進avpkt.data,並把這段的總長(byte)丟進avpkt.size
: 結果avcodec_decode_video2()有回傳非零的值,但卻沒有got_picture
:
: 嘗試連續做上一段的事情兩次,
: 則在第二次回傳非零的值,並且有got_picture
:
: 請問第一個問題:是否第一次把SPS、PPS丟入avcodec_decode_video2()時,
: 這些parameter set的內容並無法使用在丟進去的當下這個AVPacket,
: 這第一次丟入avcodec_decode_video2()實際上相當於告知解碼器解碼的參數,
: 而在第二次的時候才能順利解碼並且got_picture?
: 有大大可以詳細點的說明avcodec_decode_video2()的使用方法嗎?
: http://ffmpeg.org/上面的說明雖然幫助很大,但許多細節都沒提到......
:
: =========================================================================
:
: 第二個問題:
:
: avcodec_decode_video2()成功解碼,把畫面存在AVFrame pFrame裡面之後,
: 若我想要把這個解好的畫面"長寬大小不變"的依據Y、U、V取出存在另一塊記憶體中,
: 我需要知道這個解完的frame的編碼方式(YUV420、422或其他等等)
: 和在AVFrame pFrame中存放排列的方法,
: 請問有人知道要怎麼獲取這段解好的原始資料嗎?
:
: 現在暫時可行的做法是使用sws_scale(),因為它的output是我知道排列方式的。
: 但我擔心即使是透過sws_scale()做"原尺寸、原編碼方式"的輸出,
: 實際上仍然需要相當的計算effort,
: 也就是這一步造成了多於計算資源的浪費。
: 小弟希望在有限的電腦上盡可能的快速處理大量高解析度影像,
: 故對效率性希望能做一些提高。
:
:
: --
: 小弟這部分完全是上網找資料自學,也許有些觀念其實存在謬誤也請不吝指點
: 另外,現在要去吃個飯,晚上回來一定會回應,
: 若有大大作回覆的,或是認為我還需要補充說明什麼的
: 請不要一小時內沒看我回應就誤解小弟發問誠意不足丟了就跑,實在是吃飯時間......
: 總之請各位先進不吝指教,謝謝
:
: --
: ※ 發信站: 批踢踢實業坊(ptt.cc)
: ◆ From: 202.39.60.73
:
: ※ 發信站: 批踢踢實業坊(ptt.cc)
: ※ 轉錄者: SocketAM2 (123.192.25.86), 時間: 03/23/2012 22:35:47
: 推 deepkh:施主您好 若將這些 研究好 不就是您的不可取代之處嗎 03/23 23:59
: ㄜ...其實我沒把自己想的那麼偉大,就是想知道去哪可以學到這些而已
: → deepkh:其實 這應該去國外網站問 會比較有答案 03/23 23:59
: 請問有推薦的網站或論壇嗎,我去估狗
: → deepkh:SPS PPS 會有你要的資訊 width/height 03/24 00:01
: 我要的資訊不是長寬,這都有了
: 我要的是存著解好YUV的array的排列方式,我要直接access每個pixel
: ※ 編輯: SocketAM2 來自: 123.192.25.86 (03/24 00:14)
: 推 Bencrie:印象中都是 yuv420p,先存 y plane 再來才是 uv planes 03/24 00:22
: → Bencrie:RGB是直接一個 pixel 三個 channel 排在一起 03/24 00:23
: 我知道YUV420P、YV12等等等結構的擺放方式
: 我想知道的是avcodec_decode_video2()解出存在AVFrame pFrame裡的結構
: 根據查到的資料和實際檢視,有些我弄不懂的padding之類
: 我希望藉由直接存取pFrame取出我需要的pixel資訊
: 所以發問請教有沒有人知道那裏面的資訊是如何擺放的
: ※ 編輯: SocketAM2 來自: 123.192.25.86 (03/24 00:43)
: → adxis:發到他的 mail list 上去問吧 這部分沒有文件 03/24 02:39
: → adxis:或者翻翻看 libcodec/h264.h , h264.c ? 03/24 02:42
......是的,我該去啃他的......我知道錯了
: 推 deepkh:去 StackOverFlow 問看看吧 03/25 07:09
好網站
: → deepkh:你的問題在於大家不知道你要問什麼 got_picture 會傳回什麼 03/25 07:11
: 推 tw0614:用avpicture_layout()? 或者直接跳過每行padding 32BYTE 03/25 15:12
謝謝 我去找找資料
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 202.39.60.73
推 adxis:推回饋! 03/26 19:18
→ Ianlm:回饋的精神真的很值得鼓勵!棒! 03/26 21:50
推 chengcti:Good Job. 無私奉獻的精神, 後面可少走冤枉路. 03/26 22:59
推 VictorTom:推回饋:) 03/27 00:21
推 m2002fe:感謝你~~受益不少~ 04/25 21:45