Files
buildroot/package/libcedarc/0001-Add-converstion-to-YV12.patch
tiopex c336dad699 Add HW video engine support (#179)
* Add Cedar HW video decoder support

* Add sunxifbsink gstreamer plugin

* sunxifbsink: remove warning log
gst-omx: remove resolution check after crop

* Add gstreamer scripts

* review comments fixes

* ffmpeg: enable h264_omx encoder

* add missing hashes and use defined git commit for libcedar

* mv miyoo specific patches to board

* make `gst-omx.mk` less platform specfic

* Add header python interpreter to gst-raw.py

* Add videoscale with nearest-neighbour to play video with higher resolutions fluently

* Use HW scaler

* libcedarc: fix crash when playing 640x480 video

* kernel: Add patch to increase VRAM

* Add fast gstreamer player

* fix gst-play hangs

* Add matroska plugin

* remove target

---------

Co-authored-by: Apaczer <94932128+Apaczer@users.noreply.github.com>
2025-07-21 13:11:52 +02:00

436 lines
12 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
From ec3025abfdec1bdebe76a5f92cce8de3a73bff60 Mon Sep 17 00:00:00 2001
From: tiopxyz <tiopxyz@gmail.com>
Date: Fri, 11 Jul 2025 23:25:13 +0200
Subject: [PATCH] F1C100s: VDU supports only YUV_MB32_420; convert manually to YV12
On F1C100s boards, the video decoder supports only the
YUV_MB32_420 format, which is YUV420 stored in 32×32 macroblocks.
This format is not natively supported in GStreamer, so manual conversion
to standard YV12 is necessary for compatibility with existing video sinks.
---
openmax/vdec/src/omx_vdec_aw_decoder_linux.c | 75 +++++-
vdecoder/pixel_format.c | 258 +++++++++++++++++++
2 files changed, 330 insertions(+), 3 deletions(-)
diff --git a/openmax/vdec/src/omx_vdec_aw_decoder_linux.c b/openmax/vdec/src/omx_vdec_aw_decoder_linux.c
index 8a619ca..2976fca 100644
--- a/openmax/vdec/src/omx_vdec_aw_decoder_linux.c
+++ b/openmax/vdec/src/omx_vdec_aw_decoder_linux.c
@@ -71,6 +71,10 @@ typedef struct OmxAwDecoderContext
VideoPicture* pPicture;
OMX_BOOL bUseZeroCopyBuffer;
+ char* pYV12;
+ VideoPicture CvtPicture;
+ int tWidth;
+ int tHeight;
}OmxAwDecoderContext;
@@ -403,6 +407,52 @@ static void liReopenVideoEngine(OmxAwDecoderContext *pCtx)
return ;
}
+static int yv12_align_fill(char* p_dst, int w, int h, int aw, int ah)
+{
+ int i, j;
+ int map = aw * ah;
+ int v_size = (map) >> 2;
+ char *pv = p_dst + map;
+ char *pu = pv + v_size;// / 4
+
+ int dw = aw - w;
+ int dh = ah -h;
+ int dw_h = dw / 2;
+ int dh_h = dh / 2;
+ int w_h = w / 2;
+ int h_h = h / 2;
+ int aw_h = aw / 2;
+ int ah_h = ah / 2;
+ int map_oft = aw_h * h_h;
+
+ if((w == aw) && (h == ah))
+ return 0;
+
+
+ for(i=0;i<h_h;i++)
+ {
+ for(j=0;j<dw_h;j++)
+ {
+ pv[w_h + j + aw_h * i] = 128;
+ pu[w_h + j + aw_h * i] = 128;
+ }
+
+ }
+
+
+ for(i=0;i<dh_h;i++)
+ {
+ for(j=0;j<aw_h;j++)
+ {
+ pv[map_oft + j + aw_h * i] = 128;
+ pu[map_oft + j + aw_h * i] = 128;
+ }
+
+ }
+
+ return 0;
+}
+
static int __liCallback(OmxDecoder* pDec, DecoderCallback callback,
void* pUserData)
{
@@ -471,7 +521,7 @@ static int __liPrepare(OmxDecoder* pDec)
pCtx->mVideoConfig.nAlignStride = pCtx->mGpuAlignStride;
- pCtx->mVideoConfig.eOutputPixelFormat = PIXEL_FORMAT_YV12;//* Used to be YV12.
+ pCtx->mVideoConfig.eOutputPixelFormat = PIXEL_FORMAT_YUV_MB32_420;//* Used to be YV12.
#if (ENABLE_SCALEDOWN_WHEN_RESOLUTION_MOER_THAN_1080P)
if (pCtx->mStreamInfo.nWidth > 1920
@@ -482,6 +532,10 @@ static int __liPrepare(OmxDecoder* pDec)
pCtx->mVideoConfig.nVerticalScaleDownRatio = 1;
}
#endif
+ pCtx->tWidth = pCtx->mStreamInfo.nWidth;
+ pCtx->tHeight = pCtx->mStreamInfo.nHeight;
+ pCtx->mStreamInfo.nWidth = (pCtx->mStreamInfo.nWidth + 31) & ~31;
+ pCtx->mStreamInfo.nHeight = (pCtx->mStreamInfo.nHeight + 31) & ~31;
if(pCtx->mStreamInfo.eCodecFormat == VIDEO_CODEC_FORMAT_WMV3)
{
@@ -506,6 +560,14 @@ static int __liPrepare(OmxDecoder* pDec)
ret = InitializeVideoDecoder(pCtx->m_decoder,
&(pCtx->mStreamInfo),
&pCtx->mVideoConfig);
+ pCtx->pYV12 = (char*)malloc(sizeof(char) * pCtx->mStreamInfo.nWidth * pCtx->mStreamInfo.nHeight * 3 / 2);
+ if(pCtx->pYV12 == NULL)
+ {
+ loge("pCtx->pYV12 malloc fail\n");
+ return -1;
+ }
+ pCtx->CvtPicture.pData0 = pCtx->pYV12;
+ pCtx->CvtPicture.ePixelFormat = PIXEL_FORMAT_YV12;
if(ret != 0)
{
DestroyVideoDecoder(pCtx->m_decoder);
@@ -706,12 +768,14 @@ static OMX_BUFFERHEADERTYPE* __liDrain(OmxDecoder* pDec)
pCtx->pPicture->nWidth, pCtx->pPicture->nHeight,
pCtx->pPicture->nTopOffset,pCtx->pPicture->nBottomOffset,
pCtx->pPicture->nLeftOffset,pCtx->pPicture->nRightOffset);
+ RotatePicture(pCtx->decMemOps, pCtx->pPicture, &pCtx->CvtPicture, 0, 32, 32);
+ yv12_align_fill(pCtx->CvtPicture.pData0, pCtx-> tWidth, pCtx-> tHeight, pCtx->mStreamInfo.nWidth, pCtx->mStreamInfo.nHeight);
CdcMemFlushCache(pCtx->decMemOps, (void*)pCtx->pPicture->pData0,
pCtx->pPicture->nLineStride * pCtx->pPicture->nHeight*3/2);
OMX_PARAM_PORTDEFINITIONTYPE* outDef = getPortDef(pCtx->pOutPort);
#if USE_ALIGN_SIZE
AlignCopyYV12((unsigned char*)pOutBufHdr->pBuffer,
- (unsigned char*)pCtx->pPicture->pData0,
+ (unsigned char*)pCtx->CvtPicture.pData0,
outDef->format.video.nFrameWidth,
outDef->format.video.nFrameHeight);
@@ -785,6 +849,11 @@ static void __liClose(OmxDecoder* pDec)
DestroyVideoDecoder(pCtx->m_decoder);
pCtx->m_decoder = NULL;
}
+ if(pCtx->pYV12 != NULL)
+ {
+ free(pCtx->pYV12);
+ pCtx->pYV12 = NULL;
+ }
pCtx->mCodecSpecificDataLen = 0;
memset(pCtx->mCodecSpecificData, 0 , CODEC_SPECIFIC_DATA_LENGTH);
OmxReleaseMutex(pCtx->awMutexHandler);
@@ -835,7 +904,7 @@ static int __liSetOutputEos(OmxDecoder* pDec)
static void __liGetFormat(OmxDecoder* pDec)
{
OmxAwDecoderContext *pCtx = (OmxAwDecoderContext*)pDec;
- pCtx->mVideoConfig.eOutputPixelFormat = PIXEL_FORMAT_YV12;
+ pCtx->mVideoConfig.eOutputPixelFormat = PIXEL_FORMAT_YUV_MB32_420;
}
static inline void __liSetExtBufNum(OmxDecoder* pDec, OMX_S32 num)
diff --git a/vdecoder/pixel_format.c b/vdecoder/pixel_format.c
index 3d47e6a..3fda569 100755
--- a/vdecoder/pixel_format.c
+++ b/vdecoder/pixel_format.c
@@ -556,6 +556,259 @@ void ConvertMb32422ToYv12C(char* pSrc,char* pDstU, char*pDstV,int nPicWidth, int
//****************************************************************//
//****************************************************************//
+static void MB32_CVT_YV12(char* pSrc, char* pSrc_v, char* pDst, int nWidth, int nHeight)
+{
+ int i = 0;
+ int j = 0;
+ int m = 0;
+ int n = 0;
+ int k = 0;
+ int nMbWidth = 0;
+ int nMbHeight = 0;
+ int nMbWidth_uv = 0;
+ int nMbHeight_uv = 0;
+ int nLineStride = 0;
+ int nLineStride_uv = 0;
+ int lineNum = 0;
+ int lineNum_uv = 0;
+ int offset = 0;
+ int offset_uv = 0;
+ int maxNum = 0;
+ char* ptr = NULL;
+ char* ptr_uv = NULL;
+ char* pDstU = NULL;
+ char* pDstV = NULL;
+ int nWidth_uv = 0;
+ int nHeight_uv = 0;
+ char bufferY[32];
+ char bufferV[16], bufferU[16];
+ int nWidthMatchFlag = 0;
+ int nWidthMatchFlag_uv = 0;
+ int nCopyMbWidth = 0;
+ int nCopyMbWidth_uv = 0;
+ char *dstAsm = NULL;
+ char *dst0Asm = NULL;
+ char *dst1Asm = NULL;
+ char *srcAsm = NULL;
+ char *srcAsm_uv = NULL;
+
+ int bCnt2 = 1;
+
+ nLineStride = (nWidth + 15) &~15;
+ nMbWidth = (nWidth + 31)&~31;
+ nMbWidth >>= 5;//n 32 width / 32
+
+ nMbHeight = (nHeight + 31)&~31;
+ nMbHeight >>= 5;// / 32
+ ptr = pSrc;
+
+ nWidthMatchFlag = 0;
+ nCopyMbWidth = nMbWidth - 1;
+
+ nWidth_uv = (nWidth + 1) / 2;
+ nHeight_uv = (nHeight + 1) / 2;
+
+ nLineStride_uv = (nWidth_uv + 7)&~7;
+
+ nMbWidth_uv = (nWidth_uv * 2 + 31)&~31;
+ nMbWidth_uv >>= 5;// / 32
+
+ nMbHeight_uv = (nHeight_uv + 31)&~31;
+ nMbHeight_uv >>= 5;// / 32
+ ptr_uv = pSrc_v;
+ pDstU = pDst + (nWidth * nHeight) + (nWidth / 2 * nHeight / 2);
+ pDstV = pDst + (nWidth * nHeight);
+ nWidthMatchFlag_uv = 0;
+ nCopyMbWidth_uv = nMbWidth_uv - 1;
+
+ if ((nMbWidth << 5) == nLineStride)// * 32
+ {
+ nWidthMatchFlag = 1;
+ nCopyMbWidth = nMbWidth;
+ }
+
+ if ((nMbWidth_uv << 4) == nLineStride_uv)//*16
+ {
+ nWidthMatchFlag_uv = 1;
+ nCopyMbWidth_uv = nMbWidth_uv;
+
+ }
+
+ for (i = 0; i < nMbHeight; i++)
+ {
+ for (j = 0; j < nCopyMbWidth; j++)
+ {
+ for (m = 0; m < 32; m++)
+ {
+ if (((i << 5) + m) >= nHeight)// * 32
+ {
+ ptr += 32;
+ continue;
+ }
+ srcAsm = ptr;
+ lineNum = (i << 5) + m; //line num * 32
+ offset = lineNum * nLineStride + (j << 5);// * 32
+ dstAsm = pDst + offset;
+
+ memcpy(dstAsm, srcAsm, 32);
+
+ if (bCnt2)
+ {
+ if (((i << 4) + m) >= nHeight_uv)//i / 2 * 32
+ {
+ ptr_uv += 32;
+ ptr += 32;
+ continue;
+ }
+ srcAsm_uv = ptr_uv;
+ lineNum_uv = (i << 4) + m; //line num i / 2 * 32
+ offset_uv = lineNum_uv * nLineStride_uv + (j << 4);// * 16
+ dst0Asm = pDstU + offset_uv;
+ dst1Asm = pDstV + offset_uv;
+
+ //memcpy(dst0Asm, srcAsm_uv, 16);
+ //memcpy(dst1Asm, (void *)(srcAsm_uv + 16), 16);
+ dst0Asm[0] = srcAsm_uv[0];
+ dst0Asm[1] = srcAsm_uv[2];
+ dst0Asm[2] = srcAsm_uv[4];
+ dst0Asm[3] = srcAsm_uv[6];
+ dst0Asm[4] = srcAsm_uv[8];
+ dst0Asm[5] = srcAsm_uv[10];
+ dst0Asm[6] = srcAsm_uv[12];
+ dst0Asm[7] = srcAsm_uv[14];
+
+ dst0Asm[8] = srcAsm_uv[16];
+ dst0Asm[9] = srcAsm_uv[18];
+ dst0Asm[10] = srcAsm_uv[20];
+ dst0Asm[11] = srcAsm_uv[22];
+ dst0Asm[12] = srcAsm_uv[24];
+ dst0Asm[13] = srcAsm_uv[26];
+ dst0Asm[14] = srcAsm_uv[28];
+ dst0Asm[15] = srcAsm_uv[30];
+
+ dst1Asm[0] = srcAsm_uv[1];
+ dst1Asm[1] = srcAsm_uv[3];
+ dst1Asm[2] = srcAsm_uv[5];
+ dst1Asm[3] = srcAsm_uv[7];
+ dst1Asm[4] = srcAsm_uv[9];
+ dst1Asm[5] = srcAsm_uv[11];
+ dst1Asm[6] = srcAsm_uv[13];
+ dst1Asm[7] = srcAsm_uv[15];
+
+ dst1Asm[8] = srcAsm_uv[17];
+ dst1Asm[9] = srcAsm_uv[19];
+ dst1Asm[10] = srcAsm_uv[21];
+ dst1Asm[11] = srcAsm_uv[23];
+ dst1Asm[12] = srcAsm_uv[25];
+ dst1Asm[13] = srcAsm_uv[27];
+ dst1Asm[14] = srcAsm_uv[29];
+ dst1Asm[15] = srcAsm_uv[31];
+
+ ptr_uv += 32;
+ }
+ ptr += 32;
+ }
+ }
+
+ if (nWidthMatchFlag != 1)
+ {
+ for (m = 0; m < 32; m++)
+ {
+ if (((i << 5) + m) >= nHeight)// * 32
+ {
+ ptr += 32;
+ continue;
+ }
+ dstAsm = bufferY;
+ srcAsm = ptr;
+ lineNum = (i << 5) + m; //line num * 32
+ offset = lineNum * nLineStride + (j << 5);// * 32
+
+ memcpy(dstAsm, srcAsm, 32);
+ ptr += 32;
+ for (k = 0; k < 32; k++)
+ {
+ if ((j * 32 + k) >= nLineStride)
+ {
+ break;
+ }
+ pDst[offset + k] = bufferY[k];
+ }
+ }
+ }
+
+ if (bCnt2) {
+ if (nWidthMatchFlag_uv != 1)
+ {
+ for (m = 0; m < 32; m++)
+ {
+ if (((i << 4) + m) >= nHeight_uv)//i / 2 * 32
+ {
+ ptr_uv += 32;
+ continue;
+ }
+
+ srcAsm_uv = ptr_uv;
+ lineNum_uv = (i << 4) + m; //line num i / 2 * 32
+ offset = lineNum_uv * nLineStride_uv + (j << 4);// * 16
+ dst0Asm = bufferU;
+ dst1Asm = bufferV;
+
+ //memcpy(dst0Asm, srcAsm, 16);
+ //memcpy(dst1Asm, (char *)(srcAsm + 16), 16);
+ dst0Asm[0] = srcAsm_uv[0];
+ dst0Asm[1] = srcAsm_uv[2];
+ dst0Asm[2] = srcAsm_uv[4];
+ dst0Asm[3] = srcAsm_uv[6];
+ dst0Asm[4] = srcAsm_uv[8];
+ dst0Asm[5] = srcAsm_uv[10];
+ dst0Asm[6] = srcAsm_uv[12];
+ dst0Asm[7] = srcAsm_uv[14];
+
+ dst0Asm[8] = srcAsm_uv[16];
+ dst0Asm[9] = srcAsm_uv[18];
+ dst0Asm[10] = srcAsm_uv[20];
+ dst0Asm[11] = srcAsm_uv[22];
+ dst0Asm[12] = srcAsm_uv[24];
+ dst0Asm[13] = srcAsm_uv[26];
+ dst0Asm[14] = srcAsm_uv[28];
+ dst0Asm[15] = srcAsm_uv[30];
+
+ dst1Asm[0] = srcAsm_uv[1];
+ dst1Asm[1] = srcAsm_uv[3];
+ dst1Asm[2] = srcAsm_uv[5];
+ dst1Asm[3] = srcAsm_uv[7];
+ dst1Asm[4] = srcAsm_uv[9];
+ dst1Asm[5] = srcAsm_uv[11];
+ dst1Asm[6] = srcAsm_uv[13];
+ dst1Asm[7] = srcAsm_uv[15];
+
+ dst1Asm[8] = srcAsm_uv[17];
+ dst1Asm[9] = srcAsm_uv[19];
+ dst1Asm[10] = srcAsm_uv[21];
+ dst1Asm[11] = srcAsm_uv[23];
+ dst1Asm[12] = srcAsm_uv[25];
+ dst1Asm[13] = srcAsm_uv[27];
+ dst1Asm[14] = srcAsm_uv[29];
+ dst1Asm[15] = srcAsm_uv[31];
+ ptr_uv += 32;
+
+ for (k = 0; k < 16; k++)
+ {
+ if (((j << 4) + k) >= nLineStride_uv)// j * 16
+ {
+ break;
+ }
+ pDstV[offset + k] = bufferV[k];
+ pDstU[offset + k] = bufferU[k];
+ }
+ }
+ }
+ }
+ bCnt2 = !bCnt2;
+ }
+}
+
void ConvertPixelFormat(VideoPicture* pPictureIn, VideoPicture* pPictureOut)
{
int nMemSizeY = 0;
@@ -584,6 +837,11 @@ void ConvertPixelFormat(VideoPicture* pPictureIn, VideoPicture* pPictureOut)
if(pPictureOut->ePixelFormat==PIXEL_FORMAT_YV12)
{
+ if(pPictureIn->ePixelFormat == PIXEL_FORMAT_YUV_MB32_420)
+ {
+ MB32_CVT_YV12(pPictureIn->pData0, pPictureIn->pData1, pPictureOut->pData0, \
+ pPictureIn->nWidth, pPictureIn->nHeight);
+ }
#ifdef CEDARX_DECODER_ARM32
if(pPictureIn->ePixelFormat == PIXEL_FORMAT_YUV_MB32_420)
{
--
2.34.1