2

私が書いているアプリケーションの gstreamer-1.0 に .png 画像 (アルファ チャネル付き) をオーバーレイしようとしていますが、Web を何度も検索してドキュメントを読んだ後でも、その方法について多少混乱しています。使用する。

私が使用している方法は次のとおりです。

filesrc -> pngdec -> imagefreeze -> videoconvert -> videoscale ->videomixer -> output_of_bin input_of_bin -> videoconvert -> videoscale ->|

これは、より大きなアプリケーションの小さなセクションです。

私の問題は、videoscale 要素と videoconvert 要素のプロパティを設定することです。GSTCaps を使用することになっていると思いますが、これは機能しません。私は多くの方法を試しました。これは、オーバーレイを提供するクラスのメンバー関数です。コードが乱雑であることをあらかじめお詫びしますが、これは実験的なものです。

bool ImageOverlay::CreateElement()
{
  GstPad *source_pad, *sink_pad;
  GstElement *file_source, *png_decoder, *freeze, *colorspace,
      *video_mixer, *identity, * colorspace2, *video_scale_1, *video_scale_2;

  /* Create gstreamer elements */
  _image_overlay_element = gst_bin_new("image-player");

  if(!_image_overlay_element)
  {
    g_printerr ("Pipeline could not be created. Exiting.\n");
    return false;
  }

  // Create file source
  file_source = gst_element_factory_make ("multifilesrc",  "file-source");
  g_object_set (G_OBJECT (file_source), "location", "../Template1.png", NULL);

  if(!file_source)
  {
    g_printerr ("File could not be created. Exiting.\n");
    return false;
  }

  // Decode file
  png_decoder  = gst_element_factory_make ("pngdec", "png-decoder");
  if(!png_decoder)
  {
    g_printerr ("png-decoder could not be created. Exiting.\n");
    return false;
  }

  // Create colour space convertor
  colorspace = gst_element_factory_make("videoconvert", "colorspace");
  if(!colorspace)
  {
    g_printerr ("Colorspace could not be created. Exiting.\n");
    return false;
  }

  // Create colour space convertor
  colorspace2 = gst_element_factory_make("videoconvert", "colorspace2");
  if(!colorspace)
  {
    g_printerr ("Colorspace could not be created. Exiting.\n");
    return false;
  }

  // Create idenentiy component, does nothing but is useful for debug
  identity = gst_element_factory_make("identity", "identity");
  if(!identity)
  {
    g_printerr ("Colorspace could not be created. Exiting.\n");
    return false;
  }

  // Create a video mixer
  video_mixer = gst_element_factory_make("videomixer", "mixer");
  if(!video_mixer)
  {
    g_printerr ("videomixer could not be created. Exiting.\n");
    return false;
  }

  // Create a freeze element
  freeze = gst_element_factory_make("imagefreeze", "freeze");
  if(!freeze)
  {
    g_printerr ("ImageFreeze could not be created. Exiting.\n");
    return false;
  }

  video_scale_1 = gst_element_factory_make("videoscale", NULL);
  if(!video_scale_1)
  {
    g_printerr ("video_scale_1 could not be created. Exiting.\n");
    return false;
  }

  video_scale_2 = gst_element_factory_make("videoscale", NULL);
  if(!video_scale_2)
  {
    g_printerr ("video_scale_2 could not be created. Exiting.\n");
    return false;
  }

  // Add to the bin
  gst_bin_add_many (GST_BIN (_image_overlay_element),
                    file_source,
                    png_decoder,
                    colorspace,
                    colorspace2,
                    freeze,
                    video_mixer,
                    identity,
                    video_scale_1,
                    video_scale_2,
                    NULL);


  if (!gst_element_link_many (file_source, png_decoder, video_scale_1, freeze, NULL))
  {
    std::cout << "Could not link" << std::endl;
  }

  GstCaps * caps = gst_caps_new_simple ("video/x-raw",
                                        "format", G_TYPE_STRING, "ARGB",
                                        NULL);


  GstCaps * caps2 = gst_caps_new_simple("width", G_TYPE_INT, 640,
                                        "height", G_TYPE_INT, 480,
                                        NULL);

  gst_element_link_filtered(video_scale_1, freeze, caps2);
  gst_element_link_filtered(video_scale_2, freeze, caps2);

  if (!gst_element_link_many(freeze, video_scale_2, colorspace, NULL))
  {
    std::cout << "Could not link" << std::endl;
  }

  // Link pads to video mixer
  GstPad * sink_pad_1 = gst_element_get_request_pad (video_mixer, "sink_%u");
  GstPad * sink_pad_2 = gst_element_get_request_pad (video_mixer, "sink_%u");
  GstPad * source_2 = gst_element_get_static_pad (identity, "src");
  GstPad * source_1 = gst_element_get_static_pad (colorspace, "src");

  gst_pad_set_caps(source_2, caps);
  gst_pad_set_caps(source_1, caps);
  gst_caps_unref(caps);

  if (!gst_pad_link ( source_1, sink_pad_1) == GST_PAD_LINK_OK)
  {
    std::cout << "Could not link pads" << std::endl;
    return false;
  }

  if (!gst_pad_link ( source_2, sink_pad_2) == GST_PAD_LINK_OK)
  {
    std::cout << "Could not link pads" << std::endl;
    return false;
  }

  gst_pad_set_active(source_1, true);
  gst_pad_set_active(sink_pad_1, true);
  gst_pad_set_active(source_2, true);
  gst_pad_set_active(sink_pad_2, true);

  // Add pad to this element
  source_pad = gst_element_get_static_pad (video_mixer, "src");
  sink_pad = gst_element_get_static_pad(identity, "sink");
  gst_element_add_pad (_image_overlay_element, gst_ghost_pad_new ("src", source_pad));
  gst_element_add_pad (_image_overlay_element, gst_ghost_pad_new ("sink", sink_pad));

  return true;
}

