SmartAudio/package/allwinner/tina_multimedia/libcedarc/openmax/vdec/omx_deinterlace.cpp

688 lines
21 KiB
C++
Executable File
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.

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : deinterlace.cpp
* Description : hardware deinterlacing
* History :
*
*/
/**************** notify *********************
移植deinterlace.cpp修改的地方
1. 增加nPhyOffset变量移除CONF_VE_PHY_OFFSET
2. 将变量写死const char *str_difmt = "nv"
3. 移除CDX_CHECK的检查
4. 将 CONF_KERN_BITWIDE 设置为 64
5. 只适配了H6平台其他平台如H3/H5均没有适配
6. 若要将openmax整合到cedarx则必须重新整合di接口的调用
因为cedarx存在一套相同的di接口。
*/
#include <memoryAdapter.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#include <errno.h>
#define __STDC_FORMAT_MACROS // Otherwise not available in C++.
#include <inttypes.h>
#include <cutils/properties.h>
#include "log.h"
#include "omx_deinterlace.h"
//-----------------------------------------------------------------------------
// relation with deinterlace
//#define CONF_KERN_BITWIDE (64)
#define DI_MODULE_TIMEOUT 0x1055
#define DI_IOC_MAGIC 'D'
//DI_IOSTART use int instead of pointer* in double 32/64 platform to avoid bad definition.
#define DI_IOCSTART _IOWR(DI_IOC_MAGIC, 0, DiRectSizeT)
#define DI_IOCSTART2 _IOWR(DI_IOC_MAGIC, 1, struct DiRectSizeT)
#define DI_IOCSETMODE _IOWR(DI_IOC_MAGIC, 2, struct DiModeT)
typedef enum DiPixelformatE2 {
DI2_FORMAT_NV12 =0x00,
DI2_FORMAT_NV21 =0x01,
DI2_FORMAT_MB32_12 =0x02, //UV mapping like NV12
DI2_FORMAT_MB32_21 =0x03, //UV mapping like NV21
DI2_FORMAT_YV12 = 0x04, /* 3-plane */
DI2_FORMAT_YUV422_SP_UVUV = 0x08, /* 2-plane, New in DI_V2.2 */
DI2_FORMAT_YUV422_SP_VUVU = 0x09, /* 2-plane, New in DI_V2.2 */
DI2_FORMAT_YUV422P = 0x0c, /* 3-plane, New in DI_V2.2 */
} DiPixelformatE2;
typedef enum DiPixelformatE {
DI_FORMAT_NV12 =0x00,
DI_FORMAT_NV21 =0x01,
DI_FORMAT_MB32_12 =0x02, //UV mapping like NV12
DI_FORMAT_MB32_21 =0x03, //UV mapping like NV21
} DiPixelformatE;
typedef struct DiRectSizeT {
unsigned int nWidth;
unsigned int nHeight;
} DiRectSizeT;
typedef struct DiFbT {
#if (CONF_KERN_BITWIDE == 64)
unsigned long long addr[2]; // the address of frame buffer
#elif(CONF_KERN_BITWIDE == 32)
uintptr_t addr[2]; // the address of frame buffer
#else
#error CONF_KERN_BITWIDE is not 32 or 64
#endif
DiRectSizeT mRectSize;
DiPixelformatE eFormat;
} DiFbT;
typedef struct DiFbT2 {
int fd;
#if (CONF_KERN_BITWIDE == 64)
unsigned long long addr[3]; // the address of frame buffer
#elif(CONF_KERN_BITWIDE == 32)
uintptr_t addr[3]; // the address of frame buffer
#else
#error CONF_KERN_BITWIDE is not 32 or 64
#endif
DiRectSizeT mRectSize;
DiPixelformatE2 eFormat;
} DiFbT2;
typedef struct DiParaT {
DiFbT mInputFb; //current frame fb
DiFbT mPreFb; //previous frame fb
DiRectSizeT mSourceRegion; //current frame and previous frame process region
DiFbT mOutputFb; //output frame fb
DiRectSizeT mOutRegion; //output frame region
unsigned int nField; //process field <0-top field ; 1-bottom field>
/* video infomation <0-is not top_field_first; 1-is top_field_first> */
unsigned int bTopFieldFirst;
} DiParaT;
typedef struct DiParaT2 {
DiFbT2 mInputFb; /* current frame fb */
DiFbT2 mPreFb; /* previous frame fb */
DiFbT2 mNextFb; /* next frame fb */
/* current frame /previous frame and next frame process region */
DiRectSizeT mSourceRegion;
DiFbT2 mOutputFb; /* output frame fb */
DiRectSizeT mOutRegion; /* output frame region */
unsigned int nField; /* process field <0-first field ; 1-second field> */
/* video infomation <0-is not top_field_first; 1-is top_field_first> */
unsigned int bTopFieldFirst;
/* unsigned int update_mode; */
/* update buffer mode <0-update 1 frame, output 2 frames; 1-update 1 frame, output 1 frame> */
} DiParaT2;
typedef enum DiIntpModeT {
DI_MODE_WEAVE = 0x0, /* Copy source to destination */
DI_MODE_INTP = 0x1, /* Use current field to interpolate another field */
DI_MODE_MOTION = 0x2, /* Use 4-field to interpolate another field */
} DiIntpModeT;
typedef enum DiUpdModeT {
DI_UPDMODE_FIELD = 0x0, /* Output 2 frames when updated 1 input frame */
DI_UPDMODE_FRAME = 0x1, /* Output 1 frame when updated 1 input frame */
} DiUpdModeT;
typedef struct DiModeT {
DiIntpModeT di_mode;
DiUpdModeT update_mode;
} DiModeT;
enum {
IOMEM_UNKNOWN,
IOMEM_CMA,
IOMEM_IOMMU,
};
struct DiContext
{
Deinterlace base;
int fd;
int picCount;
int iomemType;
unsigned int nPhyOffset;
DiIntpModeT diMode;
};
static int dumpPara(DiParaT *para)
{
CEDARC_UNUSE(dumpPara);
logd("**************************************************************");
logd("*********************deinterlace info*************************");
logd(" input_fb: addr=0x%x, 0x%x, format=%d, size=(%d, %d)",
para->mInputFb.addr[0], para->mInputFb.addr[1], (int)para->mInputFb.eFormat,
(int)para->mInputFb.mRectSize.nWidth, (int)para->mInputFb.mRectSize.nHeight);
logd(" pre_fb: addr=0x%x, 0x%x, format=%d, size=(%d, %d)",
para->mPreFb.addr[0], para->mPreFb.addr[1], (int)para->mPreFb.eFormat,
(int)para->mPreFb.mRectSize.nWidth, (int)para->mPreFb.mRectSize.nHeight);
logd("output_fb: addr=0x%x, 0x%x, format=%d, size=(%d, %d)",
para->mOutputFb.addr[0], para->mOutputFb.addr[1], (int)para->mOutputFb.eFormat,
(int)para->mOutputFb.mRectSize.nWidth, (int)para->mOutputFb.mRectSize.nHeight);
logd("top_field_first=%d, field=%d", para->bTopFieldFirst, para->nField);
logd("source_regn=(%d, %d), out_regn=(%d, %d)",
para->mSourceRegion.nWidth, para->mSourceRegion.nHeight,
para->mOutRegion.nWidth, para->mOutRegion.nHeight);
logd("****************************end*******************************");
logd("**************************************************************\n\n");
return 0;
}
static int dumpPara2(DiParaT2 *para)
{
CEDARC_UNUSE(dumpPara2);
logd("**************************************************************");
logd("*********************deinterlace info*************************");
logd(" input_fb: fd=%d, addr[0~2]=0x%" PRIx64", 0x%" PRIx64", 0x%" PRIx64
",format=%d, size=(%d, %d)",
para->mInputFb.fd, para->mInputFb.addr[0], para->mInputFb.addr[1], para->mInputFb.addr[2],
(int)para->mInputFb.eFormat,
(int)para->mInputFb.mRectSize.nWidth,
(int)para->mInputFb.mRectSize.nHeight);
logd(" pre_fb: fd=%d, addr[0~2]=0x%" PRIx64", 0x%" PRIx64", 0x%" PRIx64
",format=%d, size=(%d, %d)",
para->mPreFb.fd, para->mPreFb.addr[0], para->mPreFb.addr[1], para->mPreFb.addr[2],
(int)para->mPreFb.eFormat,
(int)para->mPreFb.mRectSize.nWidth,
(int)para->mPreFb.mRectSize.nHeight);
logd(" next_fb: fd=%d, addr[0~2]=0x%" PRIx64", 0x%" PRIx64", 0x%" PRIx64
",format=%d, size=(%d, %d)",
para->mNextFb.fd, para->mNextFb.addr[0], para->mNextFb.addr[1],
para->mNextFb.addr[2],(int)para->mNextFb.eFormat,
(int)para->mNextFb.mRectSize.nWidth,
(int)para->mNextFb.mRectSize.nHeight);
logd("output_fb: fd=%d, addr[0~2]=0x%" PRIx64", 0x%" PRIx64", 0x%" PRIx64
",format=%d, size=(%d, %d)",
para->mOutputFb.fd, para->mOutputFb.addr[0], para->mOutputFb.addr[1],
para->mOutputFb.addr[2],(int)para->mOutputFb.eFormat,
(int)para->mOutputFb.mRectSize.nWidth,
(int)para->mOutputFb.mRectSize.nHeight);
logd("top_field_first=%d, field=%d", para->bTopFieldFirst, para->nField);
logd("source_regn=(%d, %d), out_regn=(%d, %d)",
para->mSourceRegion.nWidth, para->mSourceRegion.nHeight,
para->mOutRegion.nWidth, para->mOutRegion.nHeight);
logd("****************************end*******************************");
logd("**************************************************************\n\n");
return 0;
}
static int setMode2(Deinterlace* di )
{
struct DiContext* dc = (struct DiContext*)di;
DiModeT mDiModeT2;
mDiModeT2.di_mode = dc->diMode;
mDiModeT2.update_mode = DI_UPDMODE_FIELD;
logd(" di_mode = %d , update_mode = %d ",
mDiModeT2.di_mode, mDiModeT2.update_mode);
if (ioctl(dc->fd, DI_IOCSETMODE, &mDiModeT2) != 0)
{
loge("aw_di_setmode2 failed!");
return -1;
}
return 0;
}
static int getIOMemType() {
char tmp[PROP_VALUE_MAX];
int ret = property_get("ro.kernel.iomem.type", tmp, "0");
if (ret) {
if (!strcmp(tmp, "0xaf10"))
return IOMEM_IOMMU;
else if (!strcmp(tmp, "0xfa01"))
return IOMEM_CMA;
else
return IOMEM_UNKNOWN;
}
return IOMEM_CMA;
}
static void __DiDestroy(Deinterlace* di)
{
struct DiContext* dc;
dc = (struct DiContext*)di;
if (dc->fd != -1)
{
close(dc->fd);
}
free(dc);
}
static int __DiInit(Deinterlace* di)
{
struct DiContext* dc;
dc = (struct DiContext*)di;
logd("%s", __FUNCTION__);
if (dc->fd != -1)
{
logw("already init...");
return 0;
}
dc->fd = open("/dev/deinterlace", O_RDWR);
if (dc->fd == -1)
{
loge("open hw devices failure, errno(%d)", errno);
return -1;
}
dc->picCount = 0;
dc->iomemType = getIOMemType();
logd("iomem type=%d", dc->iomemType);
logd("hw deinterlace init success...");
return 0;
}
static int __DiReset(Deinterlace* di)
{
struct DiContext* dc = (struct DiContext*)di;
logd("%s", __FUNCTION__);
if (dc->fd != -1)
{
close(dc->fd);
dc->fd = -1;
}
return __DiInit(di);
}
static enum EPIXELFORMAT __DiExpectPixelFormat(Deinterlace* di)
{
struct DiContext* dc = (struct DiContext*)di;
CEDARC_UNUSE(dc);
return PIXEL_FORMAT_NV21;
}
static int __DiFlag(Deinterlace* di)
{
struct DiContext* dc = (struct DiContext*)di;
CEDARC_UNUSE(dc);
return DE_INTERLACE_HW;
}
static int __DiProcess(Deinterlace* di,
VideoPicture *pPrePicture,
VideoPicture *pCurPicture,
VideoPicture *pOutPicture,
int nField)
{
struct DiContext* dc;
dc = (struct DiContext*)di;
logv("call DeinterlaceProcess");
if(pPrePicture == NULL || pCurPicture == NULL || pOutPicture == NULL)
{
loge("the input param is null : %p, %p, %p", pPrePicture, pCurPicture, pOutPicture);
return -1;
}
if(dc->fd == -1)
{
loge("not init...");
return -1;
}
DiParaT mDiParaT;
DiRectSizeT mRealSize;
DiRectSizeT mAlignSize;
DiPixelformatE eInFormat;
DiPixelformatE eOutFormat;
//* compute pts again
if (dc->picCount < 2)
{
int nFrameRate = 30000; //* we set the frameRate to 30
pOutPicture->nPts = pCurPicture->nPts + nField * (1000 * 1000 * 1000 / nFrameRate) / 2;
}
else
{
pOutPicture->nPts = pCurPicture->nPts + nField * (pCurPicture->nPts - pPrePicture->nPts)/2;
}
logv("pCurPicture->nPts = %lld ms, pOutPicture->nPts = %lld ms, diff = %lld ms ",
pCurPicture->nPts/1000,
pOutPicture->nPts/1000,
(pOutPicture->nPts - pCurPicture->nPts)/1000
);
if (pOutPicture->ePixelFormat == PIXEL_FORMAT_NV12)
{
eOutFormat = DI_FORMAT_NV12;
}
else if (pOutPicture->ePixelFormat == PIXEL_FORMAT_NV21)
{
eOutFormat = DI_FORMAT_NV21;
}
else
{
loge("the outputPixelFormat is not support : %d",pOutPicture->ePixelFormat);
return -1;
}
//const char *str_difmt = GetConfigParamterString("deinterlace_fmt", NULL);
//CDX_LOG_CHECK(str_difmt, "'deinterlace_fmt' not define, pls check your cedarx.conf");
#if 0
char *str_difmt = "nv";
if (strcmp(str_difmt, "mb32") == 0)
{
eInFormat = DI_FORMAT_MB32_12;
}
else if (strcmp(str_difmt, "nv") == 0)
{
if (pCurPicture->ePixelFormat == PIXEL_FORMAT_NV12)
{
eInFormat = DI_FORMAT_NV12;
}
else if (pCurPicture->ePixelFormat == PIXEL_FORMAT_NV21)
{
eInFormat = DI_FORMAT_NV21;
}
else
{
loge("the inputPixelFormat is not support : %d",pCurPicture->ePixelFormat);
return -1;
}
}
else if (strcmp(str_difmt, "nv21") == 0)
{
eInFormat = DI_FORMAT_NV21;
}
else
{
eInFormat = DI_FORMAT_NV12;
}
#else
if (pCurPicture->ePixelFormat == PIXEL_FORMAT_NV12)
{
eInFormat = DI_FORMAT_NV12;
}
else if (pCurPicture->ePixelFormat == PIXEL_FORMAT_NV21)
{
eInFormat = DI_FORMAT_NV21;
}
else
{
loge("the inputPixelFormat is not support : %d",pCurPicture->ePixelFormat);
return -1;
}
#endif
mRealSize.nWidth = pCurPicture->nRightOffset - pCurPicture->nLeftOffset;
mRealSize.nHeight = pCurPicture->nBottomOffset - pCurPicture->nTopOffset;
mAlignSize.nWidth = pOutPicture->nWidth;
mAlignSize.nHeight = pOutPicture->nHeight;
mDiParaT.mInputFb.mRectSize = mAlignSize;
mDiParaT.mInputFb.eFormat = eInFormat;
mDiParaT.mPreFb.mRectSize = mAlignSize;
mDiParaT.mPreFb.eFormat = eInFormat;
mDiParaT.mOutputFb.mRectSize = mAlignSize;
mDiParaT.mOutputFb.eFormat = eOutFormat;
mDiParaT.mSourceRegion = mRealSize;
mDiParaT.mOutRegion = mRealSize;
mDiParaT.nField = nField;
mDiParaT.bTopFieldFirst = pCurPicture->bTopFieldFirst;
//* we can use the phy address
mDiParaT.mInputFb.addr[0] = pCurPicture->phyYBufAddr + dc->nPhyOffset;
mDiParaT.mInputFb.addr[1] = pCurPicture->phyCBufAddr + dc->nPhyOffset;
mDiParaT.mPreFb.addr[0] = pPrePicture->phyYBufAddr + dc->nPhyOffset;
mDiParaT.mPreFb.addr[1] = pPrePicture->phyCBufAddr + dc->nPhyOffset;
mDiParaT.mOutputFb.addr[0] = pOutPicture->phyYBufAddr + dc->nPhyOffset;
mDiParaT.mOutputFb.addr[1] = pOutPicture->phyCBufAddr + dc->nPhyOffset;
logv("VideoRender_CopyFrameToGPUBuffer aw_di_setpara start");
//dumpPara(&mDiParaT);
if (ioctl(dc->fd, DI_IOCSTART, &mDiParaT) != 0)
{
loge("aw_di_setpara failed!");
return -1;
}
dc->picCount++;
return 0;
}
static int __DiProcess2(Deinterlace* di,
VideoPicture *pPrePicture,
VideoPicture *pCurPicture,
VideoPicture *pNextPicture,
VideoPicture *pOutPicture,
int nField)
{
struct DiContext* dc;
dc = (struct DiContext*)di;
logv("call DeinterlaceProcess2");
if(pPrePicture == NULL || pCurPicture == NULL || pNextPicture == NULL || pOutPicture == NULL)
{
loge("the input param is null : %p, %p, %p, %p",
pPrePicture, pCurPicture, pNextPicture, pOutPicture);
return -1;
}
if(dc->fd == -1)
{
loge("not init...");
return -1;
}
if (dc->iomemType == IOMEM_UNKNOWN)
{
loge("iomem type unknown.");
return -1;
}
if((pNextPicture == pCurPicture) && (pPrePicture == pCurPicture))
{
dc->diMode = DI_MODE_INTP;
setMode2(di);
}
else if(dc->diMode == DI_MODE_INTP &&
(pPrePicture != pCurPicture) && (pNextPicture != pCurPicture))
{
__DiReset(di);
dc->diMode = DI_MODE_MOTION;
setMode2(di);
}
DiParaT2 mDiParaT2;
DiRectSizeT mRealSize;
DiRectSizeT mAlignSize;
DiPixelformatE2 eInFormat;
DiPixelformatE2 eOutFormat;
memset(&mDiParaT2, 0, sizeof(DiParaT2));
//* compute pts again
int nDefaultFrameRate = 30000; //* we set the frameRate to 30
int nDefaultFrameDuration = 1000*1000*1000/nDefaultFrameRate;
if (dc->picCount < 2)
{
pOutPicture->nPts = pNextPicture->nPts + nField*nDefaultFrameDuration/2;
}
else
{
if((pNextPicture->nPts - pCurPicture->nPts) > 0)
{
pOutPicture->nPts = pNextPicture->nPts
+ nField*(pNextPicture->nPts - pCurPicture->nPts)/2;
}
else
{
pOutPicture->nPts = pNextPicture->nPts + nField*nDefaultFrameDuration/2;
}
}
logv("pNextPicture->nPts = %lld ms, pOutPicture->nPts = %lld ms, diff = %lld ms ",
pNextPicture->nPts/1000,pOutPicture->nPts/1000,
(pOutPicture->nPts - pNextPicture->nPts)/1000);
if (pCurPicture->ePixelFormat == PIXEL_FORMAT_NV12)
{
eInFormat = DI2_FORMAT_NV12;
}
else if (pCurPicture->ePixelFormat == PIXEL_FORMAT_NV21)
{
eInFormat = DI2_FORMAT_NV21;
}
else if (pCurPicture->ePixelFormat == PIXEL_FORMAT_YV12)
{
eInFormat = DI2_FORMAT_YV12;
}
else
{
loge("the inputPixelFormat is not support : %d",pCurPicture->ePixelFormat);
return -1;
}
if (pOutPicture->ePixelFormat == PIXEL_FORMAT_NV12)
{
eOutFormat = DI2_FORMAT_NV12;
}
else if (pOutPicture->ePixelFormat == PIXEL_FORMAT_NV21)
{
eOutFormat = DI2_FORMAT_NV21;
}
else if (pOutPicture->ePixelFormat == PIXEL_FORMAT_YV12)
{
eOutFormat = DI2_FORMAT_YV12;
}
else
{
loge("the outputPixelFormat is not support : %d",pOutPicture->ePixelFormat);
return -1;
}
mRealSize.nWidth = pCurPicture->nRightOffset - pCurPicture->nLeftOffset;
mRealSize.nHeight = pCurPicture->nBottomOffset - pCurPicture->nTopOffset;
mAlignSize.nWidth = pOutPicture->nLineStride;
mAlignSize.nHeight = pOutPicture->nHeight;
if (dc->iomemType == IOMEM_CMA)
{
mDiParaT2.mInputFb.addr[0] = pCurPicture->phyYBufAddr + dc->nPhyOffset;
mDiParaT2.mInputFb.addr[1] = pCurPicture->phyCBufAddr + dc->nPhyOffset;
}
else if (dc->iomemType == IOMEM_IOMMU)
{
mDiParaT2.mInputFb.fd = pCurPicture->nBufFd;
}
mDiParaT2.mInputFb.mRectSize.nWidth = mAlignSize.nWidth ;
mDiParaT2.mInputFb.mRectSize.nHeight = mAlignSize.nHeight;
mDiParaT2.mInputFb.eFormat = eInFormat;
if (dc->iomemType == IOMEM_CMA)
{
mDiParaT2.mPreFb.addr[0] = pPrePicture->phyYBufAddr + dc->nPhyOffset;
mDiParaT2.mPreFb.addr[1] = pPrePicture->phyCBufAddr + dc->nPhyOffset;
}
else if (dc->iomemType == IOMEM_IOMMU)
{
mDiParaT2.mPreFb.fd = pPrePicture->nBufFd;
}
mDiParaT2.mPreFb.mRectSize.nWidth = mAlignSize.nWidth ;
mDiParaT2.mPreFb.mRectSize.nHeight = mAlignSize.nHeight;
mDiParaT2.mPreFb.eFormat = eInFormat;
if (dc->iomemType == IOMEM_CMA)
{
mDiParaT2.mNextFb.addr[0] = pNextPicture->phyYBufAddr + dc->nPhyOffset;
mDiParaT2.mNextFb.addr[1] = pNextPicture->phyCBufAddr + dc->nPhyOffset;
}
else if (dc->iomemType == IOMEM_IOMMU)
{
mDiParaT2.mNextFb.fd = pNextPicture->nBufFd;
}
mDiParaT2.mNextFb.mRectSize.nWidth = mAlignSize.nWidth ;
mDiParaT2.mNextFb.mRectSize.nHeight = mAlignSize.nHeight;
mDiParaT2.mNextFb.eFormat = eInFormat;
mDiParaT2.mSourceRegion.nWidth = mRealSize.nWidth;
mDiParaT2.mSourceRegion.nHeight = mRealSize.nHeight;
mDiParaT2.mOutRegion.nWidth = mRealSize.nWidth;
mDiParaT2.mOutRegion.nHeight = mRealSize.nHeight;
if (dc->iomemType == IOMEM_CMA)
{
mDiParaT2.mOutputFb.addr[0] = pOutPicture->phyYBufAddr + dc->nPhyOffset;
mDiParaT2.mOutputFb.addr[1] = pOutPicture->phyCBufAddr + dc->nPhyOffset;
}
else if (dc->iomemType == IOMEM_IOMMU)
{
mDiParaT2.mOutputFb.fd = pOutPicture->nBufFd;
}
mDiParaT2.mOutputFb.mRectSize.nWidth = mAlignSize.nWidth ;
mDiParaT2.mOutputFb.mRectSize.nHeight = mAlignSize.nHeight;
mDiParaT2.mOutputFb.eFormat = eOutFormat;
mDiParaT2.nField = nField;
mDiParaT2.bTopFieldFirst = pCurPicture->bTopFieldFirst;
//dumpPara2(&mDiParaT2);
if (ioctl(dc->fd, DI_IOCSTART2, &mDiParaT2) != 0)
{
loge("aw_di_setpara2 failed!");
return -1;
}
dc->picCount++;
return 0;
}
static struct DeinterlaceOps mDi =
{
.destroy = __DiDestroy,
.init = __DiInit,
.reset = __DiReset,
.expectPixelFormat = __DiExpectPixelFormat,
.flag = __DiFlag,
.process = __DiProcess,
.process2 = __DiProcess2,
};
Deinterlace* DeinterlaceCreate_Omx()
{
struct DiContext* dc = (struct DiContext*)malloc(sizeof(struct DiContext));
if(dc == NULL)
{
logw("deinterlace create failed");
return NULL;
}
memset(dc, 0, sizeof(struct DiContext));
// we must set the fd to -1; or it will close the file which fd is 0
// when destroy
dc->fd = -1;
dc->base.ops = &mDi;
return &dc->base;
}