0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何為Ctrl-SW增加輸出NV12視頻的功能?

YCqV_FPGA_EETre ? 來源:靈思中文社區(qū)論壇 ? 作者:付漢杰 ? 2021-05-24 17:37 ? 次閱讀

01介紹

Xilinx提供超低延時編解碼方案,并提供了全套軟件。MPSoC Video Codec Unit提供了詳細(xì)說明。其中的底層應(yīng)用軟件是VCU Control-Software(Ctrl-SW)。

本文主要說明為Ctrl-SW增加輸出NV12視頻的功能。

1.1. VCU輸入和輸出格式

Video Codec Unit(VCU) 輸入和輸出都是是NV12/NV16格式的視頻,Y分量存放在一塊連續(xù)內(nèi)存區(qū),UV分量交替存放在Y分量后面的連續(xù)內(nèi)存。具體信息,可以參考VCU Product Guide中的“Source Frame Format”和“Memory Format”。

Ctrl-SW的輸入文件最好是NV12/NV16格式的視頻文件,由于不需要做格式轉(zhuǎn)換,幀率(FPS)最高。但是Ctrl-SW的輸出文件缺省是圖像真實(shí)分辨率的I420/I422的文件,其中的Y、U、V分量,各自存在一塊連續(xù)內(nèi)存,UV分量沒有像NV12/NV16格式的視頻交替在一起。可以使用FFMPeg等工具,將I420的文件,轉(zhuǎn)換成NV12/NV16格式的文件。

1.2. VCU內(nèi)存的高度和寬度要求

對于視頻的輸入內(nèi)存區(qū),VCU要求高和寬都按32向上對齊。對于1920x1080分辨率,輸入的buffer大小至少是1920x1088字節(jié);對于3840x2160分辨率,輸入的buffer大小至少是3840x2176字節(jié)。

對于視頻的輸出內(nèi)存區(qū),VCU要求寬以256地址對齊,高以64地址對齊。對于1920x1080分辨率,輸出的buffer大小是2048x1088字節(jié);對于3840x2160分辨率,輸出的buffer大小是3840x2176字節(jié)。

1.3. VCU內(nèi)存的pitch

視頻數(shù)據(jù)在內(nèi)存區(qū)中存放時,兩行之間的數(shù)據(jù)可以有間隔。對于每個像素的Y分量用8-bit表示的圖像,每個像素的Y分量對應(yīng)內(nèi)存的一個字節(jié),圖像Y分量的每一行對應(yīng)的內(nèi)存大小就是其寬度代表的字節(jié)數(shù)。比如1920x1080,每一行圖像的Y分量需要1920字節(jié)內(nèi)存。如果以2048字節(jié)來存儲一行1920x1080的圖像數(shù)據(jù),則在前面存放圖像數(shù)據(jù),后面的數(shù)據(jù)被VCU忽略。也可以參考PG252的“Figure 7: Frame Buffer Pitch”。

02顯示YUV文件 2.1. 工具RAW yuv player

Github上的RAW yuv player 能顯示YUV文件,它的舊版本Sourceforge RAW yuv player在Sourceforge上。RAW yuv player的菜單“Colour”下,有各種顏色格式,菜單“Size”下有各種分辨率;菜單“Zoom”下可以選擇圖像縮放比例。

RAW yuv player的YUV420(YV12)格式,就是I420格式,可以顯示Ctrl-SW缺省輸出的YUV文件。RAW yuv player的NV12格式,也是Ctrl-SW的NV12格式,可以顯示修改后的Ctrl-SW輸出的YUV NV12文件。

2.1.1. 技巧

各種YUV文件,第一片數(shù)據(jù)一般都是分量Y。如果發(fā)現(xiàn)YUV文件的顯示有問題,可以設(shè)置好分辨率,在菜單“Colour”下選擇“Y”,只看其中的分量Y,當(dāng)成黑白圖片看。如果黑白圖片是正常的,說明分量Y是對的。

2.2. hexdump

如果圖片內(nèi)容不對,可以使用二進(jìn)制比較工具比較錯誤圖片和正確圖片,比如Beyond Compare。比較的時候,注意取消對齊設(shè)置。

如果沒有二進(jìn)制比較工具,可以使用hexdump把YUV文件按HEX格式轉(zhuǎn)換為文本文件,再用文本比較工具,比如kdiff3、meld進(jìn)行比較。hexdump輸出時,會輸出星號“*”代替一樣的行;多個重復(fù)行,也只輸出一個星號。為hexdump加上“-v”選項(xiàng),則會輸出所有數(shù)據(jù)。

