gpt4 book ai didi

c - GStreamer appsrc 到文件示例

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:41:35 24 4
gpt4 key购买 nike

我想将音频缓冲区写入文件。

问题是文件始终为空或应用程序立即停止并显示内部数据流错误

例子是:

https://gist.github.com/nzjrs/725122/16ceee88aafae389bab207818e0661328921e1ab

http://gstreamer-devel.966125.n4.nabble.com/appsrc-to-filesink-td970865.html

由他们组成:

#include <string.h>

#include <gst/gst.h>

#include <gst/app/gstappsrc.h>

/*
* an example application of using appsrc in push mode to create a video file.
* from buffers we push into the pipeline.
*/

/* Video resolution: 80 x 60 x 4 = 80x60 pixels, 32 bpp (4 bytes per pixel) = 19200 bytes */
#define BUFFER_SIZE 19200

/* 300 frames = 10 seconds of video, since we are going to save at 30fps (se the video_caps next) */
#define TOTAL_FRAMES 30000

#define QUEUED_FRAMES 30

/* these are the caps we are going to pass through the appsrc */
const gchar *video_caps =
"video/x-raw,format=RGB,width=80,height=60,bpp=32,endianness=4321,depth=24,red_mask=65280,green_mask=16711680,blue_mask=-16777216,framerate=30/1";

typedef struct
{
GMainLoop *loop;
GstElement *pipeline;
GstElement *source;
guint source_id;
guint num_frame;
} AppData;

/* This method is called by the idle GSource in the mainloop. We feed 1 buffer
* of BUFFER_SIZE bytes into appsrc.
* The ide handler is added to the mainloop when appsrc requests us to start
* sending data (need-data signal) and is removed when appsrc has enough data
* (enough-data signal).
*/
static gboolean
push_buffer (AppData * app)
{
gpointer raw_buffer;
GstBuffer *app_buffer;
GstMemory *mem;
GstFlowReturn ret;

app->num_frame++;

if (app->num_frame >= TOTAL_FRAMES) {
/* we are EOS, send end-of-stream and remove the source */
g_signal_emit_by_name (app->source, "end-of-stream", &ret);
return FALSE;
}

app_buffer = gst_buffer_new();

mem = gst_allocator_alloc (NULL, BUFFER_SIZE, NULL);

gst_buffer_append_memory(app_buffer, mem);

gst_buffer_set_size(app_buffer, BUFFER_SIZE);

/* Setting the correct timestamp for the buffer is very important, otherwise the
* resulting video file won't be created correctly */
GST_BUFFER_TIMESTAMP(app_buffer) = (GstClockTime)((app->num_frame / 30.0) * 1e9);

/* push new buffer */
g_signal_emit_by_name (app->source, "push-buffer", app_buffer, &ret);

gst_buffer_unref(app_buffer);

if (ret != GST_FLOW_OK) {
/* some error, stop sending data */
return FALSE;
}

return TRUE;
}

/* This signal callback is called when appsrc needs data, we add an idle handler
* to the mainloop to start pushing data into the appsrc */
static void
start_feed (GstElement * pipeline, guint size, AppData * app)
{
if (app->source_id == 0) {
g_print ("start feeding at frame %i\n", app->num_frame);
app->source_id = g_idle_add ((GSourceFunc) push_buffer, app);
}
}

/* This callback is called when appsrc has enough data and we can stop sending.
* We remove the idle handler from the mainloop */
static void
stop_feed (GstElement * pipeline, AppData * app)
{
if (app->source_id != 0) {
g_print ("stop feeding at frame %i\n", app->num_frame);
g_source_remove (app->source_id);
app->source_id = 0;
}
}

/* called when we get a GstMessage from the pipeline when we get EOS, we
* exit the mainloop and this testapp. */
static gboolean
on_pipeline_message (GstBus * bus, GstMessage * message, AppData * app)
{
GstState state, pending;

switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_EOS:
g_print ("Received End of Stream message\n");
g_main_loop_quit (app->loop);
break;
case GST_MESSAGE_ERROR:
{
g_print ("Received error\n");

GError *err = NULL;
gchar *dbg_info = NULL;

gst_message_parse_error (message, &err, &dbg_info);
g_printerr ("ERROR from element %s: %s\n",
GST_OBJECT_NAME (message->src), err->message);
g_printerr ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
g_error_free (err);
g_free (dbg_info);
}

g_main_loop_quit (app->loop);
break;
case GST_MESSAGE_STATE_CHANGED:
gst_element_get_state(app->source, &state, &pending, GST_CLOCK_TIME_NONE);
/* g_print ("State changed from %i to %i\n", state, pending); */
break;
default:
break;
}
return TRUE;
}

