И так начнем
Для начала немного разберемся с основными понятиями в Gstreamer
Элемент — является самым важным классом объектов в Gstreamer. Они могут объединятся в цепочку и создавать так называемый канал (pipeline). Каждый элемент имеет строго определенную функцию: чтение файла, ввод или вывод данных и т. д.
Гнезда(pads) — используются для передачи данных между элементами. В каждом элементе может быть от одного и выше гнезд.
Контейнер элементов (Bin) — объединяет цепочку элементов. С помощью данного контейнера можно управлять элементами как одним целым.
Канал (pipeline) — похож на бины, за исключением того, что место элементов он содержит контейнеры элементов.
Подробнее обо всем этом можно узнать в документации.
Теперь перейдем к реализации нашего класса.
Вот так вот выглядит класс нашего аудио плеера:
#ifndef AUDIOENGINE_H #define AUDIOENGINE_H #include <gst/gst.h> #include <glib.h> #include <QObject> class AudioEngine : public QObject { Q_OBJECT public: AudioEngine(QObject *parent = 0); ~AudioEngine(); int Init(); void MusicPlay(); void MusicPaused(); void MusicStop(); void AddFile(char *file); void SetVolume(gdouble val); gint64 GetMusicPosition(); gint64 GetMusicDuration(); void SetMusicPosition(gint64 pos); private: GstElement *pipeline; GstElement *source; GstElement *volume; gint64 pos; static void OnPadAdded(GstElement *element, GstPad *pad, gpointer data); private slots: }; #endif // AUDIOENGINE_H
В функции Init() мы инициализируем библиотеку Gstreamer:
gst_init(0, 0);
данная функция принимает аргументы командной строки argv и argc, в нашем случаи их можно опустить.
Далее создаем канал:
pipeline = gst_pipeline_new("audio-player");
и необходимые нам элементы:
source = gst_element_factory_make("filesrc", NULL); demuxer = gst_element_factory_make("decodebin", NULL); decoder = gst_element_factory_make("audioconvert", NULL); volume = gst_element_factory_make("volume", NULL); conv = gst_element_factory_make("audioconvert", NULL); sink = gst_element_factory_make("autoaudiosink", NULL);
Элемент source — предназначен для чтения аудио файлов.
demuxer — используется для декодирования аудио файла.
decoder и conv — для конвертирования аудио файла в другой формат.
volume — предназначен для регулирования громкости звука.
sinc — автоматически определяет аудио устройство и выводит данные на него…
Следует заметить что demuxer создает гнезда для каждого элемента потока и нам придется установить обработчик событий для связи demuxer с decoder. В этом нам поможет функция OnPadAdded().
Обработчик событий в нашем коде выглядит так:
g_signal_connect(demuxer, "pad-added", G_CALLBACK(OnPadAdded), decoder);
Добавляем все созданные элементы в канал:
gst_bin_add_many (GST_BIN (pipeline), source, demuxer, decoder, volume, conv, sink, NULL);
и линкуем элементы между собой.
gst_element_link (source, demuxer); gst_element_link_many (decoder, volume, conv, sink, NULL);
Функция для добавления файла в плеер выглядит примерно так:
void AudioEngine::AddFile(char *file) { g_object_set(G_OBJECT(source), "location", file, NULL); }
функция g_object_set() передает аргументы элементу source. В данном случае аргумент «location» говорит нам о том, что аудио-файл находится на локальной машине, file — путь к нашему файлу. Последний параметр NULL говорит нам о том, что элемент больше в никаких аргументах не нуждается.
Функции для запуска, остановки воспроизведения выглядят так:
void AudioEngine::AddFile(char *file) { g_object_set(G_OBJECT(source), "location", file, NULL); } void AudioEngine::MusicPlay() { gst_element_set_state(pipeline, GST_STATE_PLAYING); } void AudioEngine::MusicPaused() { gst_element_set_state(pipeline, GST_STATE_PAUSED); }
тут вроде все понятно.
Функция для регулирование громкости:
void AudioEngine::SetVolume(gdouble val) { g_object_set(G_OBJECT(volume), "volume", val, NULL); }
Функции для для получения продолжительности трека и текущего его положения:
gint64 AudioEngine::GetMusicDuration() { gint64 len; gst_element_query_duration(pipeline, GST_FORMAT_TIME, &len); return len; } gint64 AudioEngine::GetMusicPosition() { gint64 pos; gst_element_query_position(pipeline, GST_FORMAT_TIME, &pos); return pos; }
следует иметь в виду что функции возвращают значения времени в наносекундах.
И наконец-то функция для смены позиции трека:
void AudioEngine::SetMusicPosition(gint64 pos) { gst_element_set_state(pipeline, GST_STATE_PAUSED); gst_element_seek_simple(pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, pos); gst_element_set_state(pipeline, GST_STATE_PLAYING); }
для того что бы сменить позицию нам придется остановить воспроизведение, а после смены опять его запустить.
gst_element_seek_simple() принимает в аргументы наш канал, формат времени, флаг поиска позиции, и саму позицию которая измеряется в наносекундах.
Полный код приведен ниже по ссылке в месте с небольшим GUI реализованном на Qt.
Исходники на GitHab
Всем спасибо.
ссылка на оригинал статьи http://habrahabr.ru/post/204172/
Добавить комментарий