Last active
November 23, 2021 14:16
-
-
Save paulbarber/7d2e43d1e3365b2042aa to your computer and use it in GitHub Desktop.
Test of GStreamer saving to file from C code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gst-launch-1.0 videotestsrc num-buffers=100 ! tee name=t ! queue ! videoconvert ! xvimagesink sync=false t. ! queue ! videorate ! video/x-raw,framerate=25/1 ! videoconvert ! avenc_mpeg2video bitrate=3000000 ! avimux ! filesink location=test_file.avi async=0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef HAVE_CONFIG_H | |
#include "config.h" | |
#endif | |
#include "gst-app.h" | |
int | |
main (int argc, char *argv[]) | |
{ | |
// Before calling any GLib or GStreamer function, we must initialise | |
// the GLib threading system | |
if (!g_thread_supported()) | |
g_thread_init (NULL); | |
gst_init(&argc, &argv); | |
// For this test, just go straight to playing some pipeline | |
play_camera(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright (C) 2006 Tim-Philipp Müller <tim centricular net> | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a | |
* copy of this software and associated documentation files (the "Software"), | |
* to deal in the Software without restriction, including without limitation | |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
* and/or sell copies of the Software, and to permit persons to whom the | |
* Software is furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
* DEALINGS IN THE SOFTWARE. | |
* | |
* Alternatively, the contents of this file may be used under the | |
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in | |
* which case the following provisions apply instead of the ones | |
* mentioned above: | |
* | |
* This library is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Library General Public | |
* License as published by the Free Software Foundation; either | |
* version 2 of the License, or (at your option) any later version. | |
* | |
* This library is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Library General Public License for more details. | |
* | |
* You should have received a copy of the GNU Library General Public | |
* License along with this library; if not, write to the | |
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
* Boston, MA 02111-1307, USA. | |
*/ | |
#include "play.h" | |
static GMainLoop *loop; | |
static gboolean | |
my_bus_callback (GstBus *bus, GstMessage *message, gpointer data) | |
{ | |
g_print("Got %s message from %s\n", GST_MESSAGE_TYPE_NAME(message), GST_MESSAGE_SRC_NAME(message)); | |
switch (GST_MESSAGE_TYPE(message)) { | |
case GST_MESSAGE_ERROR: { | |
GError *err; | |
gchar *debug; | |
gst_message_parse_error (message, &err, &debug); | |
g_print ("Error: %s (%s)\n", err->message, debug); | |
g_error_free(err); | |
g_free(debug); | |
g_main_loop_quit(loop); | |
break; | |
} | |
case GST_MESSAGE_EOS: | |
g_main_loop_quit(loop); | |
break; | |
default: | |
break; | |
} | |
return TRUE; // continue to watch for messages | |
} | |
void | |
play_camera(void) | |
{ | |
GstBus *bus; | |
guint bus_watch_id; | |
GstElement *pipeline; | |
GstElement *videoconvert1, *videoconvert2; | |
GstElement *sink; | |
GstElement *tee; | |
GstElement *frameratefilter, *videorate; | |
GstElement *queue1, *queue2; | |
GstElement *avenc, *avimux; | |
GstElement *filesink; | |
GstElement *source; | |
GstPadTemplate *tee_src_pad_template; | |
GstPad *teepad1, *teepad2, *qpad1, *qpad2; | |
// The full video pipeline | |
pipeline = gst_pipeline_new("VideoPipeline"); | |
// Create pipeline elements | |
source = gst_element_factory_make("videotestsrc", NULL); | |
videoconvert1 = gst_element_factory_make("videoconvert", "videoconvert1"); | |
videoconvert2 = gst_element_factory_make("videoconvert", "videoconvert2"); | |
queue1 = gst_element_factory_make("queue", "queue1"); | |
queue2 = gst_element_factory_make("queue", "queue2"); | |
tee = gst_element_factory_make("tee", "tee"); | |
sink = gst_element_factory_make("xvimagesink", NULL); | |
frameratefilter = gst_element_factory_make("capsfilter", NULL); | |
videorate = gst_element_factory_make("videorate", NULL); | |
avenc = gst_element_factory_make("avenc_mpeg2video", NULL); | |
avimux = gst_element_factory_make("avimux", NULL); | |
filesink = gst_element_factory_make("filesink", NULL); | |
// check the elements | |
if(!source || !videoconvert1 || !videoconvert2 || !queue1 || !queue2 || !tee || !sink || !filesink){ | |
g_error("Creation of one element failed."); | |
return; | |
} | |
// Set parameters for some elements | |
g_object_set(G_OBJECT(source), "num-buffers", 100, NULL); | |
g_object_set(G_OBJECT(filesink), "location", "AFileFromCode.avi", "async", 0, NULL); | |
g_object_set(G_OBJECT(frameratefilter), "caps", gst_caps_from_string("video/x-raw,framerate=25/1"), NULL); | |
g_print ("Add elements to a bin ... \n"); | |
gst_bin_add_many(GST_BIN(pipeline), source, videoconvert1, videoconvert2, queue1, queue2, tee, sink, frameratefilter, videorate, avenc, avimux, filesink, NULL); | |
g_print ("and link them ... \n"); | |
if (!gst_element_link_many(source, tee, NULL)) | |
g_error("Failed to link source elements!"); | |
if (!gst_element_link_many(queue1, videoconvert1, sink, NULL)) | |
g_error("Failed to link display elements!"); | |
if (!gst_element_link_many(queue2, videorate, frameratefilter, videoconvert2, avenc, avimux, filesink, NULL)) | |
g_error("Failed to link save elements!"); | |
if ( !(tee_src_pad_template = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (tee), "src_%u"))) { | |
g_critical ("Unable to get pad template!"); | |
return; | |
} | |
// get the queue pads and request some source pads from the tee | |
qpad1 = gst_element_get_static_pad(queue1, "sink"); | |
qpad2 = gst_element_get_static_pad(queue2, "sink"); | |
teepad1 = gst_element_request_pad (tee, tee_src_pad_template, NULL, NULL); | |
g_print ("Obtained request pad %s for queue1 branch.\n", gst_pad_get_name (teepad1)); | |
teepad2 = gst_element_request_pad (tee, tee_src_pad_template, NULL, NULL); | |
g_print ("Obtained request pad %s for queue2 branch.\n", gst_pad_get_name (teepad2)); | |
if(!teepad1 || !teepad2 || !qpad1 || !qpad2){ | |
g_error("Creation of one tee pad failed."); | |
return; | |
} | |
gst_pad_link (teepad1, qpad1); | |
gst_pad_link (teepad2, qpad2); | |
gst_object_unref (GST_OBJECT (qpad1)); | |
gst_object_unref (GST_OBJECT (qpad2)); | |
gst_object_unref (GST_OBJECT (teepad1)); | |
gst_object_unref (GST_OBJECT (teepad2)); | |
// Output a dot file of the pipeline | |
// Be sure to $ export GST_DEBUG_DUMP_DOT_DIR=/tmp | |
// and run with the --gst-enable-gst-debug command line switch | |
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline_graph"); | |
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); | |
bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL); | |
gst_object_unref(bus); | |
g_print ("Play the pipeline ... \n"); | |
gst_element_set_state(pipeline, GST_STATE_PLAYING); | |
// To receive messages on the bus callback, start a main loop here, and unref below | |
g_print ("Start g_main_loop ... \n"); | |
loop = g_main_loop_new(NULL, FALSE); | |
g_main_loop_run(loop); | |
g_print ("Stop the pipeline ... \n"); | |
gst_element_set_state(pipeline, GST_STATE_NULL); | |
gst_object_unref (pipeline); | |
g_main_loop_unref(loop); | |
return; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _MY_APP_PLAY_H_INCLUDED_ | |
#define _MY_APP_PLAY_H_INCLUDED_ | |
#include <gst/gst.h> | |
void play_camera(void); | |
#endif /* _MY_APP_PLAY_H_INCLUDED_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment