在Android中播放时如何从GStreamer管道中的元素更改?

时间:2019-03-29 21:56:50

标签: android gstreamer

我想制作GStreamer android应用程序,既能够接收RTP流,又能够检测流何时关闭。

该应用程序使用默认屏幕(videotestsrc)进行初始化,但是当我想切换到流屏幕时,我无法链接垃圾箱的按钮。当管道处于 PLAYING 状态

时,就会发生此过程

为此,我使用了三个垃圾箱并将它们添加到管道中。

  1. 默认来源bin :其中包含一个带有capsfilter的videotestsrc
  2. 流源bin :这具有udpsrc,depay和解码器
  3. 显示接收器容器:它具有七个文本叠加层和一个自动视频接收器,用于通过GST_VIDEO_OVERLAY界面在屏幕上呈现视频。

应用程序使用与显示接收器箱连接的默认源箱进行初始化,因为没有信号,因此应用上显示了默认的蓝屏,而流式源箱等待rtp流(为此,我添加了一个块/ buffer探针)。

当检测到rtp流时,会将默认源容器从管道中删除(还将该容器与显示接收器容器断开链接),并将流式源容器链接到显示接收器容器。

当我尝试将默认源bin更改为流媒体源bin时,会出现问题,因为当我删除默认源bin且我想将流媒体源bin链接到show sink bin时,我得到了<强烈的> GST_PAD_LINK_NO_FORMAT 错误。

这是我用来创建垃圾箱的代码。

    gchar streaming_src_bin_string[300];
    strcpy(streaming_src_bin_string, "udpsrc port=5000 timeout=100000000 ! ");
    strcat(streaming_src_bin_string, "application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264 ! ");
    strcat(streaming_src_bin_string, "queue ! rtph264depay ! avdec_h264 name=decoder");
    data->streaming_src_bin = gst_parse_bin_from_description(streaming_src_bin_string,
                                                             FALSE,
                                                             NULL);

    gchar default_src_bin_string[300];
    strcpy(default_src_bin_string, "videotestsrc pattern=6 ! ");
    strcat(default_src_bin_string, "capsfilter name=defaultcaps caps=video/x-raw,width=(int)1280,");
    strcat(default_src_bin_string, "height=(int)800,pixel-aspect-ratio=(fraction)1/1,framerate=(fraction)5/1");
    data->default_src_bin = gst_parse_bin_from_description(default_src_bin_string,
                                                           FALSE,
                                                           NULL);

    gchar show_sink_bin_string[1024];
    strcpy(show_sink_bin_string, "textoverlay name=top-left valignment=top halignment=left font-desc=\"courier 12px\" text=\"Testing\" ! ");
    strcat(show_sink_bin_string, "textoverlay name=top-center valignment=top halignment=center font-desc=\"courier 12px\" text=\"Testing\" ! ");
    strcat(show_sink_bin_string, "textoverlay name=top-right valignment=top halignment=right font-desc=\"courier 12px\" text=\"Testing\" ! ");
    strcat(show_sink_bin_string, "textoverlay name=center-center valignment=center halignment=center font-desc=\"courier 12px\" text=\"Testing\" ! ");
    strcat(show_sink_bin_string, "textoverlay name=bottom-left valignment=bottom halignment=left font-desc=\"courier 12px\" text=\"Testing\" ! ");
    strcat(show_sink_bin_string, "textoverlay name=bottom-center valignment=bottom halignment=center font-desc=\"courier 12px\" text=\"Testing\" ! ");
    strcat(show_sink_bin_string, "textoverlay name=bottom-right valignment=bottom halignment=right font-desc=\"courier 12px\" text=\"Testing\" ! ");
    strcat(show_sink_bin_string, "glimagesink sync=false");
    data->show_sink_bin = gst_parse_bin_from_description(show_sink_bin_string, FALSE, NULL);

这是我用来切换垃圾箱的代码:

/* Method that changes the input bin to the streaming source bin
 * when the pad is IDLE */
static GstPadProbeReturn
change_input_on_idle_cb (GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
    CustomData *data = (CustomData *) user_data;
    GST_DEBUG ("Default src caps is IDLE, changing to streaming src bin"); 
    gst_bin_remove (GST_BIN (data->pipeline), data->default_src_bin);
    GST_DEBUG ("Linking streaming src with show sink");
    GstPadLinkReturn ret = gst_pad_link (data->streaming_src_bin_pad, data->show_sink_bin_pad);
    switch (ret) {
        case GST_PAD_LINK_OK: GST_DEBUG ("Pads linked"); break;
        case GST_PAD_LINK_WRONG_HIERARCHY: GST_ERROR ("Can't link pads, GST_PAD_LINK_WRONG_HIERARCHY"); break;
        case GST_PAD_LINK_WAS_LINKED: GST_ERROR ("Can't link pads, GST_PAD_LINK_WAS_LINKED"); break;
        case GST_PAD_LINK_WRONG_DIRECTION: GST_ERROR ("Can't link pads, GST_PAD_LINK_WRONG_DIRECTION"); break;
        case GST_PAD_LINK_NOFORMAT: GST_ERROR ("Can't link pads, GST_PAD_LINK_NOFORMAT"); break;
        case GST_PAD_LINK_NOSCHED: GST_ERROR ("Can't link pads, GST_PAD_LINK_NOSCHED"); break;
        case GST_PAD_LINK_REFUSED: GST_ERROR ("Can't link pads, GST_PAD_LINK_REFUSED"); break;
        default: GST_DEBUG ("Unhandled exception");
    }
    GST_DEBUG ("Link completed, removing idle probe");
    data->is_streaming = TRUE;
    return GST_PAD_PROBE_REMOVE;
}

/* Method that adds an idle probe on stream detection
 * and waits for streaming src bin to be linked before
 * removing the probe attached to the streaming src bin */
static GstPadProbeReturn
data_received_cb (GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
    GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
    if (gst_buffer_has_flags(buffer, GST_BUFFER_FLAG_DISCONT) ||
            gst_buffer_has_flags(buffer, GST_BUFFER_FLAG_CORRUPTED)) {
        return GST_PAD_PROBE_DROP;
    }
    GST_DEBUG ("Frame received");
    GST_DEBUG ("UDP stream detected, adding idle probe to default src caps");
    CustomData *data = (CustomData *) user_data;
    gst_pad_add_probe(data->default_src_bin_pad, GST_PAD_PROBE_TYPE_IDLE, change_input_on_idle_cb,
                      user_data, NULL);
    GST_DEBUG ("Linking completed, removing data received probe");
    return GST_PAD_PROBE_REMOVE;
}

这没有任何意义,因为当我在python中测试相同的东西并完美运行时,我仅在android上收到此错误。所以我没有任何线索可以解决这个问题。

0 个答案:

没有答案