DM642学习笔记(程序注释)

 2010年11月初DM642学习笔记

 

用的是瑞泰创新的实验箱(ICETEK-DM642-IDK-M),主要是视频处理部分的程序注释及思考题思路及一些不成熟的见解~~

 

实验5.6-5.19 视频驱动程序应用

DM642视频驱动程序的注释:

/*

 *  Copyright 2003 by Texas Instruments Incorporated.

 *  All rights reserved. Property of Texas Instruments Incorporated.

 *  Restricted rights to use, duplicate or disclose this code are

 *  granted through contract.

 * 

 */

/* "@(#) DDK 1.10.00.23 07-02-03 (ddk-b12)" */

#include <std.h>    //如果使用C语言,必须将此文件作为第一个头文件

#include <tsk.h> 

#include <sem.h>  

#include <gio.h>

 

#include <csl_dat.h>

#include <csl_cache.h>//使用CSL库,要用到的一些头文件,可参考CSL

 

#include <fvid.h>//视频驱动头文件

#include <edc.h>

#include <vport.h>

#include <vportcap.h>

#include <vportdis.h>

#include <saa7105.h>

#include <saa7115.h>   

 

#include <evmdm642.h>//芯片头文件

 

#include "colorbar.h"//如果显示彩色滚动条,就必须有此头文件;否则不需要

#include "evmdm642_vcapparams.h"

#include "evmdm642_vdisparams.h"  

 

/* heap IDs defined in the BIOS configuration file */

extern Int EXTERNALHEAP;//??DSP/BIOS?????¨??

 

/*

 * ======== main ========

 */

main()

{

    /******************************************************/

    /* open CSL DAT module for fast copy                  */

    /******************************************************/

    CSL_init();                                 //调用任何CSL库中的函数,必须先在此调用函数

    CACHE_clean(CACHE_L2ALL, 0, 0);                             //清洗Cache模式

    CACHE_setL2Mode(CACHE_256KCACHE);                         //设置Cache模式

CACHE_enableCaching(CACHE_EMIFA_CE00);                   //使能EMIFA CE0空间

CACHE_enableCaching(CACHE_EMIFA_CE01);                   //使能EMIFA CE1空间

    DAT_open(DAT_CHAANY, DAT_PRI_LOW, DAT_OPEN_2D); //打开数据传输

 

}

 

/*

 * ======== tskVideoLoopback ========

 * video loopback function.

 */

void tskVideoLoopback()

{

    Int i;

    int m_nWork;

    Int status;

    FVID_Handle disChan;         //设置设备句柄

    Int frames = 0;

    FVID_Frame *disFrameBuf;

Int numLinesDis = EVMDM642_vDisParamsChan.imgVSizeFld1;

//设置显示的行数,VGA为480,PAL为576

Int numLinesCap =EVMDM642_vCapParamsChan.fldYStop1 -  //设置采集行数

                                     EVMDM642_vCapParamsChan.fldYStrt1+1;

   

    /*判断是显示区域大,还是采集区域大,取其小者*/

    Int numLines = (numLinesDis > numLinesCap) ? numLinesCap : numLinesDis;

 

#ifdef _LOOPBACK

    FVID_Handle capChan;

   

    /*设置每行显示的像素数,PAL制为720*/

    Int numPixels = EVMDM642_vCapParamsChan.fldXStop1 -

       EVMDM642_vCapParamsChan.fldXStrt1+1;

  

    FVID_Frame *capFrameBuf;

   

    /*设置采集图像一行的总像素*/

    Int capLinePitch = EVMDM642_vCapParamsChan.fldXStop1 -

       EVMDM642_vCapParamsChan.fldXStrt1+1;

      

    /*设置显示图像一行的总像素*/  

    Int disLinePitch = EVMDM642_vDisParamsChan.imgHSizeFld1;

 

 

#ifdef _PIP

    VPORTCAP_Params EVMDM642_vCapParamsChan2 = EVMDM642_vCapParamsChan;

    FVID_Handle capChan2;

    FVID_Frame *capFrameBuf2;

    Int yPitch = capLinePitch >> 1;

    Int cPitch = ((capLinePitch >> 2) + 7) & (~ 7);

#endif

#endif               

 

 

    numLines *= 2; /* both fields */如果输出为PAL制,前面numLinesCap不要*2,这里再*2?

    /******************************************************/

    /* allocate both capture and display frame buffers    */

    /* in external heap memory                            */

    /******************************************************/

    /*分配采集和显示图像的存放缓冲区*/

        EVMDM642_vCapParamsChan.segId = EXTERNALHEAP;

        EVMDM642_vDisParamsChan.segId = EXTERNALHEAP;

        EVMDM642_vDisParamsSAA7105.hI2C = EVMDM642_I2C_hI2C;

        EVMDM642_vCapParamsSAA7115.hI2C = EVMDM642_I2C_hI2C;

 

    /******************************************************/

    /* initialization of capture driver                   */

    /******************************************************/

    /*建立并初始化采集设备对象*/

#ifdef _LOOPBACK

    capChan = FVID_create("/VP0CAPTURE/A/0",

            IOM_INPUT, &status, (Ptr)&EVMDM642_vCapParamsChan, NULL);

 

#ifdef _PIP

    EVMDM642_vCapParamsChan2.scale = VPORT_SCALING_ENABLE;

        EVMDM642_vCapParamsChan2.fldOp = VPORT_FLDOP_FLD1;       

        EVMDM642_vCapParamsChan2.thrld >>=1;

    capChan2 = FVID_create("/VP1CAPTURE/A/1",

            IOM_INPUT, &status, (Ptr)&EVMDM642_vCapParamsChan2, NULL);

#endif         

 

#endif         

    /******************************************************/

    /* initialization of display driver                   */

    /******************************************************/

    /*建立并初始化显示设备对象*/

    disChan = FVID_create("/VP2DISPLAY", IOM_OUTPUT,

        &status, (Ptr)&EVMDM642_vDisParamsChan, NULL);

 

   

    /******************************************************/

    /* configure video encoder & decoder                  */

    /******************************************************/

    for ( m_nWork=0;m_nWork<6;m_nWork++ )//这里的循环有何用???一直没有弄清楚

    {

           /*为保证采集和显示设备正常工作,为其设置驱动*/

           FVID_control(disChan, VPORT_CMD_EDC_BASE + EDC_CONFIG,

               (Ptr)&EVMDM642_vDisParamsSAA7105);

#ifdef _LOOPBACK

           FVID_control(capChan, VPORT_CMD_EDC_BASE + EDC_CONFIG,

               (Ptr)&EVMDM642_vCapParamsSAA7115);

#ifdef _PIP

           EVMDM642_vCapParamsSAA7115.aFmt = SAA7115_AFMT_COMPOSITE;

           FVID_control(capChan2, VPORT_CMD_EDC_BASE+EDC_CONFIG,

               (Ptr)&EVMDM642_vCapParamsSAA7115);

#endif

#endif

       }

 

    /******************************************************/

    /* start capture & display operation                  */   

    /******************************************************/

    /*开始采集和显示操作*/

    FVID_control(disChan, VPORT_CMD_START, NULL);

#ifdef _LOOPBACK

    FVID_control(capChan, VPORT_CMD_START, NULL);

#ifdef _PIP

    FVID_control(capChan2, VPORT_CMD_START, NULL);

#endif   

#endif   

   

    /********************************************************/

    /* request a frame buffer from display & capture driver */

    /********************************************************/

    /*分配采集和显示一帧图像存放的缓冲区*/

    FVID_alloc(disChan, &disFrameBuf);

#ifdef _LOOPBACK

    FVID_alloc(capChan, &capFrameBuf);

#ifdef _PIP

    FVID_alloc(capChan2, &capFrameBuf2);

#endif     

#endif

    frames ++;

 

    while(1){/* loop forever */

#ifdef _LOOPBACK

        /* copy data from capture buffer to display buffer */

        /***************************************************/

              /*将采集缓冲区的内容复制到显示缓冲区*/

        for(i = 0; i < numLines; i ++) {

            DAT_copy(capFrameBuf->frame.iFrm.y1 + i * capLinePitch,

                     disFrameBuf->frame.iFrm.y1 + i * disLinePitch,

                     numPixels);

            DAT_copy(capFrameBuf->frame.iFrm.cb1 + i * (capLinePitch >> 1),

                     disFrameBuf->frame.iFrm.cb1 + i * (disLinePitch >> 1),

                     numPixels>>1);

 

            DAT_copy(capFrameBuf->frame.iFrm.cr1 + i * (capLinePitch >> 1),

                     disFrameBuf->frame.iFrm.cr1 + i * (disLinePitch >> 1),

                     numPixels>>1);

        }

#ifdef _PIP 

        for(i = 0; i < (numLines>>1); i ++) {

            DAT_copy(capFrameBuf2->frame.iFrm.y1 + i * yPitch,

                     disFrameBuf->frame.iFrm.y1 + i * disLinePitch

                     + (disLinePitch >> 1),

                     (numPixels>>1));

            DAT_copy(capFrameBuf2->frame.iFrm.cb1 + i * cPitch,

                     disFrameBuf->frame.iFrm.cb1 + i * (disLinePitch >> 1)

                     + (disLinePitch >>2 ),

                     (numPixels >> 2));

 

            DAT_copy(capFrameBuf2->frame.iFrm.cr1 + i * cPitch,

                     disFrameBuf->frame.iFrm.cr1 + i * (disLinePitch >> 1)

                     +(disLinePitch >> 2),

                     (numPixels >> 2));

        }

#endif

        DAT_wait(DAT_XFRID_WAITALL);

        FVID_exchange(capChan, &capFrameBuf);//采集一帧图像

#ifdef _PIP

        FVID_exchange(capChan2, &capFrameBuf2);

#endif

#else  //如果定义CAPTURE则填充图像缓冲区为8条带

        fillFrmBuf(&disFrameBuf->frame.iFrm, EVMDM642_vDisParamsChan.imgHSizeFld1,

          EVMDM642_vDisParamsChan.imgVSizeFld1

            + EVMDM642_vDisParamsChan.imgVSizeFld2,

          frames % 360);

#endif

        FVID_exchange(disChan, &disFrameBuf);//将显示缓冲区中一帧图像送给显示设备    

        frames ++;             //处理下一帧图像        

   }

}

 