int
main (int argc, char *argv[])
{
AppData *app = NULL;
gchar *string = NULL;
GstBus *bus = NULL;
GstElement *appsrc = NULL;

gst_init (&argc, &argv);

app = g_new0 (AppData, 1);

app->loop = g_main_loop_new (NULL, FALSE);

/* setting up pipeline, we push video data into this pipeline that will
* then be recorded to an avi file, encoded with the h.264 codec*/
string =
g_strdup_printf ("appsrc is-live=true name=source caps=\"%s\" ! ffmpegcolorspace ! video/x-raw,format=(fourcc)I420,width=80,height=60 ! queue ! videorate ! video/x-raw,format=YUV,framerate=30/1 ! h264enc ! queue ! avimux ! queue ! filesink location=test.avi",
video_caps);
app->pipeline = gst_parse_launch (string, NULL);
g_free (string);

if (app->pipeline == NULL) {
g_print ("Bad pipeline\n");
return -1;
}

appsrc = gst_bin_get_by_name (GST_BIN (app->pipeline), "source");
/* configure for time-based format */
g_object_set (appsrc, "format", GST_FORMAT_TIME, NULL);
/* setting maximum of bytes queued. default is 200000 */
gst_app_src_set_max_bytes((GstAppSrc *)appsrc, QUEUED_FRAMES * BUFFER_SIZE);
/* uncomment the next line to block when appsrc has buffered enough */
/* g_object_set (appsrc, "block", TRUE, NULL); */
app->source = appsrc;

/* add watch for messages */
bus = gst_element_get_bus (app->pipeline);
gst_bus_add_watch (bus, (GstBusFunc) on_pipeline_message, app);
gst_object_unref (bus);

/* configure the appsrc, we will push data into the appsrc from the
* mainloop */
g_signal_connect (app->source, "need-data", G_CALLBACK (start_feed), app);
g_signal_connect (app->source, "enough-data", G_CALLBACK (stop_feed), app);

/* go to playing and wait in a mainloop */
gst_element_set_state (app->pipeline, GST_STATE_PLAYING);

/* this mainloop is stopped when we receive an error or EOS */
g_print ("Creating movie...\n");
g_main_loop_run (app->loop);
g_print ("Done.\n");

gst_app_src_end_of_stream (GST_APP_SRC (app->source));

gst_element_set_state (app->pipeline, GST_STATE_NULL);

/* Cleaning up */
gst_object_unref (app->source);
gst_object_unref (app->pipeline);
g_main_loop_unref (app->loop);
g_free (app);

return 0;
}

CMakeLists.txt(将FindGStreamer.cmake放入项目的modules/目录):

cmake_minimum_required(VERSION 2.8.11)

project(myproject)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/modules/")

find_package(GStreamer 1.0 REQUIRED COMPONENTS
app
audio
video
)

add_executable(${PROJECT_NAME}
main.c
)

target_include_directories(${PROJECT_NAME} PRIVATE ${GSTREAMER_INCLUDE_DIRS})
target_include_directories(${PROJECT_NAME} PRIVATE ${GSTREAMER_APP_INCLUDE_DIRS})

target_link_libraries(${PROJECT_NAME}
${GSTREAMER_LIBRARIES}
${GSTREAMER_APP_LIBRARIES}
${GSTREAMER_AUDIO_LIBRARIES}
${GSTREAMER_VIDEO_LIBRARIES}
glib-2.0
gobject-2.0
)

实际上,我的程序的流水线是:

appsrc is-live=true name=mysource ! flacenc ! oggmux ! filesink location=flac-audio.ogg

但我正在努力使示例按原样工作

最佳答案

使用 --gst-debug-level=2 启动很有用。提示 caps 字符串。

#include <string.h>

#include <gst/gst.h>

#include <gst/app/gstappsrc.h>

/*
* an example application of using appsrc in push mode to create a file.
* from buffers we push into the pipeline.
*/

/* S16LE 10ms frame audio */
#define BUFFER_SIZE 160

/* 300 frames = 5 minutes */
#define TOTAL_FRAMES 30000

#define QUEUED_FRAMES 30

typedef struct
{
GMainLoop *loop;
GstElement *pipeline;
GstElement *source;
guint source_id;
guint num_frame;
} AppData;

/* This method is called by the idle GSource in the mainloop. We feed 1 buffer
* of BUFFER_SIZE bytes into appsrc.
* The ide handler is added to the mainloop when appsrc requests us to start
* sending data (need-data signal) and is removed when appsrc has enough data
* (enough-data signal).
*/
static gboolean
push_buffer (AppData * app)
{
gpointer raw_buffer;
GstBuffer *app_buffer;
GstMemory *mem;
GstFlowReturn ret;

app->num_frame++;

if (app->num_frame >= TOTAL_FRAMES) {
/* we are EOS, send end-of-stream and remove the source */
g_signal_emit_by_name (app->source, "end-of-stream", &ret);
return FALSE;
}

app_buffer = gst_buffer_new();

mem = gst_allocator_alloc (NULL, BUFFER_SIZE, NULL);

gst_buffer_append_memory(app_buffer, mem);

gst_buffer_set_size(app_buffer, BUFFER_SIZE);

/* Setting the correct timestamp for the buffer is very important, otherwise the
* resulting file won't be created correctly */
GST_BUFFER_TIMESTAMP(app_buffer) = (GstClockTime)((app->num_frame / 100.0) * 1e9);

/* push new buffer */
g_signal_emit_by_name (app->source, "push-buffer", app_buffer, &ret);

gst_buffer_unref(app_buffer);

if (ret != GST_FLOW_OK) {
/* some error, stop sending data */
return FALSE;
}

return TRUE;
}

/* This signal callback is called when appsrc needs data, we add an idle handler
* to the mainloop to start pushing data into the appsrc */
static void
start_feed (GstElement * pipeline, guint size, AppData * app)
{
if (app->source_id == 0) {
g_print ("start feeding at frame %i\n", app->num_frame);
app->source_id = g_idle_add ((GSourceFunc) push_buffer, app);
}
}

/* This callback is called when appsrc has enough data and we can stop sending.
* We remove the idle handler from the mainloop */
static void
stop_feed (GstElement * pipeline, AppData * app)
{
if (app->source_id != 0) {
g_print ("stop feeding at frame %i\n", app->num_frame);
g_source_remove (app->source_id);
app->source_id = 0;
}
}

/* called when we get a GstMessage from the pipeline when we get EOS, we
* exit the mainloop and this testapp. */
static gboolean
on_pipeline_message (GstBus * bus, GstMessage * message, AppData * app)
{
GstState state, pending;

switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_EOS:
g_print ("Received End of Stream message\n");
g_main_loop_quit (app->loop);
break;
case GST_MESSAGE_ERROR:
{
g_print ("Received error\n");

GError *err = NULL;
gchar *dbg_info = NULL;

gst_message_parse_error (message, &err, &dbg_info);
g_printerr ("ERROR from element %s: %s\n",
GST_OBJECT_NAME (message->src), err->message);
g_printerr ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
g_error_free (err);
g_free (dbg_info);
}

g_main_loop_quit (app->loop);
break;
case GST_MESSAGE_STATE_CHANGED:
gst_element_get_state(app->source, &state, &pending, GST_CLOCK_TIME_NONE);
/* g_print ("State changed from %i to %i\n", state, pending); */
break;
default:
break;
}
return TRUE;
}

int
main (int argc, char *argv[])
{
AppData *app = NULL;
GstBus *bus = NULL;
GstElement *appsrc = NULL;

gst_init (&argc, &argv);

app = g_new0 (AppData, 1);

app->loop = g_main_loop_new (NULL, FALSE);

/* setting up pipeline, we push media data into this pipeline that will
* then be recorded to a file, encoded with a codec*/
app->pipeline = gst_parse_launch ("appsrc is-live=true name=source caps=audio/x-raw,format=S16LE,rate=8000,channels=1,layout=interleaved ! flacenc ! oggmux ! filesink location=flac-audio.ogg", NULL);

if (app->pipeline == NULL) {
g_print ("Bad pipeline\n");
return -1;
}

appsrc = gst_bin_get_by_name (GST_BIN (app->pipeline), "source");

/* setting maximum of bytes queued */
gst_app_src_set_max_bytes((GstAppSrc *)appsrc, QUEUED_FRAMES * BUFFER_SIZE);

/* uncomment the next line to block when appsrc has buffered enough */
/* g_object_set (appsrc, "block", TRUE, NULL); */
app->source = appsrc;

/* add watch for messages */
bus = gst_element_get_bus (app->pipeline);
gst_bus_add_watch (bus, (GstBusFunc) on_pipeline_message, app);
gst_object_unref (bus);

/* configure the appsrc, we will push data into the appsrc from the
* mainloop */
g_signal_connect (app->source, "need-data", G_CALLBACK (start_feed), app);
g_signal_connect (app->source, "enough-data", G_CALLBACK (stop_feed), app);

/* go to playing and wait in a mainloop */
gst_element_set_state (app->pipeline, GST_STATE_PLAYING);

/* this mainloop is stopped when we receive an error or EOS */
g_print ("Creating movie...\n");
g_main_loop_run (app->loop);
g_print ("Done.\n");

gst_app_src_end_of_stream (GST_APP_SRC (app->source));

gst_element_set_state (app->pipeline, GST_STATE_NULL);

/* Cleaning up */
gst_object_unref (app->source);
gst_object_unref (app->pipeline);
g_main_loop_unref (app->loop);
g_free (app);

return 0;
}

关于c - GStreamer appsrc 到文件示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42199733/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com