⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipubuffermanager.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004, Freescale Semiconductor, Inc. All Rights Reserved
//  THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
//  BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
//  Freescale Semiconductor, Inc.
//
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
//  File:  prp.cpp
//
//  Implementation of preprocessor driver methods
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <Devload.h>
#include <ceddk.h>
#include <NKIntr.h>
#include "mxarm11.h"

#include "cameradbg.h"
#include "IpuBufferManager.h"


//------------------------------------------------------------------------------
// External Functions


//------------------------------------------------------------------------------
// External Variables


//------------------------------------------------------------------------------
// Defines
#define BUFMAN_FUNCTION_ENTRY() \
    DEBUGMSG(ZONE_FUNCTION, (TEXT("++%s\r\n"), __WFUNCTION__))
#define BUFMAN_FUNCTION_EXIT() \
    DEBUGMSG(ZONE_FUNCTION, (TEXT("--%s\r\n"), __WFUNCTION__))

#define THREAD_PRIORITY                            250

#define IPU_MAX_NUM_BUFFERS                        100


//------------------------------------------------------------------------------
// Types


//------------------------------------------------------------------------------
// Global Variables


//------------------------------------------------------------------------------
// Local Variables


//------------------------------------------------------------------------------
// Local Functions


//-----------------------------------------------------------------------------
//
// Function: BufferManager
//
// Buffer manager class constructor.
//
// Parameters:
//      None.
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
IpuBufferManager::IpuBufferManager(void)
{
    MSGQUEUEOPTIONS queueOptions;

    BUFMAN_FUNCTION_ENTRY();

    InitializeCriticalSection(&m_csLockBufferQueues);

    // Create queues for read messages and write messages
    queueOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
    queueOptions.dwFlags = MSGQUEUE_ALLOW_BROKEN;
    queueOptions.dwMaxMessages = IPU_MAX_NUM_BUFFERS;
    queueOptions.cbMaxMessage = sizeof(ipuBufferData);
    queueOptions.bReadAccess = TRUE; // we need read-access to msgqueue

    // We have 3 queues for each channel:  One for idle buffers,
    // one for busy buffers, and one for filled buffers.
    // For each of these buffers, a read and write handle is needed.
    // 6 handles total

    // Create read handles to idle and busy queues
    m_hReadIdleQueue = CreateMsgQueue(NULL, &queueOptions);
    if (!m_hReadIdleQueue)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Error creating Read idle queue handle.  Initialization failed! \r\n"), __WFUNCTION__));
    }

    m_hReadBusyQueue = CreateMsgQueue(NULL, &queueOptions);
    if (!m_hReadBusyQueue)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Error creating Read busy queue handle.  Initialization failed! \r\n"), __WFUNCTION__));
    }

    m_hReadFilledQueue = CreateMsgQueue(NULL, &queueOptions);
    if (!m_hReadFilledQueue)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Error creating Read filled queue handle.  Initialization failed! \r\n"), __WFUNCTION__));
    }

    queueOptions.bReadAccess = FALSE; // we need write-access to msgqueue

    // Create read handles to idle and busy queues
    m_hWriteIdleQueue = OpenMsgQueue(GetCurrentProcess(), m_hReadIdleQueue, &queueOptions);
    if (!m_hWriteIdleQueue)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Error opening idle queue for writing.  Initialization failed! \r\n"), __WFUNCTION__));
    }

    m_hWriteBusyQueue = OpenMsgQueue(GetCurrentProcess(), m_hReadBusyQueue, &queueOptions);
    if (!m_hWriteBusyQueue)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Error opening busy queue for writing.  Initialization failed! \r\n"), __WFUNCTION__));
    }

    m_hWriteFilledQueue = OpenMsgQueue(GetCurrentProcess(), m_hReadFilledQueue, &queueOptions);
    if (!m_hWriteFilledQueue)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Error opening filled queue for writing.  Initialization failed! \r\n"), __WFUNCTION__));
    }

    BUFMAN_FUNCTION_EXIT();
}

//-----------------------------------------------------------------------------
//
// Function: ~IpuBufferManager
//
// The destructor for Class.  Deletes buffes and closes queue handles.
//
// Parameters:
//      None.
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
IpuBufferManager::~IpuBufferManager(void)
{
    DeleteBuffers();

    CloseHandle(m_hReadIdleQueue);
    CloseHandle(m_hWriteIdleQueue);
    CloseHandle(m_hReadBusyQueue);
    CloseHandle(m_hWriteBusyQueue);
    CloseHandle(m_hReadFilledQueue);
    CloseHandle(m_hWriteFilledQueue);
}


//-----------------------------------------------------------------------------
//
// Function:  AllocateBuffers
//
// This function allocates buffers and adds each to the idle buffer queue.
// This function must be called in order to allocate physically contiguous 
// buffers for use in the IPU's IDMAC.
//
// Parameters:
//      numBuffers
//          [in] Number of buffers to allocate and add
//          to the queues.
//
//      bufSize
//          [in] Size of buffer to create and enqueue.
//
// Returns:
//      Returns virtual pointer to buffer created.  
//      Returns NULL if unsuccessful.
//
//-----------------------------------------------------------------------------
BOOL IpuBufferManager::AllocateBuffers(ULONG numBuffers, ULONG bufSize)
{
    LPVOID tempVirtualAddress;
    UINT32 tempPhysicalAddress;
    pIpuBufferData pBufData;
    UINT16 i;

    BUFMAN_FUNCTION_ENTRY();

    EnterCriticalSection(&m_csLockBufferQueues);

    for (i = 0; i < numBuffers; i++)
    {
        // Allocate buffer based on the size passed in.
        tempVirtualAddress = AllocPhysMem(bufSize, PAGE_EXECUTE_READWRITE, 0, 0, (unsigned long *) &tempPhysicalAddress);
   
        if(tempVirtualAddress == NULL)    
        {
            ERRORMSG(1, (TEXT("%s : Buffer allocation failed!\r\n"), __WFUNCTION__));
            LeaveCriticalSection(&m_csLockBufferQueues);
            return FALSE;
        }

        pBufData = (pIpuBufferData) LocalAlloc(LPTR, sizeof(UINT32*) * 2);

        pBufData->pPhysAddr = (UINT32 *) tempPhysicalAddress;
        pBufData->pVirtAddr = (UINT32 *) tempVirtualAddress;

        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: Buffer %d - Size: %x, Virtual address: %x, Physical address: %x.\r\n"),
            __WFUNCTION__, i, bufSize, pBufData->pVirtAddr, pBufData->pPhysAddr));

        // Enqueue newly created buffer
        if (!WriteMsgQueue(m_hWriteIdleQueue, pBufData, sizeof(ipuBufferData), 0, 0))
        {
            DEBUGMSG(ZONE_ERROR, 
                (TEXT("%s : Buffer allocation failed!\r\n"), __WFUNCTION__));
            LeaveCriticalSection(&m_csLockBufferQueues);
            return FALSE;
        }
    }

    m_iNumBuffers = numBuffers;

    LeaveCriticalSection(&m_csLockBufferQueues);

    BUFMAN_FUNCTION_EXIT();

    // Return virtual buffer address
    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function:  SetActiveBuffer
//
// This function adds a buffer from the idle buffer queue 
// to the message queue of busy buffers for preprocessing.  If
// the idle buffer queue is empty, we take a buffer from the filled
// queue and report a dropped frame.
//
// Parameters:
//      pPhysAddr
//          [out] Pointer to physical address to hold return value.
//      
//      timeout
//          [in] Time to wait for a busy buffer.
//
// Returns:
//      Returns 1 if a frame was dropped.
//      Returns 0 if no frame was dropped.
//      Returns -1 if an error occurred.
//
//-----------------------------------------------------------------------------
DWORD IpuBufferManager::SetActiveBuffer(UINT32** ppPhysAddr, UINT32 timeout)
{
    BUFMAN_FUNCTION_ENTRY();

    DWORD dwFlags, bytesRead, retVal;
    ipuBufferData bufData;
    MSGQUEUEINFO filledQInfo;

    if (m_iNumBuffers < 4)
    {
        // If we are using less than 4 buffers, a buffer is only
        // considered free, and thus capable of being moved
        // to the busy queue, if it meets either of two criteria:
        //      1) It is in the Idle queue
        //      2) There is more than one buffer in the
        //         filled queue, indicating that one buffer
        //         can be removed without causing an error
        //         when the application attempts to read
        //         from the filled queue.
        //
        // If we have more than 4 buffer, one of these two criteria
        // will always be met.
        while(1)
        {
            // Test criteria 1)
            if (WaitForSingleObject(m_hReadIdleQueue, 0) == WAIT_OBJECT_0)
            {
                break;
            }

            // Test criteria 2)
            EnterCriticalSection(&m_csLockBufferQueues);

            GetMsgQueueInfo(m_hReadFilledQueue, &filledQInfo);
            if (filledQInfo.dwCurrentMessages > 1)
            {
                LeaveCriticalSection(&m_csLockBufferQueues);
                break;
            }

            LeaveCriticalSection(&m_csLockBufferQueues);

            // We failed both criteria, so we give up the current
            // timeslice and check again when we become active
            Sleep(0);
        }
    }

    EnterCriticalSection(&m_csLockBufferQueues);

    // A buffer has been requested.  Attempt to read from the idle
    // queue to get an available buffer.  If one is not available,
    // we must take a buffer from the filled queue.
    if(ReadMsgQueue(m_hReadIdleQueue, &bufData, sizeof(ipuBufferData), &bytesRead, 0, &dwFlags))
    {
        DEBUGMSG (ZONE_DEVICE, (TEXT("%s: Buffer read from Idle queue\r\n"), __WFUNCTION__));
        *ppPhysAddr = bufData.pPhysAddr;

        // Now send buffer to Busy queue
        if (!WriteMsgQueue(m_hWriteBusyQueue, &bufData, sizeof(ipuBufferData), 0, 0))
        {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Filled buffer queue is full!\r\n"), __WFUNCTION__));
            LeaveCriticalSection(&m_csLockBufferQueues);
            return NULL;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -