您的位置:首页 > 运维架构 > 网站架构

linux下webcam进行拍照, gstreamer架构

2013-01-14 09:26 134 查看
author: CarlsonLee(carlsonlee.freec@hotmail.com),  本代码是freecamera的一部分,freecamera源代码存在: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/gstappsink.h>

#include <gst/app/gstappsrc.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,

                       GstMessage *msg,

                       gpointer    data)

{

    GMainLoop *loop = (GMainLoop *) data;

    bus = bus;

    switch (GST_MESSAGE_TYPE (msg))

    {

    case GST_MESSAGE_EOS:

        g_main_loop_quit (loop);

        break;

    case GST_MESSAGE_ERROR:

        {

            gchar *debug;

            GError *error;

            gst_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(GstElement *src, GstElement *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 = gst_caps_new_simple ("video/x-raw-yuv",

            "width", G_TYPE_INT, width,

            "height", G_TYPE_INT, height, NULL);

    link_ok = gst_element_link_filtered (src, sink, caps);

    gst_caps_unref (caps);

    return link_ok;

}

static gboolean link_photo_cap_pp(GstElement *src, GstElement *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 = gst_caps_new_simple ("video/x-raw-yuv",

            "format", GST_TYPE_FOURCC, UI_COLOR_FORMAT,

            "width", G_TYPE_INT, width,

            "height", G_TYPE_INT, height, NULL);

    link_ok = gst_element_link_filtered (src, sink, caps);

    gst_caps_unref (caps);

    return link_ok;

}

static void on_new_photo_buffer(GstElement * elt, void* param)

{

      GstBuffer *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 = gst_app_sink_pull_buffer (GST_APP_SINK (elt));

      fwrite(GST_BUFFER_DATA(buffer), 1, GST_BUFFER_SIZE(buffer), fp);

      fclose(fp);

      gst_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;

    GstBus      *cam_photo_cap_bus = NULL;

    GstElement  *cam_photo_cap_pipeline = NULL;

    GstElement     *cam_photo_cap_bin = NULL;

    GstElement  *cam_photo_cap_src = NULL;

    GstElement     *cam_photo_cap_pp = NULL;

    GstElement     *cam_photo_cap_trans = NULL;

    GstElement     *cam_photo_cap_enc = NULL;

    GstElement     *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 = gst_pipeline_new ("cam_photo_cap");

    if(!cam_photo_cap_pipeline)

    {

        g_print("%s, %d\n", __FUNCTION__, __LINE__);  

        goto exit;

    }

    cam_photo_cap_bus = gst_pipeline_get_bus (GST_PIPELINE (cam_photo_cap_pipeline));

    gst_bus_add_watch (cam_photo_cap_bus, photo_bus_call, cam_photo_data.cam_photo_cap_loop);

    gst_object_unref (cam_photo_cap_bus);

    

    cam_photo_cap_bin     = gst_bin_new("photo_cap_bin");

    cam_photo_cap_src    = gst_element_factory_make ("v4l2src",    "photo_cap_src");

    cam_photo_cap_pp        = gst_element_factory_make ("ffmpegcolorspace",    "cam_photo_pp");

    cam_photo_cap_trans   = gst_element_factory_make ("camgrub","photo_enc_trans");

    cam_photo_cap_enc   = gst_element_factory_make ("jpegenc","photo_enc_sink");

    cam_photo_cap_sink   = gst_element_factory_make ("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 could not be created. Exiting.\n");

        goto exit ;

    }

    g_object_set (G_OBJECT (cam_photo_cap_src), "device", cam_dev_file, NULL);

    gst_app_sink_set_emit_signals((GstAppSink *)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);

    

    gst_bin_add_many (GST_BIN (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);

    

    gst_bin_add (GST_BIN (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(!gst_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;

      }    

    gst_element_set_state (cam_photo_cap_pipeline, GST_STATE_PLAYING);

    cam_photo_data.camera_status = CAM_STATUS_RUNNING;

    g_main_loop_run(cam_photo_data.cam_photo_cap_loop);

    gst_element_set_state (cam_photo_cap_pipeline, GST_STATE_NULL);    

    ret = TRUE;

exit:

    if(!ret)

    {

        camui_show_error_message(CERR_FAILED_CAPTURE_PHOTO);

    }

    if(cam_photo_cap_pipeline)

        gst_object_unref (GST_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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: