如何收听oggdemux gstreamer故障?

时间:2019-06-21 23:16:13

标签: gstreamer ogg opus gstreamer-1.0

我写了一个gstreamer应用程序,可以将opus音频转换为原始音频。如果我将不良音频(只是随机字节)馈送到管道,则管道会卡住,并且/ i在消息总线上不会收到错误消息。

我正在侦听流经管道的错误消息,但没有收到表示失败的错误代码。尽管gstreamer调试日志指示demux失败,但我可以在日志中看到以下内容:

0:00:00.021614679 22541       0xe5b190 WARN                oggdemux gstoggdemux.c:4609:gst_ogg_demux_send_event:<oggdemux0> No chain to forward event to
0:00:00.021656681 22541       0xe5b190 WARN                oggdemux gstoggdemux.c:2433:gst_ogg_demux_sink_event:<oggdemux0> EOS while trying to retrieve chain, seeking disabled

以下是我编写的一个应用示例:

#include <gst/gst.h>
#include <gst/gstbin.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
#include <stdio.h>
#include <string.h>

static GMainLoop *loop;

FILE *file = NULL;
size_t bytesRead = 0;

typedef struct _CustomData
{
  GstElement *pipeline;
  GstAppSrc *app_source;

  guint sourceid; /* To control the GSource */

} CustomData;

static gboolean push_data(CustomData *data)
{
  GstBuffer *gbuffer;
  GstFlowReturn ret;

  char buffer[1024];

  gbuffer = gst_buffer_new_and_alloc(sizeof(buffer));
  GstMapInfo info;

  bytesRead = fread(buffer, 1, sizeof(buffer), file);

  gst_buffer_map(gbuffer, &info, GST_MAP_WRITE);
  memcpy(info.data, buffer, bytesRead);
  gst_buffer_unmap(gbuffer, &info);

  if (bytesRead > 0)
  {
    //g_print("Pushing %d\n", (int)bytesRead);
    /* Push the buffer into the appsrc */
    g_signal_emit_by_name(data->app_source, "push-buffer", gbuffer, &ret);
    return TRUE;
  }
  else
  {
    g_print("file complete\n");
    gst_app_src_end_of_stream(data->app_source);
    return FALSE;
  }

  gst_buffer_unref(gbuffer);
}

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 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 gboolean bus_call(GstBus * bus, GstMessage * msg, gpointer user_data)
{
  switch (GST_MESSAGE_TYPE(msg))
  {

  case GST_MESSAGE_EOS:
    g_print("End of stream\n");
    g_main_loop_quit(loop);
    break;

  case GST_MESSAGE_ERROR:
  {
    gchar *debug;
    GError *error;

    gst_message_parse_error(msg, &error, &debug);
    g_free(debug);

    g_printerr("Error: from %s %s\n", GST_OBJECT_NAME(msg->src), error->message);
    g_error_free(error);

    g_main_loop_quit(loop);
    break;
  }
  default:
    break;
  }

  return TRUE;
}

int main(int argc,
         char *argv[])
{
  CustomData data;
  memset(&data, 0, sizeof(data));
  GstBus *bus;
  guint bus_watch_id;

  /* Initialisation */
  gst_init(&argc, &argv);

  loop = g_main_loop_new(NULL, FALSE);

  GError *error = NULL;


  data.pipeline = gst_parse_launch("concat name=c ! filesink location=program.wav appsrc name=src_00 ! oggdemux ! opusdec ! audioconvert ! audioresample ! audio/x-raw,format=S16LE,channels=1,rate=16000 ! queue ! c.", &error); 

  if (!data.pipeline)
  {
    g_printerr("Pipeline could not be created. Exiting.\n");
    return -1;
  }

  data.app_source = (G_TYPE_CHECK_INSTANCE_CAST((gst_bin_get_by_name(GST_BIN(data.pipeline), "src_00")), GST_TYPE_APP_SRC, GstAppSrc));
  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);

  /* we add a message handler */
  bus = gst_pipeline_get_bus(GST_PIPELINE(data.pipeline));
  bus_watch_id = gst_bus_add_watch(bus, bus_call, NULL);
  gst_object_unref(bus);

  file = fopen("junk.wav", "rb");

  /* Set the pipeline to "playing" state*/
  g_print("Now playing");
  gst_element_set_state(data.pipeline, GST_STATE_PLAYING);

  /* Iterate */
  g_print("Running...\n");
  g_main_loop_run(loop);

  /* Out of the main loop, clean up nicely */
  g_print("Returned, stopping playback\n");
  gst_element_set_state(data.pipeline, GST_STATE_NULL);

  g_print("Deleting pipeline\n");
  gst_object_unref(GST_OBJECT(data.pipeline));
  g_source_remove(bus_watch_id);
  g_main_loop_unref(loop);
  return 0;
}

我本来希望多路分解失败会导致消息总线,但事实并非如此。我该如何听此类错误?

我尝试了其他使用decodebin的管道,并且在消息总线上收到错误消息。以下管道按预期工作:

gst_parse_launch("concat name=c ! filesink location=program.wav appsrc name=src_00 ! decodebin ! audioconvert ! audioresample ! audio/x-raw,format=S16LE,channels=1,rate=16000 ! queue ! c.", &error);

GStreamer版本:1.8.3 操作系统:Ubuntu 16.04

1 个答案:

答案 0 :(得分:0)

该问题似乎在Gstreamer 1.14中已解决。更新后,我现在在消息总线上收到一条错误消息:

Message: Error: from oggdemux0 Could not demultiplex stream.
Error Code: GST_STREAM_ERROR_DEMUX