両方のソースのサイズを同じサイズに変更し、png 画像をビデオにオーバーレイしたいと思います。ブロックは主に機能しますが、サイズ変更やアルファ チャネルを機能させることができません。

ありがとう、

編集:

コードを修正して少し理解が深まりましたが、問題は、RGBA を使用すると capfilter がリンクされず、他のフォーマットは機能するが役に立たないことです。理由がわかりません。

bool ImageOverlay::MakeElements()
{
  try
  {
    // Creates the bin at this level
    CreatePipeline();
    GstElement *file_source, *png_decoder, *freeze, *colorspace,
        *video_mixer, *identity, * colorspace2, *video_scale_1, *video_scale_2, *caps_filter1, *caps_filter2;

    // Create elements
    file_source = CreateElementAndAddToBin("multifilesrc",  "file-source");
    png_decoder   = CreateElementAndAddToBin("pngdec", "png-decoder");
    colorspace    = CreateElementAndAddToBin("videoconvert", "colorspace");
    colorspace2   = CreateElementAndAddToBin("videoconvert", "colorspace2");
    identity      = CreateElementAndAddToBin("identity", "identity");
    video_mixer   = CreateElementAndAddToBin("videomixer", "mixer");
    freeze        = CreateElementAndAddToBin("imagefreeze", "freeze");
    video_scale_1 = CreateElementAndAddToBin("videoscale", "scale1");
    video_scale_2 = CreateElementAndAddToBin("videoscale", "scale2");
    caps_filter1  = CreateElementAndAddToBin("capsfilter", "caps_filter1");
    caps_filter2  = CreateElementAndAddToBin("capsfilter", "caps_filter2");

    // Set input file
    g_object_set (G_OBJECT (file_source), "location", "../Template1.png", NULL);

    // Create caps
    GstCaps *caps = gst_caps_new_simple ("video/x-raw",
                                         "format", G_TYPE_STRING, "YV12", //<<< IF THIS IS SET TO ARGB (THE FORMAT I WANT IT FAILS ON LINKING)
                                         "framerate", GST_TYPE_FRACTION, 25, 1,
                                         "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
                                         "width", G_TYPE_INT, 640,
                                         "height", G_TYPE_INT, 480,
                                         NULL);


    // Set caps on cap filter
    g_object_set(G_OBJECT(caps_filter2), "caps", caps, NULL);
    g_object_set(G_OBJECT(caps_filter1), "caps", caps, NULL);


    // Link up elements
    if (!gst_element_link_many (identity, video_scale_2, colorspace2, caps_filter2, video_mixer, NULL))
    {
      std::cout << "Could not link input branch" << std::endl;  //<<<< IF ARGB OR OTHER FORMATS SUCH AS RGBA ARE USED
    }                                                           // IN CAP FILTER, THIS FAILS, SAME WITH BELOW. IT WORKS WITH YV12!

    if (!gst_element_link_many (file_source, png_decoder, freeze, video_scale_1, colorspace, caps_filter1, video_mixer, NULL))
    {
      std::cout << "Could not link image source branch" << std::endl;
    }

    // Add ghost pads to this bin, allowing it to be used as an element
    SetInputElement(identity);
    SetOutputElement(video_mixer);
  }
  catch(...)
  {
    std::cout << "Overlay generator failed to build, exception thrown" << std::endl;

    // TODO - Clear up in here
    return false;
  }

  return true;
}
4

1 に答える 1