feat: basic-torial-8 finish
parent
8c0acdf21a
commit
c1a4909fd9
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"gst.h": "c"
|
||||
"gst.h": "c",
|
||||
"audio.h": "c"
|
||||
}
|
||||
}
|
|
@ -10,10 +10,12 @@ include_directories(/usr/lib/aarch64-linux-gnu/glib-2.0/include)
|
|||
# add_executable(${PROJECT_NAME} basic-tutorial-2.c)
|
||||
# add_executable(${PROJECT_NAME} basic-tutorial-3.c)
|
||||
# add_executable(${PROJECT_NAME} basic-tutorial-6.c)
|
||||
add_executable(${PROJECT_NAME} basic-tutorial-7.c)
|
||||
# add_executable(${PROJECT_NAME} basic-tutorial-7.c)
|
||||
add_executable(${PROJECT_NAME} basic-tutorial-8.c)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
gstreamer-1.0
|
||||
gobject-2.0
|
||||
glib-2.0
|
||||
gstaudio-1.0
|
||||
)
|
|
@ -0,0 +1,215 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gst/audio/audio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHUNK_SIZE 1024
|
||||
#define SAMPLE_RATE 44100
|
||||
|
||||
typedef struct _CustomData
|
||||
{
|
||||
GstElement *pipeline,*app_source,*tee,*audio_queue,*audio_convert1,*audio_resample,*audio_sink;
|
||||
GstElement *video_queue,*audio_convert2,*visual,*video_convert,*video_sink;
|
||||
GstElement *app_queue,*app_sink;
|
||||
|
||||
guint64 num_samples;
|
||||
gfloat a,b,c,d;
|
||||
|
||||
guint sourceid;
|
||||
|
||||
GMainLoop *main_loop;
|
||||
}CustomData;
|
||||
|
||||
static gboolean push_data(CustomData *data)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn ret;
|
||||
int i;
|
||||
GstMapInfo map;
|
||||
gint16 *raw;
|
||||
gint num_samples = CHUNK_SIZE / 2;
|
||||
gfloat freq;
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (CHUNK_SIZE);
|
||||
|
||||
GST_BUFFER_TIMESTAMP(buffer) = gst_util_uint64_scale(data->num_samples,GST_SECOND,SAMPLE_RATE);
|
||||
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale(num_samples,GST_SECOND,SAMPLE_RATE);
|
||||
|
||||
gst_buffer_map(buffer, &map,GST_MAP_WRITE);
|
||||
raw = (gint16 *)map.data;
|
||||
data->c +=data->d;
|
||||
data->d -=data->c /1000;
|
||||
freq = 1100 + 1000 * data->d;
|
||||
for(i = 0;i<num_samples;i++)
|
||||
{
|
||||
data->a +=data->b;
|
||||
data->b -=data->a / freq;
|
||||
raw[i] = (gint16)(500 * data->a );
|
||||
}
|
||||
gst_buffer_unmap(buffer, &map);
|
||||
data->num_samples += num_samples;
|
||||
|
||||
g_signal_emit_by_name(data->app_source,"push-buffer",buffer,&ret);
|
||||
|
||||
gst_buffer_unref(buffer);
|
||||
|
||||
if(ret != GST_FLOW_OK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void start_feed(GstElement *source, guint size, CustomData *data)
|
||||
{
|
||||
if(data->sourceid == 0)
|
||||
{
|
||||
g_print("Start feeding\n");
|
||||
data->sourceid = g_idle_add((GSourceFunc) push_data,data);
|
||||
}
|
||||
}
|
||||
|
||||
static void stop_feed(GstElement *source,CustomData *data)
|
||||
{
|
||||
if(data->sourceid != 0)
|
||||
{
|
||||
g_print("Stop feeding\n");
|
||||
g_source_remove(data->sourceid);
|
||||
data->sourceid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static GstFlowReturn new_sample(GstElement *sink,CustomData *data)
|
||||
{
|
||||
GstSample *sample;
|
||||
|
||||
g_signal_emit_by_name(sink,"pull-sample",&sample);
|
||||
if(sample)
|
||||
{
|
||||
g_print("*");
|
||||
gst_sample_unref(sample);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
static void error_cb(GstBus *bus,GstMessage *msg,CustomData *data)
|
||||
{
|
||||
GError *err;
|
||||
gchar *debug_info;
|
||||
|
||||
gst_message_parse_error(msg,&err,&debug_info);
|
||||
g_printerr("Error received from element %s: %s\n",GST_OBJECT_NAME(msg->src),err->message);
|
||||
g_printerr("Debugging information: %s\n",debug_info ? debug_info : "none");
|
||||
g_clear_error(&err);
|
||||
g_free(debug_info);
|
||||
|
||||
g_main_loop_quit(data->main_loop);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
CustomData data;
|
||||
GstPad *tee_audio_pad,*tee_video_pad,*tee_app_pad;
|
||||
GstPad *queue_audio_pad,*queue_video_pad,*queue_app_pad;
|
||||
GstAudioInfo info;
|
||||
GstCaps *audio_caps;
|
||||
GstBus *bus;
|
||||
|
||||
memset(&data,0,sizeof(data));
|
||||
data.b = 1;
|
||||
data.d = 1;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
|
||||
data.app_source = gst_element_factory_make("appsrc","audio_source");
|
||||
data.tee = gst_element_factory_make("tee","tee");
|
||||
data.audio_queue = gst_element_factory_make("queue","audio_queue");
|
||||
data.audio_convert1 = gst_element_factory_make("audioconvert","audio_convert1");
|
||||
data.audio_resample = gst_element_factory_make("audioresample","audio_resample");
|
||||
data.audio_sink = gst_element_factory_make("autoaudiosink","audio_sink");
|
||||
data.video_queue = gst_element_factory_make("queue","video_queue");
|
||||
data.audio_convert2 = gst_element_factory_make("audioconvert","audio_convert2");
|
||||
data.visual = gst_element_factory_make("wavescope","visual");
|
||||
data.video_convert = gst_element_factory_make("videoconvert","video_convert");
|
||||
data.video_sink = gst_element_factory_make("autovideosink","video_sink");
|
||||
data.app_queue = gst_element_factory_make("queue","app_queue");
|
||||
data.app_sink = gst_element_factory_make("appsink","app_sink");
|
||||
|
||||
data.pipeline = gst_pipeline_new("test-pipeline");
|
||||
|
||||
if( !data.pipeline || !data.app_source || !data.tee || !data.audio_queue || !data.audio_convert1 || !data.audio_resample
|
||||
|| !data.audio_resample || !data.audio_sink || !data.video_queue || !data.audio_convert2 || !data.visual
|
||||
|| !data.video_convert || !data.video_sink || !data.app_queue || !data.app_sink)
|
||||
{
|
||||
g_printerr("Not all element could be created.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_object_set (data.visual,"shader",0,"style",0,NULL);
|
||||
|
||||
gst_audio_info_set_format(&info,GST_AUDIO_FORMAT_S16, SAMPLE_RATE,1,NULL);
|
||||
audio_caps = gst_audio_info_to_caps(&info);
|
||||
g_object_set(data.app_source,"caps",audio_caps,"format",GST_FORMAT_TIME,NULL);
|
||||
g_signal_connect(data.app_source,"need-data",G_CALLBACK(start_feed),&data);
|
||||
g_signal_connect(data.app_source,"enough-data",G_CALLBACK(stop_feed),&data);
|
||||
|
||||
g_object_set(data.app_sink,"emit-signals",TRUE,"caps",audio_caps,NULL);
|
||||
g_signal_connect(data.app_sink,"new-sample",G_CALLBACK(new_sample),&data);
|
||||
gst_caps_unref(audio_caps);
|
||||
|
||||
gst_bin_add_many(GST_BIN(data.pipeline),data.app_source,data.tee,data.audio_queue,
|
||||
data.audio_convert1,data.audio_resample,data.audio_sink,data.video_queue,
|
||||
data.audio_convert2,data.visual,data.video_convert,data.video_sink,
|
||||
data.app_queue,data.app_sink,NULL);
|
||||
if(gst_element_link_many (data.app_source,data.tee,NULL) != TRUE ||
|
||||
gst_element_link_many (data.audio_queue,data.audio_convert1,data.audio_resample,data.audio_sink,NULL) != TRUE ||
|
||||
gst_element_link_many (data.video_queue,data.audio_convert2,data.visual,data.video_convert,data.video_sink,NULL) != TRUE ||
|
||||
gst_element_link_many (data.app_queue,data.app_sink,NULL) != TRUE)
|
||||
{
|
||||
g_printerr("ELements could not be linked.\n");
|
||||
gst_object_unref(data.pipeline);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tee_audio_pad = gst_element_get_request_pad(data.tee,"src_%u");
|
||||
g_print("Obtained request pad %s for audio branch.\n",gst_pad_get_name(tee_audio_pad));
|
||||
queue_audio_pad = gst_element_get_static_pad(data.audio_queue,"sink");
|
||||
tee_video_pad = gst_element_get_request_pad(data.tee,"src_%u");
|
||||
g_print("Obtained request pad %s for video branch.\n",gst_pad_get_name(tee_video_pad));
|
||||
queue_video_pad = gst_element_get_static_pad(data.video_queue,"sink");
|
||||
tee_app_pad = gst_element_get_request_pad(data.tee,"src_%u");
|
||||
g_print("Obtained request pad %s for app branch.\n",gst_pad_get_name(tee_app_pad));
|
||||
queue_app_pad = gst_element_get_static_pad(data.app_queue,"sink");
|
||||
if(gst_pad_link(tee_audio_pad,queue_audio_pad) != GST_PAD_LINK_OK ||
|
||||
gst_pad_link(tee_video_pad,queue_video_pad) != GST_PAD_LINK_OK ||
|
||||
gst_pad_link(tee_app_pad,queue_app_pad) != GST_PAD_LINK_OK)
|
||||
{
|
||||
g_printerr("Tee could not be linked\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gst_object_unref(queue_audio_pad);
|
||||
gst_object_unref(queue_video_pad);
|
||||
gst_object_unref(queue_app_pad);
|
||||
|
||||
bus = gst_element_get_bus(data.pipeline);
|
||||
gst_bus_add_signal_watch(bus);
|
||||
g_signal_connect(G_OBJECT(bus),"message::error",(GCallback)error_cb,&data);
|
||||
gst_object_unref(bus);
|
||||
|
||||
gst_element_set_state(data.pipeline,GST_STATE_PLAYING);
|
||||
|
||||
data.main_loop = g_main_loop_new(NULL,FALSE);
|
||||
g_main_loop_run(data.main_loop);
|
||||
|
||||
gst_element_release_request_pad(data.tee,tee_audio_pad);
|
||||
gst_element_release_request_pad(data.tee,tee_video_pad);
|
||||
gst_element_release_request_pad(data.tee,tee_app_pad);
|
||||
gst_object_unref(tee_audio_pad);
|
||||
gst_object_unref(tee_video_pad);
|
||||
gst_object_unref(tee_app_pad);
|
||||
|
||||
gst_element_set_state(data.pipeline,GST_STATE_NULL);
|
||||
gst_object_unref(data.pipeline);
|
||||
return 0;
|
||||
}
|
|
@ -123,32 +123,32 @@ BasicTutorial/fast:
|
|||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/build
|
||||
.PHONY : BasicTutorial/fast
|
||||
|
||||
basic-tutorial-7.o: basic-tutorial-7.c.o
|
||||
basic-tutorial-8.o: basic-tutorial-8.c.o
|
||||
|
||||
.PHONY : basic-tutorial-7.o
|
||||
.PHONY : basic-tutorial-8.o
|
||||
|
||||
# target to build an object file
|
||||
basic-tutorial-7.c.o:
|
||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-7.c.o
|
||||
.PHONY : basic-tutorial-7.c.o
|
||||
basic-tutorial-8.c.o:
|
||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-8.c.o
|
||||
.PHONY : basic-tutorial-8.c.o
|
||||
|
||||
basic-tutorial-7.i: basic-tutorial-7.c.i
|
||||
basic-tutorial-8.i: basic-tutorial-8.c.i
|
||||
|
||||
.PHONY : basic-tutorial-7.i
|
||||
.PHONY : basic-tutorial-8.i
|
||||
|
||||
# target to preprocess a source file
|
||||
basic-tutorial-7.c.i:
|
||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-7.c.i
|
||||
.PHONY : basic-tutorial-7.c.i
|
||||
basic-tutorial-8.c.i:
|
||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-8.c.i
|
||||
.PHONY : basic-tutorial-8.c.i
|
||||
|
||||
basic-tutorial-7.s: basic-tutorial-7.c.s
|
||||
basic-tutorial-8.s: basic-tutorial-8.c.s
|
||||
|
||||
.PHONY : basic-tutorial-7.s
|
||||
.PHONY : basic-tutorial-8.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
basic-tutorial-7.c.s:
|
||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-7.c.s
|
||||
.PHONY : basic-tutorial-7.c.s
|
||||
basic-tutorial-8.c.s:
|
||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-8.c.s
|
||||
.PHONY : basic-tutorial-8.c.s
|
||||
|
||||
# Help Target
|
||||
help:
|
||||
|
@ -159,9 +159,9 @@ help:
|
|||
@echo "... rebuild_cache"
|
||||
@echo "... edit_cache"
|
||||
@echo "... BasicTutorial"
|
||||
@echo "... basic-tutorial-7.o"
|
||||
@echo "... basic-tutorial-7.i"
|
||||
@echo "... basic-tutorial-7.s"
|
||||
@echo "... basic-tutorial-8.o"
|
||||
@echo "... basic-tutorial-8.i"
|
||||
@echo "... basic-tutorial-8.s"
|
||||
.PHONY : help
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue