x.264多執行緒并行編碼時,輸出多個nalu包,264流順序是這樣的:SPS PPS SEI IDR IDR IDR IDR P_Slice P_Slice P_Slice P_Slice..每一個I幀 P幀都產生了4個nalu,再用mp4v2封裝成mp4格式,如果把每個nalu都封裝,得到的視頻會變慢4倍,而且有些播放器放不了,請問4執行緒時,每幀的4個nalu該怎么封裝呢?
uj5u.com熱心網友回復:

我只是主執行緒x264_encoder_encode 沒用多執行緒
uj5u.com熱心網友回復:
這里的多執行緒指的是slice并行模式,pParam->i_threads = 4,param.b_sliced_threads=1
uj5u.com熱心網友回復:
有看到網上說int b_sliced_threads; // 如果為false,則一個slice只編碼成一個NALU,否則有幾個執行緒,則編碼成幾個NALU。此處我改為0后(想編碼為一個NALU還有啥引數需要配置?),編碼第一幀時候就會報錯
lookahead thread is already stopped是原始碼中x264_encoder_encode()下面代碼打出來的
if( h->lookahead->b_exit_thread )
{
x264_log( h, X264_LOG_ERROR, "lookahead thread is already stopped\n" );
return -1;
}
uj5u.com熱心網友回復:
一個不嚴謹的想法,因為FFmpeg+x264可以產出正確的mp4,而且管封裝格式的是FFmpeg(有可能呼叫了mp4v2或其它),那查閱FFmpeg如何封裝多個“并發”nalu就是一個思路。另外,如果一式四份,那我只拿一份是不是就可以解決了?
uj5u.com熱心網友回復:
就是用mp4v2封裝編碼后的264資料,對應的I幀P幀nalu用的函式是MP4WriteSample();應該并沒有專門針對并行編碼后多nalu的封裝函式(我目前為止沒查到。。),另外,并行編碼并不是一式四份,不然這樣并行也就沒意義了
uj5u.com熱心網友回復:
先把多個nalu包組成一幀,再用mp4v2封裝成mp4uj5u.com熱心網友回復:
感謝您的回復,“把多個nalu包組成一幀”,請問有什么檔案的嗎?實在是沒搞明白怎么把多個nalu組合成一幀,請指教,謝謝
uj5u.com熱心網友回復:
nalu概念就是幀的概念。如果一個nalu太大就會分為多個slice。你若直接取到nalu就不必做處理。若是取的slice則需求進行組包在保存檔案時SPS PPS SEI IDR組在一起作為一幀保存
uj5u.com熱心網友回復:
和之前的一個帖子類似,里面說的比較詳細,https://bbs.csdn.net/topics/390404342?page=1
param.i_threads設定成1的時候,碼流是SPS PPS SEI IDR P,param.i_threads設定成4的時候就成了SPS PPS SEI IDR IDR IDR IDR P P P P,每一個I 和P幀都變成了4個,想請問這種情況改怎么封裝?
uj5u.com熱心網友回復:
分成slice主要是用于網路傳輸。標準的話,看看nalu header定義和ffmpeg rtpdec部分代碼/不標準的話,直接把包拼起來就可以uj5u.com熱心網友回復:
rtpdec里面沒看出來我這種情況的組包方法呢,,

用4執行緒的原因是發現編碼速度更快,對比1和4執行緒編碼后的H264資料,1執行緒:SPS PPS SEI I P .... 4執行緒:SPS PPS SEI I1 I2 I3 I4 P1 P2 P3 P4....
4執行緒的I1(以下都簡稱I1,4執行緒的其他同理為I2 I3 I4)結尾:AD 6B 5A B7 (之前的資料和I相同,why???)
對應此位置的1執行緒的I幀(以下都簡稱I)資料為:AD 6B 5A B6 B5 AD 6B
疑問1:為什么只有最后一位不同?組包時候對這一位該怎樣處理?
插張圖,更直觀

