LoginSignup
3
4

More than 3 years have passed since last update.

gstreamerのサンプルコードをmacで動かしてみた(gstreamer、c、c++)

Last updated at Posted at 2020-12-11

はじめに

この記事は「完全に理解したTalk Advent Calendar 2020」11日目の投稿記事です。
gstreamerを使う必要があり、頑張ってたら完全理解してしまったのでその話をします。

OSはMacOS
言語はc/c++
cmakeでビルドします。

gstreamerとは

C言語で作られたライブラリで、
動画のストリーミングほか、メディアプレイヤーの再生などに使われます。
メインの処理以外は、プラグイン、ライブラリを読み込んで処理が行われています。
Wikipediaさんより

インストール

brewでインストールします。

$ brew update #必要であれば
$ brew install gstreamer
$ brew install gst-plugins-base
$ brew install gst-plugins-good
$ brew install gstreamermm #c++でバインドしたライブラリ

必要なものはこれらです。

$ brew install gst-plugins-ugly
$ brew install gst-plugins-bad

妙な名前でざわつくものもありますが、ugly、badは飛ばして大丈夫です。
公式に説明があるようです。。

パスを通す

$ brew link gstreamer
$ brew link gst-plugins-base
$ brew link gst-plugins-good
$ brew link gstreamermm #c++でバインドしたライブラリ

brew linkで /usr/local/lib/usr/local/includeにシンボリックリンクします。

cmakeを書く

gstreamerはcmakeのfindPackageは使えません。
ですが、pkg-configを使っていますのでcmakeでpkg_configを使ってリンクします。

cmake内で使われるpkg_configはパスが通っていない場合がありますので、
set(ENV{PKG_CONFIG_PATH} "/usr/local/lib/pkgconfig")
で一時的にパスを通します。
brewでインストールしリンクしたものは、/usr/local/lib/にあります。

cmake_minimum_required(VERSION 3.15)
project(testGstreamer)

set(CMAKE_CXX_STANDARD 14)

set(ENV{PKG_CONFIG_PATH} "/usr/local/lib/pkgconfig")
find_package(PkgConfig REQUIRED)

#pkg_check_modules(GSTREAMER_LIB REQUIRED IMPORTED_TARGET  gstreamer-1.0) cで使う場合はこっち
pkg_check_modules(GSTREAMERMM_LIB REQUIRED  gstreamermm-1.0)

add_executable(testGstreamer main.cpp)


target_include_directories(testGstreamer PUBLIC ${GSTREAMERMM_LIB_INCLUDE_DIRS})
target_link_libraries(testGstreamer ${GSTREAMERMM_LIB_LIBRARIES})
target_compile_options(testGstreamer PUBLIC ${GSTREAMERMM_CFLAGS_OTHER})

#target_include_directories(testGstreamer PUBLIC ${GSTREAMER_LIB_INCLUDE_DIRS}) cで使う場合はこっち
#target_link_libraries(testGstreamer ${GSTREAMER_LIB_LIBRARIES}) cで使う場合はこっち
#target_compile_options(testGstreamer PUBLIC ${GSTREAMER_CFLAGS_OTHER}) cで使う場合はこっち

exampleから引っ張ってきたコード

ここのexampleをビルドしました。


#include <gstreamermm.h>
#include <glibmm/main.h>
#include <glibmm/convert.h>
#include <iostream>
#include <stdlib.h>
#include <gstreamermm/playbin.h>

namespace
{

Glib::RefPtr<Glib::MainLoop> mainloop;

// This function is used to receive asynchronous messages in the main loop.
bool on_bus_message(const Glib::RefPtr<Gst::Bus>& /* bus */,
                    const Glib::RefPtr<Gst::Message>& message)
{
  switch(message->get_message_type()) {
  case Gst::MESSAGE_EOS:
    std::cout << std::endl << "End of stream" << std::endl;
    mainloop->quit();
    return false;
  case Gst::MESSAGE_ERROR:
  {
    Glib::RefPtr<Gst::MessageError> msgError =
        Glib::RefPtr<Gst::MessageError>::cast_static(message);

    if(msgError)
    {
      Glib::Error err;
      err = msgError->parse_error();
      std::cerr << "Error: " << err.what() << std::endl;
    }
    else
      std::cerr << "Error." << std::endl;

    mainloop->quit();
    return false;
  }
  default:
    break;
  }

  return true;
}

} // anonymous namespace

int main(int argc, char** argv)
{
  // Initialize gstreamermm:
  Gst::init(argc, argv);

  // Check input arguments:
  if(argc < 2)
  {
    std::cout << "Usage: " << argv[0] << " <media file or uri>" << std::endl;
    return EXIT_FAILURE;
  }

  // Create a playbin element.
#ifndef GSTREAMERMM_DISABLE_DEPRECATED
  Glib::RefPtr<Gst::PlayBin> playbin = Gst::PlayBin::create();
#else
  Glib::RefPtr<Gst::Element> playbin = Gst::ElementFactory::create_element("playbin");
#endif

  if(!playbin)
  {
    std::cerr << "The playbin2 element could not be created." << std::endl;
    return EXIT_FAILURE;
  }

  // Take the commandline argument and ensure that it is a uri:
  Glib::ustring uri;

  if(gst_uri_is_valid(argv[1]))
    uri = argv[1];
  else
    uri = Glib::filename_to_uri(argv[1]);

  // Set the playbyin2's uri property.
  playbin->set_property("uri", uri);

  // Create the main loop.
  mainloop = Glib::MainLoop::create();

  // Get the bus from the playbin, and add a bus watch to the default main
  // context with the default priority:
  Glib::RefPtr<Gst::Bus> bus = playbin->get_bus();
  bus->add_watch(sigc::ptr_fun(&on_bus_message));

  // Now set the playbin to the PLAYING state and start the main loop:
  std::cout << "Setting to PLAYING." << std::endl;
  playbin->set_state(Gst::STATE_PLAYING);
  std::cout << "Running." << std::endl;
  mainloop->run();

  // Clean up nicely:
  std::cout << "Returned. Setting state to NULL." << std::endl;
  playbin->set_state(Gst::STATE_NULL);

  return EXIT_SUCCESS;
}

実行

$ ./testGstreamer https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm
Setting to PLAYING.
Running.

End of stream
Returned. Setting state to NULL.

スクリーンショット 2020-12-11 18.31.40(2).png

上のような画面が出てダウンロードしながら再生が行われます。
また、実行時、引数をローカルファイルにしても再生されますし、
mp3でも再生が行われます。

終わりに

今回は、gstreamerを使わないといけなくなったので、
まずは試しで使いました。

コマンドとしても用意されていますので、色々遊べると思います。

参考

公式
公式リファレンス

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4