freebsd-ports/multimedia/nuppelvideo/files/patch-nuvrec.c
Mario Sergio Fujikawa Ferreira 331e4213c9 New port NuppelVideo version 0.52a: A very low CPU usage VCR/DVR
application

Submitted by:	Steve O'Hara-Smith <steve@sohara.org>
2003-03-05 22:27:25 +00:00

396 lines
12 KiB
C

diff -ur ../NuppelVideo-0.52a/nuvrec.c ./nuvrec.c
--- ../NuppelVideo-0.52a/nuvrec.c Wed Jul 4 23:59:58 2001
+++ ./nuvrec.c Mon Feb 10 21:43:02 2003
@@ -27,14 +27,22 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <machine/ioctl_meteor.h>
+#include <machine/ioctl_bt848.h>
#include <sys/soundcard.h>
-#include <linux/videodev.h>
-#include <linux/wait.h>
+#include <sys/wait.h>
#include <errno.h>
#include "minilzo.h"
#include "RTjpegN.h"
#include "nuppelvideo.h"
+typedef unsigned char UINT8;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+typedef signed char INT8;
+typedef signed int INT32;
+typedef signed long long INT64;
+
// #define TESTINPUT 1
// #define TESTSPLIT 1
#define KEYFRAMEDIST 30
@@ -47,11 +55,28 @@
#define MAXBYTESFORCE 2100000000
#endif
-// we need the BTTV_FIELDNR, so we really know how many frames we lose
-#define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)
+#define PAL 1
+#define NTSC 2
+#define SECAM 3
+#define PALN 4
+#define PALM 5
+#define PALBDGHI PAL
+#define NTSCJ 6
+#define NTSCM NTSC
+
+/* PAL is 768 x 576. NTSC is 640 x 480 */
+#define PAL_HEIGHT 576
+#define SECAM_HEIGHT 576
+#define NTSC_HEIGHT 480
+
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <signal.h>
/* Globals */
+int bktr_dev[] = { METEOR_DEV0, METEOR_DEV1, METEOR_DEV2,
+ METEOR_DEV3, METEOR_DEV_SVIDEO };
int fd; // output file haendle
int ostr=0;
__s8 *strm;
@@ -71,10 +96,10 @@
unsigned long long audiobytes;
int effectivedsp;
int ntsc=0; // default to PAL, this info is only for the video header
+int secam=0;
int quiet;
int rawmode=0;
-int usebttv=1;
-struct video_audio origaudio;
+int usebttv=0;
//#define DP(DSTRING) fprintf(stderr, "%s\n", DSTRING);
#define DP(DSTRING)
@@ -173,9 +198,6 @@
kill(pid, 9);
if (recordaudio) kill(pid2, 9);
- // reset audio settings
- if (ioctl(fd, VIDIOCSAUDIO, &origaudio)<0) perror("VIDIOCSAUDIO");
-
if (!quiet) fprintf(stderr, "\n"); // preserve status line
exit(i);
}
@@ -201,24 +223,25 @@
unsigned char *startaudio;
if (init_shm) {
- shmid = shmget(IPC_PRIVATE, video_buffer_size*video_buffer_count +
+ shmid = shmget(0xdeadbeef, video_buffer_size*video_buffer_count +
audio_buffer_size*audio_buffer_count +
video_buffer_count*sizeof(vidbuffertyp) +
audio_buffer_count*sizeof(audbuffertyp),
- IPC_EXCL | IPC_CREAT | 0600);
+ IPC_CREAT | SHM_R | SHM_W);
if (shmid == -1)
ERROR("shmget");
}
- sharedbuffer = shmat(shmid, IPC_RMID, SHM_RND);
+ sharedbuffer = shmat(shmid, (char *) 0, 0);
if (sharedbuffer == (char*)-1)
{
+ fprintf (stderr, "shmid %d\n", shmid);
perror("shmat");
if(shmctl(shmid, IPC_RMID, NULL))
perror("shmctl");
exit(-1);
}
- if(shmctl(shmid, IPC_RMID, NULL))
- ERROR("shmctl");
+// if(shmctl(shmid, IPC_RMID, NULL))
+// ERROR("shmctl");
videobuffer = (struct vidbuffertype *)sharedbuffer;
startaudiodesc = (char *)(sharedbuffer + video_buffer_count*sizeof(vidbuffertyp));
@@ -899,24 +922,6 @@
#ifdef TESTINPUT
tf+=2; // when reading from files we won't lose frames ;)
#else
- if (usebttv) {
- // i hate it when interfaces changes and a non existent ioctl doesn't make an error
- // and doesn't return -1, returning 0 instead and making no error is really weird
- if (ioctl(fd, BTTV_FIELDNR, &tf)) {
- perror("BTTV_FIELDNR");
- usebttv = 0;
- fprintf(stderr, "\nbttv_fieldnr not supported by bttv-driver"
- "\nuse insmod/modprobe bttv card=YOURCARD field_nr=1 to activate f.n."
- "\nfalling back to timecode routine to determine lost frames\n");
- }
- if (tf==0) {
- usebttv = 0;
- fprintf(stderr, "\nbttv_fieldnr not supported by bttv-driver"
- "\nuse insmod/modprobe bttv card=YOURCARD field_nr=1 to activate f.n."
- "\nfalling back to timecode routine to determine lost frames\n");
- }
- }
-
// here is the non preferable timecode - drop algorithm - fallback
if (!usebttv) {
@@ -1073,21 +1078,125 @@
exit(-1);
}
+INT64 av_gettime(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (INT64)tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+static int nsignals = 0;
+static void catchsignal(int signal)
+{
+ nsignals++;
+ return;
+}
+
+static int bktr_init(int video_fd, int width, int height, UINT8 **video_buf, int channel)
+{
+ int format = PAL;
+ struct meteor_geomet geo;
+ int c;
+ int h_max;
+ struct sigaction act,old;
+
+ if (channel < 0 || channel > 4)
+ channel = 1;
+ if (ntsc) {
+ format = NTSC;
+ } else if (secam) {
+ format = SECAM;
+ }
+
+ memset(&act,0,sizeof(act));
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = catchsignal;
+ sigaction(SIGUSR1,&act,&old);
+
+ geo.rows = height;
+ geo.columns = width;
+ geo.frames = 1;
+ geo.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12;
+
+ switch (format) {
+ case PAL: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALBDGHI; break;
+ case PALN: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALN; break;
+ case PALM: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALM; break;
+ case SECAM: h_max = SECAM_HEIGHT; c = BT848_IFORM_F_SECAM; break;
+ case NTSC: h_max = NTSC_HEIGHT; c = BT848_IFORM_F_NTSCM; break;
+ case NTSCJ: h_max = NTSC_HEIGHT; c = BT848_IFORM_F_NTSCJ; break;
+ default: h_max = PAL_HEIGHT; c = BT848_IFORM_F_PALBDGHI; break;
+ }
+ if (height <= h_max/2) {
+ geo.oformat |= METEOR_GEO_EVEN_ONLY;
+ }
+
+ if (ioctl(video_fd, METEORSETGEO, &geo) < 0) {
+ perror ("METEORSETGEO");
+ return -EIO;
+ }
+
+ if (ioctl(video_fd, BT848SFMT, &c) < 0) {
+ perror ("BT848SFMT");
+ return -EIO;
+ }
+
+ c = bktr_dev[channel];
+ if (ioctl(video_fd, METEORSINPUT, &c) < 0) {
+ perror ("METEORSINPUT");
+ return -EIO;
+ }
+ *video_buf = (UINT8 *) mmap((caddr_t)0, width*height*3,
+ PROT_READ, MAP_SHARED, video_fd, (off_t) 0);
+ if (*video_buf == MAP_FAILED) {
+ perror ("mmap");
+ return -EIO;
+ }
+ c = METEOR_CAP_CONTINOUS;
+ ioctl(video_fd, METEORCAPTUR, &c);
+ c = SIGUSR1;
+ ioctl (video_fd, METEORSSIGNAL, &c);
+ return 0;
+}
+
+/* note: we support only one picture read at a time */
+static void bktr_getframe(int width, int height, UINT64 per_frame)
+{
+ int size, halfsize;
+ UINT64 curtime;
+ static UINT64 last_frame_time = 0;
+
+ size = width * height;
+ halfsize = size << 1;
+
+ curtime = av_gettime();
+ if (!last_frame_time
+ || ((last_frame_time + per_frame) > curtime)) {
+ if (!usleep (last_frame_time + per_frame + per_frame/8 - curtime)) {
+ if (!nsignals)
+ printf ("\nSLEPT NO signals - %d microseconds late\n",
+ av_gettime() - last_frame_time - per_frame);
+ }
+ }
+ nsignals = 0;
+
+ last_frame_time = curtime;
+}
+
+
// ----------------------------------------------------------
// -- MAIN --------------------------------------------------
int main(int argc, char** argv)
{
- struct video_mmap mm;
- struct video_mbuf vm;
- struct video_channel vchan;
- struct video_audio va;
- struct video_tuner vt;
+ int tuner_fd;
+ int video_frame_rate = 25;
+ UINT64 per_frame = (UINT64) (((UINT64)1000000 * (UINT64)10000) / (UINT64)video_frame_rate);
+ UINT8 *video_buf = NULL;
- char *videodevice = "/dev/video0";
+ char *videodevice = "/dev/bktr0";
char c;
- int secam;
- int channel=0;
+ int channel=1;
double frequency=0.0;
long v4lfrequency=0;
int volume = -1;
@@ -1277,109 +1386,28 @@
testinput();
#else
- fd = open(videodevice, O_RDWR|O_CREAT);
+ fd = open(videodevice, O_RDONLY);
if(fd<=0){
perror("open");
fatherhandler(-1);
}
-
- if(ioctl(fd, VIDIOCGMBUF, &vm)<0)
- {
- perror("VIDIOCMCAPTUREi0");
- fatherhandler(-1);
+ tuner_fd = open ("/dev/tuner0", O_RDWR);
+ if (tuner_fd < 0) {
+ perror("Warning: Tuner not opened continuing");
}
- if(vm.frames<2)
- {
- fprintf(stderr, "stoopid prog want min 2 cap buffs!\n");
- fatherhandler(-1);
- }
-
- // fprintf(stderr, "We have vm.frames=%d\n", vm.frames);
-
- buf = (unsigned char*)mmap(0, vm.size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (buf<=0)
- {
- perror("mmap");
- fatherhandler(-1);
- }
-
-
- vchan.channel = channel;
- if(ioctl(fd, VIDIOCGCHAN, &vchan)<0) perror("VIDIOCGCHAN");
-
- // choose the right input
- if(ioctl(fd, VIDIOCSCHAN, &vchan)<0) perror("VIDIOCSCHAN");
-
- // if channel has a audio then activate it
- if ((vchan.flags & VIDEO_VC_AUDIO)==VIDEO_VC_AUDIO) {
- // we assume only a channel with audio can have a tuner therefore
- // we only tune here if we are supposed to
- if (frequency != 0.0) {
- v4lfrequency = ((unsigned long)frequency)*16;
- v4lfrequency |= ((unsigned long)( (frequency-(v4lfrequency/16))*100 )*16)/100; // ??????
- if (ioctl(fd, VIDIOCSFREQ, &v4lfrequency)<0) perror("VIDIOCSFREQ");
- if (!quiet) fprintf(stderr, "tuner frequency set to '%5.4f' MHz.\n", frequency);
- }
- if (!quiet) fprintf(stderr, "%s\n", "unmuting tv-audio");
- // audio hack, to enable audio from tvcard, in case we use a tuner
- va.audio = 0; // use audio channel 0
- if (ioctl(fd, VIDIOCGAUDIO, &va)<0) perror("VIDIOCGAUDIO");
- origaudio = va;
- if (!quiet) fprintf(stderr, "audio volume was '%d'\n", va.volume);
- va.audio = 0;
- va.flags &= ~VIDEO_AUDIO_MUTE; // now this really has to work
-
- if ((volume==-1 && va.volume<32768) || volume!=-1) {
- if (volume==-1) {
- va.volume = 32768; // no more silence 8-)
- } else {
- va.volume = volume;
- }
- if (!quiet) fprintf(stderr, "audio volume set to '%d'\n", va.volume);
- }
- if (ioctl(fd, VIDIOCSAUDIO, &va)<0) perror("VIDIOCSAUDIO");
- } else {
- if (!quiet) fprintf(stderr, "channel '%d' has no tuner (composite)\n", channel);
+
+ bktr_init (fd, w, h, &video_buf, channel);
+ if (frequency != 0.0) {
+ v4lfrequency = (unsigned long)(frequency*16);
+ if (ioctl(tuner_fd, TVTUNER_SETFREQ, &v4lfrequency)<0)
+ perror("TVTUNER_SETFREQ");
+ if (!quiet)
+ fprintf(stderr, "tuner frequency set to '%5.4f' MHz.\n", frequency);
}
- // setting video mode
- vt.tuner = 0;
- if(ioctl(fd, VIDIOCGTUNER, &vt)<0) perror("VIDIOCGTUNER");
- if (ntsc) { vt.flags |= VIDEO_TUNER_NTSC; vt.mode |= VIDEO_MODE_NTSC; }
- else if (secam) { vt.flags |= VIDEO_TUNER_SECAM; vt.mode |= VIDEO_MODE_SECAM; }
- else { vt.flags |= VIDEO_TUNER_PAL; vt.mode |= VIDEO_MODE_PAL; }
- vt.tuner = 0;
- if(ioctl(fd, VIDIOCSTUNER, &vt)<0) perror("VIDIOCSTUNER");
-
- // make sure we use the right input
- if(ioctl(fd, VIDIOCSCHAN, &vchan)<0) perror("VIDIOCSCHAN");
-
- mm.height = h;
- mm.width = w;
- mm.format = VIDEO_PALETTE_YUV420P ; /* YCrCb422 */
-
- mm.frame = 0;
- if(ioctl(fd, VIDIOCMCAPTURE, &mm)<0) perror("VIDIOCMCAPTUREi0");
- mm.frame = 1;
- if(ioctl(fd, VIDIOCMCAPTURE, &mm)<0) perror("VIDIOCMCAPTUREi1");
-
while(1) {
- frame=0;
- mm.frame = 0;
- if(ioctl(fd, VIDIOCSYNC, &frame)<0) perror("VIDIOCSYNC0");
- else {
- if(ioctl(fd, VIDIOCMCAPTURE, &mm)<0) perror("VIDIOCMCAPTURE0");
- DP("Captured 0er");
- bufferit(buf+vm.offsets[0]);
- }
- frame=1;
- mm.frame = 1;
- if(ioctl(fd, VIDIOCSYNC, &frame)<0) perror("VIDIOCSYNC1");
- else {
- if(ioctl(fd, VIDIOCMCAPTURE, &mm)<0) perror("VIDIOCMCAPTURE1");
- DP("Captured 1er");
- bufferit(buf+vm.offsets[1]);
- }
+ bktr_getframe (w, h, per_frame);
+ bufferit(video_buf);
}
#endif