xilinx@XSZHANKF$ hexdump -x test_1080p_h264.264.1f.i420.1920x1080.yuv 》 test_1080p_h264.264.1f.i420.1920x1080.yuv.hex

xilinx@XSZHANKF$ hexdump -v -x test_1080p_h264.264.1f.i420.1920x1080.yuv 》 test_1080p_h264.264.1f.i420.1920x1080.yuv.v.hex

03輸出NV12/NV16格式文件

如果Ctrl-SW能輸出NV12/NV16格式的文件,Ctrl-SW就能直接對自己的文件進(jìn)行編碼,測試時更加方便。

經(jīng)過研究,在Ctrl-SW 2020.2里,實(shí)現(xiàn)了輸出NV12/NV16格式文件的功能。

3.1. 選項(xiàng)

Ctrl-SW里有三種分辨率,分別是圖像的真實(shí)分辨率,Meta數(shù)據(jù)分辨率,內(nèi)存塊(buffer)分辨率。

圖像的真實(shí)分辨率,是真實(shí)顯示的分辨率。

在Ctrl-SW里,為YUV數(shù)據(jù)分配內(nèi)存時,根據(jù)圖像分辨率,并按對齊要求像是對齊圖像分辨率后,得到Y(jié)UV數(shù)據(jù)的內(nèi)存塊大小,這就是對應(yīng)的內(nèi)存塊(buffer)分辨率。對于解碼,1920x1080分辨率的內(nèi)存塊是2048x1088字節(jié);3840x2160分辨率的buffer是3840x2176字節(jié)。

另外分配內(nèi)存后,每個內(nèi)存塊有一個對應(yīng)的Meta數(shù)據(jù),保存YUV數(shù)據(jù)的分辨率。Meta數(shù)據(jù)分辨率可能比內(nèi)存塊分辨率低。1920x1080分辨率的Meta數(shù)據(jù)分辨率是2048x1088;而3840x2160分辨率的Meta數(shù)據(jù)分辨率卻是3840x2160,在高度上并沒有像1080p時向上對齊。

所以輸出NV12/NV16的視頻時,也有多種組合。為了測試方便,實(shí)現(xiàn)了輸出各種組合的NV12/NV16的視頻。

如果使用選項(xiàng)“-yuv-nvx”,按得到的Meta數(shù)據(jù)的分辨率信息,從Y和UV分量的地址,逐行寫入到文件。

如果使用選項(xiàng)“-yuv-nvx-1buffer”,行依照pitch長度,高使用分辨率的高度并向上按64字節(jié)對齊,計算出YUV整個的內(nèi)存區(qū)大小,相當(dāng)于內(nèi)存塊(buffer)分辨率,一次性寫入到文件。

如果使用選項(xiàng)“-yuv-nvx-stride”,行依照pitch長度,高使用分辨率的高度,從Y和UV分量的地址,逐行輸出。相當(dāng)于寬按內(nèi)存塊(buffer)分辨率,高按Meta數(shù)據(jù)分辨率輸出。

如果使用選項(xiàng)“-yuv-nvx-dispay”,按得到的顯示分辨率信息,從Y和UV分量的地址,逐行輸出。

另外,還附帶增加了輸出YUV文件時跳幀、抽幀的功能。如果使用選項(xiàng)“--yuv-skip-num”,則前面的指定數(shù)量的幀不會被輸出;比如指定5,前面的5幀不會被寫入到Y(jié)UV文件。如果使用選項(xiàng)“--yuv-skip-interval”,則指定數(shù)字的倍數(shù)序號的幀,才會被輸出;比如指定數(shù)字3,則只有序號是3的倍數(shù)的幀才會被寫入到Y(jié)UV文件。

04代碼

在Ctrl-SW 2020.2里,添加如下代碼后,可以直接輸出NV12/NV16格式的文件。

下面是增加的全局變量定義。

int gi_yuv_output_skip_frame_num=0;

int gi_yuv_output_skip_frame_interval=0;

int gi_yuv_output_nvx_flag=0;

int gi_yuv_output_nvx_1buffer_flag=0;

int gi_yuv_output_nvx_stride_flag=0;

int gi_yuv_output_nvx_dispay_flag=0;

int gi_yuv_output_dispay_width=0;

int gi_yuv_output_dispay_height=0;

下面是增加的ctrlsw_decoder的命令行選項(xiàng)。

opt.addInt(“--yuv-skip-num”, &gi_yuv_output_skip_frame_num, “Skip frame number before writing YUV file.”);

opt.addInt(“--yuv-skip-interval”, &gi_yuv_output_skip_frame_interval, “Interval frame number when writing YUV file.”);

opt.addFlag(“-yuv-nvx”, &gi_yuv_output_nvx_flag, “Output NV12/NV16 YUV file.”, 1);

opt.addFlag(“-yuv-nvx-1buffer”, &gi_yuv_output_nvx_1buffer_flag, “Output one continuous NV12/NV16 buffer to YUV file.”, 1);

opt.addFlag(“-yuv-nvx-stride”, &gi_yuv_output_nvx_stride_flag, “Output NV12/NV16 YUV file with VCU round-up padding/stride.”, 1);

opt.addFlag(“-yuv-nvx-dispay”, &gi_yuv_output_nvx_dispay_flag, “Output NV12/NV16 YUV file with display width.”, 1);

下面是在UncompressedOutputWriter::ProcessFrame()內(nèi)部增加的判斷是否輸出NV12/NV16格式的視頻文件的判斷代碼。

if( gi_yuv_output_skip_frame_num_local 《 gi_yuv_output_skip_frame_num )

{

return;

}

if( 0 == (gi_yuv_output_skip_frame_num_local%gi_yuv_output_skip_frame_interval) )

{

return;

}

if( ( 1 == gi_yuv_output_nvx_flag ) || ( 1 == gi_yuv_output_nvx_1buffer_flag )

|| ( 1 == gi_yuv_output_nvx_stride_flag ) || ( 1 == gi_yuv_output_nvx_dispay_flag ) )

{

ProcessFrameNVx( tRecBuf, info, iBdOut);

return;

}

下面是顯示視頻參數(shù)的代碼,用于調(diào)試,可以被屏蔽掉。

void UncompressedOutputWriter::ShowVideoInfo(AL_TBuffer& tRecBuf, AL_TInfoDecode info, int iBdOut)

