For help, I call the hikvision SDK camera, and it returns the yv12 data stream after decoding, what should I do?

My call in c++:

long g_nPort;
cv::Mat g_BGRImage;
void CALLBACK DecCBFun(long nPort, char* pBuf, long nSize, FRAME_INFO* pFrameInfo, long nUser, long nReserved2)
{
    if(pFrameInfo->nType == T_YV12)
    {
        if(g_BGRImage.empty())
        {
            g_BGRImage.create(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);
        }
        cv::Mat YUVImage(pFrameInfo->nHeight + pFrameInfo->nHeight/2, pFrameInfo->nWidth, CV_8UC1, (unsigned char*)pBuf);

        cvtColor(YUVImage, g_BGRImage, cv::COLOR_YUV2BGR_YV12);
        imshow("RGBImage", g_BGRImage);
        cv::waitKey(15);
        YUVImage.~Mat();
    }
}

I want to use pyOpencv to achieve the same function, what should I do?
The parameter pBuf is the data stream returned by yv12;
My python call:

DECODECALLBACK = CFUNCTYPE(None,c_long,c_char_p,c_long,POINTER(FRAME_INFO),c_long,c_long)
@DECODECALLBACK
def g_decode_callback (nPort:c_long, pBuf:c_char_p, nSize:c_long, pFrameInfo:POINTER(FRAME_INFO), nUser:c_long, nReserved2:c_long):
    frameInfo = pFrameInfo.contents
    #YU12
    if frameInfo.nType == T_YV12:
         srcImg = np.zeros((frameInfo.nHeight,frameInfo.nWidth,3),dtype=np.uint8)
        
        # print(srcImg)

    return 0

Well, cvtColor has Python equivalent:

dstImg = cv2.cvtColor(srcImg,cv2.COLOR_YUV2BGR_YV12)
cv2.imShow("RGBImage",dstImg)
cv2.waitKey()

if the question was:
“how to get the p_char_p into a numpy array”

then numpy.fromBuffer (followed by a reshape()) might solve it

Yes, I have tried like this:

DECODECALLBACK = CFUNCTYPE(None,c_long,c_char_p,c_long,POINTER(FRAME_INFO),c_long,c_long)
@DECODECALLBACK
def g_decode_callback (nPort:c_long, pBuf:c_char_p, nSize:c_long, pFrameInfo:POINTER(FRAME_INFO), nUser:c_long, nReserved2:c_long):
    frameInfo = pFrameInfo.contents
    #YU12
    if frameInfo.nType == T_YV12:
        buf_arr = np.array(pBuf)
        arr_val = np.frombuffer(buf_arr,dtype=np.uint8).reshape((frameInfo.nWidth,frameInfo.nHeight))
        print(arr_val)

    return 0

But it returns the following error:

Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 232, in 'calling callback function'
  File "E:\python_coding\QtGUIDemo\source\camera\HKPlay.py", line 40, in g_decode_callback
    arr_val = np.frombuffer(buf_arr,dtype=np.uint8).reshape((frameInfo.nWidth,frameInfo.nHeight))
ValueError: cannot reshape array of size 12 into shape (1920,1080)

The data returned by pBuf is not equal in size, so I don’t know how to deal with it

if this is an ip cam, packets will get fragmented along the way.
you probably have to look at c_long and accumulate / concat buffers, until you have a full yuv image

@berak

Yes, this is an ip cam,
How should I distinguish the data length of audio and video, this c_long contains the size of audio

so, please ignore last remark, since i’m wrong about c_long

@berak
So what I don’t understand is how cv::Mat does it, what do I need to do in python to do it