实验5.20 视频图像处理-取反

1.将程序改成屏幕1/4进行取反,而其他不变

在主程序中ICETEKDM642PCIImageProcessReverse()函数前加if(i<(numLines/2)),即:

if(i<(numLines/2))

                            ICETEKDM642PCIImageProcessReverse();

并将ICETEKDM642PCIImageProcessReverse()函数中的循环体改为如下:

       for ( i=0;i<720/2;i++ )

              nMemTemp[i]=~nMemTemp[i];

 

2.例程中处理了亮度信号,以下是处理色差信号:

for ( i = 0; i < numLines; i ++ )

{

m_nID=DAT_copy(capFrameBuf->frame.iFrm.cb1+i*(capLinePitch>>1),nMemTemp,numPixels>>1);

DAT_wait(m_nID);

 

ICETEKDM642PCIImageProcessReverse();

 

DAT_copy(nMemTemp,disFrameBuf->frame.iFrm.cb1+i*(disLinePitch>>1),numPixels>>1);

           

for ( m_nWork=0;m_nWork<numPixels>>1;m_nWork++ )

              nMemTemp[m_nWork]=0x080;

                           

DAT_copy(nMemTemp,disFrameBuf->frame.iFrm.y1+i*disLinePitch,numPixels);           DAT_copy(nMemTemp,disFrameBuf->frame.iFrm.cr1+i*(disLinePitch>>1),numPixels>>1);

}

出现的问题:图像显示时右半屏有闪烁???~~~

 

实验5.21 视频图像处理-直方图统计

程序注释:源程序中定义的js变量不知为何用,于是就删除了~~~

#include "ICETEK-DM642-PCI.h"

 

//工作变量

#pragma DATA_SECTION(nMemTemp, ".INTPROCBUFF");

#pragma DATA_ALIGN(nMemTemp,128);

unsigned char nMemTemp[720];

#pragma DATA_SECTION(nHisto, ".INTPROCBUFF");

