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

📄 vop.cpp

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*************************************************************************

This software module was originally developed by 

	Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation
	Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
	Bruce Lin (blin@microsoft.com), Microsoft Corporation
	Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation
	(date: March, 1996)

in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). 
This software module is an implementation of a part of one or more MPEG-4 Video tools 
as specified by the MPEG-4 Video. 
ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications 
thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. 
Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. 
The original developer of this software module and his/her company, 
the subsequent editors and their companies, 
and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. 
Copyright is not released for non MPEG-4 Video conforming products. 
Microsoft retains full right to use the code for his/her own purpose, 
assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products. 
This copyright notice must be included in all copies or derivative works. 

Copyright (c) 1996, 1997.


Module Name:

	vop.hpp

Abstract:

	class for Video Object Plane 

Revision History:

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

#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "basic.hpp"
#include "transf.hpp"
#include "warp.hpp"
#include "vop.hpp"
#include "typeapi.h"

#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

#define new DEBUG_NEW				   
#endif // __MFC_

Int numPln = 4;

CVideoObjectPlane::~CVideoObjectPlane ()
{
	delete [] m_ppxl;
}

Void CVideoObjectPlane::allocate (CRct r, CPixel pxl) 
{
	m_rc = r;
	delete [] m_ppxl, m_ppxl = NULL;

	// allocate pixels and initialize
	if (m_rc.empty()) return;
	m_ppxl = new CPixel [m_rc.area ()];
	for (UInt i = 0; i < m_rc.area (); i++)
		m_ppxl [i] = pxl;
//	memset (m_ppxl, pxl, m_rc.area () * sizeof (CPixel));
}

Void CVideoObjectPlane::copyConstruct (const CVideoObjectPlane& vop, CRct r) 
{
	if (!r.valid()) 
		r = vop.where ();
	if (!vop.valid () || (!vop.m_rc.empty () && vop.m_ppxl == NULL))
		assert (FALSE);
	allocate (r, transpPixel);
	if (!valid ()) return; 

	// Copy data
	if (r == vop.where ())
		memcpy (m_ppxl, vop.pixels (), m_rc.area () * sizeof (PixelF));
	else {
		r.clip (vop.where ()); // find the intersection
		CoordI x = r.left; // copy pixels
		Int cbLine = r.width * numPln;
		CPixel* ppxl = (CPixel*) pixels (x, r.top);
		const CPixel* ppxlVop = vop.pixels (x, r.top);
		Int widthCurr = where ().width;
		Int widthVop = vop.where ().width;
		for (CoordI y = r.top; y < r.bottom; y++) {
			memcpy (ppxl, ppxlVop, cbLine);
			ppxl += widthCurr;
			ppxlVop += widthVop;
		}
	}
}

Void CVideoObjectPlane::swap (CVideoObjectPlane& vop) 
{
	assert (this && &vop);
	CRct rcT = vop.m_rc; 
	vop.m_rc = m_rc; 
	m_rc = rcT; 
	CPixel* ppxlT = vop.m_ppxl; 
	vop.m_ppxl = m_ppxl; 
	m_ppxl = ppxlT; 
}

CVideoObjectPlane::CVideoObjectPlane (const CVideoObjectPlane& vop, CRct r) : m_ppxl (NULL)
{
	copyConstruct (vop, r);
}

CVideoObjectPlane::CVideoObjectPlane (CRct r, CPixel pxl) : m_ppxl (NULL)
{
	allocate (r, pxl);
}

CVideoObjectPlane::CVideoObjectPlane (const Char* vdlFileName) : m_ppxl (NULL)
{
	FILE* pf = fopen (vdlFileName, "rb");
	// write overhead
	Int c0 = getc (pf);
	Int c1 = getc (pf);
	assert (c0 == 'V' && (c1 == 'M' || c1 == 'B') );
	CRct rc;
	if (c1 == 'M'){
		fread (&rc.left, sizeof (CoordI), 1, pf);
		fread (&rc.top, sizeof (CoordI), 1, pf);
		fread (&rc.right, sizeof (CoordI), 1, pf);
		fread (&rc.bottom, sizeof (CoordI), 1, pf);
		rc.width = rc.right - rc.left;
	}
	else {
		U8 byte1, byte2;
		Int sign;
		byte1 = getc (pf);
		byte2 = getc (pf);
		sign = ((byte1 / 128) == 1) ? 1 : -1;
		rc.left = byte1 % 128;
		rc.left = (rc.left * 256) + byte2;
		rc.left *= sign; 

		byte1 = getc (pf);
		byte2 = getc (pf);
		sign = ((byte1 / 128) > 0) ? 1 : -1;
		rc.top = byte1 % 128;
		rc.top = (rc.top * 256) + byte2;
		rc.top *= sign; 

		byte1 = getc (pf);
		byte2 = getc (pf);
		sign = ((byte1 / 128) > 0) ? 1 : -1;
		rc.right = byte1 % 128;
		rc.right = (rc.right * 256) + byte2;
		rc.right *= sign; 

		byte1 = getc (pf);
		byte2 = getc (pf);
		sign = ((byte1 / 128) > 0) ? 1 : -1;
		rc.bottom = byte1 % 128;
		rc.bottom = (rc.bottom * 256) + byte2;
		rc.bottom *= sign;
		rc.width = rc.right - rc.left;
	}
	allocate (rc);

	// read the actual data
	fread (m_ppxl, sizeof (CPixel), where ().area (), pf);
	fclose (pf);
}

CVideoObjectPlane::CVideoObjectPlane (
	const Char* pchFileName, 
	UInt ifr, 
	const CRct& rct,
	ChromType chrType,
	Int nszHeader
) : m_ppxl (NULL)
{
	assert (!rct.empty ());
	assert (ifr >= 0);
	assert (nszHeader >= 0);
	Int iWidth = rct.width, iHeight = rct.height ();
	UInt area = rct.area ();
	Int iUVWidth = iWidth, iUVHeight = iHeight;
	Int uiXSubsample = 1, uiYSubsample = 1;
	if (chrType == FOUR_TWO_TWO)	{
		uiXSubsample = 2;
		iUVWidth = (iWidth + 1) / uiXSubsample;
	}
	else if (chrType == FOUR_TWO_ZERO)	{
		uiXSubsample = 2;
		uiYSubsample = 2;
		iUVWidth = (iWidth + 1) / uiXSubsample;
		iUVHeight = (iHeight + 1) / uiYSubsample;
	}	
	UInt iUVArea = iUVWidth * iUVHeight;

	// allocate mem for buffers
	U8* pchyBuffer = new U8 [area];
	U8* pchuBuffer = new U8 [iUVArea];
	U8* pchvBuffer = new U8 [iUVArea];
	U8* pchyBuffer0 = pchyBuffer;
	U8* pchuBuffer0 = pchuBuffer;
	U8* pchvBuffer0 = pchvBuffer;

	// read data from a file
	FILE* fpYuvSrc = fopen (pchFileName, "rb");
	assert (fpYuvSrc != NULL);
	UInt skipSize = (UInt) ((Float) (ifr * sizeof (U8) * (area + 2 * iUVArea)));
	fseek (fpYuvSrc, nszHeader + skipSize, SEEK_SET);
	Int size = (Int) fread (pchyBuffer, sizeof (U8), area, fpYuvSrc);
	assert (size != 0);
	size = (Int) fread (pchuBuffer, 1, iUVArea, fpYuvSrc);
	assert (size != 0);
	size = (Int) fread (pchvBuffer, 1, iUVArea, fpYuvSrc);
	assert (size != 0);
	fclose(fpYuvSrc);

	// assign buffers to a vframe
	allocate (rct, opaquePixel); 
	CPixel* p = (CPixel*) pixels ();
	for (CoordI y = 0; y < iHeight; y++) {					
		if ((y % uiYSubsample) == 1) { 
			pchuBuffer -= iUVWidth; 
			pchvBuffer -= iUVWidth;	
		}
		for (CoordI x = 0; x < iWidth; x++) {				
			p -> pxlU.yuv.y = *pchyBuffer++;
			p -> pxlU.yuv.u = *pchuBuffer;
			p -> pxlU.yuv.v = *pchvBuffer;
			if (chrType == FOUR_FOUR_FOUR || (x % uiXSubsample) != 0)	{
				pchuBuffer++;
				pchvBuffer++;
			}
			p++;
		}
	}
	delete [] pchyBuffer0;
	delete [] pchuBuffer0;
	delete [] pchvBuffer0;
}

