我需要翻译一个包含以下函数的图像处理SDK的C头文件:
#define SDK_API __declspec(dllimport)
SDK_API BOOL WINAPI SetSourceYUVJ420(HANDLE Display, BYTE **YUV420P, int *LineSize, int srcWidth, int srcHeight);
该函数用于向SDK传递YUVJ420帧。
在我的代码中,帧存储在一个PAVPicture记录(在FFVCL组件库中定义)中,使用:
data: array[0..7] of pbyte;
linesize: array[0..7] of integer;
解码一个视频帧后,FFVCL触发一个事件,在这个事件中,该帧作为appicture类型为PAVPicture可用。
我是这样翻译的:
function SetSourceYUVJ420(Display: UIntPtr; YUV420P: Pointer; LineSize: Pointer; srcWidth, srcHeight: integer): boolean stdcall; external 'SDK.DLL' name '_SetSourceYUVJ420@20';
并像这样使用:
SetSourceYUVJ420(Display, @APicture.data[0], @APicture.linesize[0], W, H);
. .但是这样我就少了一些指针/地址。
SDK文档是中式英语并且已经过时。我确实有一个C示例,它使用FFMpeg进行解码,当帧完成时,pFrame(类型AVFrame)的部分被传递给SDK:
unsigned WINAPI MYTest() {
AVFormatContext *pFormatCtx;
unsigned int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame = NULL;
AVPacket packet;
int frameFinished;
av_register_all();
pFormatCtx = avformat_alloc_context();
avformat_open_input(&pFormatCtx, "..\..\images\Test.mp4",NULL,NULL);
av_find_stream_info(pFormatCtx);
videoStream=-1;
for (i=0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
}
// Get a pointer to the codec context for the video stream
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
// Open codec
avcodec_open2(pCodecCtx, pCodec,0) < 0;
// Allocate video frame
pFrame = av_frame_alloc();
// Read frames and save first five frames to disk
i = 0;
BOOL fSetBuffer = FALSE;
BOOL f = FALSE;
while (av_read_frame(pFormatCtx, &packet) >= 0 && !fTerminate) {
// Is this a packet from the video stream?
if(packet.stream_index==videoStream) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if ( frameFinished ) {
// This function told SDK, new video imcoming, with video format is YUV420
SetSourceYUVJ420(gDisplay, pFrame->data, pFrame->linesize, pCodecCtx->width, pCodecCtx->height);
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
avformat_close_input(&pFormatCtx);
return TRUE;
}
这是AVFrame的声明(取自FFMPeg的frame.h):
typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
/**
* pointer to the picture/channel planes.
* This might be different from the first allocated byte
*
* Some decoders access areas outside 0,0 - width,height, please
* see avcodec_align_dimensions2(). Some filters and swscale can read
* up to 16 bytes beyond the planes, if these filters are to be used,
* then 16 extra bytes must be allocated.
*/
uint8_t *data[AV_NUM_DATA_POINTERS];
/**
* For video, size in bytes of each picture line.
* For audio, size in bytes of each plane.
*
* For audio, only linesize[0] may be set. For planar audio, each channel
* plane must be the same size.
*
* For video the linesizes should be multiplies of the CPUs alignment
* preference, this is 16 or 32 for modern desktop CPUs.
* Some code requires such alignment other code can be slower without
* correct alignment, for yet other it makes no difference.
*
* @note The linesize may be larger than the size of usable data -- there
* may be extra padding present for performance reasons.
*/
int linesize[AV_NUM_DATA_POINTERS];
<SNIP>
} AVFrame;
问题:
- 如何正确翻译C函数定义
- 如何使用提供的FFVCL类型调用此函数
这里缺少了很多细节。我会试着引导你走向正确的方向,但请不要把这个答案当成是确定的。为了编写二进制互操作代码,您确实需要一个完整而清晰的二进制接口规范。你可能需要再做些调查才能弄清这件事的真相。
首先,让我们看看HANDLE
类型。这可能是Win32类型HANDLE
,在这种情况下,它将翻译为THandle
。更有可能的是,它是由相关库定义的类型。也许最好翻译为Pointer
或NativeInt
。我认为是后者。
参数BYTE**
是BYTE*
的数组。这似乎是由调用方分配的。您可能会将其转换为Delphi中的PPByte
。这是指向Byte
的指针。
下一个参数为LineSize
,类型为int*
。这是一个int
数组。所以字面翻译应该是PInteger
,指向Integer
的指针。
最后两个形参为简单整数。
所以函数将被声明为:
function SetSourceYUVJ420(
Display: NativeInt;
YUV420P: PPByte;
LineSize: PInteger;
srcWidth: Integer;
srcHeight: integer
): LongBool; stdcall; external 'SDK.DLL' name '_SetSourceYUVJ420@20';
还需要翻译结构体。它是这样的:
type
TAVFrame = record
data: array [0..7] of PByte;
linesize: array [0..7] of Integer;
end;
PAVFrame = ^TAVFrame;
显然,您的代码将需要获得显示句柄。我看不出你打算怎样去做那件事。想必你已经知道怎么做了。同样地,你需要创建一个调用av_frame_alloc
的帧。再说一遍,我只能假设你已经知道怎么做了。
var
Display: NativeInt;
Frame: PAVFrame;
那么调用将像这样进行:
if not SetSourceYUVJ420(Display, @Frame.data[0], @Frame.linesize[0], W, H) then
.... handle error
从你展示的C代码来看,为了调用这个函数,需要做很多事情。为了使函数工作,你需要所有的东西都是正确的。也就是说,如果你的代码不工作,问题可能完全在我们看不到的代码中,这些代码不包括在你的问题中。