I2起始: 00 00 00 01 65 01 E2 22 10 E8 91 40
我的理解是把I1 I2 I3 I4的slice_data組成和I的一樣,決議I2如下圖

疑問2:此處I2的slice_data銜接上I1的slice_data應該和I的資料相同,即為B5 AD 6B.....,實際我決議出來的卻是24 50 00 12.....
請問應該怎樣拼接I1 I2 I3 I4的slice_data組成I,還請指教,非常感謝
uj5u.com熱心網友回復:
資料不全沒看明白只記得一幀的第一個slice是2為拼成1位元組,好像后面的是直接不要第一個位元組
uj5u.com熱心網友回復:
您說的這個沒太看明白呢
1執行緒的I幀資料是:00 00 00 01 65 88 84 3A 08 43 E0 00 24 4B 2C ........ 59 F5 6B 5A D6 B5 AD 6B 5A B6 B5 AD 6B 55 55 .........
4執行緒的I1資料是: 00 00 00 01 65 88 84 3A 08 43 E0 00 24 4B 2C ........ 59 F5 6B 5A D6 B5 AD 6B 5A B7
I2資料是: 00 00 00 01 65 01 E2 22 10 E8 91 40 00 48 7E 4C 99 32 64 A9 2A
附圖

用工具H264BSAnalyzer分析出I2 的slice_header是:01 E2 22 10 再加上6bit資料[1110 10](沒理解錯的話是按bit的),所以原始I2資料10的下一byte:E8的低2bit開始是slice_data,再接上后面的資料91 40....也即I2的slice_data是[00 + 1001 0001 0100 0000.......]
I1最后一個資料是B7[1011 0111],根據rbsp_slice_trainling_bits的話最后一位1應該是補上去的,所以I1的slice_data最后一個資料是[1011 011].和I2的slice_data 拼在一起的話是[1011 011 + 00 +1001 0001 0100 0000]也即[1011 0110 0100 1000 1010 0000 0.....]也即B6 28 A0.......和最原始的B6 B5 AD 6B 55 55 對不上。。
不清楚是不是這樣分析的還請指教下 謝謝
uj5u.com熱心網友回復:
這個沒處理過。我也查了下,看配置哪里可以再修改下uj5u.com熱心網友回復:
非常感謝,
貼下現在在用的x264編碼配置:
x264_param_default(Param);
x264_param_default_preset(Param, "ultrafast", "zerolatency");
Param->i_csp = X264_CSP_I400;
Param->i_width = 640;
Param->i_height = 480;
Param->i_fps_den = 1;
Param->i_threads = 4;
x264_param_apply_profile(Param, "high");
【有查到i_threads和 b_sliced_threads兩個引數, b_sliced_threads如果為false,則一個slice只編碼成一個NALU;否則有幾個執行緒,則編碼成幾個NALU】。原始碼中zerolatency 會設定b_sliced_threads = 1
嘗試把b_sliced_threads賦為0(或者也試過用其他的如fastdecode等),在編碼時候會報錯,x264 [error]: lookahead thread is already stopped,是x264_encoder_encode()里因為b_exit_thread為1打出來的,再加列印發現,
原始碼中的
if(pic_in != NULL)
{
}
else
{
printf("set h->lookahead->b_exit_thread = 1 \n");//add by xxx
......
h->lookahead->b_exit_thread = 1;
........
}
在編碼第一幀時候,就會執行到else分支,打出了四次自己加的列印:set h->lookahead->b_exit_thread = 1 ,再編碼第二幀報錯x264 [error]: lookahead thread is already stopped
然后就沒找到更進一步的原因呢。。剛接觸,很多不清楚,還望指教,蟹蟹蟹蟹
uj5u.com熱心網友回復:
兩個方向1.改配置,編碼后的碼流為單NALU,2.現有配置下編出來的多NALU碼流怎么組裝
還請大神們能指教
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/99462.html
標籤:多媒體/流媒體開發
上一篇:Oracle作業1
下一篇:又沒有免費的視頻下載軟體?
