2440/2416/6410/S5PV210之wince+android系统驱动开发者

等待新发生的事情

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  作者:gooogleman 平台:OK2440/TE2440(wince5.0) 日期:2010-12-21

  经过一番折腾,P通道预览,C通道保存拍照图片的功能是实现了,并且采用了飞凌2440 摄像头驱动动态分配DMA的办法,这样大大节省了内存,可是郁闷的是有很多时间拍照不会产生图片,可是采用静态分配DMA的方式却可以每次都保存一个图片,为什么呢?我记得以前没有用C通道保存大分辨率图片的时候都会这样的,只是一直没有理会,现在这个摄像头快收工了却发生了这样的事情,真是太邪乎了,咋办呢?只能老老实实比较代码呗。应用并没有差异,主要是驱动看上去有点玄机。下面贴出来一起瞧瞧。

拍照正常的


//=============================================================================
//  数据处理线程IST
//
//=============================================================================
DWORD CameraCaptureThread(void)
{
 unsigned char tmp=0;
 static unsigned int time,old_time;
 static unsigned int cam_intr;

 
 RETAILMSG(1, (TEXT("CameraCaptureThread funtion run test!!!\r\n")));
 while(1)
 {
  
        //RETAILMSG(1, (TEXT(" Camera interrupt.....before WaitForSingleObject\r\n")));
  WaitForSingleObject(CameraEvent, DisplayTime);
  
        //RETAILMSG(1, (TEXT(" Camera interrupt.....after WaitForSingleObject\r\n")));
  
  //RETAILMSG(MSG_EN_1,(_T("CameraCaptureThread(%d)++\r\n"), frame_count));

  //RETAILMSG(1,(_T("CameraCaptureThread(%d)++\r\n"), frame_count));

#if 0
  if (frame_count <= 2) {
   frame_count++;
   // Enable camera interrupt
   s2440INT->rINTSUBMSK &= ~(BIT_SUB_CAM_P|BIT_SUB_CAM_C);
   s2440INT->rINTMSK &= ~BIT_CAM;
   
   continue;
  }
#endif
  
  //if( DisplayEnable )
  {

   frame_count++;

   if (s2440INT->rINTSUBMSK & BIT_SUB_CAM_C)
   {
    cam_intr = BIT_SUB_CAM_C;
    //RETAILMSG(1,(_T("CAM_C, ts %d\r\n"), GetTickCount()));
   }
   
   if (s2440INT->rINTSUBMSK & BIT_SUB_CAM_P)
   {
    cam_intr = BIT_SUB_CAM_P;
    //RETAILMSG(1,(_T("CAM_P, ts %d\r\n"), GetTickCount()));
   }
   
   
   // EINT20 to measure time
//   s2440IOP->rGPGDAT |= (1<<12);
//   time = GetTickCount();
//   RETAILMSG(1,(TEXT("+time:%d\r\n"),(time - old_time)));

   // delay for capture
   //Sleep(CAPTURE_TIME);   // polling mode

                     //liudiping
   // display the image 
   //if ((DRIVER_PREVIEW_ENABLE == 1) & (cam_intr == BIT_SUB_CAM_P))
   {
    //RETAILMSG(1,(TEXT("-------------------\r\n")));
    //Display_Cam_Image(64, 64, QCIF_XSIZE, QCIF_YSIZE, PORT_A);
    Display_Cam_Image(0,0, 240, 240, PORT_A);
   }

   //else if (DRIVER_PREVIEW_ENABLE == 2) 
   if (cam_intr == BIT_SUB_CAM_C)
   {
    RETAILMSG(1, (TEXT(" Camera interrupt.....BIT_SUB_CAM_C@@@@")));
    Buffer_codec_info_update();
   }

   if (cam_intr == BIT_SUB_CAM_P)//RGB格式使用的是P通道
   {
    RETAILMSG(1, (TEXT(" Camera interrupt.....BIT_SUB_CAM_P@@@@")));
    Buffer_preview_info_update();
   }

   // add by wogo at 2009.04.25
   s2440INT->rSUBSRCPND = INTSUB_CAM_P;
   s2440INT->rSUBSRCPND = INTSUB_CAM_C;
   s2440INT->rSRCPND = BIT_CAM;

   if (s2440INT->rINTPND & BIT_CAM)
   {
    s2440INT->rINTPND = BIT_CAM;
   }
   s2440INT->rINTSUBMSK &= ~(INTSUB_CAM_P | INTSUB_CAM_C);
   s2440INT->rINTMSK &= ~BIT_CAM;
   RETAILMSG(1,(TEXT("::: SYSINTR_CAM    OEMInterruptDone\r\n")));
    
   // Enable camera interrupt
   s2440INT->rINTSUBMSK &= ~(BIT_SUB_CAM_P | BIT_SUB_CAM_C);
   s2440INT->rINTMSK &= ~BIT_CAM;

    //RETAILMSG(1, (TEXT(" Camera interrupt.....Done@@@@")));
/*
   if (DRIVER_PREVIEW_ENABLE == 1)
    Camif_Capture(CAPTURE_ON, CAPTURE_OFF);
   else if (DRIVER_PREVIEW_ENABLE == 2) 
    Camif_Capture(CAPTURE_OFF, CAPTURE_ON);
*/
   
   // EINT20 to measure time   
//   s2440IOP->rGPGDAT &= ~(1<<12);
//   old_time = GetTickCount();
//   RETAILMSG(1,(TEXT("-time:%d\r\n"),(old_time-time)));
   
  }
 }
}

