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

📄 linux_fb_surf.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2003 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 

#include "minisite.h"
#include "hxvsurf.h"
#include "coloracc.h"

#include "minisurf.h"
#include "platform/unix/linux_fb_surf.h"

#include "minifmt.h"

//#include <unistd.h>
#include <fcntl.h>
#include <linux/fb.h>
//#include <linux/kd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
//#include <sys/time.h>
//#include <sys/types.h>
//#include <sys/select.h>

static CFmtObj ImageHelper;

CLinuxFrameBufferSurface::CLinuxFrameBufferSurface(IUnknown* pContext, 
					 CMiniBaseSite* pSite)
    :  CMiniBaseSurface(pContext, pSite)
    , m_nScreenNumber(0)
    , m_unDepth(0)
    , m_nBitsPerPixel(0)
    , m_nCompositionSize(0)
    , m_pCompositionSurface(NULL)
    , m_frameBufferFD(-1)
    , m_pFrameBuffer(0)
{}

CLinuxFrameBufferSurface::~CLinuxFrameBufferSurface()
{
    if (m_frameBufferFD != -1)
    {
	m_pFrameBuffer = 0;

	close(m_frameBufferFD);
	m_frameBufferFD = -1;
	
    }

    HX_FREE(m_pCompositionSurface);
    m_nCompositionSize  = 0;
    m_nCompositionPitch = 0;
    memset(&m_surfaceSize, 0, sizeof( m_surfaceSize ) );
}


HX_RESULT CLinuxFrameBufferSurface::_CreateDestBuffer(int cidIn,
                                              int nWidth,
                                              int nHeight,
                                              int& nCount)
{
    HX_RESULT res = HXR_OK;

    HX_ASSERT( m_pSite );
    //HX_ASSERT( m_unDepth );

    //For now, we just support 1 format
    HX_ASSERT( cidIn == CID_I420 );
    
    //Get the size of this site.
    m_pSite->GetSize(m_surfaceSize);

    //Malloc the room to hold the actual bits.
    HXBitmapInfo bmiTemp;
    ImageHelper.MakeBitmap( &bmiTemp,
                      sizeof(bmiTemp),
                      GetDstCID(),
                      m_surfaceSize.cx,
                      m_surfaceSize.cy,
                      NULL,
                      0);
    
    m_nCompositionPitch = ImageHelper.GetBitmapPitch(&bmiTemp);
    int imageSize = bmiTemp.bmiHeader.biSizeImage;
    res = _ResizeVideoBuffer(imageSize);

    HX_ASSERT( ImageHelper.GetBitmapColor(&bmiTemp) == GetDstCID() );

    if (!m_pFrameBuffer)
    {
	res = _OpenFrameBuffer();
    }
    
    return res;
}

         
HX_RESULT CLinuxFrameBufferSurface::_LockDestBuffer(UCHAR** ppDestPtr,
					       LONG32* pnDestPitch,
					       int& cid,
					       REF(HXxSize) srcSize,
					       int nIndex)
{
    *ppDestPtr = m_pCompositionSurface;
    *pnDestPitch = m_nCompositionPitch;
    cid = GetDstCID();
    
    return HXR_OK;
}

         
HX_RESULT CLinuxFrameBufferSurface::_TransferToDestBuffer(UCHAR* pSrcBuffer,
                                                  HXBitmapInfoHeader* pBitmapInfo,
                                                  HXxRect* prSrcRect,
                                                  HXxRect* prDstRect,
                                                  UCHAR* pDstBuffer,
                                                  LONG32 nDstPitch)
{
    HX_RESULT res = HXR_OK;
    int nCidIn = ImageHelper.GetBitmapColor( (HXBitmapInfo*)pBitmapInfo );
    //This minisite, as written, is just doing a blind I420->RGB32
    //color convert. Feel free to add whatever you want...
    HX_ASSERT( nCidIn == CID_I420 );
    if( nCidIn == CID_I420 )
    {
        //This calls the m_fpColorConverter init'ed in the base class.
        res =  CMiniBaseSurface::_TransferToDestBuffer(pSrcBuffer,
                                                       pBitmapInfo,
                                                       prSrcRect,
                                                       prDstRect,
                                                       pDstBuffer,
                                                       nDstPitch);
    }

    return res;
}

         
HX_RESULT CLinuxFrameBufferSurface::_UnlockDestBuffer(UCHAR* pSurfPtr, int nIndex=0)
{
    return HXR_OK;
}

         
HX_RESULT CLinuxFrameBufferSurface::_RenderDestBuffer(HXxRect* prSrcRect,
						 HXxRect* prDestRect,
						 int nIndex)
{
    HX_RESULT res = HXR_FAILED;

    int imgWidth  = prDestRect->right - prDestRect->left;
    int imgHeight = prDestRect->bottom - prDestRect->top;
    

    if (m_pFrameBuffer)
    {
#ifdef HELIX_FEATURE_CC_RGB32out
	UINT32* pSrc = (UINT32*)m_pCompositionSurface;
#elif defined(HELIX_FEATURE_CC_RGB565out)
	UINT16* pSrc = (UINT16*)m_pCompositionSurface;
#endif
	UINT16* pDest = m_pFrameBuffer;

	int srcDelta = 0;
	int dstDelta = 0;

	// Compute how much of the image we want to copy
	int lines = (imgHeight < m_fbHeight) ? imgHeight : m_fbHeight;
	int copyWidth = imgWidth;

	if (imgWidth < m_fbWidth)
	{
	    dstDelta = m_fbWidth - imgWidth;
	}
	else if (imgWidth > m_fbWidth)
	{
	    srcDelta = imgWidth - m_fbWidth;
	    copyWidth = m_fbWidth;
	}
	
	// Center image
	int left = (m_fbWidth / 2) - (copyWidth / 2);
	int top = (m_fbHeight / 2) - (lines / 2);
	pDest += top * m_fbWidth + left;
	
	int i = 0;
	for (int y = 0; y < lines; y++)
	{
	    for (int x = 0; x < copyWidth; x++)
	    {
#ifdef HELIX_FEATURE_CC_RGB32out
		// We need to convert RGB32 -> RGB565
		UINT32 src   = *pSrc++;
		UINT32 dst = (((src & 0x00f80000) >> 8) | 
			      ((src & 0x0000fc00) >> 5) | 
			      ((src & 0x000000f8) >> 3));
		*pDest++ = (UINT16)dst;
#elif defined(HELIX_FEATURE_CC_RGB565out)
		*pDest++ = *pSrc++;
#endif
	    }
	    pSrc += srcDelta;
	    pDest += dstDelta;
	}

	res = HXR_OK;
    }
    
    return res;
}

         
HX_RESULT CLinuxFrameBufferSurface::_DestroyDestBuffer(int cid, int nCount)
{
  HX_FREE(m_pCompositionSurface);
    m_nCompositionSize  = 0;
    m_nCompositionPitch = 0;
    memset(&m_surfaceSize, 0, sizeof( m_surfaceSize ) );
    
    return HXR_OK;
}

