2015-03-23 2 views
1

Привет всем Я пытаюсь изменить скорость воспроизведения аудиофайла с помощью библиотеки gstreamer в c. Я следил за большинством руководств на веб-сайте gstreamer, но единственное, что не работает, это скорость воспроизведения.Как изменить скорость воспроизведения аудиопотока в Gstreamer?

Способ, которым он настроен прямо сейчас, скорость должна быть удвоена, когда «.» встречается, но ничего не происходит. Могут ли какие-либо опытные пользователи gstreamer дать некоторую информацию?

typedef struct bindata { 
    GMainLoop *loop; 
    GstElement *pipeline, *source, *mp3decoder, *volume, *pulseout; 
    gboolean playing; 
} bindata; 

static bindata data; 

static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer *misc){ 
    //GMainLoop *loop = (GMainLoop *) misc; 
    switch (GST_MESSAGE_TYPE(msg)){ 
     case GST_MESSAGE_EOS: { 
      g_message("End of stream.\n"); 
      g_main_loop_quit(data.loop); 
      break; 
     } 
     case GST_MESSAGE_ERROR:{ 
      GError *error; 
      gst_message_parse_error(msg, &error, NULL); 
      g_printerr("%s\n", error->message); 
      g_error_free(error); 

      g_main_loop_quit(data.loop); 
      break; 
     } 
     default: break; 
    } 
    return TRUE; 
} 

static gboolean keypress (GIOChannel *src, GIOCondition cond, bindata *data){ 
    int c; 
    gdouble vol; 
    GstFormat format = GST_FORMAT_TIME; 

    //if(g_io_channel_read_unichar(src, str, NULL) != G_IO_STATUS_NORMAL){ 
    if((c = getchar()) == EOF){ 
     return TRUE; 
    } 

    switch(c){ 
     case '+': 
      g_object_get(data->volume, "volume", &vol,NULL); 
      if (vol >= 10) break; 
      g_object_set (data->volume, "volume", vol + 0.1, NULL); 
      break; 
     case '-': 
      g_object_get(data->volume, "volume", &vol, NULL); 
      if (vol <= 0.1) break; 
      g_object_set (data->volume, "volume", vol - 0.1, NULL); 
      break; 
     case '.': 
      g_print("speed up \n"); 
      gst_element_send_event(data->pulseout, gst_event_new_step(format, 20, 2.0, TRUE, FALSE)); 
      break; 
     case ',': 
      g_print("speed down \n"); 
      break; 
     case ' ': 
      data->playing = !data->playing; 
      gst_element_set_state (data->pipeline, data->playing ? GST_STATE_PLAYING : GST_STATE_PAUSED); 
      break; 
     default: 
      break; 
    } 
    return TRUE; 
} 

int main(int argc, char *argv[]){ 
    GstBus *bus; 
    guint bus_watch_id; 
    GIOChannel *io_stdin; 

    gst_init(&argc, &argv); 
    memset (&data, 0, sizeof(data)); 
    data.loop = g_main_loop_new(NULL, false); 

    if(argc != 2){ 
     g_printerr("Usage: ./play <URI: mp3 file>"); 
     return -1; 
    } 

    io_stdin = g_io_channel_unix_new (fileno (stdin)); 
    g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) keypress, &data); 

    data.pipeline = gst_pipeline_new ("audio-player"); 
    data.source  = gst_element_factory_make ("filesrc", "file source"); 
    data.mp3decoder = gst_element_factory_make ("mad", "mad mp3"); 
    data.volume  = gst_element_factory_make ("volume", "volume"); 
    data.pulseout = gst_element_factory_make ("pulsesink", "pulse audio"); 

    if(!data.pipeline || !data.source || !data.mp3decoder || !data.pulseout || !data.volume) { 
     g_printerr("Some element(s) could not be created. Exiting. \n"); 
     return -1; 
    } 

    g_object_set (G_OBJECT (data.source), "location", argv[1], NULL); 
    g_object_set (G_OBJECT(data.volume), "volume", 0.01, NULL); 

    bus = gst_pipeline_get_bus(GST_PIPELINE(data.pipeline)); 
    bus_watch_id = gst_bus_add_watch(bus, bus_call, NULL); 
    gst_object_unref(bus); 

    gst_bin_add_many(GST_BIN (data.pipeline), data.source, data.mp3decoder, data.volume, data.pulseout, NULL); 
    gst_element_link_many (data.source, data.mp3decoder, data.volume, data.pulseout, NULL); 

    gst_element_set_state(data.pipeline, GST_STATE_PLAYING); 
    data.playing = TRUE; 
    g_print ("Running...\n"); 
    g_main_loop_run(data.loop); 
    g_print ("ended. \n"); 
    gst_element_set_state(data.pipeline, GST_STATE_NULL); 
    gst_object_unref(GST_OBJECT(data.pipeline)); 
    g_source_remove (bus_watch_id); 
    g_main_loop_unref (data.loop); 

    return 0; 
} 

ответ

0