----------------------------------------------------------------------------------------

拍照偶尔不能生成图片的

//摄像头中断线程
/*
等待中断事件。

确认有一个来自 OS 的脉动性事件

执行任何必要的板级中断处理以完成中断。在该示例中,我们将确认该中断。

在尽可能短的时间内处理该中断

创建 CELOGDATA 以供在 Kernel Tracker 中查看。

检查并确认是否设置了 g_fPRRunning 标志,然后设置 g_hevPRStart 事件。

调用 InterruptDone()。

在调用 InterruptDone 之前,OS 不会提供此 IRQ 上的其他中断。

再次等待中断事件
*/
DWORD CameraCaptureThread(void)
{
 unsigned char tmp=0;
 static unsigned int time,old_time;
 static unsigned int cam_intr;
 
 while(1)
 {
  WaitForSingleObject(CameraEvent, dwDisplayTimeout);//等待中断
  
  
 // RETAILMSG(1,(_T("CameraCaptureThread(%d)++\r\n"), frame_count));

#if 0
  if (frame_count <= 2) {
   frame_count++;
   // Enable camera interrupt 使能摄像头中断
   s2440INT->rINTSUBMSK &= ~(BIT_SUB_CAM_P|BIT_SUB_CAM_C);
   s2440INT->rINTMSK &= ~BIT_CAM;
   
   continue;
  }
#endif
  

  Lock();// {EnterCriticalSection(&m_Lock);}

  __try
  {

   if (s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_C )) //决定IRQ_SUB_CAM_C位中断请求是否被处理,若某位被设置为1,则该位相对应的中断产生后将被忽略(CPU不处理该中断请求)
   {
    frame_count++;
    cam_intr |= ( 1 << IRQ_SUB_CAM_C );  //(1<<11)
      
    s2440INT->SUBSRCPND  =  (1<<IRQ_SUB_CAM_C);//IRQ_SUB_CAM_P中断请求  该中断请求将被处理
    s2440INT->INTSUBMSK &= ~(1<<IRQ_SUB_CAM_C);//设置为0则对其进行中断处理
    //RETAILMSG(1,(_T("CAM_C, ts %d\r\n"), GetTickCount()));//GetTickCount()函数,该函数的返回值是DWORD型,表示以毫秒为单位的计算机启动后经历的时间间隔
   }

   if (s2440INT->INTSUBMSK & ( 1 << IRQ_SUB_CAM_P ))//判断是IRQ_SUB_CAM_P中断
   {
    cam_intr |= ( 1 << IRQ_SUB_CAM_P );
    
    s2440INT->SUBSRCPND  =  (1<<IRQ_SUB_CAM_P);//IRQ_SUB_CAM_P中断请求  该中断请求将被处理
    s2440INT->INTSUBMSK &= ~(1<<IRQ_SUB_CAM_P);
     //RETAILMSG(1,(_T("CAM_P, ts %d\r\n"), GetTickCount()));
   }
   
   InterruptDone(g_CamSysIntr);  //标识中断处理完成  
  
   //time = GetTickCount();
   //RETAILMSG(1,(TEXT("+time:%d\r\n"),(time - old_time)));

   // Handle any interrupts on the input source
   if (cam_intr & ( 1 << IRQ_SUB_CAM_P ))
   {
    // display the image 
    if (DisplayEnable== 1)
    Display_Cam_Image(sDISINFO.pos_x,sDISINFO.pos_y,sDISINFO.dis_x, sDISINFO.dis_y, PORT_A);//刷新显示

    Buffer_preview_info_update();//刷新预览 RGB
    cam_intr &= ~( 1 << IRQ_SUB_CAM_P );
   }
    
   if (cam_intr & ( 1 << IRQ_SUB_CAM_C ))
   {
    Buffer_codec_info_update();  //YCbCr
    cam_intr &= ~( 1 << IRQ_SUB_CAM_C );
   }


  }
  __except(EXCEPTION_EXECUTE_HANDLER)
  {
   RETAILMSG(PM_MSG, (TEXT("Camera.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
  }
    
  Unlock();
   
  // Enable camera interrupt
  //s2440INT->rINTSUBMSK &= ~(BIT_SUB_CAM_P|BIT_SUB_CAM_C);
  //s2440INT->rINTMSK &= ~BIT_CAM;

 }
 return 0;
}

CRITICAL_SECTION m_Lock;

void Lock()   {EnterCriticalSection(&m_Lock);}
void Unlock() {LeaveCriticalSection(&m_Lock);}

 

  细心的人一定会发现,这两个函数有两个比较大的差别,那就是Lock()和 Unlock()函数这两个函数是临界段相关函数,直觉告诉我,极有可能是这个问题,因为这是最玄乎的OS东西,删掉试试看。

  应用程序拍照函数

//拍照
void COV9650Dlg::Onpaizhao()
{
 // TODO: Add your control notification handler code here
 //PINGPONG_PR image;
 PINGPONG YUVData;
 //
 
 int i;
 
 //WORD width=GetSystemMetrics(SM_CXSCREEN);
 //WORD height=GetSystemMetrics(SM_CYSCREEN);
 int width;
 int height;
 int line, col;
 BOOL ret;
 if(count==2)
 {
   
  width=1024;
  height=768;
 }
 if(count==3)
 {
  width=640;
  height=480; 
  
 }
 if(count==4)
 {
  width=800;
  height=600; 
  
 }
 
 
 
 //BYTE* DDBdata=new BYTE[width*height*2];
 //BYTE* DDBdata=NULL;
 //BYTE*  DDBdata=new BYTE[width*height*2];
 BYTE* DIBdata=NULL;
 U16*  DDBdata=new U16[width*height];

 //U16*  TempDDBdata=new U16[width*height*2];
 //
 //bufferYUV--width*height for Y data;width*height/4 for U and V data
 //
 BYTE* bufferYUV=new BYTE[width*height+width*height/4+width*height/4];
 
 //BYTE* YData=new BYTE[width*height];
 //BYTE* CbData=new BYTE[width*height];
 //BYTE* CrData=new BYTE[width*height];

 //
 //BYTE* RData=new BYTE[width*height*2];
 //BYTE* GData=new BYTE[width*height*2];
 //BYTE* BData=new BYTE[width*height*2];

 //------------2010.10.26--------------
 //
 //U16* RData=new U16[width*height];
 //U16* GData=new U16[width*height];
 //U16* BData=new U16[width*height];
 //
 //unsigned int RData[width*height*2];
 //unsigned int GData[width*height*2];
 //unsigned int BData[width*height*2];

 
 // always uses P port to get pictrue //获得最新1帧的RGB图像
 // ret=DeviceIoControl(m_hled,CAM_IOCTL_SAMSUNG_CAM_PR,NULL,NULL,(PBYTE)&image,NULL,NULL,NULL);
 // now try to use C port to get YUV data then change into RGB data
 ret=DeviceIoControl(m_hled,CAM_IOCTL_SAMSUNG_CAM,NULL,NULL,(PBYTE)&YUVData,NULL,NULL,NULL);
 if(!ret)
  AfxMessageBox(_T("读取图片失败!"));
 else
 {
  SetKMode(TRUE);

  RETAILMSG(1,(_T("test before memcpy(bufferYUV\r\n")));
  //memcpy(DDBdata,(void *)image.rgb_address,width*height*2);
  //2010.09.29
  memcpy(bufferYUV,(void *)YUVData.y_address,width*height);
  // just use Y
  RETAILMSG(1,(_T("test before memcpy((bufferYUV+width*height)\r\n")));
  memcpy((bufferYUV+width*height),(void *)YUVData.cb_address,width*height/4);
  RETAILMSG(1,(_T("test before memcpy((bufferYUV+width*height+width*height/4)\r\n")));
  memcpy((bufferYUV+width*height+width*height/4),(void *)YUVData.cr_address,width*height/4);

  RETAILMSG(1,(_T("test after memcpy\r\n")));
  SetKMode(FALSE);
  
  //
  //-----------Oh,My god!I make wrong thing--------2010.10.12-----------
  //
  // void yuv420_to_rgb565(int width, int height, unsigned char *src, unsigned short *dst)
  RETAILMSG(1,(_T("test before yuv420_to_rgb565\r\n")));
  yuv420_to_rgb565(width,height,bufferYUV, DDBdata);
  RETAILMSG(1,(_T("test after yuv420_to_rgb565\r\n")));

  //DDBdata=(BYTE*)TempDDBdata;
  // 2010.10.25
  //memcpy(DDBdata,(void *)TempDDBdata,width*height*2);

  CBitmap bitmap;//图片
  HBITMAP dstBmp;
  bitmap.CreateBitmap(width,height,1,16,DDBdata);//创建一张位图
  HDC hdcSrc = CreateCompatibleDC(NULL);
  HDC hdcDst = CreateCompatibleDC(NULL);
   BITMAPINFOHEADER   bih   =   {0};//位图信息头  
         bih.biBitCount   =   16;//每个像素字节大小  
         bih.biCompression   =   BI_RGB;  
         bih.biHeight   =   height;//高度  
         bih.biPlanes   =   1;  
         bih.biSize   =   sizeof(BITMAPINFOHEADER);  
         bih.biSizeImage   =  0;// width*height*2;//图像数据大小  
         bih.biWidth   =   width;//宽度  
         BITMAPFILEHEADER   bfh   =   {0};//位图文件头  
         bfh.bfOffBits   =   sizeof(BITMAPFILEHEADER)   +   sizeof(BITMAPINFOHEADER);//到位图数据的偏移量  
         bfh.bfSize   =   bfh.bfOffBits + width*height*2;//文件总的大小  
         bfh.bfType   =   (WORD)0x4d42;   //,0x4d42就是"BM",以这个表示该文件为位图文件
   BITMAPINFO bi={0};
   bi.bmiHeader=bih;
  dstBmp=CreateDIBSection(hdcDst, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void **)&DIBdata, NULL, 0);
  SelectObject(hdcDst, dstBmp);
  SelectObject(hdcSrc, bitmap);
  BitBlt(hdcDst, 0, 0, width, height, hdcSrc, 0, 0, SRCCOPY);//将位图复制到实际的设备环境中
  CFile file(_T("Image.bmp"),CFile::modeCreate|CFile::modeReadWrite);
  file.Write(&bfh,sizeof(bfh));
  file.Write(&bih,sizeof(bih));
  file.Write(DIBdata,width*height*2);
  file.Close();
 
 }
 delete []DDBdata;
 //2010.10.25
 //delete []TempDDBdata;
 // 2010.11.04 YUV
 delete []bufferYUV;
 
}

posted on 2010-12-21 11:10  gooogleman  阅读(717)  评论(14编辑  收藏  举报