GStreamerのシンプルなオーディオプレーヤー

最近、小さなオーディオプレーヤーを実装する必要がありました。 さまざまな理由で、Gstreamerライブラリを選択しました。 そして、私は得た知識を共有することにしました。 以下の情報が誰かに役立つことを願っています。



それでは始めましょう



まず、Gstreamerの基本概念を見てみましょう


要素-これは、Gstreamerのオブジェクトの最も重要なクラスです。 これらをチェーンで組み合わせて、いわゆるチャネル(パイプライン)を作成できます。 各要素には、ファイルの読み取り、データの入力または出力など、厳密に定義された機能があります。



ソケット(パッド)-要素間でデータを転送するために使用されます。 各要素には1つ以上のネストを含めることができます。



要素コンテナ(ビン)-要素のチェーンを結合します。 このコンテナを使用すると、要素全体を管理できます。



パイプラインは、要素の代わりに要素コンテナーが含まれていることを除いて、ビンに似ています。



このすべての詳細については、 ドキュメントを参照してください



それでは、クラスの実装に移りましょう。


オーディオプレーヤーのクラスは次のようになります。



audioengine.h
#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);
      
      





要素ソース-オーディオファイルの読み取り用。

demuxer-オーディオファイルのデコードに使用されます。

デコーダとconv-オーディオファイルを別の形式に変換します。

音量-音量を制御するように設計されています。

sinc-オーディオデバイスを自動的に検出し、データを出力します...



デマルチプレクサはストリームの各要素に対してソケットを作成し、デマルチプレクサとデコーダを通信するイベントハンドラをインストールする必要があることに注意してください。 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()関数は、ソース要素に引数を渡します。 この場合、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()は、チャネル、時間形式、位置検索フラグ、およびナノ秒単位で測定される位置自体を引数として受け取ります。



完全なコードは、Qtに実装された小さなGUIとのリンクにあります。

GitHabソース



どうもありがとう。



All Articles