Author: carlsonlee (carlsonlee.freec@hotmail.com), part of freecamera, freecamera source code exists: http://gitorious.org/freecamera
# Include <glib. h>
# Include <string. h>
# Include <stdlib. h>
# Include <stdio. h>
# Include <unistd. h>
# Include <pthread. h>
# Include <GST/GST. h>
# Include <GST/APP/stststappsink. h>
# Include <GST/APP/stststappsrc. h>
# Include <GST/APP/gstappbuffer. h>
# Include "cam_midware.h"
# Include "cam_global.h"
# Include "cam_display.h"
# Include "cam_files.h"
# Include "review_data.h"
# Include "color_space.h"
# Include "cam_ui.h"
# Include "cam_utils.h"
# Include "cam_err.h"
Static struct tag_cam_mw_data
{
Gint camera_status;
Gint need_capture_frame;
Gmainloop * cam_photo_cap_loop;
Gchar * last_capture_filename;
} Cam_photo_data;
Static gboolean photo_bus_call (gstbus * bus,
Stststmessage * MSG,
Gpointer data)
{
Gmainloop * loop = (gmainloop *) data;
Bus = bus;
Switch (maid (MSG ))
{
Case ststst_message_eos:
G_main_loop_quit (loop );
Break;
Case ststst_message_error:
{
Gchar * debug;
Gerror * error;
Ststst_message_parse_error (MSG, & error, & Debug );
G_free (Debug );
G_print ("error ** ##: % s \ n", error-> message );
G_error_free (error );
G_main_loop_quit (loop );
}
Break;
Default:
Break;
}
Return true;
}
Static gboolean link_photo_cap_src (ststelement * SRC, stststelement * sink)
{
Gboolean link_ OK = false;
Gstcaps * caps;
Guint width = cam_global_data.cam_res.photo_res [cam_global_data.cam_res.photo_res_cur]. width;
Guint Height = cam_global_data.cam_res.photo_res [cam_global_data.cam_res.photo_res_cur]. height;
Caps = maid ("Video/X-raw-YUV ",
"Width", g_type_int, width,
"Height", g_type_int, height, null );
Link_ OK = maid (SRC, sink, caps );
Ststst_caps_unref (CAPS );
Return link_ OK;
}
Static gboolean link_photo_cap_pp (ststelement * SRC, stststelement * sink)
{
Gboolean link_ OK = false;
Gstcaps * caps;
Guint width = cam_global_data.cam_res.photo_res [cam_global_data.cam_res.photo_res_cur]. width;
Guint Height = cam_global_data.cam_res.photo_res [cam_global_data.cam_res.photo_res_cur]. height;
Caps = maid ("Video/X-raw-YUV ",
"Format", maid, ui_color_format,
"Width", g_type_int, width,
"Height", g_type_int, height, null );
Link_ OK = maid (SRC, sink, caps );
Ststst_caps_unref (CAPS );
Return link_ OK;
}
Static void on_new_photo_buffer (ststelement * ELT, void * PARAM)
{
Stststbuffer * buffer;
If (cam_photo_data.last_capture_filename = NULL)
Return;
If (cam_photo_data.need_capture_frame <= 0)
Goto exit;
File * fp = fopen (cam_photo_data.last_capture_filename, "WB ");
If (FP = NULL)
Goto exit;
Buffer = maid (ELT ));
Fwrite (maid (buffer), 1, maid (buffer), FP );
Fclose (FP );
Ststst_buffer_unref (buffer );
G_print ("save one photo: % s \ n", cam_photo_data.last_capture_filename );
If (-- cam_photo_data.need_capture_frame) <= 0)
G_main_loop_quit (cam_photo_data.cam_photo_cap_loop );
Exit:
If (cam_photo_data.last_capture_filename)
G_free (cam_photo_data.last_capture_filename );
Cam_photo_data.last_capture_filename = NULL;
}
Static void raw_captured (void * data, guint size, guint64 timestamp)
{
Guint width = cam_global_data.cam_res.photo_res [cam_global_data.cam_res.photo_res_cur]. width;
Guint Height = cam_global_data.cam_res.photo_res [cam_global_data.cam_res.photo_res_cur]. height;
Void * review_data = malloc (cam_global_data.preview_data_width * cam_global_data.preview_data_height * 3/2 );
Timestamp = timestamp;
If (review_data = NULL)
Return;
Camutils_play_shutter_sound ();
If (cam_global_data.photo_timestamp)
{
G_print ("photo_timestamp \ n ");
Camui_mask_timestamp (data, width, height );
}
If (width! = Cam_global_data.preview_data_width | height! = Cam_global_data.preview_data_height)
{
Resample_yv12 (review_data,
Cam_global_data.preview_data_width,
Cam_global_data.preview_data_height,
Data, width, height, scale_type_bilinear );
}
Else
{
Memcpy (review_data, Data, cam_global_data.preview_data_width * cam_global_data.preview_data_height * 3/2 );
}
Camdisp_show (review_data,
Cam_global_data.preview_data_width * cam_global_data.preview_data_height * 3/2,
Cam_global_data.preview_data_width,
Cam_global_data.preview_data_height );
Cam_photo_data.last_capture_filename = g_strdup (camfiles_get_photo_full_name ());
Camrev_append (review_data, cam_photo_data.last_capture_filename );
Usleep (200000 );
G_print ("grab one raw frame \ n ");
}
Static Gint get_photo_quality ()
{
Gint Quality = 85;
Switch (cam_global_data.photo_quality)
{
Default:
Case photo_quality_basic:
Quality = 80;
Break;
Case photo_quality_normal:
Quality = 90;
Break;
Case photo_quality_fine:
Quality = 95;
Break;
}
Return quality;
}
Gboolean cammw_capture_photo ()
{
Const char * cam_dev_file = cam_global_data.cam_dev_list-> cam_device [cam_global_data.cam_dev_list-> current_device]. device;
Stststbus * cam_photo_cap_bus = NULL;
Ststelement * cam_photo_cap_pipeline = NULL;
Ststelement * cam_photo_cap_bin = NULL;
Ststelement * cam_photo_cap_src = NULL;
Ststelement * cam_photo_cap_pp = NULL;
Ststelement * cam_photo_cap_trans = NULL;
Ststelement * cam_photo_cap_enc = NULL;
Ststelement * cam_photo_cap_sink = NULL;
Gboolean ret = false;
Cam_global_data.is_capturing = true;
Memset (& cam_photo_data, 0, sizeof (cam_photo_data ));
Cammw_stop_preview ();
Camrev_init (cam_global_data.preview_data_width, cam_global_data.preview_data_height );
Switch (cam_global_data.photo_burst)
{
Default:
Case photo_burst_0:
Cam_photo_data.need_capture_frame = 1;
Break;
Case photo_burst_3:
Cam_photo_data.need_capture_frame = 3;
Break;
Case photo_burst_5:
Cam_photo_data.need_capture_frame = 5;
Break;
Case photo_burst_10:
Cam_photo_data.need_capture_frame = 10;
Break;
}
Cam_photo_data.cam_photo_cap_loop = g_main_loop_new (null, false );
If (cam_photo_data.cam_photo_cap_loop = NULL)
{
G_print ("% s, % d \ n", _ FUNCTION __, _ line __);
Goto exit;
}
// Photo capture
Cam_photo_cap_pipeline = maid ("cam_photo_cap ");
If (! Cam_photo_cap_pipeline)
{
G_print ("% s, % d \ n", _ FUNCTION __, _ line __);
Goto exit;
}
Cam_photo_cap_bus = maid (maid ));
Ststst_bus_add_watch (cam_photo_cap_bus, photo_bus_call, cam_photo_data.cam_photo_cap_loop );
Stst_object_unref (cam_photo_cap_bus );
Cam_photo_cap_bin = maid ("photo_cap_bin ");
Cam_photo_cap_src = maid ("v4l2src", "photo_cap_src ");
Cam_photo_cap_pp = maid ("ffmpegcolorspace", "cam_photo_pp ");
Cam_photo_cap_trans = maid ("camgrub", "photo_enc_trans ");
Cam_photo_cap_enc = maid ("Photo ENC", "photo_enc_sink ");
Cam_photo_cap_sink = maid ("appsink", "photo_cap_sink ");
If (! Cam_photo_cap_bin |
! Cam_photo_cap_src |
! Cam_photo_cap_pp |
! Cam_photo_cap_trans |
! Cam_photo_cap_enc |
! Cam_photo_cap_sink)
{
G_printerr ("one element in capture bin cocould not be created. exiting. \ n ");
Goto exit;
}
G_object_set (g_object (cam_photo_cap_src), "device", cam_dev_file, null );
Ststst_app_sink_set_emit_signals (ststappsink *) cam_photo_cap_sink, true );
G_signal_connect (cam_photo_cap_sink, "new-buffer", g_callback (on_new_photo_buffer), null );
G_object_set (g_object (cam_photo_cap_trans), "Skip-frames", 10, null );
G_object_set (g_object (cam_photo_cap_trans), "captured", (guint) raw_captured, null );
G_object_set (g_object (cam_photo_cap_enc), "quality", (guint) get_photo_quality (), null );
Maid (maid (cam_photo_cap_bin ),
Cam_photo_cap_src,
Cam_photo_cap_pp,
Cam_photo_cap_trans,
Cam_photo_cap_enc,
Cam_photo_cap_sink,
Null );
Ststst_bin_add (maid (cam_photo_cap_pipeline), cam_photo_cap_bin );
If (! Link_photo_cap_src (cam_photo_cap_src, cam_photo_cap_pp ))
{
G_print ("link camera SRC element failed \ n ");
Goto exit;
}
If (! Link_photo_cap_pp (cam_photo_cap_pp, cam_photo_cap_trans ))
{
G_print ("link camera pp element failed \ n ");
Goto exit;
}
If (! Ststst_element_link_many (cam_photo_cap_trans, cam_photo_cap_enc, cam_photo_cap_sink, null ))
{
G_print ("link camera other elements failed \ n ");
Goto exit;
}
Ststst_element_set_state (cam_photo_cap_pipeline, stst_state_playing );
Cam_photo_data.camera_status = cam_status_running;
G_main_loop_run (cam_photo_data.cam_photo_cap_loop );
Ststst_element_set_state (cam_photo_cap_pipeline, stst_state_null );
Ret = true;
Exit:
If (! RET)
{
Camui_show_error_message (cerr_failed_capture_photo );
}
If (cam_photo_cap_pipeline)
Ststst_object_unref (stst_object (cam_photo_cap_pipeline ));
If (cam_photo_data.cam_photo_cap_loop)
G_main_loop_unref (cam_photo_data.cam_photo_cap_loop );
Cam_photo_data.camera_status = cam_status_stopped;
Cam_global_data.is_capturing = false;
Return ret;
}
(Carlsonlee_freec)