Управление скоростью воспроизведения осуществляется путем обращения с gst_event_new_seek или gst_element_seek, установив свойство скорости, можно найти в документации на https://developer.gnome.org/gstreamer/stable/gstreamer-GstEvent.html#gst-event-new-seek и http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstElement.html#gst-element-seek

+0

Я также попытался это и в соответствии с документацией , значение скорости в gst_event_new_step также должно выполнить ту же задачу. Несмотря на то, что gst_event_new_seek тоже не работал для меня, компилируется и работает нормально, но сообщений об ошибках нет. – oneb1got

0
the following, while oriented on video rather than audio, 
shows how to change the playback speed. 

it is from: 
<http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+13%3A+Playback+speed> 

#include <string.h> 
#include <gst/gst.h> 

typedef struct _CustomData { 
    GstElement *pipeline; 
    GstElement *video_sink; 
    GMainLoop *loop; 

    gboolean playing; /* Playing or Paused */ 
    gdouble rate;  /* Current playback rate (can be negative) */ 
} CustomData; 

/* Send seek event to change rate */ 
static void send_seek_event (CustomData *data) { 
    gint64 position; 
    GstFormat format = GST_FORMAT_TIME; 
    GstEvent *seek_event; 

    /* Obtain the current position, needed for the seek event */ 
    if (!gst_element_query_position (data->pipeline, &format, &position)) { 
    g_printerr ("Unable to retrieve current position.\n"); 
    return; 
    } 

    /* Create the seek event */ 
    if (data->rate > 0) { 
    seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 
     GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, 0); 
    } else { 
    seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 
     GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, position); 
    } 

    if (data->video_sink == NULL) { 
    /* If we have not done so, obtain the sink through which we will send the seek events */ 
    g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL); 
    } 

    /* Send the event */ 
    gst_element_send_event (data->video_sink, seek_event); 

    g_print ("Current rate: %g\n", data->rate); 
} 

/* Process keyboard input */ 
static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) { 
    gchar *str = NULL; 

    if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) { 
    return TRUE; 
    } 

    switch (g_ascii_tolower (str[0])) { 
    case 'p': 
    data->playing = !data->playing; 
    gst_element_set_state (data->pipeline, data->playing ? GST_STATE_PLAYING : GST_STATE_PAUSED); 
    g_print ("Setting state to %s\n", data->playing ? "PLAYING" : "PAUSE"); 
    break; 
    case 's': 
    if (g_ascii_isupper (str[0])) { 
     data->rate *= 2.0; 
    } else { 
     data->rate /= 2.0; 
    } 
    send_seek_event (data); 
    break; 
    case 'd': 
    data->rate *= -1.0; 
    send_seek_event (data); 
    break; 
    case 'n': 
    if (data->video_sink == NULL) { 
     /* If we have not done so, obtain the sink through which we will send the step events */ 
     g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL); 
    } 

    gst_element_send_event (data->video_sink, 
     gst_event_new_step (GST_FORMAT_BUFFERS, 1, data->rate, TRUE, FALSE)); 
    g_print ("Stepping one frame\n"); 
    break; 
    case 'q': 
    g_main_loop_quit (data->loop); 
    break; 
    default: 
    break; 
    } 

    g_free (str); 

    return TRUE; 
} 

int main(int argc, char *argv[]) { 
    CustomData data; 
    GstStateChangeReturn ret; 
    GIOChannel *io_stdin; 

    /* Initialize GStreamer */ 
    gst_init (&argc, &argv); 

    /* Initialize our data structure */ 
    memset (&data, 0, sizeof (data)); 

    /* Print usage map */ 
    g_print (
    "USAGE: Choose one of the following options, then press enter:\n" 
    " 'P' to toggle between PAUSE and PLAY\n" 
    " 'S' to increase playback speed, 's' to decrease playback speed\n" 
    " 'D' to toggle playback direction\n" 
    " 'N' to move to next frame (in the current direction, better in PAUSE)\n" 
    " 'Q' to quit\n"); 

    /* Build the pipeline */ 
    data.pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL); 

    /* Add a keyboard watch so we get notified of keystrokes */ 
#ifdef _WIN32 
    io_stdin = g_io_channel_win32_new_fd (fileno (stdin)); 
#else 
    io_stdin = g_io_channel_unix_new (fileno (stdin)); 
#endif 
    g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data); 

    /* Start playing */ 
    ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING); 
    if (ret == GST_STATE_CHANGE_FAILURE) { 
    g_printerr ("Unable to set the pipeline to the playing state.\n"); 
    gst_object_unref (data.pipeline); 
    return -1; 
    } 
    data.playing = TRUE; 
    data.rate = 1.0; 

    /* Create a GLib Main Loop and set it to run */ 
    data.loop = g_main_loop_new (NULL, FALSE); 
    g_main_loop_run (data.loop); 

    /* Free resources */ 
    g_main_loop_unref (data.loop); 
    g_io_channel_unref (io_stdin); 
    gst_element_set_state (data.pipeline, GST_STATE_NULL); 
    if (data.video_sink != NULL) 
    gst_object_unref (data.video_sink); 
    gst_object_unref (data.pipeline); 
    return 0; 
} 
Смежные вопросы