#pragma DATA_ALIGN(nHisto,128);

unsigned int nHisto[256];

unsigned char imgHisto[HISTOHIGH*HISTOWIDTH];//128*256

int mi,mj,m_nWork1;

unsigned int m_nWork,*pWork;

unsigned char *pImg,*pImg1;

 

void ICETEKDM642PCIBoardInit()//直方图显示区域初始化

{

       for ( mi=0;mi<HISTOHIGH*HISTOWIDTH;mi++ )

              imgHisto[mi]=1;

       for ( mi=0;mi<256;mi++ )

              nHisto[mi]=0;

}

 

#pragma CODE_SECTION(ICETEKDM642PCIStatistic,".text1")

void ICETEKDM642PCIStatistic()//统计一帧图像的直方图

{

       int i;

       for ( i=0;i<720;i++ )

       {

              nHisto[nMemTemp[i]]++;

       }

}

 

#pragma CODE_SECTION(ICETEKDM642PCIHistogram,".text1")

void ICETEKDM642PCIHistogram()//将统计的一帧图像的直方图显示在显示区域上

{

       m_nWork=0;

       for ( mi=0;mi<256;mi++ )//找出各灰度级别像素总数最大的

              if ( m_nWork<nHisto[mi] )

                     m_nWork=nHisto[mi];

                    

       m_nWork/=(HISTOHIGH-1);//求出比例因子(即像素总数最大值/显示区域的高度)

      

       for ( mi=0;mi<256;mi++ )//转换各灰度级,将其映射到显示区域(即:各个灰度级的像素/比例因子)

       {

              nHisto[mi]/=m_nWork;

       }

      

       for ( mi=0;mi<HISTOHIGH*HISTOWIDTH;mi++ )//将显示区域置白

              imgHisto[mi]=1;

             

       pImg = imgHisto; //pImg指针指向显示区域首地址

       pImg += ((HISTOHIGH-1)*HISTOWIDTH); //mImg指针指向显示区域尾地址

       pImg++;//???

      

       for ( mi=1;mi<255;mi++,pImg++ )

       {

              for ( mj=0,pImg1=pImg;mj<nHisto[mi];mj++,pImg1-=HISTOWIDTH )

                     (*pImg1)=HISTOCOLOR;//对应的显示区域填充颜色,这里还是不太明白

       }

 

       for ( mi=0;mi<256;mi++ ) //清除直方图统计的数组

              nHisto[mi]=0;

}

 

实验5.22 视频图像处理-直方图均衡化增强

程序注释:直方图均衡化,其实质是图像增强的一种。

#include "math.h"

#include "ICETEK-DM642-PCI.h"

 

//工作变量

#pragma DATA_SECTION(nMemTemp, ".INTPROCBUFF");

#pragma DATA_ALIGN(nMemTemp,128);

unsigned char nMemTemp[720];

#pragma DATA_SECTION(fHisto, ".INTPROCBUFF");

#pragma DATA_ALIGN(fHisto,128);

float fHisto[256];//

#pragma DATA_SECTION(lut, ".INTPROCBUFF");

#pragma DATA_ALIGN(lut,128);

unsigned char lut[256];//保存新的灰度级,是通过上一帧图像计算的

int mi,mj,m_nWork1;

unsigned int m_nWork,*pWork,js;

unsigned char *pImg,*pImg1;

float m_fWork;

 

void ICETEKDM642PCIBoardInit()

{

       js=0;

       for ( mi=0;mi<256;mi++ )

       {

              fHisto[mi]=0.0f;

              lut[mi]=0;

       }

}

 

#pragma CODE_SECTION(ICETEKDM642PCIStatistic,".text1")

void ICETEKDM642PCIStatistic()

{

       int i;

       for ( i=0;i<720;i++ )

       {

              fHisto[nMemTemp[i]]++;//统计灰度直方图

              nMemTemp[i]=lut[nMemTemp[i]];//新的灰度级映射(通过上一帧图像计算出的新灰度级,处理这一帧图像)

       }

}

 

#pragma CODE_SECTION(ICETEKDM642PCIHistogramEnhance,".text1")

void ICETEKDM642PCIHistogramEnhance()//

{

       m_fWork=720*576; fHisto[0]/=m_fWork;

      

       for ( mi=1;mi<256;mi++ )//灰度直方图频率

       {

              fHisto[mi]/=m_fWork;

              fHisto[mi]+=fHisto[mi-1];

       }

      

       for ( mi=0;mi<256;mi++ )//计算新的灰度级

       {

              m_fWork=fHisto[mi];

              m_fWork*=255;

              lut[mi]=(unsigned char)m_fWork;//这就是新的灰度级

       }

       for ( mi=0;mi<256;mi++ )//灰度直方图数组清0

              fHisto[mi]=0.0f;

}

 

实验5.23 视频图像处理-中值滤波

中值滤波算法实质是一种图像噪声的抑制。该系统实现中值滤波算法速度极慢。

 

实验5.24 视频图像处理-边缘检测(Sobel算子)

Sobel算子实质是图像的锐化处理,主要目的是突出图像中的细节或者增强被模糊了的细节。

       但是对这个算法程序实现不是很明白。

       for ( mi=0;mi<MWIDTH;mi++,pImg1++,pImg2++,pImg3++ )

       {

              x3=(*pImg1); x6=(*pImg2); x9=(*pImg3);

              m_nWork1=x7+x8+x8-x2-x2-x3;

              m_nWork2=x3+x6+x6-x4-x4-x7;

             

              if ( m_nWork1<m_nWork2 )////对这个算法的程序实现不是很明白

                     m_nWork1=m_nWork2;

             

              m_nWork2=m_nWork1+x9-x1;

             

              if ( m_nWork2>255 )    m_nWork2=255;

              else if ( m_nWork2<0 )  m_nWork2=0;

             

              nMemTemp[mi+180]=m_nWork2;

             

              x1=x2; x2=x3;

              x4=x5; x5=x6;

              x7=x8; x8=x9;

       }

 

实验5.25 视频图像处理-傅立叶变换

       对傅立叶变换的知识比较空白。压根没看懂~~~


 

实验5.26 视频图像处理-色彩空间变换

程序注释:

void ICETEKDM642PCIYUVRGB()

{

       int i,j;

       int r,g,b,y,u,v;

       unsigned char *py,*pu,*pv,*pr,*pg,*pb;

      

       py=m_dbFrameY; pu=m_dbFrameU; pv=m_dbFrameV;

       pr=m_dbTargetImageR; pg=m_dbTargetImageG; pb=m_dbTargetImageB;

       for ( i=0;i<SIMGHEIGHT;i++ )  

       { 

              for ( j=0;j<SIMGWIDTH;j+=2 )   ////列720点,360个32bit,

              {

                     u=(*pu); v=(*pv); y=(*py);

                     u-=128; v-=128;

                     r=y+1.402*u;

                     g=y-0.34414*u-0.71414*v;

                     b=y+1.772*v;

                     if ( r>255 )     r=255;

                     else if ( r<0 )  r=0;

                     if ( g>255 )    g=255;

                     else if ( g<0 )  g=0;

                     if ( b>255 )    b=255;

                     else if ( b<0 )  b=0;

                    

                     (*pr)=r; pr++;

                     (*pg)=g; pg++;

                     (*pb)=b; pb++;

                     py++; y=(*py);

                     r=y+1.402*u;

                     g=y-0.34414*u-0.71414*v;

                     b=y+1.772*v;

                     if ( r>255 )     r=255;

                     else if ( r<0 )  r=0;

                     if ( g>255 )    g=255;

                     else if ( g<0 )  g=0;

                     if ( b>255 )    b=255;

                     else if ( b<0 )  b=0;

                    

                     (*pr)=r; pr++;

                     (*pg)=g; pg++;

                     (*pb)=b; pb++;

                     py++; pu++; pv++;

              }

    }

}

////在计算机中,用RGB方式描述一个像素需要R、G、B共3个字节。而用YUV方式描述,则对于每2个像素,Y用2个字节,U取相同的值,用一个字节,V取相同的值,

////用一个字节,平均每个像素2个字节。理解了这一点,对于上面的程序就理解了~~~

你可能感兴趣的:(视频,图像处理,dsp,DM642)