Void CVideoObjectPlane::where (const CRct& r) 
{
	if (!valid ()) return; 
	if (where () == r) return; 
	CVideoObjectPlane* pvop = new CVideoObjectPlane (*this, r);
	swap (*pvop);
	delete pvop;
}

CRct CVideoObjectPlane::whereVisible() const 
{
	if (!valid () || !m_rc.valid ()) return CRct ();

	CoordI left = where ().right - 1;
	CoordI top = where ().bottom - 1;
	CoordI right = where ().left;
	CoordI bottom = where ().top;
	const CPixel* ppxlThis = pixels ();
	for (CoordI y = where ().top; y < where ().bottom; y++) {
		for (CoordI x = where ().left; x < where ().right; x++) {
			if (ppxlThis -> pxlU.rgb.a != transpValue) {
				left = min (left, x);
				top = min (top, y);
				right = max (right, x);
				bottom = max (bottom, y);
			}
			ppxlThis++;
		}
	}
	right++;
	bottom++;
	return CRct (left, top, right, bottom);

	if (!valid () || !m_rc.valid ()) return CRct ();}

CPixel CVideoObjectPlane::pixel (CoordI x, CoordI y, UInt accuracy_ori) const
{	
	UInt accuracy1 = accuracy_ori + 1;
	CoordI left = (CoordI) floor ((Double) (x >> accuracy1)); // find the coordinates of the four corners
	CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
	left = checkrange (left, wLeft, wRight1);
	CoordI right = (CoordI) ceil ((Double) (x >> accuracy1));
	right = checkrange (right, wLeft, wRight1);
	CoordI top = (CoordI) floor ((Double) (y >> accuracy1));
	top	= checkrange (top, wTop, wBottom1);
	CoordI bottom = (CoordI) ceil ((Double) (y >> accuracy1));
	bottom = checkrange (bottom, wTop, wBottom1);

	UInt accuracy2 = (accuracy_ori << 1) + 2;
	const CPixel lt = pixel (left, top);
	const CPixel rt = pixel (right, top);
	const CPixel lb = pixel (left, bottom);
	const CPixel rb = pixel (right, bottom);
	const Int distX = (x - left) << accuracy1;
	const Int distY = (y - top) << accuracy1;
	Int x01 = (distX * (rt.pxlU.rgb.r - lt.pxlU.rgb.r) + (Int) lt.pxlU.rgb.r) << accuracy1; // use p.59's notation (Wolberg, Digital Image Warping)
	Int x23 = (distX * (rb.pxlU.rgb.r - lb.pxlU.rgb.r) + (Int) lb.pxlU.rgb.r) << accuracy1; 
	Int r = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255);
	x01 = (distX * (rt.pxlU.rgb.g - lt.pxlU.rgb.g) + (Int) lt.pxlU.rgb.g) << accuracy1; // use p.59's notation
	x23 = (distX * (rb.pxlU.rgb.g - lb.pxlU.rgb.g) + (Int) lb.pxlU.rgb.g) << accuracy1;
	Int g = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255);
	x01 = (distX * (rt.pxlU.rgb.b - lt.pxlU.rgb.b) + (Int) lt.pxlU.rgb.b) << accuracy1; // use p.59's notation
	x23 = (distX * (rb.pxlU.rgb.b - lb.pxlU.rgb.b) + (Int) lb.pxlU.rgb.b) << accuracy1;
	Int b = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255);
	x01 = (distX * (rt.pxlU.rgb.a - lt.pxlU.rgb.a) + (Int) lt.pxlU.rgb.a) << accuracy1; // use p.59's notation
	x23 = (distX * (rb.pxlU.rgb.a - lb.pxlU.rgb.a) + (Int) lb.pxlU.rgb.a) << accuracy1;
	Int a = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255);
	return CPixel ((U8) r, (U8) g, (U8) b, (U8) a);
}

CPixel CVideoObjectPlane::pixel (CoordD x, CoordD y) const
{
	CoordI left = (CoordI) floor (x); // find the coordinates of the four corners
	CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
	left = checkrange (left, wLeft, wRight1);
	CoordI right = (CoordI) ceil (x);
	right = checkrange (right, wLeft, wRight1);
	CoordI top = (CoordI) floor (y);
	top	= checkrange (top, wTop, wBottom1);
	CoordI bottom = (CoordI) ceil (y);
	bottom = checkrange (bottom, wTop, wBottom1);

	const CPixel lt = pixel (left, top);
	const CPixel rt = pixel (right, top);
	const CPixel lb = pixel (left, bottom);
	const CPixel rb = pixel (right, bottom);
	const Double distX = x - left;
	const Double distY = y - top;
	Double x01 = distX * (rt.pxlU.rgb.r - lt.pxlU.rgb.r) + lt.pxlU.rgb.r; // use p.59's notation (Wolberg, Digital Image Warping)
	Double x23 = distX * (rb.pxlU.rgb.r - lb.pxlU.rgb.r) + lb.pxlU.rgb.r;
	Int r = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255);
	x01 = distX * (rt.pxlU.rgb.g - lt.pxlU.rgb.g) + lt.pxlU.rgb.g; // use p.59's notation
	x23 = distX * (rb.pxlU.rgb.g - lb.pxlU.rgb.g) + lb.pxlU.rgb.g;
	Int g = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255);
	x01 = distX * (rt.pxlU.rgb.b - lt.pxlU.rgb.b) + lt.pxlU.rgb.b; // use p.59's notation
	x23 = distX * (rb.pxlU.rgb.b - lb.pxlU.rgb.b) + lb.pxlU.rgb.b;
	Int b = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255);
	x01 = distX * (rt.pxlU.rgb.a - lt.pxlU.rgb.a) + lt.pxlU.rgb.a; // use p.59's notation
	x23 = distX * (rb.pxlU.rgb.a - lb.pxlU.rgb.a) + lb.pxlU.rgb.a;
	Int a = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255);
	return CPixel ((U8) r, (U8) g, (U8) b, (U8) a);
}

own CVideoObjectPlane* CVideoObjectPlane::warp (const CAffine2D& aff) const // affine warp
{
	CSiteD stdLeftTopWarp = aff * CSiteD (where ().left, where ().top);
	CSiteD stdRightTopWarp = aff * CSiteD (where ().right, where ().top);
	CSiteD stdLeftBottomWarp = aff * CSiteD (where ().left, where ().bottom);
	CSiteD stdRightBottomWarp = aff * CSiteD (where ().right, where ().bottom);
	CRct rctWarp (stdLeftTopWarp, stdRightTopWarp, stdLeftBottomWarp, stdRightBottomWarp);

	CVideoObjectPlane* pvopRet = new CVideoObjectPlane (rctWarp);
	CPixel* ppxlRet = (CPixel*) pvopRet -> pixels ();
	CAffine2D affInv = aff.inverse ();
	for (CoordI y = rctWarp.top; y < rctWarp.bottom; y++) {
		for (CoordI x = rctWarp.left; x < rctWarp.right; x++) {
			CSiteD src = affInv * CSiteD (x, y); 
			CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
			CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
			CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
			CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
			if (
				where ().includes (fx, fy) && 
				where ().includes (fx, cy) && 
				where ().includes (cx, fy) && 
				where ().includes (cx, cy)
			)
				*ppxlRet = pixel (src);
			ppxlRet++;
		}
	}
	return pvopRet;
}

own CVideoObjectPlane* CVideoObjectPlane::warp (const CAffine2D& aff, const CRct& rctWarp) const // affine warp
{
	CVideoObjectPlane* pvopRet = new CVideoObjectPlane (rctWarp);
	CPixel* ppxlRet = (CPixel*) pvopRet -> pixels ();
	//CAffine2D affInv = aff.inverse ();
	for (CoordI y = rctWarp.top; y < rctWarp.bottom; y++) {
		for (CoordI x = rctWarp.left; x < rctWarp.right; x++) {
			CSiteD src = aff * CSiteD (x, y); 
			CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
			CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
			CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
			CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
			if (
				where ().includes (fx, fy) && 
				where ().includes (fx, cy) && 
				where ().includes (cx, fy) && 
				where ().includes (cx, cy)
			)
				*ppxlRet = pixel (src);
			ppxlRet++;
		}
	}

⌨️ 快捷键说明

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