cheese r711 - in branches/cheese-vala: . src



Author: jhaitsma
Date: Sun May  4 21:34:48 2008
New Revision: 711
URL: http://svn.gnome.org/viewvc/cheese?rev=711&view=rev

Log:
More webcam stuff implemented

Modified:
   branches/cheese-vala/   (props changed)
   branches/cheese-vala/src/Makefile.am
   branches/cheese-vala/src/cheese-webcam.vala

Modified: branches/cheese-vala/src/Makefile.am
==============================================================================
--- branches/cheese-vala/src/Makefile.am	(original)
+++ branches/cheese-vala/src/Makefile.am	Sun May  4 21:34:48 2008
@@ -42,7 +42,7 @@
 	$(cheese_VALASOURCES:.vala=.h) 
 
 cheese.vala.stamp: $(cheese_VALASOURCES)
-	$(VALAC) -C -g $(VALA_CFLAGS) $^
+	$(VALAC) -C $(VALA_CFLAGS) $^
 	touch $@
 
 cheese_LDADD = \

Modified: branches/cheese-vala/src/cheese-webcam.vala
==============================================================================
--- branches/cheese-vala/src/cheese-webcam.vala	(original)
+++ branches/cheese-vala/src/cheese-webcam.vala	Sun May  4 21:34:48 2008
@@ -40,8 +40,7 @@
 		DICE            = (1 << 9),
 		WARP            = (1 << 10)
 	}
-	
-	
+		
 	public class FrameRate : GLib.Object {
 		public int numerator;
 		public int denominator;
@@ -107,6 +106,11 @@
 		}
 	}
 
+	public string udi { get; construct; }
+	int cur_device_num = -1;
+	VideoFormat cur_video_format;
+	FrameRate cur_frame_rate;
+	
 	ArrayList<Device> devices = new ArrayList<Device> ();
 	Pipeline pipeline; 
   	Gst.Bus  bus;
@@ -129,29 +133,19 @@
 	Element effect_filter;
 	Element csp_post_effect;
 
-	ulong photo_handler_signal_id;
+	ulong photo_handler_id;
 
-	bool is_recording;
-	bool pipeline_is_playing;
+	bool is_recording = false;
+	bool pipeline_is_playing = false;
 	string photo_filename;
 	
 	/* Dummy variable used to increase ref count */
 	Element sink_ref;
+		
 /*    
   XF86VidModeGamma normal_gamma;
   float flash_intensity;
 */
-	int num_webcam_devices;
-	string device_name;
-  /*
-	CheeseWebcamDevice *webcam_devices;
-  int x_resolution;
-  int y_resolution;
-  int selected_device;
-  CheeseVideoFormat *current_format;
-  GHashTable *supported_resolutions;
-
-*/
 	public Webcam (Widget window) {
 		this.video_window = window;
 	}
@@ -159,9 +153,28 @@
 	public void setup () {
 		detect_webcam_devices ();
 		print_devices ();
+		create_video_display_bin ();
+		create_photo_save_bin ();
+		create_video_save_bin ();
+
+		pipeline = new Pipeline ("pipeline");
+
+		pipeline.add_many (video_display_bin, photo_save_bin);
+		bool ok;
+		ok = video_display_bin.link (photo_save_bin);
+
+		var bus = pipeline.get_bus ();
+		bus.add_signal_watch ();
+		
+		bus.message += on_bus_message;
+		if (!ok)
+			error ("Unable link pipeline for photo");
+
+		threads_enter();
+		// FIXME XF86VidModeGetGamma (GDK_DISPLAY (), 0, &(priv->normal_gamma));
+		threads_leave();		
 	}
-	
-	
+		
 	void print_devices () {
 		int i = 0;
 		print ("Following devices have been detected\n");
@@ -181,23 +194,39 @@
 				}
 				print ("\n");
 			}
-
 		}
 	}
 	
 	public void play () {
+		pipeline.set_state (State.PLAYING);
+		set_x_overlay ();
+		pipeline_is_playing = true;		
 	}
 
 	public void stop () {
+		pipeline.set_state (State.NULL);
+		pipeline_is_playing = false;		
 	}
 