{

// only print one time.

static int i_call_time=0;

if( 0 != i_call_time )

{

return;

}

i_call_time++;

iBdOut = convertBitDepthToEven(iBdOut);

auto const iSizePix = (iBdOut + 7) 》》 3;

TFourCC tRecFourCC = AL_PixMapBuffer_GetFourCC(&tRecBuf);

printFourCC( tRecFourCC, “Recorded frame buffer”, __func__, __LINE__ );

int sx = 1, sy = 1;

AL_GetSubsampling(tRecFourCC, &sx, &sy);

int iPitchSrcY = AL_PixMapBuffer_GetPlanePitch(&tRecBuf, AL_PLANE_Y);

int iPitchSrcUV = AL_PixMapBuffer_GetPlanePitch(&tRecBuf, AL_PLANE_UV);

if( iPitchSrcY != iPitchSrcUV )

{

LogInfo(“YUV Y Plane pitch: %d does not equal to UV Plane pitch:%d at %s:%d.

”,

iPitchSrcY, iPitchSrcUV, __func__, __LINE__ );

}

LogVerbose(“YUV Y Plane pitch:%d, UV Plane pitch:%d at %s:%d.

”, iPitchSrcY, iPitchSrcUV, __func__, __LINE__ );

AL_TDimension tYuvDim = AL_PixMapBuffer_GetDimension(&tRecBuf);

int const iRoundUpYWidth = RoundUp(tYuvDim.iWidth, 256);

if( iPitchSrcY != iRoundUpYWidth )

{

LogInfo(“YUV Y Plane pitch %d does not equal to Y Round-up Width:%d at %s:%d.

”,

iPitchSrcY, iRoundUpYWidth, __func__, __LINE__ );

}

// For 1920x1080, YuvDim.iHeight is always rounded up, it is 1920x1088.

// For 3840x2160, YuvDim.iHeight is not rounded up, it is 3840x2160.

int const iRoundUpHeight = RoundUp(tYuvDim.iHeight, 64);

if( tYuvDim.iHeight != iRoundUpHeight )

{

// For 4K video, tYuvDim.iHeight(2160) does not equal to Round-up Height(2176)

LogInfo(“YUV Height: %d does not equal to Round-up Height:%d at %s:%d.

”,

tYuvDim.iHeight, iRoundUpHeight, __func__, __LINE__ );

}

//int const iNumPix = tYuvDim.iHeight * tYuvDim.iWidth; // For I420 without extra padding bytes.

const AL_EChromaMode stRecChromaMode = AL_GetChromaMode(tRecFourCC);

//int const iNumPixC = AL_GetChromaMode(tRecFourCC) == AL_CHROMA_MONO ? 0 : ((tYuvDim.iWidth + sx - 1) / sx) * ((tYuvDim.iHeight + sy - 1) / sy);

int const iLineNumPixC = (stRecChromaMode == AL_CHROMA_MONO) ? 0 : ((tYuvDim.iWidth + sx - 1) / sx) ;

int const iRoundUpLineNumPixC = (stRecChromaMode == AL_CHROMA_MONO) ? 0 : ((iPitchSrcUV + sx - 1) / sx) ;

// Get display in sResolutionFound()

int const iNumPix = tYuvDim.iHeight * tYuvDim.iWidth;

int const iRoundUpNumPix = iRoundUpHeight * iPitchSrcY;

int const iNumPixC = iLineNumPixC * ((tYuvDim.iHeight + sy - 1) / sy);

int const iRoundUpNumPixC = iRoundUpLineNumPixC * ((iRoundUpHeight + sy - 1) / sy);

int i_y_buffer_size = iRoundUpNumPix * iSizePix;

int i_uv_buffer_size = 2 * iRoundUpNumPixC * iSizePix;

int i_yuv_buffer_size = i_y_buffer_size + i_uv_buffer_size;

LogVerbose(“Subsampling sx:%d, sy:%d at %s:%d.

”, sx, sy, __func__, __LINE__ );

LogVerbose(“Height:%d, Width:%d at %s:%d.

”, tYuvDim.iHeight, tYuvDim.iWidth, __func__, __LINE__ );

LogVerbose(“Roundup Height:%d, Width:%d at %s:%d.

”, iRoundUpHeight, iPitchSrcY, __func__, __LINE__ );

LogVerbose(“iNumPix:%d, iLineNumPixC:%d, iNumPixC:%d, iSizePix:%d at %s:%d.

”, iNumPix, iLineNumPixC, iNumPixC, iSizePix, __func__, __LINE__ );

LogVerbose(“iRoundUpNumPix:%d, iRoundUpLineNumPixC:%d, iRoundUpNumPixC:%d at %s:%d.

”, iRoundUpNumPix, iRoundUpLineNumPixC, iRoundUpNumPixC, __func__, __LINE__ );

LogVerbose(“NV12/NV16 YUV Plane Y: %d, UV: %d YUV: %d bytes at %s:%d.

”,

i_y_buffer_size, i_uv_buffer_size, i_yuv_buffer_size, __func__, __LINE__ );

uint8_t* p_buff_y_plane = AL_PixMapBuffer_GetPlaneAddress(&tRecBuf, AL_PLANE_Y);

uint8_t* p_buff_uv_plane = AL_PixMapBuffer_GetPlaneAddress(&tRecBuf, AL_PLANE_UV);

LogVerbose(“NV12/NV16 YUV Y Plane address: %p, UV Plane address: %p at %s:%d.

”,

p_buff_y_plane, p_buff_uv_plane, __func__, __LINE__ );

int const iOffsetY_UV_Plane = ( (unsigned long long)p_buff_uv_plane - (unsigned long long)p_buff_y_plane);

if( i_y_buffer_size != iOffsetY_UV_Plane )

{

LogInfo(“YUV Y Plane sieze: %d does not equal to offset: %d between Y/UV plane at %s:%d.

”,

i_y_buffer_size, iOffsetY_UV_Plane, __func__, __LINE__ );

}

}

下面是增加的輸出NV12/NV16格式的視頻文件的主體代碼。

void UncompressedOutputWriter::ProcessFrameNVx(AL_TBuffer& tRecBuf, AL_TInfoDecode info, int iBdOut)

{

if(?。╕uvFile.is_open() || CertCrcFile.is_open()))

return;

static int i_call_time=0;

i_call_time++;

iBdOut = convertBitDepthToEven(iBdOut);

auto const iSizePix = (iBdOut + 7) 》》 3;

TFourCC tRecFourCC = AL_PixMapBuffer_GetFourCC(&tRecBuf);

#if 1

ShowVideoInfo( tRecBuf, info, iBdOut);

#endif

int sx = 1, sy = 1;

AL_GetSubsampling(tRecFourCC, &sx, &sy);

int iPitchSrcY = AL_PixMapBuffer_GetPlanePitch(&tRecBuf, AL_PLANE_Y);

int iPitchSrcUV = AL_PixMapBuffer_GetPlanePitch(&tRecBuf, AL_PLANE_UV);

AL_TDimension tYuvDim = AL_PixMapBuffer_GetDimension(&tRecBuf);

const AL_EChromaModestRecChromaMode = AL_GetChromaMode(tRecFourCC);

int const iLineNumPixC = (stRecChromaMode == AL_CHROMA_MONO) ? 0 : ((tYuvDim.iWidth + sx - 1) / sx) ;

uint8_t* p_buff_y_plane = AL_PixMapBuffer_GetPlaneAddress(&tRecBuf, AL_PLANE_Y);

LogVerbose(“NV12/NV16 YUV data Y Plane address: %p at %s:%d.

”, p_buff_y_plane, __func__, __LINE__ );

LogVerbose(“YUV data with VCU padding Height:%d, Y Width:%d, UV Width:%d at %s:%d.

”,

tYuvDim.iHeight, iPitchSrcY, iPitchSrcUV, __func__, __LINE__ );

if( 1 == gi_yuv_output_nvx_1buffer_flag )

{

// For 1920x1080, YuvDim.iHeight is always rounded up, it is 1920x1088.

// For 3840x2160, YuvDim.iHeight is not rounded up, it is 3840x2160.

int const iWriteHeight = RoundUp(tYuvDim.iHeight, 64);

//int const iNumPix = tYuvDim.iHeight * tYuvDim.iWidth; // For I420 without extra padding bytes.

int const iRoundUpNumPix = iWriteHeight * iPitchSrcY; // For NV12/NV16 with extra padding bytes.

//int const iNumPixC = AL_GetChromaMode(tRecFourCC) == AL_CHROMA_MONO ? 0 : ((tYuvDim.iWidth + sx - 1) / sx) * ((tYuvDim.iHeight + sy - 1) / sy);

int const iRoundUpLineNumPixC = (stRecChromaMode == AL_CHROMA_MONO) ? 0 : ((iPitchSrcUV + sx - 1) / sx) ;

int const iRoundUpNumPixC = iRoundUpLineNumPixC * ((iWriteHeight + sy - 1) / sy);

int i_y_buffer_size = iRoundUpNumPix * iSizePix;

int i_uv_buffer_size = 2 * iRoundUpNumPixC * iSizePix;

int i_yuv_buffer_size = i_y_buffer_size + i_uv_buffer_size;

// Display YUV file: 1920x1080: 2048x1088; 3840x2160: 3840 x 2176

if( 1 == i_call_time )

{

LogInfo(“Diplay NV12/NV16 YUV file of one continuous buffer with Height:%d, Y Width:%d, UV Width:%d at %s:%d.

”,

iWriteHeight, iPitchSrcY, iPitchSrcUV, __func__, __LINE__ );

}

YuvFile.write((const char*)p_buff_y_plane, i_yuv_buffer_size);

}

else

{

int iWriteHeight;

int iWriteYWidth;

int iWriteUVWidth;

// For 1920x1080, YuvDim.iHeight is always rounded up, it is 1920x1088.

// For 3840x2160, YuvDim.iHeight is not rounded up, it is 3840x2160.

if( 1 == gi_yuv_output_nvx_stride_flag )

{

iWriteHeight = tYuvDim.iHeight;

iWriteYWidth = iPitchSrcY;

iWriteUVWidth = 2 * ((iPitchSrcUV + sx - 1) / sx);

LogVerbose(“Diplay NV12/NV16 YUV file of stride with Height:%d, Y Width:%d, UV Width:%d at %s:%d.

”,

tYuvDim.iHeight, iPitchSrcY, iPitchSrcUV, __func__, __LINE__ );

}

else

{

if( 0 != gi_yuv_output_dispay_height )

{

// Display YUV file: 1920x1080: 1920x1080.

iWriteHeight = gi_yuv_output_dispay_height;

}

else

{

// Display YUV file: 1920x1080: 1920x1088.

iWriteHeight =tYuvDim.iHeight;

}

if( 0 != gi_yuv_output_dispay_width )

{

iWriteYWidth = gi_yuv_output_dispay_width;

iWriteUVWidth = 2 * ((gi_yuv_output_dispay_width + sx - 1) / sx);

}

else

{

iWriteYWidth =tYuvDim.iWidth;

iWriteUVWidth = 2 * iLineNumPixC;

}

}

if( 1 == i_call_time )

{

LogInfo(“Diplay NV12/NV16 YUV file with Height: %d, Y Width: %d, UV Width: %d at %s:%d.

”,

iWriteHeight, iWriteYWidth, iWriteUVWidth, __func__, __LINE__ );

}

// two writes, skipp padding bytes between Y plane and UV plane.

uint8_t* p_buff_y=p_buff_y_plane;

int iYBytes=0;

for( int i=0; i《iWriteHeight; i++ )

{

// Write each line of Y plane, and skipp padding bytes between each line.

YuvFile.write((const char*)p_buff_y, iWriteYWidth);

p_buff_y = p_buff_y + iPitchSrcY;

iYBytes+=iWriteYWidth;

}

uint8_t* p_buff_uv_plane = AL_PixMapBuffer_GetPlaneAddress(&tRecBuf, AL_PLANE_UV);

LogVerbose(“NV12/NV16 YUV data UV Plane address: %p at %s:%d.

”, p_buff_uv_plane, __func__, __LINE__ );

uint8_t* p_buff_uv=p_buff_uv_plane;

int iUVBytes=0;

for( int i=0; i《(iWriteHeight/sy); i++ )

{

// Write each line of UV plane, and skipp padding bytes between each line.

YuvFile.write((const char*)p_buff_uv, iWriteUVWidth);

p_buff_uv = p_buff_uv + iPitchSrcUV;

iUVBytes+=iWriteUVWidth;

}

LogVerbose(“write NV12/NV16 YUV data Y: %d bytes, UV: %d bytes at %s:%d.

”,

iYBytes, iUVBytes, __func__, __LINE__ );

}

}

055. 測試

在開發(fā)過程中,測試了1920x1080、3840x2160分辨率的NV12圖像。

5.1. 1080分辨率

1920x1080分辨率時,以內(nèi)存塊分辨率輸出,分辨率是1920x1088;以pitch長度和分辨率高度向上對齊后輸出,分辨率是2048x1088;以pitch長度和Meta分辨率的高度輸出,分辨率是2048x1088;以顯示分辨率輸出,分辨率是1920x1080。如果沒有特殊說明,圖像都是NV12格式的,也是以NV12格式顯示。

查看YUV文件時,必須設(shè)置正確的分辨率和格式,否則數(shù)據(jù)顯示會混亂。

以分辨率1920x1080顯示選項(xiàng)“-yuv-nvx-dispay”輸出的圖片,結(jié)果正常。

以分辨率2048x1088顯示選項(xiàng)“-yuv-nvx-1buffer”輸出的圖片,結(jié)果正常。右邊有一塊紅色圖像,是因?yàn)閷?yīng)的內(nèi)存區(qū)沒有真實(shí)圖像數(shù)據(jù)。

以分辨率2048x1088顯示選項(xiàng)“-yuv-nvx-stride”輸出的圖片,結(jié)果正常。右邊也有一塊紅色圖像。

5.1.1. 分辨率顯示格式錯誤的現(xiàn)象

以分辨率1920x1080顯示分辨率2048x1088圖片,圖像混亂了。因?yàn)閷?shí)際圖像數(shù)據(jù)每行2048字節(jié),顯示時每行1920字節(jié),所以讀出的數(shù)據(jù)混亂了,上面的連續(xù)紅色塊變成了小塊,分布到了圖像各處。

以分辨率2048x1080顯示分辨率2048x1088圖片,最上面有綠條,因?yàn)榘?行的Y分量數(shù)據(jù)當(dāng)成了UV分量數(shù)據(jù)。這8行的實(shí)際圖像是黑色的。

5.2. 3840x2160分辨率

3840x2160分辨率時,以pitch長度和分辨率高度向上對齊后的分辨率輸出,分辨率是3840x2176;其它模式輸出,分辨率都是3840x2160。

以分辨率3840x2160顯示選項(xiàng)“-yuv-nvx-dispay”輸出的圖片,結(jié)果正常。

