Gstreamer-音频数据播放之PCM

下述代码使用场景:

用于需要在当前设备端播放PCM音频数据

// push buffer to appsrc
bool push_data(const char *data, int data_size)
{
    GstBuffer *buffer = gst_buffer_new_allocate(NULL, data_size, NULL);

    GstMapInfo map;

    gst_buffer_map(buffer, &map, GST_MAP_WRITE);
    memcpy((guchar *)map.data, data, gst_buffer_get_size(buffer));

    GstFlowReturn ret;
    g_signal_emit_by_name(m_app_src, "push-buffer", buffer, &ret);
    gst_buffer_unmap(buffer, &map);
    gst_buffer_unref(buffer);
    if (ret != GST_FLOW_OK) {
        g_printerr("[push_data], push_data fail ret: %d.\n", ret);
        return false;
    }

    return true;
}

// 初始化 pipeline
//  |---------------------------pipeline-----------------------------|
//  | appsrc->audioconvert->audioresample->capsfilter->autoaudiosink |
//  |----------------------------------------------------------------|
bool init(int sample_rate, int channel, const char *formate)
{
    m_app_src = gst_element_factory_make("appsrc", "app_src");
    if (!m_app_src) {
        g_printerr("[init], failed to create a appsrc.\n");
        return false;
    }

    m_audio_convert = gst_element_factory_make("audioconvert", "audio_convert");
    if (!m_audio_convert) {
        g_printerr("[init], failed to create a audioconvert.\n");
        return false;
    }
    m_audio_resample = gst_element_factory_make("audioresample", "audio_resample");
    if (!m_audio_resample) {
        g_printerr("[init], failed to create a audioconvert.\n");
        return false;
    }

    m_auto_audio_sink = gst_element_factory_make("autoaudiosink", "auto_audio_sink");
    if (!m_auto_audio_sink) {
        g_printerr("[init], failed to create a autoaudiosink.\n");
        return false;
    }

    m_pipeline = gst_pipeline_new("pipeline");
    if (!m_pipeline) {
        g_printerr("[init], failed to create a pipeline.\n");
        return false;
    }

    GstCaps *audioCaps = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING, formate, "rate", G_TYPE_INT,
        sample_rate, "channels", G_TYPE_INT, channel, "layout", G_TYPE_STRING, "interleaved", "is-live", G_TYPE_BOOLEAN,
        TRUE, nullptr);
    if (!audioCaps) {
        g_printerr("[init], audioCaps is null.\n");
        return false;
    }

    g_object_set(G_OBJECT(m_app_src), "caps", audioCaps, nullptr);
    gst_caps_unref(audioCaps);

    m_caps_filter = gst_element_factory_make("capsfilter", "caps_filter");
    if (!m_caps_filter) {
        g_printerr("[init], caps_filter elements could be created.\n");
        return false;
    }
    GstCaps *caps = gst_caps_new_simple(
        "audio/x-raw", "format", G_TYPE_STRING, "S16LE", "rate", G_TYPE_INT, 48000, "channels", G_TYPE_INT, 2, nullptr);
    if (!caps) {
        g_printerr("[init], caps new fail.\n");
        return false;
    }
    g_object_set(G_OBJECT(m_caps_filter), "caps", caps, nullptr);
    gst_caps_unref(caps);

    gst_bin_add_many(
        GST_BIN(m_pipeline), m_app_src, m_audio_convert, m_audio_resample, m_caps_filter, m_auto_audio_sink, nullptr);

    if (gst_element_link_many(
            m_app_src, m_audio_convert, m_audio_resample, m_caps_filter, m_auto_audio_sink, nullptr) != TRUE) {
        g_printerr("[init], gst_element_link_filtered fail.\n");
        return false;
    }

    if (gst_element_set_state(m_pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
        g_printerr("[init], play audioplayer fail.\n");
        return false;
    }

    g_printerr("[init], init audioplayer successfully.\n");
    m_isPlaying = true;
    return true;
}