-	public void start_recording (string filename) {
+	public void start_recording (string filename) {		
+		video_file_sink.set ("location", filename);
+		change_sink (video_display_bin, video_save_bin, photo_save_bin);
+		is_recording = true;
 	}
 
 	public void stop_recording () {
+		/* Send EOS message down the pipeline by stopping video and audio source*/
+		video_source.set_state (State.NULL);
+		video_source.set_locked_state (true);
+		audio_source.set_state (State.NULL);
+		audio_source.set_locked_state (true);		
 	}
 
 	public void take_photo (string filename) {
+		photo_filename = filename;		
+		/* Take the photo by connecting the handoff signal */
+		photo_handler_id = Signal.connect (photo_sink, "handoff", (GLib.Callback)on_photo_data, this);		
+		flash ();
 	}
 
 	public ArrayList<Device> get_devices () {
@@ -218,12 +247,37 @@
 		set_x_overlay ();
 	}
 	
-	void on_photo_data (Element element, Buffer buffer, Pad pad) {
+
+	void on_photo_data (Element element, Buffer buffer, Pad pad) {		
+		var caps = buffer.get_caps ();
+		weak Structure structure;
+		structure = caps.get_structure (0);
+		int width, height;
+		structure.get_int ("width", out width);
+		structure.get_int ("height", out height);
+
+		int stride = (int)buffer.size/height;
+		var pixbuf = new Pixbuf.from_data (buffer.data, Colorspace.RGB, 
+						   false, 8, width, height, stride, 
+						   null);
+
+		pixbuf.save (photo_filename, "jpeg");
+		/* Emit photo_saved signal */
+		photo_saved ();
 		
+		SignalHandler.disconnect (photo_sink, photo_handler_id);
 	}
 	
 	void on_bus_message (Gst.Bus bus, Message message) {
-		
+		if (message.type == Gst.MessageType.EOS) {
+			/* Emit video saved signal */
+			video_saved ();
+
+			video_source.set_locked_state (false);
+			audio_source.set_locked_state (false);
+			change_sink (video_display_bin, photo_save_bin, video_save_bin);
+			is_recording = false;  
+		}
 	}
 
 	void get_video_devices_from_hal () throws WebcamError {
@@ -433,22 +487,142 @@
 		}
 	}
 	
-	bool create_webcam_source_bin () {
-		return false;
+	void create_webcam_source_bin () throws WebcamError {
+		if (devices.size == 0) {
+			// FIXME: throw error
+			webcam_source_bin = (Gst.Bin)parse_bin_from_description ("videotestsrc name=video_source ! capsfilter name=capsfilter ! identity", true);
+		} else {
+			/* If we have a matching video device use that one, otherwise use the first */
+			cur_device_num = 0;
+			for (int i = 1; i < devices.size; i++) {
+				if (devices[i].udi == udi)
+					cur_device_num = i;
+			}
+			
+			int max_res = 0;
+			/* Select highest resolution */
+			foreach (VideoFormat format in devices[cur_device_num].video_format) {
+				if (format.width > max_res) {
+					max_res = format.width;
+					cur_video_format = format;
+				}
+			}
+			float max_frame_rate = 0.0f;
+			/* Select highest frame rate */
+			foreach (FrameRate frame_rate in cur_video_format.frame_rate) {
+				float f = (float)frame_rate.numerator / frame_rate.denominator;
+				if (f > max_frame_rate) {
+					max_frame_rate = f;
+					cur_frame_rate = frame_rate;
+				}
+			}
+			var webcam_input = "%s name=video_source device=%s ! capsfilter name=capsfilter caps=%s,width=%d,height=%d,framerate=%d/%d ! identity".printf (
+                                    devices[cur_device_num].gstreamer_element_name,
+                                    devices[cur_device_num].device,
+                                    cur_video_format.mime_type,
+                                    cur_video_format.width,
+                                    cur_video_format.height,
+                                    cur_frame_rate.numerator,
+                                    cur_frame_rate.denominator);
+			print ("%s\n", webcam_input);
+			// FIXME: throw error
+			webcam_source_bin = (Gst.Bin)parse_bin_from_description (webcam_input, true);
+
+		}
+		video_source = webcam_source_bin.get_by_name ("video_source");
+		capsfilter = webcam_source_bin.get_by_name ("capsfilter");					
 	}
-	
-	bool create_video_display_bin () {
-		return false;
+
+	void create_video_display_bin () throws WebcamError {		
+		video_display_bin = new Gst.Bin ("video_display_bin");
+		create_webcam_source_bin ();
+		
+		effect_filter = ElementFactory.make ("identity", "effect");
+		csp_post_effect = ElementFactory.make ("ffmpegcolorspace", "csp_post_effect");
+
+		var tee = ElementFactory.make ("tee", "tee");
+		var save_queue = ElementFactory.make ("queue", "save_queue");
+		var video_display_queue = ElementFactory.make ("queue", "video_display_queue");
+
+		var video_scale = ElementFactory.make ("videoscale", "video_scale");
+		/* Use bilinear scaling */
+		video_scale.set ("method", 1);
+
+		var video_sink = ElementFactory.make ("gconfvideosink", "video_sink");
+
+		video_display_bin.add_many (webcam_source_bin, effect_filter, csp_post_effect, 
+					    tee, save_queue, video_display_queue, video_scale, video_sink);
+		bool ok;
+		ok = webcam_source_bin.link_many (effect_filter, csp_post_effect, tee);
+		ok &= tee.link_many (save_queue);
+		ok &= tee.link_many (video_display_queue, video_scale, video_sink);
+		
+		if (!ok)
+			throw new WebcamError.FAILED ("create_video_display_bin (): Error linking gstreamer elements together");
+
+		/* add ghostpad */
+		var pad = save_queue.get_pad ("src");
+		video_display_bin.add_pad (new GhostPad("src", pad));		
 	}
 
-	bool create_photo_save_bin () {
-		return false;
+	void create_photo_save_bin () throws WebcamError {
+		photo_save_bin = new Gst.Bin ("photo_save_bin");
+		var csp_photo_save_bin = ElementFactory.make ("ffmpegcolorspace", "csp_photo_save_bin");
+		photo_sink = ElementFactory.make ("fakesink", "photo_sink");
+
+		photo_save_bin.add_many (csp_photo_save_bin,photo_sink);
+
+		/* add ghostpad */
+		var pad = csp_photo_save_bin.get_pad ("sink");
+		photo_save_bin.add_pad (new GhostPad ("sink", pad));
+
+		var caps = new Caps.simple ("video/x-raw-rgb", "bpp", typeof (int), 24,
+      					    "depth", typeof (int), 24);
+		bool ok;
+		ok = csp_photo_save_bin.link_filtered (photo_sink, caps);
+		if (!ok)
+			throw new WebcamError.FAILED ("create_photo_save_bin (): Error linking gstreamer elements together");
+
+		photo_sink.set ("signal-handoffs", true);		
 	}
 	
-	bool create_video_save_bin () {
-		return false;
+	void create_video_save_bin () throws WebcamError {
+		video_save_bin = new Gst.Bin ("video_save_bin");
+
+		audio_source = ElementFactory.make ("gconfaudiosrc", "audio_source");
+		var audio_queue = ElementFactory.make ("queue", "audio_queue");
+		var audio_convert = ElementFactory.make ("audioconvert", "audio_convert");      
+		var audio_enc = ElementFactory.make ("vorbisenc", "audio_enc");
+
+		var video_save_csp = ElementFactory.make ("ffmpegcolorspace", "video_save_csp");
+		var video_enc = ElementFactory.make ("theoraenc", "video_enc");
+		video_enc.set ("keyframe-force", 1);
+		var video_save_scale = ElementFactory.make ("videoscale", "video_save_scale");
+		/* Use bilinear scaling */
+		video_save_scale.set ("method", 1);
+
+		var mux = ElementFactory.make ("oggmux", "mux");
+		video_file_sink = ElementFactory.make ("filesink", "video_file_sink");
+
+		video_save_bin.add_many (audio_source, audio_queue, audio_convert, 
+					 audio_enc, video_save_csp, video_save_scale, video_enc, 
+				         mux, video_file_sink);
+
+		/* add ghostpad */
+		var pad = video_save_csp.get_pad ("sink");
+		video_save_bin.add_pad (new GhostPad ("sink", pad));
+		bool ok;
+		ok = audio_source.link_many (audio_queue, audio_convert, audio_enc, mux,
+					     video_file_sink);
+
+		ok &= video_save_csp.link_many (video_save_scale, video_enc);
+		ok &= video_enc.link (mux);
+		if (!ok)
+			throw new WebcamError.FAILED ("create_video_save_bin (): Error linking gstreamer elements together");		
 	}
-	void flash_set_intensity (float intesity) {
+	
+	
+	void flash_set_intensity (float intensity) {
 		
 	}
 	void on_flash_dim () {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]