int CLinuxFrameBufferSurface::GetDstCID(int nIndex)
{
    //Right now the mini site just always outputs in RGB32. 
#ifdef HELIX_FEATURE_CC_RGB32out
    return CID_RGB32;
#elif defined(HELIX_FEATURE_CC_RGB565out)
    return CID_RGB565;
#endif
}

HX_RESULT CLinuxFrameBufferSurface::_ResizeVideoBuffer( INT32 nSize)
{
    HX_RESULT retVal=HXR_OK;

    //XXXgfw. Trade off here. We can use lots of mem if we just return and
    //the user has scaled the image up very much and then goes back down.
    //If we don't just return we can do tons and tons of mallocs. Maybe we
    //should add a timed callback to reclaim some of this mem after a few
    //seconds.
    if(nSize <= m_nCompositionSize)
        return retVal;

    if(m_pCompositionSurface == NULL)
    {
        m_pCompositionSurface = (UCHAR*) malloc(nSize);
    }
    else
    {
        m_pCompositionSurface = (UCHAR*) realloc(m_pCompositionSurface, nSize);
    }
    if( m_pCompositionSurface )
    {
        m_nCompositionSize = nSize;
    }
    else
    {
        HX_ASSERT("We can't alloc the composition surface." == NULL );
        m_nCompositionSize = 0;
    }

    return retVal;
}

HX_RESULT CLinuxFrameBufferSurface::_OpenFrameBuffer()
{
    HX_RESULT res = HXR_FAILED;

    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    char *fbp = 0;
    int x = 0, y = 0;
    long int location = 0;

  /* Open the file for reading and writing */
    m_frameBufferFD = open("/dev/fb0", O_RDWR);

    if (m_frameBufferFD == -1) 
    {
	printf("Error: cannot open framebuffer device.\n");
    }
    else if (ioctl(m_frameBufferFD, FBIOGET_FSCREENINFO, &finfo)) 
    {
	printf("Error reading fixed information.\n");
    }
    else if (ioctl(m_frameBufferFD, FBIOGET_VSCREENINFO, &vinfo)) 
    {
	printf("Error reading variable information.\n");
    }
    else
    {
	printf("xres:%i , yres:%i , BBP:%i\n ", 
	       vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

	m_fbWidth = vinfo.xres;
	m_fbHeight = vinfo.yres;
	int screen_size  = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
		
		
	/* Map the device to memory */
	m_pFrameBuffer = (UINT16*)mmap(0, screen_size, 
				       PROT_READ | PROT_WRITE, MAP_SHARED,
				       m_frameBufferFD, 0);       
	if ((int)m_pFrameBuffer == -1) 
	{ 
	    printf("Error: failed to map framebuffer device to memory.\n"); 
	}
	else
	{
	    res = HXR_OK;
	}
    }

    return res;
}

⌨️ 快捷键说明

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