Android 创建gstreamer管道以修改零件

Android 创建gstreamer管道以修改零件,android,c,gstreamer,Android,C,Gstreamer,我正在处理一个音频流,我希望能够修改我正在传输的文件,以及我正在传输的目标。为此,我将修改filesrc的位置,或者修改udpsink的主机/端口 我很难理解我需要知道的一切,以便将这条管道连接在一起并进行比赛。之前,我对所有内容都进行了硬编码,并使用gst管道解析工具处理以下管道: filesrc location=/storage/sdcard0/Music/RunToTheHills.ogg ! oggdemux ! vorbisdec ! audioresample ! audiocon

我正在处理一个音频流,我希望能够修改我正在传输的文件,以及我正在传输的目标。为此,我将修改filesrc的位置,或者修改udpsink的主机/端口

我很难理解我需要知道的一切,以便将这条管道连接在一起并进行比赛。之前,我对所有内容都进行了硬编码,并使用gst管道解析工具处理以下管道:

filesrc location=/storage/sdcard0/Music/RunToTheHills.ogg ! oggdemux ! vorbisdec ! audioresample ! audioconvert ! audio/x-raw-int,channels=2,depth=16,width=16,rate=44100 ! rtpL16pay  ! udpsink host=192.168.100.126 port=9001
data->pipeline = gst_pipeline_new("pipeline");

data->filesrc = gst_element_factory_make("filesrc", NULL);
if (!data->filesrc) {
    GST_ERROR("Failed to create filesrc.");
    return NULL;
}
g_object_set(G_OBJECT(data->filesrc), "location", "/storage/sdcard0/Music/RunToTheHills.ogg", NULL);

data->fileblock = gst_element_get_static_pad(data->filesrc, "src");

data->ogg = gst_element_factory_make("oggdemux", NULL);
if (!data->ogg) {
    GST_ERROR("Failed to create oggdemux.");
    return NULL;
}

data->vorbis = gst_element_factory_make("vorbisdec", NULL);
if (!data->vorbis) {
    GST_ERROR("Failed to create vorbisdec.");
    return NULL;
}

data->resample = gst_element_factory_make("audioresample", NULL);
if (!data->resample) {
    GST_ERROR("Failed to create audioresample.");
    return NULL;
}

data->convert = gst_element_factory_make("audioconvert", NULL);
if (!data->convert) {
    GST_ERROR("Failed to create audioconvert.");
    return NULL;
}

data->caps = gst_caps_new_simple("audio/x-raw-int",
        "channels", G_TYPE_INT, 2,
        "depth", G_TYPE_INT, 16,
        "width", G_TYPE_INT, 16,
        "rate", G_TYPE_INT, 44100);

if (!data->caps) {
    GST_ERROR("Failed to create caps");
    return NULL;
}

data->rtp = gst_element_factory_make("rtpL16pay", NULL);
if (!data->rtp) {
    GST_ERROR("Failed to create rtpL16pay.");
    return NULL;
}

data->udp = gst_element_factory_make("udpsink", NULL);
if (!data->udp) {
    GST_ERROR("Failed to create udpsink.");
    return NULL;
}
g_object_set(G_OBJECT(data->udp), "host", "192.168.100.126", NULL);
g_object_set(G_OBJECT(data->udp), "port", 9001, NULL);


if (!data->ogg || !data->vorbis || !data->resample || !data->convert || !data->caps || !data->rtp || !data->udp) {
    GST_ERROR("Unable to create all elements!");
    return NULL;
}

gst_bin_add_many(GST_BIN(data->pipeline), data->filesrc, data->ogg, data->vorbis,
        data->resample, data->convert, data->caps, data->rtp, data->udp);

/* Link all the elements together */
gst_element_link(data->filesrc, data->ogg);
gst_element_link(data->ogg, data->vorbis);
gst_element_link(data->vorbis, data->resample);
gst_element_link(data->resample, data->convert);
gst_element_link_filtered(data->convert, data->rtp, data->caps);
gst_element_link(data->rtp, data->udp);
data->pipeline = gst_parse_launch("filesrc location=/storage/sdcard0/Music/RunToTheHills.ogg ! oggdemux ! vorbisdec ! audioresample ! audioconvert ! audio/x-raw-int,channels=2,depth=16,width=16,rate=44100 ! rtpL16pay  ! udpsink host=192.168.100.126 port=9001", &error);
if (error) {
    gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message);
    g_clear_error (&error);
    set_ui_message(message, data);
    g_free (message);
    return NULL;
}
现在我想更改filesrc位置,以及上面提到的udp主机/端口

我的应用程序是一个使用NDK的Android应用程序。但是,这不应影响设置管道所需的代码

这是我到目前为止得到的结果,它导致了一个断层

我的数据结构:

/**
 * Structure to hold all the various variables we need.
 * This is handed to callbacks
 */