以分辨率3840x2176顯示選項(xiàng)“-yuv-nvx-1buffer”輸出的圖片,結(jié)果正常。下面有一條綠色,也是因?yàn)閷?yīng)的內(nèi)存區(qū)沒有有效的圖像數(shù)據(jù)。

5.2.1. x2160分辨率顯示格式錯誤的現(xiàn)象

以分辨率3840x2176格式顯示分辨率3840x2160的圖片,最下面有綠條,是因?yàn)榘巡糠諹V分量數(shù)據(jù)當(dāng)成了Y分量數(shù)據(jù),導(dǎo)致最下面部分圖像缺少UV分量數(shù)據(jù)。

以分辨率3840x2160、I420格式顯示選項(xiàng)“-yuv-nvx-stride”輸出的NV12分辨率3840x2176圖片,輪廓正常,色彩異常。輪廓正常,是因?yàn)閷分量數(shù)據(jù)的解析是對的;色彩異常是因?yàn)閷V分量數(shù)據(jù)的解析是錯的。

06未來工作

未來可以繼續(xù)測試NV16的圖像,也可以測試其它分辨率的圖像。

原文標(biāo)題:【工程師分享】MPSoC VCU Ctrl-SW 2020.2 輸出NV12的YUV文件

文章出處:【微信公眾號:FPGA開發(fā)圈】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Xilinx
    +關(guān)注

    關(guān)注

    71

    文章

    2155

    瀏覽量

    120850
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2966

    瀏覽量

    73812
  • VCU
    VCU
    +關(guān)注

    關(guān)注

    17

    文章

    80

    瀏覽量

    20403

原文標(biāo)題:【工程師分享】MPSoC VCU Ctrl-SW 2020.2 輸出NV12的YUV文件

文章出處:【微信號:FPGA-EETrend,微信公眾號:FPGA開發(fā)圈】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    何為TPS56x25x選擇電感器和輸出電容器

    電子發(fā)燒友網(wǎng)站提供《如何為TPS56x25x選擇電感器和輸出電容器.pdf》資料免費(fèi)下載
    發(fā)表于 09-03 11:07 ?0次下載
    如<b class='flag-5'>何為</b>TPS56x25x選擇電感器和<b class='flag-5'>輸出</b>電容器

    智融SW6206/SW6208+賽芯XB4908!性價比很高的22.5W移動電源方案!

    最近看到很多發(fā)布的產(chǎn)品用到了智融SW6206/SW6208,今天就分享下我們自己的22.5W的移動電源方案。 我們采用的是:SW6208+XB4908*2的組合兼具功能的同時還有不錯性
    的頭像 發(fā)表于 08-28 23:40 ?792次閱讀
    智融<b class='flag-5'>SW</b>6206/<b class='flag-5'>SW</b>6208+賽芯XB4908!性價比很高的22.5W移動電源方案!

    基于RK3588J的6路MIPI CSI視頻采集案例分享,多路視頻系統(tǒng)必看!

    ./multi_camera_display -M rockchip -i 84,66,75,93,102,111 -S 1920x1080 -f NV12 -F NV12 -b 4 -o 208:71:1920x1080 圖 8
    發(fā)表于 08-22 11:51

    SW6306V四口多協(xié)議升降壓移動電源SOC中文手冊

    SW6306是支持AACC多口應(yīng)用,最大支持PD100W輸出
    發(fā)表于 07-16 10:51 ?66次下載

    發(fā)現(xiàn) SW 大小波,應(yīng)該聯(lián)想到什么?應(yīng)排查什么?

    大家在測試電源電路時,有時會碰到輸出電壓異常、輸出紋波過大等情況,此時通常會排查 SW 信號來判斷電路工作是否正常,異常狀況下 SW 波形會呈現(xiàn)大小波現(xiàn)象。 今天我們就來一起看下,
    的頭像 發(fā)表于 07-10 15:20 ?3202次閱讀
    發(fā)現(xiàn) <b class='flag-5'>SW</b> 大小波,應(yīng)該聯(lián)想到什么?應(yīng)排查什么?

    何為ESP8266構(gòu)建自定義盾牌?

    我正在尋找某種如何為ESP8266構(gòu)建自定義盾牌的指南。 到目前為止,我已經(jīng)使用 NODEMCU 構(gòu)建了功能原型,但我現(xiàn)在想簡化事情并使其更小。 1. 是否有一些書面的、開放的硬件指南 (很好
    發(fā)表于 07-08 07:17

    LT8620的SW、BST引腳對地短路是怎么回事?

    輸入為48V,輸出12V、1A,在正常運(yùn)行中,突然異常,最終檢查到LT8620的SW引腳與BST引腳對地短路; 此現(xiàn)象已發(fā)生兩起,另一起為SW、BST、INTVCC均對地短路
    發(fā)表于 05-24 06:42

    瑞芯微工業(yè)處理器8K視頻編解碼+8K顯示案例測試

    本案例使用GStreamer API通過ARM從本地導(dǎo)入8K視頻文件(H.264編碼格式或H.265編碼格式),然后進(jìn)行H.264或H.265(NV12)解碼,將解碼后的圖像以30fps或60fps的幀率,實(shí)時顯示到HDMI顯示器。
    發(fā)表于 04-28 14:28 ?697次閱讀
    瑞芯微工業(yè)處理器8K<b class='flag-5'>視頻</b>編解碼+8K顯示案例測試

    ONMCU DIL 3V3 CTRL板數(shù)據(jù)手冊

    電子發(fā)燒友網(wǎng)站提供《ONMCU DIL 3V3 CTRL板數(shù)據(jù)手冊.rar》資料免費(fèi)下載
    發(fā)表于 04-22 18:14 ?0次下載
    ONMCU DIL 3V3 <b class='flag-5'>CTRL</b>板數(shù)據(jù)手冊

    微軟計劃在網(wǎng)頁版和Win11版Outlook增加Ctrl+C/V復(fù)制粘貼功能

    按照最新規(guī)劃,在網(wǎng)頁版Outlook及新版Windows版Outlook中,使用者有望借助Ctrl+C和Ctrl+V的鍵盤組合,實(shí)現(xiàn)不同文件夾間的郵件復(fù)制粘貼,從而提升工作效率。
    的頭像 發(fā)表于 04-17 10:09 ?424次閱讀

    如何才能增加fpga+fx3通過uvc輸出視頻的幀率?

    我使用網(wǎng)上的開發(fā)板然后修改了程序,原本輸出720p30幀,現(xiàn)在想輸出1080p30幀,但最多輸出20幀。 在fpga那邊只能輸出20幀,如果繼續(xù)增加
    發(fā)表于 02-28 07:55

    VS009 HDMI視頻采集卡芯片方案

    :4K604445.USB3.0采集:4K60,1080P6.視頻格式:NV12,YUY2,RGB32,P0107.支持多種操作系統(tǒng):windows,Linux,MAC等8.支持手機(jī)采集機(jī)畫面定制9.特色:支持HD
    的頭像 發(fā)表于 01-18 14:55 ?1379次閱讀
    VS009 HDMI<b class='flag-5'>視頻</b>采集卡芯片方案

    安橋sr功放無視頻輸出問題

    安橋SR功放是一款高性能的音頻功放設(shè)備,其主要功能是放大音頻信號,提供高質(zhì)量的聲音輸出。然而,有時用戶可能會遇到SR功放無視頻輸出的問題。在本文中,我們將探討可能導(dǎo)致這個問題的原因,并
    的頭像 發(fā)表于 01-04 16:47 ?1433次閱讀

    智融科技SW2505H、SW3566H、SW2325通過UFCS融合快充功能認(rèn)證

    近日,智融科技新款芯片產(chǎn)品SW2505H成功獲得了融合快速充電功能認(rèn)證證書,證書編號0302347161910R0M-UFCS00075。此款產(chǎn)品是繼智融SW2325、SW3566H后
    的頭像 發(fā)表于 12-19 16:34 ?1150次閱讀
    智融科技<b class='flag-5'>SW</b>2505H、<b class='flag-5'>SW</b>3566H、<b class='flag-5'>SW</b>2325通過UFCS融合快充<b class='flag-5'>功能</b>認(rèn)證

    請問AD5522輸出高阻時SW3是閉合還是打開的?SW2和SW5可以單獨(dú)控制嗎?

    一個閉環(huán)狀態(tài),該狀態(tài)最好可以支持預(yù)加載DAC功能。 我想過用SW3的輸出(CFF管腳),但是不知道輸出高阻時,SW3是斷開的還是閉合的?
    發(fā)表于 12-05 08:00