看板 C_and_CPP 關於我們 聯絡資訊
感謝版上各位前輩以及估狗大神的幫忙 研究了一段時間後有了些心得,整理出來給其他有接觸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