Initial commit
[jamendo] / branches / nota-show-app / src / gstapplication.c
1 /***************************************************************************
2  *            gstapplication.c
3  *
4  *  Wed Nov 18 15:06:29 2009
5  *  Copyright  2009  marcin
6  *  <marcin.miklas@teleca.com>
7  ****************************************************************************/
8
9 #include <gst/gst.h>
10 #include <gst/app/gstappsink.h>
11 #include <signal.h>
12
13 #include "notaio.h"
14 #include "pdu.h"
15
16
17 typedef struct
18 {
19   GstElement *pipe;
20   GstElement *src;
21   GstElement *flt;
22   GstElement *vfl;
23   GstElement *vrt;
24   GstElement *enc;
25   GstElement *sink;
26
27   gboolean stop;
28 } App;
29
30 void quitHandler(int sig);
31 void pipeline_init(App *app, gboolean start);
32 void pipeline_cleanup(App* app);
33
34 App s_app;
35
36 int main(int argc, char* argv[])
37 {
38         App* app = &s_app;
39         int frame_counter = 0;
40         ServiceMessage* smsg;
41         int smsg_len = 0;
42
43         /* Service socket to use for connecting to the service node. */
44         HSSockID sockid;
45         HErrorCode err;
46
47         /* The first parameter specifies the service to connect to (SID).
48          * The other parameters are reserved for legacy purposes.
49          */
50         sockid = n_connect(DEFAULT_SID, NULL, NULL);
51
52         /* sockid will be the number of the socket we got (>0), if successful,
53          * or <0 if something went wrong. Let's check:
54          */
55         if (sockid < 0) {
56                 return -1;
57         }
58
59         printf("Connected socket %d to service '%d'.\n", sockid, DEFAULT_SID);
60
61         gst_init (&argc, &argv);
62         pipeline_init(app, TRUE);
63
64         printf("gstreamer pipeline started\n");
65
66         // register CTRL+C handling
67         signal(SIGINT, quitHandler);
68
69         // flip image
70         if(argc>1 && argv[1][0]=='f')
71                 g_object_set(G_OBJECT(app->vfl), "method",  2, NULL);
72
73         while (!app->stop && !gst_app_sink_is_eos (GST_APP_SINK (app->sink))) {
74                 GstBuffer *buf;
75
76                 frame_counter += 1;
77
78                 buf = gst_app_sink_pull_buffer (GST_APP_SINK (app->sink));
79                 smsg = pack_pdu(PUT_IMAGE, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf), &smsg_len);
80                 gst_buffer_unref (buf);
81
82                 /* Send the through the socket specified by sockid. The last parameter, 
83                  * HSSendBlocking, means we will
84                  * use blocking mode, i.e. the call to Hsend will only return once all
85                  * data has been sent (or an error is detected).
86                  */
87                 err = n_send(sockid, smsg, smsg_len, HSSendBlocking);
88                 free(smsg);
89                 if(err < 0){
90                         return -1;
91                 }
92
93                 /* If no error condition was raised, Hsend will return the
94                  * number of bytes sent. Let's check this against what we
95                  * intended to send, just to be sure (with a blocking call, the
96                      * return value should always be equal to the "data_len" parameter
97                  * of Hsend).
98                  */
99                 if (err == smsg_len)
100                         printf("Frame %5d send.\n",frame_counter);
101                 else
102                         printf("Sent %d out of %d bytes.\n", err, smsg_len);
103
104         }
105
106         pipeline_cleanup (app);
107
108         smsg = pack_pdu (DISCONNECT,NULL, 0, &smsg_len);
109         n_send(sockid, smsg, smsg_len, HSSendBlocking);
110         free(smsg);
111
112         n_disconnect(sockid);
113         
114         return 0;
115 }
116
117 void quitHandler(int sig) {
118         printf("\nStopping...\n");
119         s_app.stop = TRUE;
120 }
121
122 void pipeline_init(App *app, gboolean start) {
123         GstCaps* flt_caps = gst_caps_new_simple ("video/x-raw-yuv",
124               "width", G_TYPE_INT, 320,
125               "height", G_TYPE_INT, 240,
126               "framerate", GST_TYPE_FRACTION, 10, 1,
127               NULL);
128         
129         app->pipe = gst_pipeline_new (NULL);
130         app->src = gst_element_factory_make ("v4l2src", NULL);
131         app->flt = gst_element_factory_make ("capsfilter", "flt");
132         g_object_set (G_OBJECT (app->flt), "caps", flt_caps, NULL);
133         app->vrt = gst_element_factory_make ("videorate", "vr");
134         app->vfl = gst_element_factory_make ("videoflip", "vfl");
135         g_object_set(G_OBJECT(app->vfl), "method",  0, NULL);
136         app->enc = gst_element_factory_make ("jpegenc", NULL);
137         app->sink = gst_element_factory_make ("appsink", NULL);
138
139         gst_bin_add_many (GST_BIN (app->pipe), app->src, app->flt, app->vrt, app->vfl, app->enc, app->sink, NULL);
140         gst_element_link_many (app->src, app->flt, app->vrt, app->vfl, app->enc, app->sink, NULL);
141
142         if (start) 
143                 gst_element_set_state (app->pipe, GST_STATE_PLAYING);
144 }
145
146 void pipeline_cleanup(App* app) {
147         gst_element_set_state (app->pipe, GST_STATE_NULL);
148         //TODO free pipeline
149 }