#include #include #include /* * Global objects are usually a bad thing. For the purpose of this * example, we will use them, however. */ GstElement *pipeline, *source, *bin, *parser, *ff1, *text1, *text2, *text3, *text4, *text5, *ff2, *sink, *mixer, *ff3; pthread_t thread1, thread2; typedef struct _TextOverlays TextOverlays; typedef struct _ImageBinElements ImageBinElements; struct _TextOverlays{ GstElement* texts[5]; }; struct _ImageBinElements{ GstElement *bin; GstElement *filesrc; GstElement *pngdec; GstElement *videoscale; GstElement *videobox; GstElement *alpha; GstElement *ff1; GstElement *ff2; GstElement *ff3; GstCaps *pngcaps; GstCaps *scalecaps; }; static void initImageBin(ImageBinElements *ibe){ ibe->bin = gst_bin_new("image_pipe"); ibe->filesrc = gst_element_factory_make("filesrc","img-src"); ibe->pngdec = gst_element_factory_make("pngdec","img-dec"); ibe->videoscale = gst_element_factory_make("videoscale","img-scale"); ibe->videobox = gst_element_factory_make("videobox","img-box"); ibe->alpha = gst_element_factory_make("alpha","img-alpha"); ibe->ff1 = gst_element_factory_make("ffmpegcolorspace","img-ff1"); ibe->ff2 = gst_element_factory_make("ffmpegcolorspace","img-ff2"); ibe->ff3 = gst_element_factory_make("ffmpegcolorspace","img-ff3"); gst_bin_add_many(GST_BIN(ibe->bin), ibe->filesrc, ibe->pngdec, ibe->ff1, ibe->videoscale, ibe->ff2, ibe->videobox, ibe->alpha, ibe->ff3, NULL); ibe->pngcaps = gst_caps_from_string("image/png"); ibe->scalecaps = gst_caps_from_string("video/x-raw-yuv,width=72,height=54"); } static void linkImageBin(ImageBinElements *ibe){ gst_element_link_many(ibe->pngdec, ibe->ff1, ibe->videoscale, NULL); gst_element_link_many(ibe->ff2, ibe->videobox, ibe->alpha, ibe->ff3, NULL); gst_element_link_filtered(ibe->filesrc, ibe->pngdec, ibe->pngcaps); gst_element_link_filtered(ibe->videoscale, ibe->ff2, ibe->scalecaps); if(!gst_pad_is_linked(gst_element_get_pad(ibe->filesrc, "src"))) g_print("Error filesrc not linked!\n"); } TextOverlays *txt; ImageBinElements *ibm; static void init_struct1(){ txt = (TextOverlays*) malloc(sizeof(TextOverlays)); txt->texts[0] = text1; txt->texts[1] = text2; txt->texts[2] = text3; txt->texts[3] = text4; txt->texts[4] = text5; } static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GMainLoop *loop = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_print ("End-of-stream\n"); g_main_loop_quit (loop); break; case GST_MESSAGE_ERROR: { gchar *debug; GError *err; gst_message_parse_error (msg, &err, &debug); g_free (debug); g_print ("Error: %s\n", err->message); g_error_free (err); g_main_loop_quit (loop); break; } default: break; } return TRUE; } static void new_pad (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; /* We can now link this pad with the audio decoder */ g_print ("Dynamic pad created, linking parser/decoder\n"); sinkpad = gst_element_get_pad (ff1, "sink"); g_print("Linking pads\n"); gst_pad_link (pad, sinkpad); g_print("Pads were linked\n"); if(!gst_pad_is_linked(pad)){ g_print("ERROR pad was not linked!!!\n"); }else{ g_print("Dynamic pads are linked\n"); } gst_object_unref (sinkpad); } void *change(void* ptr0){ time_t start_time = time(NULL); time_t now; char a = 0; char field [20]; char command [20]; char value [20]; while(TRUE){ sleep(3); now = time(NULL); int len = scanf("%s %s %s",&field, &command, &value); printf("read input: %s\nread command: %s\nread value: %s\n", field, command, value); int param = 0; gboolean render = FALSE; if(strcmp(field, "text1") == 0){ param = 0; render = TRUE; }else if(strcmp(field, "text2") == 0){ param = 1; render = TRUE; }else if(strcmp(field, "text3") == 0){ param = 2; render = TRUE; }else if(strcmp(field, "text4") == 0){ param = 3; render = TRUE; }else if(strcmp(field, "text5") == 0){ param = 4; render = TRUE; } if(render){ if(strcmp(command, "text") == 0){ if(strcmp(value, "NULL") == 0) g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "text", "", NULL); else g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "text", value, NULL); } if(strcmp(command, "hloc") == 0){ if(!strcmp(value, "left")){ g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "halignment", 0, NULL); }else if(!strcmp(value, "center")){ g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "halignment", 1, NULL); }else if(!strcmp(value, "right")){ g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "halignment", 2, NULL); } } if(strcmp(command, "vloc") == 0){ if(!strcmp(value, "middle")){ g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "valignment", 0, NULL); }else if(!strcmp(value, "bottom")){ g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "valignment", 1, NULL); }else if(!strcmp(value, "top")){ g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "valignment", 2, NULL); } } if(strcmp(command, "dx") == 0){ int val = atoi(value); g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "deltax", val, NULL); } if(strcmp(command, "dy") == 0){ int val = atoi(value); g_object_set(G_OBJECT((GstElement*)(((TextOverlays*)ptr0)->texts[param])), "deltay", val, NULL); } } if(strcmp(field, "ready") == 0){ gst_element_set_state(pipeline ,GST_STATE_READY); } if(strcmp(field, "play") == 0){ gst_element_set_state(pipeline ,GST_STATE_PLAYING); } } } void *change2(void* ptr0){ time_t start_time = time(NULL); time_t now; double b = 0.9999; while(TRUE){ sleep(1); now = time(NULL); //if(now%3 <=1 ){ printf("New alpha value: %f\n", b); // gst_element_set_state (bin, GST_STATE_READY); //g_object_set(G_OBJECT (ptr), "left", b, "top", b, NULL); g_print("Setting new alpha value\n"); // g_object_set(G_OBJECT (ptr), "alpha", b, "method", 3, NULL); // gst_element_set_state (bin, GST_STATE_PLAYING); b=b-0.01; if(b < 0.5) b = 0.9999; if(start_time - now >= 240) break; //} } } int main (int argc, char *argv[]) { GMainLoop *loop; GstBus *bus; gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* create elements */ pipeline = gst_pipeline_new ("video-streamer"); bin = gst_bin_new ("image-loader"); source = gst_element_factory_make ("videotestsrc", "testsrc"); parser = gst_element_factory_make ("decodebin", "decoder"); ff1 = gst_element_factory_make ("ffmpegcolorspace", "ff1"); text1 = gst_element_factory_make ("textoverlay", "text1"); text2 = gst_element_factory_make ("textoverlay", "text2"); text3 = gst_element_factory_make ("textoverlay", "text3"); text4 = gst_element_factory_make ("textoverlay", "text4"); text5 = gst_element_factory_make ("textoverlay", "text5"); ff2 = gst_element_factory_make ("ffmpegcolorspace", "ff2"); mixer = gst_element_factory_make("videomixer","mixer"); ff3 = gst_element_factory_make("ffmpegcolorspace","ff6"); sink = gst_element_factory_make("autovideosink","autovsink"); ibm = (ImageBinElements*) malloc(sizeof(ImageBinElements)); initImageBin(ibm); GstCaps *pngcaps = gst_caps_from_string("image/png"); GstCaps *filter = gst_caps_from_string("video/x-raw-yuv,width=72,height=54"); if (!pipeline || !source || !parser || !ff1 || !text1 || !text2 || !text3 || !text4 || !text5 || !ff2 || !sink || !mixer || !ff3 || !ibm || !ibm->bin || !ibm->filesrc || !ibm->pngdec || !ibm->ff1 || !ibm->videoscale || !ibm->ff2 || !ibm->videobox || !ibm->alpha || !ibm->ff3) { g_print ("One element could not be created\n"); return -1; } /* set filename property on the file source. Also add a message * handler. */ g_object_set (G_OBJECT (text1), "text", "bla1", NULL); g_object_set (G_OBJECT (text1), "halignment", 0, NULL); g_object_set (G_OBJECT (text1), "valignment", 2, NULL); g_object_set (G_OBJECT (text2), "text", "bla2", NULL); g_object_set (G_OBJECT (text2), "halignment", 1, NULL); g_object_set (G_OBJECT (text2), "valignment", 2, NULL); g_object_set (G_OBJECT (ibm->filesrc), "location" ,"./NetBSD1.png", NULL); g_object_set (G_OBJECT (ibm->videobox), "left", -60, "top", -60, "border-alpha", 0.0, "alpha", 1.0, NULL); g_object_set (G_OBJECT (ibm->alpha), "alpha", 0.9999, NULL); g_object_set (G_OBJECT (mixer), "background", 2, NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); /* put all elements in a bin */ // gst_bin_add_many (GST_BIN (bin), //filesrc, pngdec, ff3, scale, ff4, box, alpha, ff7, NULL); gst_bin_add_many (GST_BIN (pipeline), source, parser, ff1, text1, text2, text3, text4, text5, ff2, sink, mixer, ff3, ibm->bin, NULL); /* link together - note that we cannot link the parser and * decoder yet, becuse the parser uses dynamic pads. For that, * we set a pad-added signal handler. */ gst_element_link (source, parser); gst_element_link_many (ff1, text1, text2, text3, text4, text5, ff2, NULL); gst_element_link_many (mixer, ff3, sink, NULL); linkImageBin(ibm); GstPad *imagesrcpad = gst_element_get_pad(ibm->ff3,"src"); GstPad *livesrcpad = gst_element_get_pad(ff2,"src"); GstPad *livesinkpad = gst_element_get_request_pad(mixer, "sink_2"); GstPad *imagesinkpad = gst_element_get_request_pad(mixer, "sink_1"); GstPadLinkReturn a = 0; a = gst_pad_link(imagesrcpad, imagesinkpad); g_print("Image link returned: %d\n", a); a = gst_pad_link(livesrcpad, livesinkpad); g_print("Live link returned: %d\n", a); g_signal_connect (parser, "pad-added", G_CALLBACK (new_pad), NULL); /* Now set to playing and iterate. */ g_print ("Running\n"); init_struct1(); pthread_create(&thread1, NULL, change, txt); //pthread_create(&thread2, NULL, change2, alpha); g_print ("Setting to PLAYING\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); printf("Looping from now\n"); g_main_loop_run (loop); /* clean up nicely */ g_print ("Returned, stopping playback\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); return 0; }