feat: basic-torial-8 finish

master
邱棚 2023-02-18 15:41:47 +00:00
parent 8c0acdf21a
commit c1a4909fd9
4 changed files with 238 additions and 20 deletions

View File

@ -1,5 +1,6 @@
{
"files.associations": {
"gst.h": "c"
"gst.h": "c",
"audio.h": "c"
}
}

View File

@ -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
)

215
basic-tutorial-8.c Normal file
View File

@ -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;
}

View File

@ -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