📄 vivot.c
字号:
/*
* Copyright (c) 1995,2000 TriMedia Technologies Inc.
*
* +------------------------------------------------------------------+
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such |
* | a license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided|
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be construed as a commitment by |
* | TriMedia Technologies. |
* | |
* | this code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +------------------------------------------------------------------+
*
* Module name : vivot.c 1.6
*
* Last update : 23:59:51 - 97/03/31
*
* Description :
*
* Revision :
* Built for the TCS 1.1 release
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <tm1/mmio.h>
#include <ops/custom_defs.h>
#include <tm1/tmVI.h>
#include <tm1/tmVO.h>
#include <tm1/tmBoard.h>
#include <tm1/tmAvFormats.h>
#include <tm1/tmVImmio.h>
#include <tm1/tmVOmmio.h>
#include <tm1/tmInterrupts.h>
#include <tm1/tmProcessor.h>
#include <tmlib/tmlibc.h>
#include <tmlib/dprintf.h>
#define VID_RDY_VI 1 /* buffer is ready for vi to use */
#define VID_RDY_MM 2 /* buffer is ready for mm to use */
#define VID_RDY_VO 4 /* buffer is ready for vo to use */
#define NUM_BUF_ENTRIES 4
#define CACHE_LINE_SIZE 64
typedef struct _videoBuf { /* video buffer structure example */
UInt32 Y; /* buffer pointer for Y */
UInt32 U; /* buffer pointer for U */
UInt32 V; /* buffer pointer for V */
UInt32 flag; /* flags used in buffer management */
} vBuf, *pvBuf;
static vBuf fullResBuf[NUM_BUF_ENTRIES];
static vBuf cif422Buf[NUM_BUF_ENTRIES];
static vBuf bkBuf[1];
static vBuf genBuf[NUM_BUF_ENTRIES];
static Int viInst;
static viInstanceSetup_t viInstSup;
static viYUVSetup_t viYUVSup;
static Int voInst;
static voInstanceSetup_t voInstSup;
static voYUVSetup_t voYUVSup;
static voOverlaySetup_t voOverlaySup;
static Int cifStride = 384;
static Int cifWidth = 352;
static Int cifHeight = 240;
static Int fullStride = 768;
static Int fullWidth = 720;
static Int fullHeight = 480;
#define VID_NUMBUFS 4
static Bool DummyCode = False; /* software workaround for hw bug 21217
* Very ugly, if you have a tm1s1.1 or
* better you don't want to know what the
* workaround is....
*/
static Char *Header = "\nTriMedia Video-In to Video-Out "
"Example Program Version 2.0\n";
static int viNum = 0;
static int mmNum = 0;
static int voNum = 0;
static int yFieldStride = 0;
static int uvFieldStride = 0;
static int overlayFieldStride = 0;
static int yScanWidth = 0;
static int uvScanWidth = 0;
static int cpUsize = 0;
static Bool capField = False;
static Bool firstField = False;
static Bool runningOverlay = False;
static int loopCount = 1000;
static int voISRCount = 0;
static UInt videoStandard = vasNTSC;
static UInt adapterType = vaaCVBS;
static void
my_abort(Char * name, Int err)
{
assert(name != Null);
fprintf(stderr, "%s failed, error code %x\n", name, err);
exit(-1);
}
/***** Copy back a memory piece: One big copyback slows down the compiler */
void
invalidateRange(void *ptr, unsigned long size)
{
unsigned long i;
char *p = ptr;
for (i = 0; i < size; i += CACHE_LINE_SIZE)
INVALIDATE(p + i, 1);
}
void
copybackRange(void *ptr, unsigned long size)
{
unsigned long i;
char *p = ptr;
for (i = 0; i < size; i += CACHE_LINE_SIZE)
COPYBACK(p + i, 1);
}
void
voTestISR()
{
unsigned long vo_status = MMIO(VO_STATUS);
int votmpNum;
#pragma TCS_handler
voISRCount++;
if (voYTR(vo_status))
voAckYTR_ACK();
if (voURUN(vo_status))
voAckURUN_ACK();
if (voHBE(vo_status))
voAckHBE_ACK();
if (voBUF2EMPTY(vo_status))
voAckBFR2_ACK();
if (voBUF1EMPTY(vo_status)) { /* bfr1 empty */
if (runningOverlay) {
if (voFIELD2(vo_status)) {
/* from f1 to f2 */
voYUVChangeBuffer(voInst,
bkBuf[0].Y + yFieldStride,
bkBuf[0].U + uvFieldStride,
bkBuf[0].V + uvFieldStride);
voOverlayChangeBuffer(voInst,
genBuf[voNum].Y + overlayFieldStride);
}
else {
votmpNum = (voNum + 1) % VID_NUMBUFS;
if (genBuf[votmpNum].flag == VID_RDY_VO) {
genBuf[voNum].flag = VID_RDY_VI;
voNum = votmpNum;
}
voYUVChangeBuffer(voInst,
bkBuf[0].Y,
bkBuf[0].U,
bkBuf[0].V);
voOverlayChangeBuffer(voInst,
genBuf[voNum].Y);
}
}
else {
if (voFIELD2(vo_status)) {
/* from f1 to f2 */
voYUVChangeBuffer(voInst,
(Char *)genBuf[voNum].Y + yFieldStride,
(Char *)genBuf[voNum].U + uvFieldStride,
(Char *)genBuf[voNum].V + uvFieldStride);
}
else {
votmpNum = (voNum + 1) % VID_NUMBUFS;
if (genBuf[votmpNum].flag == VID_RDY_VO) {
genBuf[voNum].flag = VID_RDY_VI;
voNum = votmpNum;
}
voYUVChangeBuffer(voInst,
genBuf[voNum].Y,
genBuf[voNum].U,
genBuf[voNum].V);
}
}
voAckBFR1_ACK();
/*
* In the handler for a level-triggered interrupt,
* the interrupt acknowledge store must be issued at least
* two cycles before the ijmp which ends the handler;
* see section 3.4.3.3 of the Databook for details.
* The #pragma TCS_break_dtree here assures this,
* as the following dtree contains a minimum of three cycles.
*/
#pragma TCS_break_dtree
return;
}
}
void
viTestISR()
{
unsigned long vi_status = MMIO(VI_STATUS);
int oddField;
int vitmpNum;
#pragma TCS_handler
oddField = viExtractODD(vi_status);
if ((vi_status & 0x1) == 0) {
/*
* This is due to hardware bug 21390, a spurious interrupt
* may occur. Since we have only enabled capture_enable (0x1)
* we should not check on threshold_reached (0x2)
*/
return;
}
if (viHBE(vi_status)) {
/*
* Highway banmdwidth, VI needs more bandwidth. You can play
* with the highway arbitration setting
*/
viAckHBE_ACK();
return;
}
if (capField) {
vitmpNum = (viNum + 1) % VID_NUMBUFS;
if (oddField & (genBuf[vitmpNum].flag == VID_RDY_VI)) {
if (DummyCode) {
invalidateRange((void *)MMIO(DRAM_BASE), cpUsize);
memcpy(genBuf[viNum].U, MMIO(DRAM_BASE), cpUsize);
copybackRange((void *)genBuf[viNum].U, cpUsize);
}
genBuf[viNum].flag = VID_RDY_MM;
viNum = vitmpNum;
viYUVChangeBuffer(viInst,
genBuf[viNum].Y,
(DummyCode) ? (UInt32) MMIO(DRAM_BASE) : genBuf[viNum].U,
genBuf[viNum].V);
}
viAckCAP_ACK();
/*
* In the handler for a level-triggered interrupt,
* the interrupt acknowledge store must be issued at least
* two cycles before the ijmp which ends the handler;
* see section 3.4.3.3 of the Databook for details.
* The #pragma TCS_break_dtree here assures this,
* as the following dtree contains a minimum of three cycles.
*/
#pragma TCS_break_dtree
return;
}
/*
* !!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!
* This acknowledge really should be done at the end
* of the ISR just before the dtree_break. That will
* work on the tm1s1.1 and further, but due to the
* hardware bug 21217 in combination with 3016 we are
* forced to acknowledge before we process the data.
* HW bug 21217 makes us copy the U-buffer from
* MMIO base into a real U-buffer. This takes a long
* time, which makes us hit hardware bug 3016. HW bug 3016
* says: acknowledge in the vertical blanking interval or
* you are hosed. So we need to acknowledge in time.
* For the HALFRES we are still fast enough to not hit this
* 3016 bug.
*
* Now because we acknowledge too soon, the hardware
* already starts with the next capture with the old
* buffer pointers. This results swapped fields and
* therefore we swap the field (i.e. change from:
* if (!oddField) ---> if (oddField) to avoid interlace
* artifacts.
*/
if (DummyCode)
viAckCAP_ACK();
if (firstField) {
firstField = False;
if ( (DummyCode) && (oddField) ) {
firstField = True;
} else if ( (!DummyCode) && (!oddField) ) {
/* skip even field to get sync */
firstField = True;
} else {
/* always start with odd field */
viYUVChangeBuffer(viInst,
genBuf[viNum].Y + yScanWidth,
(DummyCode) ? (UInt32) MMIO(DRAM_BASE) + uvScanWidth
: genBuf[viNum].U + uvScanWidth,
genBuf[viNum].V + uvScanWidth);
}
}
else {
vitmpNum = (viNum + 1) % VID_NUMBUFS;
if (genBuf[vitmpNum].flag == VID_RDY_VI) {
if (DummyCode) {
invalidateRange((void *)MMIO(DRAM_BASE), cpUsize);
memcpy(genBuf[viNum].U, MMIO(DRAM_BASE), cpUsize);
copybackRange((void *)genBuf[viNum].U, cpUsize);
}
genBuf[viNum].flag = VID_RDY_MM;
viNum = vitmpNum;
}
viYUVChangeBuffer(viInst,
genBuf[viNum].Y,
(DummyCode) ? (UInt32) MMIO(DRAM_BASE)
: genBuf[viNum].U,
genBuf[viNum].V);
firstField = 1;
}
/*
* Force two cycles between the ack and ending the ISR
*/
if (!DummyCode)
viAckCAP_ACK(); /* read comments above on the acknowledge */
/*
* In the handler for a level-triggered interrupt,
* the interrupt acknowledge store must be issued at least
* two cycles before the ijmp which ends the handler;
* see section 3.4.3.3 of the Databook for details.
* The #pragma TCS_break_dtree here assures this,
* as the following dtree contains a minimum of three cycles.
*/
#pragma TCS_break_dtree
return;
}
void
CIF422OVERLAY(unsigned long yP, unsigned long uP, unsigned long vP,
unsigned long ovP)
{
unsigned char *pp;
unsigned char *pY0;
unsigned char *pY1;
unsigned char *pU;
unsigned char *pV;
unsigned int *tmpPtr;
int i, j;
pY0 = (unsigned char *) yP;
pU = (unsigned char *) uP;
pV = (unsigned char *) vP;
pp = (unsigned char *) yP;
pY1 = ++pp;
tmpPtr = (unsigned int *) ovP;
for (i = 0; i < cifHeight; i++) {
for (j = 0; j < 176; j++) {
*tmpPtr = ((*pY1++ & 0xff) << 24) | (*pV++ & 0xff) << 16 |
((*pY0++ & 0xff) << 8) | (*pU++ & 0xff) << 0;
tmpPtr++;
pY1++;
pY0++;
}
for (j = 0; j < 16; j++) {
pY0 += 2;
pY1 += 2;
pU++;
pV++;
}
}
}
void
mmBufUpdate()
{
int mmtmpNum;
mmtmpNum = (mmNum + 1) % VID_NUMBUFS;
if (genBuf[mmtmpNum].flag == VID_RDY_MM) {
genBuf[mmNum].flag = VID_RDY_VO;
mmNum = mmtmpNum;
}
}
void
mmOvlyBufUpdate()
{
int mmtmpNum;
mmtmpNum = (mmNum + 1) % VID_NUMBUFS;
if (genBuf[mmtmpNum].flag == VID_RDY_MM) {
/*
* genBuf[mmtmpNum] has the newly captured image from
* video-in
*
* convert genBuf[mmtmpNum].YUV CIF422 to
* gebbuf[mmNum].Y-Overlay
*
* that is: convert them from Y U V planar to YVYU
*
* put the YVYU in genBuf[mmNum] and label it VO ready for
* display
*
* set mmNum=mmtmpNum
*/
CIF422OVERLAY(genBuf[mmtmpNum].Y, genBuf[mmtmpNum].U,
genBuf[mmtmpNum].V, genBuf[mmNum].Y);
genBuf[mmNum].flag = VID_RDY_VO;
mmNum = mmtmpNum;
}
}
UInt32
allocSz(int bufSz)
{
UInt32 temp;
int i;
if ((temp = (UInt32) _cache_malloc(bufSz, -1)) == Null)
my_abort("_cache_malloc", 0);
memset(temp, 0, bufSz);
for (i = 0; i < bufSz; i += CACHE_LINE_SIZE)
COPYBACK((void *) (temp + i), 1);
return temp;
}
void
allocCif422()
{
int i, szY, szUV;
szY = (cifStride * (cifHeight + 4));
szUV = ((cifStride >> 1) * (cifHeight + 4));
for (i = 0; i < VID_NUMBUFS; i++) {
cif422Buf[i].Y = allocSz(szY);
cif422Buf[i].U = allocSz(szUV);
cif422Buf[i].V = allocSz(szUV);
cif422Buf[i].flag = VID_RDY_VI;
DP(("Allocate CIF422Buf i %d Y %x U %x V %x\n",
i, cif422Buf[i].Y, cif422Buf[i].U, cif422Buf[i].V));
}
}
void
allocFullRes()
{
int i, szY, szUV;
szY = (fullStride * (fullHeight + 4));
szUV = ((fullStride >> 1) * (fullHeight + 4));
for (i = 0; i < VID_NUMBUFS; i++) {
fullResBuf[i].Y = allocSz(szY);
fullResBuf[i].U = allocSz(szUV);
fullResBuf[i].V = allocSz(szUV);
fullResBuf[i].flag = VID_RDY_VI;
DP(("Allocate fullResBuf i %d Y %x U %x V %x\n",
i, fullResBuf[i].Y, fullResBuf[i].U, fullResBuf[i].V));
}
}
void
allocBkBuf()
{
int szY, szUV;
szY = (768 * (576 + 4));
szUV = ((768 >> 1) * (576 + 4));
bkBuf[0].Y = allocSz(szY);
bkBuf[0].U = allocSz(szUV);
bkBuf[0].V = allocSz(szUV);
bkBuf[0].flag = VID_RDY_VI;
DP(("Allocate bkBuf Y %x U %x V %x\n",
bkBuf[0].Y, bkBuf[0].U, bkBuf[0].V));
}
void
cpGenBuf(vBuf * buf, int numBuf, int flag)
{
vBuf *pBuf;
int i;
pBuf = buf;
for (i = 0; i < numBuf; i++) {
genBuf[i].Y = pBuf[i].Y;
genBuf[i].U = pBuf[i].U;
genBuf[i].V = pBuf[i].V;
genBuf[i].flag = flag;
}
}
int
readYUVFiles(char *baseName, int hsize, int vsize,
UInt32 ybuf, UInt32 ubuf, UInt32 vbuf)
{
int count, ySize, uvSize, row;
char fn[80];
unsigned char *pb;
FILE *fp;
printf("reading the overlay file...\n");
/* get memory */
ySize = hsize * vsize;
uvSize = (ySize >> 1);
/* just read Y file: binary */
sprintf(fn, "%s.y", baseName);
fp = fopen(fn, "rb");
if (!fp)
return (4);
count = fread((char *) ybuf, 1, ySize, fp);
fclose(fp);
copybackRange((void*)ybuf, ySize);
/* just read U file: binary */
sprintf(fn, "%s.u", baseName);
fp = fopen(fn, "rb");
if (!fp)
return (4);
pb = (unsigned char *) ubuf;
count = 0;
for (row = 0; row < (vsize >> 1); row++) {
count += fread(pb, 1, (hsize >> 1), fp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -