Navigation
Home
gpl
danovitschwebcam
1.0
capture.c








































capture.c
   
   /*
    *
    * capture.c - part of Danovitsch Webcam
    *
    * Copyright (C) 2001 by Daan Vreeken
    *
    * Published under the terms of the GNU Public License 2.0
    * (or any later version)
    *
    */
   
   
   
   #include <stdlib.h>
   #include <fcntl.h>
   #include <sys/mman.h>
   #include <unistd.h>
   #include <sys/time.h>
   
   #include <machine/ioctl_bt848.h>
   #include <machine/ioctl_meteor.h>
   
   #include "tvtypes.h"
   #include "webcam.h"
   
   
   #define PAL_DIM_X		768
   #define PAL_DIM_Y		576
   
   #define MAX_MMAP_SIZE		(ImageWidth*ImageHeight*4)
   
   
   
   int			Capture_Device = -1;
   int			Width = PAL_DIM_X;
   int			Height = PAL_DIM_Y;
   unsigned char		*Frame;
   unsigned char		*FrameBuffer;
   struct timeval		FrameTime;
   int			NewFrame=0;
   
   int			Capture_Fifo[2];
   
   
   
   enum Capture_SettingID
   {
   	NoID=0, ID_Brightness, ID_Hue, ID_CSaturation, ID_Contrast,
   	ID_Input, ID_InputF, ID_Format, ID_Audio, ID_Channel, ID_ChannelType
   };
   
   enum Capture_SettingType
   {
   	NoType=0, Type_Number, Type_Text
   };
   
   enum Capture_SettingDevice
   {
   	NoDev=0, Dev_Bktr, Dev_Tuner
   };
   
   struct Capture_SettingsArr
   {
   	const enum Capture_SettingID		ID;
   	const char				*Name;
   	const enum Capture_SettingType		Type;
   	const enum Capture_SettingDevice	Device;
   	const int				MinVal;
   	const int				MaxVal;
   	int					NumValue;
   	char					*OrgValue;
   	char					*TxtValue;
   };
   
   struct Capture_SettingsArr	Capture_Settings[] = {
   	{ID_Brightness,"Brightness",Type_Number,Dev_Bktr,0,255,142,NULL,NULL},
   	{ID_Hue,"Hue",Type_Number,Dev_Bktr,0,256,255,NULL,NULL},
   	{ID_CSaturation,"Saturation",Type_Number,Dev_Bktr,0,255,128,NULL},
   	{ID_Contrast,"Contrast",Type_Number,Dev_Bktr,0,255,128,NULL,NULL},
   	{ID_InputF,"InputF",Type_Text,Dev_Bktr,0,0,0,"Cam1",NULL},
   //	{ID_InputF,"InputF",Type_Text,Dev_Bktr,0,0,0,"ATV",NULL},
   	{ID_Input,"Input",Type_Text,Dev_Bktr,0,0,0,"EXT-1",NULL},
   	{ID_Format,"Format",Type_Text,Dev_Bktr,0,0,0,"PAL-BDGHI",NULL},
   	{ID_Audio,"Audio",Type_Text,Dev_Tuner,0,0,0,"MUTE",NULL},
   //	{ID_Channel,"TunerChannel",Type_Number,Dev_Tuner,0,400,29,NULL,NULL},
   //	{ID_ChannelType,"ChannelType",Type_Text,Dev_Tuner,0,0,0,"WEUROPE",NULL},
   	{NoID,NULL,NoType,NoDev,0,0,0,NULL,NULL}};
   
   struct Capture_TextTable
   {
   	const enum Capture_SettingID	ID;
   	const char	*Text;
   	int		Value;
   };
   
   struct Capture_TextTable	Capture_SettingText[] = {
   	//Video inputs
   	{ID_Input,"EXT-1",METEOR_INPUT_DEV0},
   	{ID_Input,"TUNER",METEOR_INPUT_DEV1},
   	{ID_Input,"SVHS-composite",METEOR_INPUT_DEV2},
   	{ID_Input,"SVHS",METEOR_INPUT_DEV_SVIDEO},
   	{ID_Input,"EXT-2",METEOR_INPUT_DEV3},
   	//Friendly-named video inputs ;-)
   	{ID_InputF,"Cam1",METEOR_INPUT_DEV0},
   	{ID_InputF,"Cam2",METEOR_INPUT_DEV_SVIDEO},
   	{ID_InputF,"Tuner",METEOR_INPUT_DEV1},
   	{ID_InputF,"ATV",METEOR_INPUT_DEV2},
   	//Video formats
   	{ID_Format,"AUTO",BT848_IFORM_F_AUTO},
   	{ID_Format,"NTSC-M",BT848_IFORM_F_NTSCM},
   	{ID_Format,"NTSC-J",BT848_IFORM_F_NTSCJ},
   	{ID_Format,"PAL-BDGHI",BT848_IFORM_F_PALBDGHI},
   	{ID_Format,"PAL-M",BT848_IFORM_F_PALM},
   	{ID_Format,"PAL-N",BT848_IFORM_F_PALN},
   	{ID_Format,"SECAM",BT848_IFORM_F_SECAM},
   	{ID_Format,"RSVD",BT848_IFORM_F_RSVD},
   	//Audio sources
   	{ID_Audio,"TUNER",AUDIO_TUNER},
   	{ID_Audio,"EXTERN",AUDIO_EXTERN},
   	{ID_Audio,"INTERN",AUDIO_INTERN},
   	{ID_Audio,"MUTE",AUDIO_MUTE},
   	{ID_Audio,"UNMUTE",AUDIO_UNMUTE},
   	//Tuner channel types
   	{ID_ChannelType,"NABCST",CHNLSET_NABCST},
   	{ID_ChannelType,"CABLEIRC",CHNLSET_CABLEIRC},
   	{ID_ChannelType,"CABLEHRC",CHNLSET_CABLEHRC},
   	{ID_ChannelType,"WEUROPE",CHNLSET_WEUROPE},
   	{ID_ChannelType,"JPNBCST",CHNLSET_JPNBCST},
   	{ID_ChannelType,"JPNCABLE",CHNLSET_JPNCABLE},
   	{ID_ChannelType,"XUSSR",CHNLSET_XUSSR},
   	{ID_ChannelType,"AUSTRALIA",CHNLSET_AUSTRALIA},
   	{ID_ChannelType,"FRANCE",CHNLSET_FRANCE},
   	{NoID,NULL,0}};
   
   
   
   int Capture_LookupText(struct Capture_SettingsArr *Set, char *Text)
   {
   	struct Capture_TextTable	*Entry = &Capture_SettingText[0];
   
   	while ((Entry->ID!=NoID) && ((Entry->ID!=Set->ID) || (strcasecmp(Entry->Text,Text))))
   		Entry++;
   
   	if (Entry->ID==NoID)
   		return -1;
   
   	return Entry->Value;
   }
   
   
   
   char *Capture_GetTextValue(char *Name)
   {
   	struct Capture_SettingsArr	*Set = &Capture_Settings[0];
   
   	while ((Set->ID!=NoID) && (strcasecmp(Set->Name,Name)))
   		Set++;
   
   	if (Set->ID==NoID)
   		return NULL;
   
   	return Set->TxtValue;
   }
   
   
   
   int Capture_Set(struct Capture_SettingsArr *SetPtr, char *Name, int Value, char *Txt)
   {
   	TV_INT32			Int;
   	int				Int2;
   	unsigned long			Request;
   	int				Result = -1;
   	struct Capture_SettingsArr	*Set = SetPtr;
   	int				Device;
   
   	//If no direct pointer was gives, try figuring it out by the name...
   	if (Set==NULL)
   	{
   		Set=&Capture_Settings[0];
   
   		while ((Set->ID!=NoID) && (strcmp(Set->Name,Name)))
   			Set++;
   
   		if (Set->ID==NoID)
   		{
   			ExitFatal("Wrong Capture_Set() name!!");
   		}
   	}
   
   	switch (Set->Type)
   	{
   	case Type_Number:
   		if ((Value<Set->MinVal) || (Value>Set->MaxVal))
   		{
   			Error("Wrong value!");
   			return 0;
   		}
   		Set->NumValue=Value;
   		Int=Value;
   
   		switch (Set->ID)
   		{
   		case ID_Brightness:
   			Request=METEORSBRIG;
   			break;
   		case ID_Hue:
   			Request=METEORSHUE;
   			break;
   		case ID_CSaturation:
   			Request=METEORSCSAT;
   			break;
   		case ID_Contrast:
   			Request=METEORSCONT;
   			break;
   		case ID_Channel:
   			Request=TVTUNER_SETCHNL;
   			break;
   		}
   
   		switch (Set->Device)
   		{
   		case Dev_Bktr:
   			Device=Capture_Device;
   			break;
   
   		case Dev_Tuner:
   			Device=open("/devs/tuner0",O_RDONLY);
   			if (Device==-1)
   			{
   				Error("Could not open tuner!");
   				return 0;
   			}
   			break;
   		}
   
   		if (Result=ioctl(Device,Request,&Int)==-1)
   			Error("ioctl failed! (req:%ld val:%ld)",Request,Int);
   		
   		if (Set->Device==Dev_Tuner)
   			close(Device);
   
   		break;
   
   	case Type_Text:
   		Int=Capture_LookupText(Set,Txt);
   		if (Int==-1)
   		{
   			Error("Wrong text! (id:%s txt:%s)",Set->Name,Txt);
   			return 0;
   		}
   
   		if (Set->TxtValue!=NULL)
   			free(Set->TxtValue);
   
   		Set->TxtValue=(char *)malloc(strlen(Txt)+1);
   		if (Set->TxtValue==NULL)
   		{
   			Error("Could not allocate memory for setting! (skipping this one)");
   			return 0;
   		}
   		memcpy(Set->TxtValue,Txt,strlen(Txt)+1);
   
   		switch (Set->ID)
   		{
   		case ID_Input:
   		case ID_InputF:
   			Request=METEORSINPUT;
   			break;
   		case ID_Format:
   			Request=BT848SFMT;
   			break;
   		case ID_Audio:
   			Request=BT848_SAUDIO;
   			break;
   		case ID_ChannelType:
   			Request=TVTUNER_SETTYPE;
   			break;
   		default:
   			Error("!!?!?!?!??!!? %d",Int);
   		}
   
   		switch (Set->Device)
   		{
   		case Dev_Bktr:
   			Device=Capture_Device;
   			break;
   
   		case Dev_Tuner:
   			Device=open("/devs/tuner0",O_RDONLY);
   			if (Device==-1)
   			{
   				Error("Could not open tuner!");
   			}
   			break;
   		}
   
   		if (Result=ioctl(Device,Request,&Int)==-1)
   			Error("ioctl failed! (txt:%s req:%ld val:%ld %ld)",Txt,Request,Int,AUDIO_TUNER);
   
   		if (Set->Device==Dev_Tuner)
   			close(Device);
   
   		break;
   
   	default:
   		Error("Capture_Set: Don't know what to do?!");
   	}
   
   	if (Result==-1)
   		return 0;
   	else
   		return 1;
   }
   
   
   
   void Capture_SetFormat(void)
   {
   	TV_INT32		Format;
   	struct meteor_geomet	Geo;
   	
   
   	//PAL
   	Format=BT848_IFORM_F_PALBDGHI;
   	
   	if (ioctl(Capture_Device,BT848SFMT,&Format)==-1)
   		Error("ioctl failed!");
   	
   	//Geometry
   	Geo.columns=ImageWidth;
   	Geo.rows=ImageHeight;
   	Geo.frames=1;
   	Geo.oformat=METEOR_GEO_RGB24 | METEOR_GEO_ODD_ONLY;
   	//Geo.oformat=METEOR_GEO_RGB24;
   	
   	if (ioctl(Capture_Device,METEORSETGEO,&Geo)==-1)
   		Error("ioctl failed!");
   }
   
   
   
   void Capture_SetSource(void)
   {
   	int		Source;
   	TV_INT32	Bright;
   
   	
   	//external video input
   	Source=METEOR_INPUT_DEV0;
   	
   	if (ioctl(Capture_Device,METEORSINPUT,&Source)==-1)
   		Error("ioctl failed!");
   		
   	/* audio:
   	Source=AUDIO_INTERN;
   	
   	if (ioctl(Capture_Device,BT848_SAUDIO,&Source)==-1)
   		Error("ioctl failed!");
   	*/
   
   	//brightness
   	Bright=128+13;
   	
   	if (ioctl(Capture_Device,METEORSBRIG,&Bright)==-1)
   		Error("ioctl failed!");
   }
   
   
   static void FrameDone_Handler(int Signal)
   {
   	unsigned char	Nop = 0x00;
   
   	write(Capture_Fifo[0],&Nop,1);
   }
   
   
   
   void Capture_Setup(void)
   {
   	int		Signal = SIGUSR1;
   
   
   	FrameBuffer=(unsigned char *)malloc(MAX_MMAP_SIZE);
   	if (FrameBuffer==NULL)
   		ExitFatal("Could not allocate FrameBuffer!");
   
   	Frame=(unsigned char *)mmap((caddr_t)0,MAX_MMAP_SIZE,PROT_READ,MAP_SHARED,Capture_Device,(off_t)0);
   	if (Frame==(unsigned char *)-1)
   		ExitFatal("mmap failed!");
   	
   	signal(SIGUSR1,FrameDone_Handler);
   
   	if (ioctl(Capture_Device,METEORSSIGNAL,&Signal)==-1)
   		ExitFatal("iotrcl failed!");
   }
   
   
   
   void Capture_Single()
   {
   	TV_INT32	Capture;
   	
   	Capture=METEOR_CAP_SINGLE;
   	//Capture=METEOR_CAP_CONTINOUS;
   	
   	if (ioctl(Capture_Device,METEORCAPTUR,&Capture)==-1)
   		Error("could not start single capture!");
   
   	gettimeofday(&FrameTime,NULL);
   	NewFrame=1;
   }
   
   
   
   void Capture_Shutdown()
   {
   	if (Frame!=NULL)
   		munmap(Frame,MAX_MMAP_SIZE);
   
   	if (Capture_Device!=-1)
   		close(Capture_Device);
   
   	Output("Shutdown capture device");
   }
   
   
   
   
   

syntax highlighted by Code2HTML, v. 0.9.1


Email me with questions/comments : Daan <Daan @ pa4dan . nl>