feat: basic-torial-8 finish
parent
8c0acdf21a
commit
c1a4909fd9
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"files.associations": {
|
"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-2.c)
|
||||||
# add_executable(${PROJECT_NAME} basic-tutorial-3.c)
|
# add_executable(${PROJECT_NAME} basic-tutorial-3.c)
|
||||||
# add_executable(${PROJECT_NAME} basic-tutorial-6.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}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
gstreamer-1.0
|
gstreamer-1.0
|
||||||
gobject-2.0
|
gobject-2.0
|
||||||
glib-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
|
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/build
|
||||||
.PHONY : BasicTutorial/fast
|
.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
|
# target to build an object file
|
||||||
basic-tutorial-7.c.o:
|
basic-tutorial-8.c.o:
|
||||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-7.c.o
|
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-8.c.o
|
||||||
.PHONY : basic-tutorial-7.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
|
# target to preprocess a source file
|
||||||
basic-tutorial-7.c.i:
|
basic-tutorial-8.c.i:
|
||||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-7.c.i
|
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-8.c.i
|
||||||
.PHONY : basic-tutorial-7.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
|
# target to generate assembly for a file
|
||||||
basic-tutorial-7.c.s:
|
basic-tutorial-8.c.s:
|
||||||
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-7.c.s
|
$(MAKE) -f CMakeFiles/BasicTutorial.dir/build.make CMakeFiles/BasicTutorial.dir/basic-tutorial-8.c.s
|
||||||
.PHONY : basic-tutorial-7.c.s
|
.PHONY : basic-tutorial-8.c.s
|
||||||
|
|
||||||
# Help Target
|
# Help Target
|
||||||
help:
|
help:
|
||||||
|
@ -159,9 +159,9 @@ help:
|
||||||
@echo "... rebuild_cache"
|
@echo "... rebuild_cache"
|
||||||
@echo "... edit_cache"
|
@echo "... edit_cache"
|
||||||
@echo "... BasicTutorial"
|
@echo "... BasicTutorial"
|
||||||
@echo "... basic-tutorial-7.o"
|
@echo "... basic-tutorial-8.o"
|
||||||
@echo "... basic-tutorial-7.i"
|
@echo "... basic-tutorial-8.i"
|
||||||
@echo "... basic-tutorial-7.s"
|
@echo "... basic-tutorial-8.s"
|
||||||
.PHONY : help
|
.PHONY : help
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue