Multimedia/GStreamer

GStreamer pwg: ch. 13 part 1

Roien 2021. 12. 22.
반응형

 

13.     Different Scheduling Modes

 

Ÿ   live streaming

    n  PUSH 선호

Ÿ   on-demand display 를 하는 경우

    n  PULL 선호

    n  ex. video player

 

 

1.     모두 push mode인 경우

    A.     첫 번째 element가 자신의 src pad data push하여 다음 element sink pad에 전달

    B.      두 번째 element sink pad _chain() 함수로 전달 받은 buffer를 처리

                         i.         _chain()은 자신의 src pad gst_pad_push를 호출하여 다음 element sink pad로 전달

 

2.     sink pad pull, src pad push (현재 element pipeline flow control을 담당)

    A.     sink pad pull mode로 활성화 시 GstTask를 시작

                         i.         스레드는 gst_pad_pull_range를 호출하여 upstream element src pad _get_range를 호출

    B.      upstream element _get_range

                         i.         random access하여 buffer를 채움

    C.      전달 받은 buffer source pad push

 

3.      element 내 모든 pad pull mode

    A.     sink src가 모두 pull mode이면, 동작이 다음 element에도 의존

    B.      이말은 나의 src가 먼저 뒤의 element pull slave로 깨어나 get_range를 수행하고,

    C.      여기서 나의 sink pad pull_range를 호출함을 의미

                         i.         , GstTask thread가 안 돌아도 됨 (내가 flow control을 담당하지 않음)

 

 

pad push 혹은 pull mode로 동작할 수 있음

Ÿ   push mode

    n  _chain() operating elements

        s   sink pad혹은 source pad 상의 chain-function을 지님

    n  sink pad 상에 chain-function을 지닌 element data source push

    n  peer element srcpad 상의 gst_pad_push를 사용하면 (앞의 element push 하면)

        s   이것이 현재 element _chain() 을 호출하게 함

        s   이때 element buffer source pad push

    n  dataflow의 시작을 push out을 통해 수행

        s   이후 모든 downstream element들은  _chain함수가 호출됨

 

Ÿ   pull mode

 

 

13.1.     The pad activation stage

READY -> PAUSED로 상태 변경 시 pad activated

source pad부터 활성화 되고 sink pad가 활성화 됨

 

Ÿ   _activate()

    n  pad _activate() 함수가 호출됨

    n  기본으로 "push-mode"로 활성화 됨

        s   gst_pad_activate_mode()가 호출됨 with GST_PAD_MODE_PUSH scheduling mode

    n  _activate() override 가능함

    n  다른 scheduling mode로 결정할 수 있음

 

Ÿ   _activate_mode()

    n  pad가 어떤 mode로 활성화 되었는지 알려줌

 

element pad들은 서로 다른 mode로 동작 가능

 

Ÿ   모든 pad push-mode로 활성화 된 경우

    n  element는 전체적으로 push-mode로 동작함

    n  source element

        s   source pad buffer push하여 downstream element buffer를 받음

        s   , source pad가 동작을 시작

        s   downstream element upstream element가 보낸 buffer sinkpads _chain() 함수를 사용해 받음

            -       _chain() 함수는 source pad 상으로 buffer push out

    n  push-mode로 동작하려면,

        s    sinkpad chain-function이 설정 되어야 함

            -       gst_pad_set_chain_function으로 설정

        s   모든 downstream element는 동일 mode로 동작해야 함

 

 

Ÿ   pull + push

    n  source pad push-mode로 동작하는 동안, sinkpad driving force로 동작

    n  sink pad pipeline 뒤에서 driving force(추진력, 원동력)가 됨

    n  driving force가 되려면, pad는 활성화 될 시 GstTask(thread)를 시작해야 함

        s   thread gst_pad_pull_range을 호출하여 data access하고, 이를 source pad push

    n  ,  element pipeline에서 data flow를 제어함을 의미

    n  이렇게 동작하려면,

        s   모든 downstream element들은 push mode여야 함

        s   모든 upstream element pull-mode 여야 함

 

    n  GST_PAD_MODE_PULL인 경우 (GST_QUERY_SCHEDULING query의 결과가)

        s   source pad들은 downstream element에 의해 PULL mode로 활성화

        s   source pad getrange 함수가 설정 되어 있어야 이 mode로 동작 가능

            -       gst_pad_set_getrange_function

 

Ÿ    element 내 모든 pad PULL mode

    n  task를 시작하는걸 의미하지는 않음

    n  downstream element에서의 pull slave를 의미함

        s   downstream element "주도적"으로 pull 할 것 임

    n  _get_range 함수로 data random access

        s   gst_pad_set_getrange_function으로 설정

    n  element sinkpad를 지닌다면,

        s    pad들과 peer pad들은 PULL access mode로 동작해야함

    n  sink element pull mode,

        s   task를 시작해서 sink pad 상의 get_pad_pull_range를 호출해야만 함

        s   upstream SCHEDULING query GST_PAD_MODE_PULL scheduling mode인 경우에만 가능

 

 

13.2.     pads driving the pipeline

 

Ÿ   sink pad pull mode + src pad push mode

    n  task를 시작하여 pipeline data flow를 시작함

    n  sink pad에서 data에 대해 random access 하여 src data push

    n  유용한 경우

        s   demuxers, parsers 혹은 특정 decoders

            -       data parsing 되지 않은 상태로 전달 되는 경우

    n  ex. MPEG-audio or video stream

            -       이 경우 byte 단위의 정확한 access가 필요함

            -       이런 element들은 push mode로도 동작할 수 있어야 함

        s   특정 audio outputs

            -       input data flow에 대해 control이 필요한 경우

            -       ex. Jack sound server

 

Ÿ   PULL이 유용한 경우는

    n  data에 대한 "주도권"을 가져야 하는 경우임

        s   내가 원하는 시점에 parsing을 적절한 방법으로 할 수 있어야 하는 경우 등

 

 

    1)     upstream element pull mode를 지원하는지 확인

    2)     위가 pull mode면 나의 sink pad pull mode로 활성화

 

 

activate_mode 함수

#include "filter.h"
#include <string.h>
 
static gboolean gst_my_filter_activate (GstPad      * pad,
                                             GstObject   * parent);
static gboolean gst_my_filter_activate_mode (GstPad      * pad,
                                             GstObject   * parent,
                                             GstPadMode    mode,
                         gboolean      active);
static void gst_my_filter_loop      (GstMyFilter * filter);
 
G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT);
GST_ELEMENT_REGISTER_DEFINE(my_filter, "my-filter", GST_RANK_NONE, GST_TYPE_MY_FILTER);
 
static void
gst_my_filter_init (GstMyFilter * filter) {
[..]
  gst_pad_set_activate_function (filter->sinkpad, gst_my_filter_activate);
  gst_pad_set_activatemode_function (filter->sinkpad,
      gst_my_filter_activate_mode);
[..]
}
 
[..]
static gboolean
gst_my_filter_activate (GstPad * pad, GstObject * parent) {
  GstQuery *query;
  gboolean pull_mode;
 
  /* first check what upstream scheduling is supported */
  query = gst_query_new_scheduling ();
 
  if (!gst_pad_peer_query (pad, query)) {
    gst_query_unref (query);
    goto activate_push;
  }
 
  /* see if pull-mode is supported */
  pull_mode = gst_query_has_scheduling_mode_with_flags (query,
      GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
  gst_query_unref (query);
 
  if (!pull_mode)
    goto activate_push;
 
  /* now we can activate in pull-mode. GStreamer will also
   * activate the upstream peer in pull-mode */
  return gst_pad_activate_mode (pad, GST_PAD_MODE_PULL, TRUE);
 
activate_push:
  {
    /* something not right, we fallback to push-mode */
    return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE);
  }
}
 
static gboolean
gst_my_filter_activate_pull (GstPad    * pad,
                 GstObject * parent,
                 GstPadMode  mode,
                 gboolean    active)
{
  gboolean res;
  GstMyFilter *filter = GST_MY_FILTER (parent);
 
  switch (mode) {
    case GST_PAD_MODE_PUSH:
      res = TRUE;
      break;
    case GST_PAD_MODE_PULL:
      if (active) {
        filter->offset = 0;
        res = gst_pad_start_task (pad,
            (GstTaskFunction) gst_my_filter_loop, filter, NULL);
      } else {
        res = gst_pad_stop_task (pad);
      }
      break;
    default:
      /* unknown scheduling mode */
      res = FALSE;
      break;
  }
  return res;
}

  

#define BLOCKSIZE 2048
 
    static void
    gst_my_filter_loop (GstMyFilter * filter) {
      GstFlowReturn ret;
      guint64 len;
      GstBuffer *buf = NULL;
 
      if (!gst_pad_query_duration (filter->sinkpad, GST_FORMAT_BYTES, &len)) {
        GST_DEBUG_OBJECT (filter, "failed to query duration, pausing");
        goto stop;
      }
 
       if (filter->offset >= len) {
        GST_DEBUG_OBJECT (filter, "at end of input, sending EOS, pausing");
        gst_pad_push_event (filter->srcpad, gst_event_new_eos ());
        goto stop;
      }
 
      /* now, read BLOCKSIZE bytes from byte offset filter->offset */
      ret = gst_pad_pull_range (filter->sinkpad, filter->offset,
          BLOCKSIZE, &buf);
 
      if (ret != GST_FLOW_OK) {
        GST_DEBUG_OBJECT (filter, "pull_range failed: %s", gst_flow_get_name (ret));
        goto stop;
      }
 
      /* now push buffer downstream */
      ret = gst_pad_push (filter->srcpad, buf);
 
      buf = NULL; /* gst_pad_push() took ownership of buffer */
 
      if (ret != GST_FLOW_OK) {
        GST_DEBUG_OBJECT (filter, "pad_push failed: %s", gst_flow_get_name (ret));
        goto stop;
      }
 
      /* everything is fine, increase offset and wait for us to be called again */
      filter->offset += BLOCKSIZE;
      return;
 
    stop:
      GST_DEBUG_OBJECT (filter, "pausing task");
      gst_pad_pause_task (filter->sinkpad);
    }

 

Ÿ   pull sink pad task input output에 대한 제어를 수행

    n  input을 읽고 이를 source pad 'PUSH'

Ÿ   예전 push mode 보다는 유연함을 제공함

 

 

반응형

'Multimedia > GStreamer' 카테고리의 다른 글

GStreamer pwg: ch 12  (0) 2021.12.22
GStreamer pwg: ch 13  (0) 2021.12.22
GStreamer pwg: ch 13 part 2  (0) 2021.12.22
GStreamer pwg: ch. 14  (0) 2021.12.22
GStreamer pwg: ch. 15  (0) 2021.12.22

댓글