现在的位置: 首页 > 综合 > 正文

directshow+wince6.0+pxa310+双camera

2013年02月04日 ⁄ 综合 ⁄ 共 6989字 ⁄ 字号 评论关闭

于3G手机应用视频电话的时候要双camera,那么就存在切换的问题,我就在开发板上进行了调试。marvell的zylonite开发板Windows Mobile6.0 BSP关于camera的驱动变化还是很明显的,采用了wince6.0的camera驱动。
找了半天才在微软的MSDN上看到了各个pdd函数的说明。整个设计的原理就是APP先停止preview,发出切换sensor的指令,驱动响应,把sensor相关的都换成另外一个sensor,然后再重新preview。

首先camera的应用程序得自己写,不然双camera的切换无法在应用上修改,于是找了个camera的应用代码参考了下,居然都编译不过,晕,我不是做app的,但是又没有人帮我,只好硬着头皮看资料看代码。幸好自己也做过一点PC上的应用程序,终于看懂,原来采用WTL+directshow写的camera应用,mainframe+manager+ view+setting结构很清晰。应用程序写上如下代码:

BOOL CCameraManager::CameraSwitchSensor(CAMERA_SWITCH sensor)
 
{
     LRESULT hr;

     CComPtr
<IAMCameraControl> pCameraControl;

     
long lCurrentVal,lCurrentFlags;

     
long CameraControl_Switch=CameraControl_Flash+0xff;

     
if(sensor>=SENSOR_MAX)
         
return FALSE;

     CHK(m_pVideoCapFilter
->QueryInterface(&pCameraControl));

     CHK(pCameraControl
->Get(CameraControl_Switch, &lCurrentVal, &lCurrentFlags));
     
if(lCurrentVal == sensor)
     
{
         
//return TRUE;
     }

     CHK(pCameraControl
->Set(CameraControl_Switch, sensor, CameraControl_Flags_Manual));

err_exit:
    
if( FAILED( hr ))
    
{
        CCameraParam::GetCameraParam()
->GetErrorlog()->WriteLog(L"Error: CCameraManager::CameraSwitchSensor");
        
return FALSE;
    }

    
return TRUE;
 }
 

红色字体为关键,由于通过dshow才控制camera,所以得找到dshow动作对应于驱动的接口,参考wm的文档并调试,发现这个可以控制camera,会调用CAM_IOControl,Ioctl=IOCTL_CS_PROPERTY,

EXTERN_C
BOOL
CAM_IOControl(
    DWORD   dwContext,
    DWORD   Ioctl,
    UCHAR 
* pInBufUnmapped,
    DWORD   InBufLen, 
    UCHAR 
* pOutBufUnmapped,
    DWORD   OutBufLen,
    DWORD 
* pdwBytesTransferred
   )
{
    DEBUGMSG( ZONE_FUNCTION, ( _T(
"CAM_IOControl(%08x): IOCTL:0x%x, InBuf:0x%x, InBufLen:%d, OutBuf:0x%x, OutBufLen:0x%x) "), dwContext, Ioctl, pInBufUnmapped, InBufLen, pOutBufUnmapped, OutBufLen ) );
    
//NKDbgPrintfW(L"CAM_IOControl 0x%x", Ioctl);

    UCHAR 
* pInBuf = NULL;
    UCHAR 
* pOutBuf = NULL;
    DWORD dwErr 
= ERROR_INVALID_PARAMETER;
    BOOL  bRc   
= FALSE;
    
    
if ( ( NULL == pInBufUnmapped )
         
|| ( InBufLen < sizeof ( CSPROPERTY ) )
         
|| ( NULL == pdwBytesTransferred ) )
    
{
        SetLastError( dwErr );

        
return bRc;
    }


    
//All buffer accesses need to be protected by try/except
    pInBuf = pInBufUnmapped;

    pOutBuf 
= pOutBufUnmapped;

    CAMERAOPENHANDLE 
* pCamOpenHandle = reinterpret_cast<CAMERAOPENHANDLE *>( dwContext );
    CAMERADEVICE     
* pCamDevice     = pCamOpenHandle->pCamDevice;
    CSPROPERTY       
* pCsProp        = reinterpret_cast<CSPROPERTY *>(pInBuf);
    
    
if ( NULL == pCsProp )
    
{
        DEBUGMSG( ZONE_IOCTL
|ZONE_ERROR, (_T("CAM_IOControl(%08x): Invalid Parameter. "), dwContext ) );
        
return dwErr;
    }

    
    
switch ( Ioctl )
    
{
        
// Power Management Support.
        case IOCTL_POWER_CAPABILITIES:
        
case IOCTL_POWER_QUERY:
        
case IOCTL_POWER_SET:
        
case IOCTL_POWER_GET:
        
{
            NKDbgPrintfW(L
"camera IOCTL_POWER+");

            DEBUGMSG( ZONE_IOCTL, ( _T(
"CAM_IOControl(%08x): Power Management IOCTL "), dwContext ) );
            __try 
            
{
                dwErr 
= pCamDevice->AdapterHandlePowerRequests(Ioctl, pInBuf, InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );
            }

            __except ( EXCEPTION_EXECUTE_HANDLER )
            
{
                DEBUGMSG( ZONE_IOCTL, ( _T(
"CAM_IOControl(%08x):Exception in Power Management IOCTL"), dwContext ) );
            }

            
break;
        }


        
case IOCTL_CS_PROPERTY:
        
{
            DEBUGMSG( ZONE_IOCTL, ( _T(
"CAM_IOControl(%08x): IOCTL_CS_PROPERTY "), dwContext ) );

            __try 
            
{
                dwErr 
= pCamDevice->AdapterHandleCustomRequests( pInBuf,InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );

                
if ( ERROR_NOT_SUPPORTED == dwErr )
            
{
                
if ( TRUE == IsEqualGUID( pCsProp->Set, CSPROPSETID_Pin ) )
                    
{   
                        dwErr 
= pCamDevice->AdapterHandlePinRequests( pInBuf, InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );
                    }

                    
else if ( TRUE == IsEqualGUID( pCsProp->Set, CSPROPSETID_VERSION ) )
                    
{
                        dwErr 
= pCamDevice->AdapterHandleVersion( pOutBuf, OutBufLen, pdwBytesTransferred );
                    }

                    
else if ( TRUE == IsEqualGUID( pCsProp->Set, PROPSETID_VIDCAP_VIDEOPROCAMP ) )
                    
{   
                        dwErr 
= pCamDevice->AdapterHandleVidProcAmpRequests( pInBuf,InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );
                    }

                    
else if ( TRUE == IsEqualGUID( pCsProp->Set, PROPSETID_VIDCAP_CAMERACONTROL ) )
                    
{   
                        dwErr 
= pCamDevice->AdapterHandleCamControlRequests( pInBuf,InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );
                    }

                
else if ( TRUE == IsEqualGUID( pCsProp->Set, PROPSETID_VIDCAP_VIDEOCONTROL ) )
                
{   
                    dwErr 
= pCamDevice->AdapterHandleVideoControlRequests( pInBuf,InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );
                }

                
else if ( TRUE == IsEqualGUID( pCsProp->Set, PROPSETID_VIDCAP_DROPPEDFRAMES) )
                
{   
                    dwErr 
= pCamDevice->AdapterHandleDroppedFramesRequests( pInBuf,InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );
                }

                }

            }

            __except ( EXCEPTION_EXECUTE_HANDLER )
            
{
                DEBUGMSG( ZONE_IOCTL, ( _T(
"CAM_IOControl(%08x):Exception in IOCTL_CS_PROPERTY"), dwContext ) );
            }


            
break;
        }


        
default:
        
{
            DEBUGMSG( ZONE_IOCTL, (_T(
"CAM_IOControl(%08x): Unsupported IOCTL code %u "), dwContext, Ioctl ) );
            dwErr 
= ERROR_NOT_SUPPORTED;

            
break;
        }

    }

    
    
// pass back appropriate response codes
    SetLastError( dwErr );

    
return ( ( dwErr == ERROR_SUCCESS ) ? TRUE : FALSE );
}

哈哈,红色字体就是IAMCameraControl的set接口对应于driver会被调用的地方,由于这里还是driver的mdd层,所以尽量不改,于是放到pdd层来实现,很自然的想到AdapterHandleCustomRequests,该函数会调用pdd的DWORD CCameraPdd::HandleAdapterCustomProperties( PUCHAR pInBuf, DWORD  InBufLen, PUCHAR pOutBuf, DWORD  OutBufLen, PDWORD pdwBytesTransferred ),本来这函数是空函数,结果这里就可以放入双camera的切换代码了(不知道是微软写的还是marvell写的,想的真周到,以前还没有的,现在就有了,赞一个),实现如下:

DWORD CCameraPdd::HandleAdapterCustomProperties( PUCHAR pInBuf, DWORD  InBufLen, PUCHAR pOutBuf, DWORD  OutBufLen, PDWORD pdwBytesTransferred )
{  
    typedef 
enum
    
{
        SENSOR_FRONT,
        SENSOR_REAR,
        SENSOR_MAX,
    }
CAMERA_SWITCH;   
    
    CONST LONG CAMERACONTROL_SWITCH 
= CSPROPERTY_CAMERACONTROL_FLASH+0XFF;    
    PCSPROPERTY_CAMERACONTROL_S pCsPropCamControlInput  
= NULL;
    CSPROPERTY       
* pCsProp = reinterpret_cast<CSPROPERTY *>(pInBuf);
    
   
   
    
if( ( TRUE == IsEqualGUID( pCsProp->Set, PROPSETID_VIDCAP_CAMERACONTROL ) ) 
        && (pCsProp->Id ==
 CAMERACONTROL_SWITCH))        
    
{
        pCsPropCamControlInput 
= reinterpret_cast<PCSPROPERTY_CAMERACONTROL_S>(pInBuf);
        
switch(pCsProp->Flags)

抱歉!评论已关闭.