Only in motion-3.2.4_snap5: .video.c.swp
diff -ru motion-3.2.4_snap5/conf.c motion-3.2.4_snap5-pvrpatch/conf.c
--- motion-3.2.4_snap5/conf.c	2005-10-29 07:53:09.000000000 +0200
+++ motion-3.2.4_snap5-pvrpatch/conf.c	2006-02-18 01:13:56.228971576 +0100
@@ -529,6 +529,18 @@
 
 #ifdef HAVE_FFMPEG
 	{
+	"ffmpeg_device",
+	"\n############################################################\n"
+	"# Treat device as ffmpeg compliant video stream\n"
+	"############################################################\n\n"
+	"# Setting this flag treats the device specified previously\n"
+	"# as an ffmpeg compliant video stream. This could be a mpeg1,\n"
+	"# mpeg2, mpeg4, divx, xvid, or other compliant video stream.\n",
+	CONF_OFFSET(ffmpeg_device),
+	copy_bool,
+	print_bool
+	},
+	{
 	"ffmpeg_cap_new",
 	"\n############################################################\n"
 	"# Film (mpeg) File Output - ffmpeg based\n"
diff -ru motion-3.2.4_snap5/conf.h motion-3.2.4_snap5-pvrpatch/conf.h
--- motion-3.2.4_snap5/conf.h	2005-10-29 07:06:17.000000000 +0200
+++ motion-3.2.4_snap5-pvrpatch/conf.h	2006-02-18 01:13:56.229971424 +0100
@@ -55,6 +55,7 @@
 	int pre_capture;
 	int post_capture;
 	int switchfilter;
+	int ffmpeg_device;
 	int ffmpeg_cap_new;
 	int ffmpeg_cap_motion;
 	int ffmpeg_bps;
diff -ru motion-3.2.4_snap5/video.c motion-3.2.4_snap5-pvrpatch/video.c
--- motion-3.2.4_snap5/video.c	2006-02-18 01:49:03.147704216 +0100
+++ motion-3.2.4_snap5-pvrpatch/video.c	2006-02-18 01:39:24.665646856 +0100
@@ -711,10 +711,190 @@
 }
 #endif /*WITHOUT_V4L*/
 
+#ifdef HAVE_FFMPEG
+static unsigned char *ffmpeg_start(struct context *cnt, struct video_dev *viddev, int input, int norm)
+{
+	int dev=viddev->fd;
+    	int err=0, i=0, width=0, height=0;
+	viddev->fcx = NULL;
+	viddev->ccx = NULL;
+	viddev->codec = NULL;
+	viddev->ffmpeg_video_index = -1;
+	struct video_channel vid_chnl;
+
+	if (input != IN_DEFAULT) {
+		memset(&vid_chnl, 0, sizeof(struct video_channel));
+		vid_chnl.channel = input;
+		if (ioctl (dev, VIDIOCGCHAN, &vid_chnl) == -1) {
+			motion_log(LOG_ERR, 1, "ioctl (VIDIOCGCHAN)");
+		} else {
+			vid_chnl.channel = input;
+			vid_chnl.norm    = norm;
+			if (ioctl (dev, VIDIOCSCHAN, &vid_chnl) == -1) {
+				motion_log(LOG_ERR, 1, "ioctl (VIDIOCSCHAN)");
+				return (NULL);
+			}
+		}
+	}
+	// Open the input file.
+	motion_log(LOG_DEBUG, 0, "Openning ffmpeg video stream device: %s", viddev->video_device);
+	err = av_open_input_file(&viddev->fcx, viddev->video_device, NULL, 0, &viddev->params);
+	if(err<0){
+		motion_log(LOG_ERR, 1, "Fatal: Can't open video device (%s) using ffmpeg", viddev->video_device);
+		motion_log(LOG_ERR, 1, "Motion Exits");
+		exit(-1);
+	}
+
+	// Find the stream info.
+	err = av_find_stream_info(viddev->fcx);
+	if(err<0) {
+ 		motion_log(LOG_ERR, 0, "Fatal: Could not locate ffmpeg stream info.");
+ 		motion_log(LOG_ERR, 1, "Motion Exits");
+ 		exit(-1);
+ 	}
+
+		// Find the first video stream.
+ 	motion_log(LOG_DEBUG, 0, "Found %d ffmpeg streams.", viddev->fcx->nb_streams);
+ 	for(i=0; i<viddev->fcx->nb_streams; i++){
+ 		viddev->ccx=&viddev->fcx->streams[i]->codec;
+ 		if(viddev->ccx->codec_type==CODEC_TYPE_VIDEO) break;
+ 	}
+ 	viddev->ffmpeg_video_index=i;
+ 	motion_log(LOG_DEBUG, 0, "Obtained ffmpeg video_index (%d).", viddev->ffmpeg_video_index);
+
+    
+	// Open stream.
+ 	if(viddev->ffmpeg_video_index>=0){
+  		viddev->codec = avcodec_find_decoder(viddev->ccx->codec_id);
+ 		if(viddev->codec)
+ 			err = avcodec_open(viddev->ccx, viddev->codec);
+		if(err<0) {
+ 			motion_log(LOG_ERR, 1, "Fatal: Can't open ffmpeg codec");
+ 			motion_log(LOG_ERR, 1, "Motion Exits");
+     			av_close_input_file(viddev->fcx);
+ 			exit(-1); 
+ 		} else {
+ 			motion_log(LOG_DEBUG, 0, "Found ffmpeg video stream codec: %s", viddev->codec->name);
+ 		}
+ 	} else {
+ 		motion_log(LOG_ERR, 1, "Fatal: ffmpeg video stream not found");
+ 		motion_log(LOG_ERR, 1, "Motion Exits");
+     		av_close_input_file(viddev->fcx);
+ 		exit(-1);
+ 	}
+ 	width = viddev->ccx->width;
+ 	height = viddev->ccx->height;
+ 	motion_log(LOG_DEBUG, 0, "Size of image: %d x %d x 3/2 = %d.", width, height, (width*height*3)/2);
+ 	viddev->ffmpeg_fmt=VIDEO_PALETTE_YUV420P;
+	viddev->ffmpeg_bufsize=(width*height*3)/2;
+  	viddev->ffmpeg_maxbuffer=1;
+  	viddev->ffmpeg_curbuffer=0;
+  	viddev->ffmpeg_buffers[0]=mymalloc((width*height*3)/2);
+  	viddev->ffmpeg_buffers[1]=mymalloc((width*height*3)/2);
+
+	return viddev->ffmpeg_buffers[0];
+}
+
+static int ffmpeg_next(struct video_dev *viddev, unsigned char *map)
+{
+	int len1=0, got_picture=0;
+    	unsigned char *cap_map;
+	AVPicture av_pict;
+	AVPacket av_pkt;
+	AVFrame *av_frame=avcodec_alloc_frame();
+
+	int curbuf = 0, err = 0;
+	
+	viddev->ffmpeg_curbuffer++;
+	if (viddev->ffmpeg_curbuffer > viddev->ffmpeg_maxbuffer)
+		viddev->ffmpeg_curbuffer=0;
+	curbuf=viddev->ffmpeg_curbuffer;
+	cap_map=viddev->ffmpeg_buffers[curbuf];
+	
+	while(!got_picture) {
+		if(!viddev->fcx) {
+			motion_log(LOG_ERR, 0, "NULL pointer for AVFrameContext viddev->fcx.");
+			motion_log(LOG_ERR, 0, "Motion Exits");
+			exit(-1);
+		}
+		err = av_read_frame(viddev->fcx, &av_pkt);
+		switch(err) {
+			case AVERROR_UNKNOWN:
+				motion_log(LOG_ERR, 1, "Unknown error reading AVFrame");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+				break;
+			case AVERROR_IO:
+				motion_log(LOG_ERR, 1, "IO error reading AVFrame");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+				break;
+			case AVERROR_NUMEXPECTED:
+				motion_log(LOG_ERR, 1, "Number syntax expected in file name while reading AVFrame");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+				break;
+			case AVERROR_INVALIDDATA:
+				motion_log(LOG_ERR, 1, "Invalid data while reading AVFrame");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+				break;
+			case AVERROR_NOMEM:
+				motion_log(LOG_ERR, 1, "Out of memory while reading AVFrame");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+				break;
+			case AVERROR_NOFMT:
+				motion_log(LOG_ERR, 1, "Unkown format while reading AVFrame");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+				break;
+			case AVERROR_NOTSUPP:
+				motion_log(LOG_ERR, 1, "Operation not supported while reading AVFrame");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+				break;
+			default:
+				break;
+		}
+		if(av_pkt.stream_index==viddev->ffmpeg_video_index) {
+			if(!viddev->ccx) {
+				motion_log(LOG_ERR, 0, "NULL pointer for AVCodecContext viddev->ccx.");
+				motion_log(LOG_ERR, 0, "Motion Exits");
+				exit(-1);
+			}
+			len1 = avcodec_decode_video(viddev->ccx, av_frame, &got_picture, av_pkt.data, av_pkt.size);
+		}
+	}
+	if (got_picture) {
+		avpicture_alloc(&av_pict, PIX_FMT_YUV420P, viddev->ccx->width, viddev->ccx->height);
+
+		img_convert(&av_pict, PIX_FMT_YUV420P, (AVPicture*) av_frame, viddev->ccx->pix_fmt, viddev->ccx->width, viddev->ccx->height);
+
+		memset(map, 0, (viddev->ccx->width*viddev->ccx->height*3)/2);
+		memcpy(map, av_pict.data[0], (viddev->ccx->width*viddev->ccx->height*3)/2);
+	} else {
+		motion_log(LOG_WARNING, 0, "Fatal: Unable to decode video packets into frame.");
+		exit(-1);
+	}
+
+        av_free_packet(&av_pkt);
+	
+        // Clean up
+        avpicture_free(&av_pict);
+        av_free(av_frame);
+	// FIXME: This should be closed before exiting motion
+    	// av_close_input_file(av_fcx);
+
+	return 0;
+}
+
+#endif
+
 /**
  * vid_start
  *
- * vid_start setup the capture device. This will be either a V4L device or a netcam.
+ * vid_start setup the capture device. This will be either a V4L device or a netcam or an mpeg stream.
  * The function does the following:
  * - If the camera is a netcam - netcam_start is called and function returns
  * - Width and height are checked for valid value (multiple of 16)
@@ -722,7 +902,7 @@
  *   only copied to the from the conf struct to the imgs struct during program startup
  *   The width and height can no leter be changed via http remote control as this would
  *   require major re-memory allocations of all image buffers.
- * - Setup basic V4L properties incl palette incl setting 
+ * - Setup basic V4L or ffmpeg stream properties incl palette incl setting 
  * - Open the device
  * - Returns the device number.
  *
@@ -743,35 +923,119 @@
 {
 	struct config *conf = &cnt->conf;
 	int dev = -1;
+	int i=-1, width=0, height=0, input=0, norm=0;
 
 	if (conf->netcam_url) {
 		return netcam_start(cnt);
 	}
 
-#ifndef WITHOUT_V4L
-	/* Start a new block so we can make declarations without breaking good old
-	 * gcc 2.95 or older.
+	/* We use width and height from conf in this function. They will be assigned
+	 * to width and height in imgs here, and cap_width and cap_height in 
+	 * rotate_data won't be set until in rotate_init.
+	 * Motion requires that width and height is a multiple of 16 so we check
+	 * for this first.
 	 */
-	{
-		int i = -1;
-		int width, height, input, norm, tuner_number;
-		unsigned long frequency;
+	if (conf->width % 16) {
+		motion_log(LOG_ERR, 0,
+		           "config image width (%d) is not modulo 16",
+		           conf->width);
+		return -1;
+	}
+	if (conf->height % 16) {
+		motion_log(LOG_ERR, 0,
+			   "config image height (%d) is not modulo 16",
+			   conf->height);
+		return -1;
+	}
+#ifdef HAVE_FFMPEG
+	if (conf->ffmpeg_device) {
+		cnt->imgs.width=conf->width;
+		cnt->imgs.height=conf->height;
+		input = conf->input;
+		norm = conf->norm;
+		pthread_mutex_lock(&vid_mutex);
+		while (viddevs[++i]) {
+			if (!strcmp(conf->video_device, viddevs[i]->video_device)) {
+				int fd;
+				cnt->imgs.type=viddevs[i]->ffmpeg_fmt;
+				switch (cnt->imgs.type) {
+					case VIDEO_PALETTE_GREY:
+						cnt->imgs.motionsize=width*height;
+						cnt->imgs.size=width*height;
+						break;
+					case VIDEO_PALETTE_RGB24:
+					case VIDEO_PALETTE_YUV422:
+						cnt->imgs.type=VIDEO_PALETTE_YUV420P;
+					case VIDEO_PALETTE_YUV420P:
+						cnt->imgs.motionsize=width*height;
+						cnt->imgs.size=(width*height*3)/2;
+						break;
+				}
+				fd=viddevs[i]->fd;
+				pthread_mutex_unlock(&vid_mutex);
+				motion_log(LOG_DEBUG, 0, "Found viddev %d using image size of %d.", i, cnt->imgs.size);
+				return fd;
+			}
+		}
+		viddevs=myrealloc(viddevs, sizeof(struct video_dev *)*(i+2), "vid_start");
+		viddevs[i]=mymalloc(sizeof(struct video_dev));
+		memset(viddevs[i], 0, sizeof(struct video_dev));
+		viddevs[i+1]=NULL;
 
-		/* We use width and height from conf in this function. They will be assigned
-		 * to width and height in imgs here, and cap_width and cap_height in 
-		 * rotate_data won't be set until in rotate_init.
-		 * Motion requires that width and height is a multiple of 16 so we check
-		 * for this first.
-		 */
-		if (conf->width % 16) {
-			motion_log(LOG_ERR, 0, "config image width (%d) is not modulo 16", conf->width);
-			return -1;
+		pthread_mutexattr_init(&viddevs[i]->attr);
+		pthread_mutex_init(&viddevs[i]->mutex, NULL);
+
+		dev=open(conf->video_device, O_RDWR);
+		if (dev <0) {
+			motion_log(LOG_ERR, 1, "Failed to open video device %s", conf->video_device);
+			motion_log(LOG_ERR, 0, "Motion Exits");
+			exit(1);
 		}
+		viddevs[i]->fd = dev;
+		viddevs[i]->brightness=0;
+		viddevs[i]->contrast=0;
+		viddevs[i]->saturation=0;
+		viddevs[i]->hue=0;
+		viddevs[i]->owner=-1;
 
-		if (conf->height % 16) {
-			motion_log(LOG_ERR, 0, "config image height (%d) is not modulo 16", conf->height);
+		viddevs[i]->ffmpeg_fmt=VIDEO_PALETTE_YUV420P;
+		viddevs[i]->video_device = conf->video_device;
+
+		if(!ffmpeg_start(cnt, viddevs[i], input, norm)) {
+			motion_log(LOG_DEBUG, 0, "Failed in ffmpeg_start.");
+			pthread_mutex_unlock(&vid_mutex);
 			return -1;
 		}
+		cnt->imgs.type=viddevs[i]->ffmpeg_fmt;
+		width = viddevs[i]->ccx->width;
+		height = viddevs[i]->ccx->height;
+		cnt->imgs.width=width;
+		cnt->imgs.height=height;
+		switch (cnt->imgs.type) {
+			case VIDEO_PALETTE_GREY:
+				cnt->imgs.size=width*height;
+				cnt->imgs.motionsize=width*height;
+			break;
+			case VIDEO_PALETTE_RGB24:
+			case VIDEO_PALETTE_YUV422:
+				cnt->imgs.type=VIDEO_PALETTE_YUV420P;
+			case VIDEO_PALETTE_YUV420P:
+				cnt->imgs.size=(width*height*3)/2;
+				cnt->imgs.motionsize=width*height;
+			break;
+		}
+		pthread_mutex_unlock(&vid_mutex);
+		motion_log(LOG_DEBUG, 0, "Started ffmpeg stream with image size of %d and motionsize %d.", cnt->imgs.size, cnt->imgs.motionsize);
+		return dev;
+	}
+#endif
+#ifndef WITHOUT_V4L
+	/* Start a new block so we can make declarations without breaking good old
+	 * gcc 2.95 or older.
+	 */
+	{
+		int tuner_number;
+		unsigned long frequency;
 
 		width = conf->width;
 		height = conf->height;
@@ -902,7 +1166,9 @@
 int vid_next(struct context *cnt, unsigned char *map)
 {
 	struct config *conf=&cnt->conf;
-	int ret = -1;		
+	int ret = -1;
+        int i = -1;
+        int dev = cnt->video_dev;
 
 	if (conf->netcam_url) {
 		if (cnt->video_dev == -1)
@@ -911,15 +1177,41 @@
 		ret = netcam_next(cnt, map);
 		return ret;
 	}
+#ifdef HAVE_FFMPEG
+	if(conf->ffmpeg_device) {
+		while (viddevs[++i])
+			if (viddevs[i]->fd==dev)
+				break;
+
+		if (!viddevs[i])
+			return -1;
+
+		if (viddevs[i]->owner != cnt->threadnr) {
+			pthread_mutex_lock(&viddevs[i]->mutex);
+			viddevs[i]->owner = cnt->threadnr;
+			viddevs[i]->frames = conf->roundrobin_frames;
+			cnt->switched = 1;
+		}
+		map = ffmpeg_next(viddevs[i], map);
+		if (--viddevs[i]->frames <= 0) {
+			viddevs[i]->owner = -1;
+			pthread_mutex_unlock(&viddevs[i]->mutex);
+		}
+		if(cnt->rotate_data.degrees > 0) {
+			/* rotate the image as specified */
+			rotate_map(cnt, map);
+		}
+		return (int)map;
+	}
+#endif
+
 #ifndef WITHOUT_V4L
 
 	/* We start a new block so we can make declarations without breaking
 	 * gcc 2.95 or older
 	 */
 	{
-		int i = -1;
 		int width, height;
-		int dev = cnt->video_dev;
 
 		/* NOTE: Since this is a capture, we need to use capture dimensions. */
 		width = cnt->rotate_data.cap_width;
diff -ru motion-3.2.4_snap5/video.h motion-3.2.4_snap5-pvrpatch/video.h
--- motion-3.2.4_snap5/video.h	2005-10-30 12:41:52.000000000 +0100
+++ motion-3.2.4_snap5-pvrpatch/video.h	2006-02-18 01:13:56.237970208 +0100
@@ -13,6 +13,9 @@
 #define _LINUX_TIME_H 1
 #ifndef WITHOUT_V4L
 #include <linux/videodev.h>
+#ifdef HAVE_FFMPEG
+#include <ffmpeg/avformat.h>
+#endif
 #endif
 
 /* video4linux stuff */
@@ -63,6 +66,19 @@
 	int v4l_maxbuffer;
 	int v4l_bufsize;
 #endif
+#ifdef HAVE_FFMPEG
+	AVFormatContext * fcx;
+	AVCodecContext * ccx;
+	AVCodec * codec;
+	AVFormatParameters params;
+	unsigned char *ffmpeg_buffers[2];
+	int ffmpeg_fmt;
+	int ffmpeg_video_index;
+	int ffmpeg_curbuffer;
+	int ffmpeg_maxbuffer;
+	int ffmpeg_bufsize;
+#endif
+	    
 };
 
 /* video functions, video.c */
