I420格式介紹
在webrtc中android和ios系統(tǒng)采集攝像頭獲取到原始數(shù)據(jù)后,
一幀原始圖像會(huì)被轉(zhuǎn)化為標(biāo)準(zhǔn)的YUV420P格式,也就是I420格式,
轉(zhuǎn)換的函數(shù)使用的是libyuv中的ConvertToI420()函數(shù)
YUV格式詳細(xì)講解
進(jìn)行裁剪操作需要對(duì)I420格式的內(nèi)存分布有深入的了解,推薦大家看這篇文章:
http://blog.csdn.net/jefry_xdz/article/details/7931018
其中I420就是YUV420P格式
裁剪圖像的含義
裁剪就是去掉某些區(qū)域,剩下指定的區(qū)域,
本文所講的裁剪就是摳圖,摳去出原圖像的某個(gè)內(nèi)部區(qū)域
裁剪的用途
我們可以將裁剪后的視頻傳遞給h264編碼器,然后將輸出保存成MP4文件(還需要加上聲音),即可模仿Instagram軟件中拍攝方形視頻的功能。
代碼如下:
代碼中假設(shè)視頻寬度和“Image Stride”相同
什么是stride? 參考這篇文章:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa473780(v=vs.85).aspx
這里使用到了webrtc中的部分代碼其中I420VideoFrame格式定義為
https://code.google.com/p/webrtc/source/browse/trunk/webrtc/video_frame.h?r=8434
所以dst_frame是這樣生成的:
dst_frame->CreateEmptyFrame(dst_width_, dst_height_,
dst_width_, (dst_width_ + 1) / 2,
(dst_width_ + 1) / 2);
int zp_getImageBlock(const I420VideoFrame& src_frame, I420VideoFrame& dst_frame,int start_w,int start_h)
{
//I420格式說(shuō)明參考的這個(gè)博客 http://blog.csdn.net/jefry_xdz/article/details/7931018
assert(start_w >= 0 && start_h >= 0);
//start_w 開(kāi)始點(diǎn)距離左邊的距離
//start_h 開(kāi)始點(diǎn)距離上邊的距離
//起始點(diǎn)可以決定裁剪視頻的哪個(gè)區(qū)域,不一定是中心區(qū)域
int src_width = src_frame.width();
int src_height = src_frame.height();
int dst_width = dst_frame.width();
int dst_height = dst_frame.height();
if (start_w + dst_width > src_width ||
start_h + dst_height > src_height) {
//區(qū)域設(shè)置不合理,已經(jīng)超出原始視頻范圍
return -1;
}
if(dst_height > src_height || dst_width > src_width)
{
//只能縮小,不能擴(kuò)大,擴(kuò)大使用libyuv的scale函數(shù)
return -1;
}
int w_cut = start_w;
int h_cut = start_h;
//切除的部分必須是偶數(shù),因?yàn)槊克膫€(gè)像素對(duì)應(yīng)一個(gè)u,v
assert(w_cut%2==0);
assert(h_cut%2==0);
const uint8* src_y = src_frame.buffer(kYPlane);
uint8* dst_y = dst_frame.buffer(kYPlane);
const uint8* src_u = src_frame.buffer(kUPlane);
uint8* dst_u = dst_frame.buffer(kUPlane);
const uint8* src_v = src_frame.buffer(kVPlane);
uint8* dst_v = dst_frame.buffer(kVPlane);
//取Y
for (int row = 0; row < dst_height; ++row) {
for (int col = 0; col < dst_width; ++col) {
//計(jì)算目標(biāo)區(qū)域的下標(biāo)對(duì)應(yīng)于源數(shù)據(jù)的哪個(gè)下標(biāo)
//目標(biāo)區(qū)域的下表row*dst_width+col
//(h_cut+row)*src_width+(w_cut+col)
dst_y[row*dst_width+col] = src_y[(h_cut+row)*src_width+(w_cut+col)];
}
}
//取U,V
int k = 0;
for (int row = 0; row < dst_height; row+=2) {
for (int col = 0; col < dst_width; col+=2) {
int old_index = (h_cut+row)*src_width/4+(w_cut+col)/2;
dst_u[k] = src_u[old_index];
dst_v[k] = src_v[old_index];
k++;
}
}
return 0;
}
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。