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

📄 videoin.cpp

📁 ati driver
💻 CPP
字号:
/******************************************************************************//	File:			VideoIn.cpp//	Description:	High-Level ATI Radeon Video Capture Interface.//	Copyright 2001, Carlos Hasan/*******************************************************************************/#include <Debug.h>#include "VideoIn.h"#include <memory.h>static const theater_standard kStandard[] = {	C_THEATER_NTSC,	C_THEATER_NTSC_JAPAN,	C_THEATER_NTSC_443,	C_THEATER_PAL_M,	C_THEATER_PAL_BDGHI,	C_THEATER_PAL_N,	C_THEATER_PAL_60,	C_THEATER_PAL_NC,	C_THEATER_SECAM,//	C_THEATER_NTSC_RAW};static const theater_source kSource[] = {	C_THEATER_TUNER,	C_THEATER_COMPOSITE,	C_THEATER_SVIDEO};static const capture_buffer_mode kMode[] = {	C_RADEON_CAPTURE_FIELD_DOUBLE,	C_RADEON_CAPTURE_BOB_DOUBLE,	C_RADEON_CAPTURE_WEAVE_DOUBLE};	static const struct {	struct {		int width, height;	} total;	struct {		int left, top;		int width, height;	} active;	struct {		int left, top;		int width, height;	} vbi;} kTiming[] = {	{ {  910, 525 }, { 112, 37, 755, 480 }, {  73, 13, 798, 20 } },	// NTSC-M	{ {  910, 525 }, { 112, 37, 755, 480 }, {  73, 13, 798, 24 } },	// NTSC-Japan	{ { 1042, 525 }, { 126, 37, 940, 480 }, {  73, 13, 798, 24 } }, // NTSC-443	{ {  910, 525 }, { 103, 37, 764, 480 }, {  73, 13, 798, 24 } }, // PAL-M		{ { 1135, 625 }, { 154, 35, 928, 576 }, { 132, 11, 924, 24 } },	// PAL-BDGHI	{ { 1135, 625 }, { 154, 35, 928, 576 }, { 132, 11, 924, 24 } }, // PAL-N	{ { 1125, 625 }, { 132, 37, 736, 480 }, { 100, 13, 770, 26 } }, // PAL-60	{ {  910, 625 }, { 125, 35, 957, 576 }, { 132, 11, 924, 24 } }, // PAL-NC	{ { 1135, 625 }, { 149, 35, 933, 576 }, { 132, 11, 924, 24 } },	// SECAM	{ {  910, 525 }, { 112, 37, 755, 480 }, {  73, 13, 798, 22 } }	// NTSC-Raw};CVideoIn::CVideoIn( const char *dev_name )	:	fRadeon( dev_name ),		fCapture(fRadeon),		fI2CPort(fRadeon),		fTheater(fRadeon),		fTuner(fI2CPort),		fSound(fI2CPort),		fBuffer0(0),		fBuffer1(0),		fBuffer0Handle(0),		fBuffer1Handle(0),		convert_buffer( NULL ),		fBufferLength(0),		fBufferBytesPerRow(0),		fBufferSequence(0),		fBufferPeriod(0),		started( false ){	Trace("CVideoIn::CVideoIn()");}CVideoIn::~CVideoIn(){	Trace("CVideoIn::~CVideoIn()");	FreeBuffers();	}status_t CVideoIn::InitCheck() const{	status_t res;		Trace("CVideoIn::InitCheck()");	if( (res = fRadeon.InitCheck()) != B_OK )		return res;			if( (res = fCapture.InitCheck()) != B_OK )		return res;			if( (res = fI2CPort.InitCheck()) != B_OK )		return res;			return fTheater.InitCheck();}int CVideoIn::Capabilities() const{	return (fTuner.InitCheck() == B_OK ? C_VIDEO_IN_HAS_TUNER + C_VIDEO_IN_HAS_COMPOSITE + C_VIDEO_IN_HAS_SVIDEO : 0) +		   (fSound.InitCheck() == B_OK ? C_VIDEO_IN_HAS_SOUND : 0);}void CVideoIn::Start(video_in_source source, video_in_standard standard,					 video_in_capture_mode mode, int width, int height){	char buffer[256];	sprintf(buffer, "CVideoIn::Start(%s, %d, %d)",		mode == C_VIDEO_IN_FIELD ? "C_VIDEO_IN_FIELD" :		mode ==	C_VIDEO_IN_BOB ? "C_VIDEO_IN_BOB" : "C_VIDEO_IN_WEAVE", width, height);	Trace(buffer);		if( started )		Stop();			switch (mode) {	case C_VIDEO_IN_FIELD:	case C_VIDEO_IN_BOB:		width = Clamp(width, 0, kTiming[standard].active.width);		height = Clamp(height, 0, kTiming[standard].active.height / 2);		break;	case C_VIDEO_IN_WEAVE:		width = Clamp(width, 0, kTiming[standard].active.width);		height = Clamp(height, 0, kTiming[standard].active.height);		break;	}			fBufferBytesPerRow = (2 * width + 15) & ~15;	fBufferLength = (fBufferBytesPerRow * height + 15) & ~15;		FreeBuffers();	// TBD:	// no error handling !!!!	fRadeon.AllocateGraphicsMemory( 		mt_local, 		mode == C_VIDEO_IN_BOB ? 4 * fBufferLength : 2 * fBufferLength,		&fBuffer0, &fBuffer0Handle );			fRadeon.AllocateGraphicsMemory( 		mt_local, 		mode == C_VIDEO_IN_BOB ? 2 * fBufferLength : 1 * fBufferLength,		&fBuffer1, &fBuffer1Handle );				convert_buffer = malloc( mode == C_VIDEO_IN_BOB ? 4 * fBufferLength : 2 * fBufferLength );		fBufferPeriod = 1000000000LL / getFrameRate( standard );		if( mode == C_VIDEO_IN_BOB )		fBufferPeriod >>= 1;	fTheater.SetStandard(kStandard[standard], kSource[source]);	fTheater.SetSize(width, (mode != C_VIDEO_IN_WEAVE ? 2 * height : height));	fCapture.SetBuffer(C_RADEON_CAPTURE_CCIR656, kMode[mode], fBuffer0, fBuffer1, fBufferLength, fBufferBytesPerRow >> 1);	fCapture.SetClip(0, kTiming[standard].vbi.height, width - 1, kTiming[standard].vbi.height + (mode != C_VIDEO_IN_WEAVE ? height : height >> 1) - 1);	fTheater.SetEnable(true, false);	if( fSound.InitCheck() == B_OK )		fSound.SetEnable(true);	fCapture.SetInterrupts(true);	fCapture.Start();}void CVideoIn::Stop(){	Trace("CVideoIn::Stop()");		if( !started )		return;	fCapture.Stop();	fCapture.SetInterrupts(false);	if( fSound.InitCheck() == B_OK )		fSound.SetEnable(false);		fTheater.SetEnable(false, false);		FreeBuffers();}void CVideoIn::FreeBuffers(){	if( fBuffer0Handle > 0 ) {		fRadeon.FreeGraphicsMemory( mt_local, fBuffer0Handle );		fBuffer0Handle = 0;	}			if( fBuffer1Handle > 0 ) {		fRadeon.FreeGraphicsMemory( mt_local, fBuffer1Handle );		fBuffer1Handle = 0;	}		if( convert_buffer != NULL ) {		free( convert_buffer );		convert_buffer = NULL;	}}void CVideoIn::SetBrightness(int brightness){	Trace("CVideoIn::SetBrightness()");		fTheater.SetBrightness(brightness);}void CVideoIn::SetContrast(int contrast){	Trace("CVideoIn::SetContrast()");		fTheater.SetContrast(contrast);}void CVideoIn::SetSaturation(int saturation){	Trace("CVideoIn::SetSaturation()");		fTheater.SetSaturation(saturation);}void CVideoIn::SetHue(int hue){	Trace("CVideoIn::SetHue()");		fTheater.SetHue(hue);}void CVideoIn::SetSharpness(int sharpness){	Trace("CVideoIn::SetSharpness()");	fTheater.SetSharpness(sharpness);}void CVideoIn::SetFrequency(float frequency, float picture){	Trace("CVideoIn::SetFrequency()");		if (fTuner.Type() != C_TUNER_NONE)		fTuner.SweepFrequency(frequency, picture);}float CVideoIn::FrequencyForChannel(int channel, video_in_standard standard){	float frequency = 0;	Trace("CVideoIn::FrequencyForChannel()");	if (fTuner.Type() != C_TUNER_NONE) {		switch (standard) {		case C_VIDEO_IN_NTSC:		case C_VIDEO_IN_NTSC_RAW:			// NTSC Cable			if (channel >= 2 && channel <= 6) {				frequency = 55.25 + 6.00 * (channel - 2);			}			else if (channel >= 7 && channel <= 13) {				frequency = 175.25 + 6.00 * (channel - 7);			}			else if (channel >= 14 && channel <= 22) {				frequency = 121.25 + 6.00 * (channel - 14);			}			else if (channel >= 23 && channel <= 36) {				frequency = 217.25 + 6.00 * (channel - 23);			}			else if (channel >= 37 && channel <= 62) {				frequency = 301.25 + 6.00 * (channel - 37);			}			else if (channel >= 63 && channel <= 94) {				frequency = 457.25 + 6.00 * (channel - 63);			}			else if (channel >= 95 && channel <= 99) {				frequency = 91.25 + 6.00 * (channel - 95);			}			else if (channel >= 100 && channel <= 125) {				frequency = 649.25 + 6.00 * (channel - 100);			}			else {				frequency = 0;			}			break;		case C_VIDEO_IN_NTSC_JAPAN:		case C_VIDEO_IN_NTSC_443:		case C_VIDEO_IN_PAL_M:		case C_VIDEO_IN_PAL_BDGHI:		case C_VIDEO_IN_PAL_N:		case C_VIDEO_IN_PAL_60:		case C_VIDEO_IN_PAL_NC:		case C_VIDEO_IN_SECAM:			break;		}	}	return frequency;}bool CVideoIn::SetChannel(int channel, video_in_standard standard){	Trace("CVideoIn::SetChannel()");		if (fTuner.Type() == C_TUNER_NONE)		return true;	const float frequency = FrequencyForChannel(channel, standard);			switch (standard) {	case C_VIDEO_IN_NTSC:	case C_VIDEO_IN_NTSC_RAW:		return fTuner.SweepFrequency(frequency, C_TUNER_NTSC_PICTURE_CARRIER / 100.0f);		break;	case C_VIDEO_IN_NTSC_JAPAN:	case C_VIDEO_IN_NTSC_443:	case C_VIDEO_IN_PAL_M:	case C_VIDEO_IN_PAL_BDGHI:	case C_VIDEO_IN_PAL_N:	case C_VIDEO_IN_PAL_60:	case C_VIDEO_IN_PAL_NC:	case C_VIDEO_IN_SECAM:		return fTuner.SweepFrequency(frequency, C_TUNER_PAL_PICTURE_CARRIER / 100.0f);	}	return false;}int CVideoIn::Capture(color_space colorSpace, void * bits, int bitsLength,					  int bytesPerRow, int * sequence, short * number, bigtime_t * when){//	Trace("CVideoIn::Capture()");	int mask, counter;	if ((mask = fCapture.WaitInterrupts(sequence, when, fBufferPeriod)) == 0)		return 0;	*number = ((mask & (C_RADEON_CAPTURE_BUF0_INT | C_RADEON_CAPTURE_BUF1_INT)) != 0 ? 0 : 1);		int32 captured_buffer = 		((mask & C_RADEON_CAPTURE_BUF0_INT) != 0 ? fBuffer0 :		 (mask & C_RADEON_CAPTURE_BUF1_INT) != 0 ? fBuffer1 :		 (mask & C_RADEON_CAPTURE_BUF0_EVEN_INT) != 0 ? fBuffer0 + fBufferLength :		 (mask & C_RADEON_CAPTURE_BUF1_EVEN_INT) != 0 ? fBuffer1 + fBufferLength : 0);		 	/*PRINT(("colorSpace:%x, bitsLength: %d, fBufferLength: %d, bytesPerRow: %d, fBufferBytesPerRow: %d\n",		colorSpace, bitsLength, fBufferLength, bytesPerRow, fBufferBytesPerRow ));*/		// always copy into main memory first, even if it must be converted by CPU - 	// reading from graphics mem is incredibly slow	if (colorSpace == B_YCbCr422 && bitsLength <= fBufferLength && bytesPerRow == fBufferBytesPerRow) {		fRadeon.DMACopy( captured_buffer, bits, bitsLength, true, false );	}		else if (colorSpace == B_RGB32 && bitsLength <= 2 * fBufferLength && bytesPerRow == 2 * fBufferBytesPerRow) {			fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );#define RGB32#include "yuv_converter.h"#undef RGB32	}		else if (colorSpace == B_RGB16 && bitsLength <= fBufferLength && bytesPerRow == fBufferBytesPerRow) {		fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );#define RGB16#include "yuv_converter.h"#undef RGB16	}		else if (colorSpace == B_RGB15 && bitsLength <= fBufferLength && bytesPerRow == fBufferBytesPerRow) {		fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );#define RGB15#include "yuv_converter.h"#undef RGB15	}	else if (colorSpace == B_GRAY8 && 2 * bitsLength <= fBufferLength && 2 * bytesPerRow == fBufferBytesPerRow) {		fRadeon.DMACopy( captured_buffer, convert_buffer, fBufferLength, true, false );				static const unsigned short mask[] = {			0x00ff, 0x00ff, 0x00ff, 0x00ff };		asm volatile(		"1:\n"			"movq		0x00(%0),%%mm0\n"	// mm0 = Cr2' Y3 Cb2' Y2 Cr0' Y1 Cb0' Y0			"movq		0x08(%0),%%mm1\n"	// mm1 = Cr6' Y7 Cb6' Y6 Cr4' Y5 Cb4' Y4				"pand		%3,%%mm0\n"			// mm0 =  00  Y3  00  Y2  00  Y1  00  Y0			"pand		%3,%%mm1\n"			// mm1 =  00  Y7  00  Y6  00  Y5  00  Y4			"packuswb	%%mm1,%%mm0\n"		// mm0 =  Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0			"movq		%%mm0,(%1)\n"		// destination[0] = mm0			"addl		$0x10,%0\n"			// source += 16			"addl		$0x08,%1\n"			// destination += 8			"subl		$0x08,%2\n"			"jg			1b\n"			"emms\n"			:			: "r" (convert_buffer), "r" (bits), "r" (bitsLength), "m" (mask));	}	else if( colorSpace == B_NO_COLOR_SPACE ) {		// special case: only wait for image but don't copy it		;	} 	else {		PRINT(("CVideoIn::Capture() - Bad buffer format\n"));	}		counter = *sequence - fBufferSequence;	fBufferSequence = *sequence;	return counter;}void CVideoIn::Trace(const char * message) const{	PRINT(("\x1b[0;30;34m%s\x1b[0;30;47m\n", message));}int32 CVideoIn::getFrameRate( video_in_standard standard ){	// TODO: I'm not really sure about these values	static const int32 frame_rate[] = {		29976, 29976, 29976, 25000, 25000, 25000, 29976, 25000, 25000, 29976	};		return frame_rate[standard];}void CVideoIn::getActiveRange( video_in_standard standard, CRadeonRect &rect ){	// in theory, we would ask fTheatre;	// in practice, values retrieved from there don't work; 	// e.g. for PAL, according to Theatre, VBI height is 38, but you must set up the	// clipping unit to height 24! I have no clue what goes wrong there	rect.SetTo( 		kTiming[standard].active.left,		kTiming[standard].active.top,		kTiming[standard].active.left + kTiming[standard].active.width - 1,		kTiming[standard].active.top + kTiming[standard].active.height - 1 );}

⌨️ 快捷键说明

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