typedef struct _CustomData {
    jobject app; /* The Java app */
    GstElement *pipeline; /* gStreamer pipeline */
    GstElement *filesrc; /* Input file */
    GstPad *fileblock; /* Used to block filesrc */
    GstElement *ogg; /* Ogg demultiplexer */
    GstElement *vorbis; /* Vorbis decoder */
    GstElement *resample;
    GstElement *convert;
    GstCaps *caps;
    GstElement *rtp; /* RTP packer */
    GstElement *udp; /* UDP sender */
    GMainContext *context; /* GLib Context */
    GMainLoop *main_loop; /* GLib main loop */
    gboolean initialised; /* True after initialisation */
    GstState state; /* Pipeline state */
    GstState target_state; /* What state we want to put the pipeline into */
    gint64 duration; /* Clip length */
    gint64 desired_position; /* Where we want to track to within the clip */
    GstClockTime last_seek_time; /* Used to throttle seeking */
    gboolean is_live; /* Live streams don't need buffering */
} CustomData;
下面是我创建的管道:

filesrc location=/storage/sdcard0/Music/RunToTheHills.ogg ! oggdemux ! vorbisdec ! audioresample ! audioconvert ! audio/x-raw-int,channels=2,depth=16,width=16,rate=44100 ! rtpL16pay  ! udpsink host=192.168.100.126 port=9001
data->pipeline = gst_pipeline_new("pipeline");

data->filesrc = gst_element_factory_make("filesrc", NULL);
if (!data->filesrc) {
    GST_ERROR("Failed to create filesrc.");
    return NULL;
}
g_object_set(G_OBJECT(data->filesrc), "location", "/storage/sdcard0/Music/RunToTheHills.ogg", NULL);

data->fileblock = gst_element_get_static_pad(data->filesrc, "src");

data->ogg = gst_element_factory_make("oggdemux", NULL);
if (!data->ogg) {
    GST_ERROR("Failed to create oggdemux.");
    return NULL;
}

data->vorbis = gst_element_factory_make("vorbisdec", NULL);
if (!data->vorbis) {
    GST_ERROR("Failed to create vorbisdec.");
    return NULL;
}

data->resample = gst_element_factory_make("audioresample", NULL);
if (!data->resample) {
    GST_ERROR("Failed to create audioresample.");
    return NULL;
}

data->convert = gst_element_factory_make("audioconvert", NULL);
if (!data->convert) {
    GST_ERROR("Failed to create audioconvert.");
    return NULL;
}

data->caps = gst_caps_new_simple("audio/x-raw-int",
        "channels", G_TYPE_INT, 2,
        "depth", G_TYPE_INT, 16,
        "width", G_TYPE_INT, 16,
        "rate", G_TYPE_INT, 44100);

if (!data->caps) {
    GST_ERROR("Failed to create caps");
    return NULL;
}

data->rtp = gst_element_factory_make("rtpL16pay", NULL);
if (!data->rtp) {
    GST_ERROR("Failed to create rtpL16pay.");
    return NULL;
}

data->udp = gst_element_factory_make("udpsink", NULL);
if (!data->udp) {
    GST_ERROR("Failed to create udpsink.");
    return NULL;
}
g_object_set(G_OBJECT(data->udp), "host", "192.168.100.126", NULL);
g_object_set(G_OBJECT(data->udp), "port", 9001, NULL);


if (!data->ogg || !data->vorbis || !data->resample || !data->convert || !data->caps || !data->rtp || !data->udp) {
    GST_ERROR("Unable to create all elements!");
    return NULL;
}

gst_bin_add_many(GST_BIN(data->pipeline), data->filesrc, data->ogg, data->vorbis,
        data->resample, data->convert, data->caps, data->rtp, data->udp);

/* Link all the elements together */
gst_element_link(data->filesrc, data->ogg);
gst_element_link(data->ogg, data->vorbis);
gst_element_link(data->vorbis, data->resample);
gst_element_link(data->resample, data->convert);
gst_element_link_filtered(data->convert, data->rtp, data->caps);
gst_element_link(data->rtp, data->udp);
data->pipeline = gst_parse_launch("filesrc location=/storage/sdcard0/Music/RunToTheHills.ogg ! oggdemux ! vorbisdec ! audioresample ! audioconvert ! audio/x-raw-int,channels=2,depth=16,width=16,rate=44100 ! rtpL16pay  ! udpsink host=192.168.100.126 port=9001", &error);
if (error) {
    gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message);
    g_clear_error (&error);
    set_ui_message(message, data);
    g_free (message);
    return NULL;
}
有人能给我一些关于我哪里出错的提示吗

出于兴趣,这里是我以前的工作管道:

filesrc location=/storage/sdcard0/Music/RunToTheHills.ogg ! oggdemux ! vorbisdec ! audioresample ! audioconvert ! audio/x-raw-int,channels=2,depth=16,width=16,rate=44100 ! rtpL16pay  ! udpsink host=192.168.100.126 port=9001
data->pipeline = gst_pipeline_new("pipeline");

data->filesrc = gst_element_factory_make("filesrc", NULL);
if (!data->filesrc) {
    GST_ERROR("Failed to create filesrc.");
    return NULL;
}
g_object_set(G_OBJECT(data->filesrc), "location", "/storage/sdcard0/Music/RunToTheHills.ogg", NULL);

data->fileblock = gst_element_get_static_pad(data->filesrc, "src");

data->ogg = gst_element_factory_make("oggdemux", NULL);
if (!data->ogg) {
    GST_ERROR("Failed to create oggdemux.");
    return NULL;
}

data->vorbis = gst_element_factory_make("vorbisdec", NULL);
if (!data->vorbis) {
    GST_ERROR("Failed to create vorbisdec.");
    return NULL;
}

data->resample = gst_element_factory_make("audioresample", NULL);
if (!data->resample) {
    GST_ERROR("Failed to create audioresample.");
    return NULL;
}

data->convert = gst_element_factory_make("audioconvert", NULL);
if (!data->convert) {
    GST_ERROR("Failed to create audioconvert.");
    return NULL;
}

data->caps = gst_caps_new_simple("audio/x-raw-int",
        "channels", G_TYPE_INT, 2,
        "depth", G_TYPE_INT, 16,
        "width", G_TYPE_INT, 16,
        "rate", G_TYPE_INT, 44100);

if (!data->caps) {
    GST_ERROR("Failed to create caps");
    return NULL;
}

data->rtp = gst_element_factory_make("rtpL16pay", NULL);
if (!data->rtp) {
    GST_ERROR("Failed to create rtpL16pay.");
    return NULL;
}

data->udp = gst_element_factory_make("udpsink", NULL);
if (!data->udp) {
    GST_ERROR("Failed to create udpsink.");
    return NULL;
}
g_object_set(G_OBJECT(data->udp), "host", "192.168.100.126", NULL);
g_object_set(G_OBJECT(data->udp), "port", 9001, NULL);


if (!data->ogg || !data->vorbis || !data->resample || !data->convert || !data->caps || !data->rtp || !data->udp) {
    GST_ERROR("Unable to create all elements!");
    return NULL;
}

gst_bin_add_many(GST_BIN(data->pipeline), data->filesrc, data->ogg, data->vorbis,
        data->resample, data->convert, data->caps, data->rtp, data->udp);

/* Link all the elements together */
gst_element_link(data->filesrc, data->ogg);
gst_element_link(data->ogg, data->vorbis);
gst_element_link(data->vorbis, data->resample);
gst_element_link(data->resample, data->convert);
gst_element_link_filtered(data->convert, data->rtp, data->caps);
gst_element_link(data->rtp, data->udp);
data->pipeline = gst_parse_launch("filesrc location=/storage/sdcard0/Music/RunToTheHills.ogg ! oggdemux ! vorbisdec ! audioresample ! audioconvert ! audio/x-raw-int,channels=2,depth=16,width=16,rate=44100 ! rtpL16pay  ! udpsink host=192.168.100.126 port=9001", &error);
if (error) {
    gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message);
    g_clear_error (&error);
    set_ui_message(message, data);
    g_free (message);
    return NULL;
}

您不能简单地将oggdemux链接到vorbisdec,因为demux有时具有pad

您需要为demux的“pad added”信号添加一个处理函数,然后在那里执行链接

/* Connect to the pad-added signal */
g_signal_connect (data->ogg, "pad-added", G_CALLBACK (pad_added_handler), data);
和处理程序:

void on_pad_added (GstElement *src, GstPad *new_pad, CustomData *data)
{
GstPad *sink_pad = gst_element_get_static_pad (data->vorbis, "sink");
GstPadLinkReturn ret;
GstCaps *new_pad_caps = NULL;
GstStructure *new_pad_struct = NULL;
const gchar *new_pad_type = NULL;

g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));

/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sink_pad)) {
g_print ("  We are already linked. Ignoring.\n");
goto exit;
}

/* Check the new pad's type */
new_pad_caps = gst_pad_get_caps (new_pad);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {
g_print ("  It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);
goto exit;
}

/* Attempt the link */
ret = gst_pad_link (new_pad, sink_pad);
if (GST_PAD_LINK_FAILED (ret)) {
g_print ("  Type is '%s' but link failed.\n", new_pad_type);
} else {
g_print ("  Link succeeded (type '%s').\n", new_pad_type);
}

exit:
/* Unreference the new pad's caps, if we got them */
if (new_pad_caps != NULL)
gst_caps_unref (new_pad_caps);

/* Unreference the sink pad */
gst_object_unref (sink_pad);
}

另外,由于您遇到了分段错误,我认为存在内存问题。您确定使用的是CustomData结构吗?我注意到您使用的是data->element而不是data.element。

我目前正在解决这个问题,每次管道发生更改时都会重新创建管道。如果我找到更好的方法,我会把它贴在这里。