![]() |
![]() |
||||||
![]() |
|||||||
|
/*
*
* capture.c - part of Danovitsch Webcam
*
* Copyright (C) 2001, 2003 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"
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,255,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("/dev/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("/dev/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;
if (ImageHeight>240)
Geo.oformat=METEOR_GEO_RGB24;
else
Geo.oformat=METEOR_GEO_RGB24 | METEOR_GEO_ODD_ONLY;
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 <Danovitsch @ Vitsch . net> |