Gstreamer command 정리

‍정승우·2021년 8월 29일
0
post-thumbnail

Gstreamer란?

gstreamer는 여러가지 데이터 소스들이 유기적으로 다른 어플리케이션이나 프로그램에 스트림이 될수있도록 데이터를 변형하고 사용가능하도록 만들어주는 역할을 한다.
카메라를 작동시킬때 필요한 가장 기본적인 gstreamer의 command를 매번 복붙해서 사용하다 보니 property, capability등에 필요한 파라미터 설정법과 같이 pipeline의 문법을 이해하면 cmd에서나 cv2.Videocapture에서 유연한 대처를 할 수 있을것이라 생각한다.

유튜브에서 유명한 폴아저씨의 설명을 토대로 내용을 정리해 보았다.
[출처] 폴아저씨 유튭

  • 처음 예제
cv2.VideoCapture('nvarguscamerasrc sensor-id=0 \
! video/x-raw(memory:NVMM), width=3264, height=2464, framerate=21/1,format=NV12 \
! nvvidconv flip-method=0 ! video/x-raw, width=1920, height=1080, format=BGRx\
! videoconvert ! video/x-raw, format=BGR ! appsink')
  • src1 -> sink1 -> sink2 ...
    전체적으로 !를 경계로 하여 처음엔 source이고, 중간중간은 format을 변형시키는 모듈이 존재하며, 마지막에는 stream을 하는 sink로 데이터를 전달하는 Pipeline을 형성하게 된다.
    src는 카메라, 마이크 등과 같이 입력장치에서 도출되고, 이렇게 src1를 변형하면 sink1에 input으로 집어 넣게 된다. 하지만 또다른 sink2로 연결하게되면 sink1은 sink2입장에서 src가 될수 있다.
    이렇게 사용되는 어법을 이해하고 어떤 인자가 필요한지 확인하고 다룰줄 안다면 굳이 전체 커맨드를 외우거나 복붙을 하지 않아도 사용가능하다!!

  • 설치사항

sudo apt-get install v4l-utils

gst-launch-1.0 & gst-inspect-1.0

audio demo cmd

 gst-launch-1.0 audiotestsrc ! alsasink

audiotestsrc(source) -> alsasink(sink) 우웅 하는소리가 들리게 된다.

단순히 소리를 들려주는 이 소스에서 어떤 인자들이 필요하고, 설정을 해줘야 하는지 확인을 하고자 한다면 다음과 같이 입력을 해주면 된다

 gst-inspect-1.0 audiotestsrc
 gst-inspect-1.0 alsasink

이러면 source의 factory detail, plugin detail등 온갖정보를 모두 확인할수있다.
여기서 주요하게 확인해야하는 내용은 Pad부분이다. 모듈별로 설정 가능한 것은 크게 properties와 capabilities로 나뉘는데 이를 여기에서 확인 할 수 있다.
또한 Pad에서 src로만 표현되는 모듈은 그저 src로만 사용가능하고, sink가 있는 경우는 그렇지 않다.
이제 inspect를 이용하여 확인한 property와 caps를 어떻게 적용하는지 살펴보자.

1) properties

property parameter는 inspect에서 확인 할수 있다. 수많은 element property가 있지만 wave와 freq을 다음과 같이 입력하여 수정할 수 있다.

 gst-launch-1.0 audiotestsrc wave=0 freq=800 ! alsasink

여기에서 주의해야할 문법은 property parameter사이에는 반드시 띄어쓰기(콤마(,)아님)를 한다. 또한 !를 기준으로 앞뒤에 띄어쓰기 한칸이 있어야 한다. 여기에서는 !다음에 바로 sink가 오므로, caps설정 없이 바로 alsasink로 데이터를 보내는 것을 확인할 수 있다.

2) caps (capabilities)

inspect를 통해 확인하면 다음과 같은 설명이 있다.

Capabilities:
  audio/x-raw
              format:{ (string)S8, (string)U8,.....

이처럼 src와 sink에서 제공가능하고, 입력가능한 포맷이 존재한다. 따라서 그에 맞게 변환하는 과정을 포함해야 src에서 sink로 전달이 가능하다. 앞선 예제에서는 caps설정이 없어도 잘 작동한 것을 확인 할 수 있다. 이때는 default값이 잘 맞았기 때문에 따로 설정할 필요가 없었지만 연습을 위해서 caps를 설정해보자

  • 올바르게 작동하는 경우
 gst-launch-1.0 audiotestsrc wave=0 freq=800 ! audio-x-raw,format=U8 ! alsasink

위와같이 입력한다면 작동이 잘 될것이다. audiotestsrc에서 audio-x-raw,format=U8 형태로 전달할 능력이 되고, alsasink에서도 받아들일 수 있기 때문이다.

  • 올바르게 작동하지 않는 경우
 gst-launch-1.0 audiotestsrc wave=0 freq=800 ! audio-x-raw,format=U18LE ! alsasink

이번에는 format인 U18LE로 적용시켜보면 에러가 나온다. inspect로 찾아보면 U18LE는 src에서는 제공가능하지만 sink에서는 호환되지 않기 때문에다. 연습을 위해 굳이 U18LE를 사용하여 alsasink에 전달하고자 한다면 다음과 같이 convert를 한번 더 해주어야 한다.

 gst-launch-1.0 audiotestsrc wave=0 freq=800 ! audio-x-raw,format=U18LE ! audioconvert ! alsasink
 
  gst-launch-1.0 audiotestsrc wave=0 freq=800 ! audio-x-raw,format=U18LE ! audioconvert ! audio-x-raw,format=U8 ! alsasink

두 command중 위의 경우에는 audioconvert에 format caps를 따로 지정하지 않았다. 이경우에 alsasink가 요구하는 format에 자동으로 맞추어 전달하게 된다. 한편, 아래의 경우에는 format=U8으로 지정하여 전달했다는 것이 차이점이다.

audioconvert의 경우, inspect를 통해 확인해보면, src와 sink 두가지 pad내용이 존재한다.
이는 앞서 말했던 scr1->sink1->sink2에서 src1입장에서는 sink1이 sink이면서 동시에 sink2입장에서는 src인 경우에 해당한다. 이와같이 sink와 src 두가지 모두에 사용가능한 모듈이 convert의 역할을 할 수 있다.

videotestsrc 예제

gst-launch-1.0 videotestsrc ! ximagesink
gst-launch-1.0 videotestsrc pattern=11 ! ximagesink # pattern property변경

위의 입력은 실행이 잘된다. 여기에서도 마찬가지로, src의 format을 변형하여 sink에 넣는 연습을 해보고자 다음과 같이 입력을 해보면, 에러가 발생한다.

#에러발생
gst-launch-1.0 videotestsrc ! video/x-raw,format=BGR ! ximagesink

따라서 gst-inspect-1.0을 이용하여 ximagesink의 caps에 format에 대한 내용을 확인해보면, 확인이 되지 않는다는것을 알 수 있다. 이 경우에 간편하게 autovideoconvert를 이용하면 작동하게 된다.

gst-launch-1.0 videotestsrc pattern=11 ! video/x-raw,format=BGR ! autovideoconvert ! ximagesink

이를 이용하면 sink와 src사이에 연동가능한 format으로 자동변환되어 전달된다.
이제 format에 대한 걱정은 없다. 여기에서 해상도에 대한 변환을 하고싶다면 videoconvert의 caps를 이용해 다음과 같이 해상도를 변경할 수 있다.

gst-launch-1.0 videotestsrc ! video/x-raw,format=BGR ! autovideoconvert ! videoconvert ! video/x-raw, width=1280, height=960 ! ximagesink

"boom look at that! giddyup!" -Paul McWhorter

이렇게 모듈의 사용법, 필요한 property, caps확인법을 알았으니 jetson nano, xavier와 같은 nvidia기기에서 평소에 많이 쓰던 nvarguscamerasrc를 쓰는법을 알아보자.

nvarguscamerasrc & nvvidconv

(Nvidia arguments camera src & Nvidia video convert)

앞서 배웠던 autovideoconvert를 이용해 nvarguscamerasrc와 ximagesink사이의 연결을 자동으로 할수 있다.

#### nvarguscamerasrc : module that represents the camera ####
gst-launch-1.0 nvarguscamerasrc ! autovideoconvert ! ximagesink

또한 nvvidconv를 이용해 videoconvert와 같은 역할을 수행한다.

gst-launch-1.0 nvarguscamerasrc ! \
nvvidconv flip-method=2 ! video/x-raw,width=1280,height=840 ! \
autovideoconvert ! ximagesink

nvarguscamerasrc의 caps에는 video/x-raw와 video/x-raw(memory:NVMM) 두가지 caps가 존재한다. video/x-raw와 다르게 video/x-raw(memory:NVMM)를 사용할땐 설정에 괄호가 있기때문에 ' '(따옴표)를 이용하여 caps를 설정해야 한다. 반면 cv2.VideoCapture에서는 ' '를 사용하지 않아도 된다.

gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM),width=3264,height=2464,framerate=21/1' ! \
nvvidconv flip-method=2 ! video/x-raw,width=640,height=480 ! \
autovideoconvert ! ximagesink

여기서 tip은 nvarguscamerasrc의 cap에서 절대 축소된 모드의 해상도를 사용하면 안된다. 만약 최대 지원 해상도가 3264x2464처럼 큰경우에, 1920x1080을 사용하게 된다면, 주어진 FOV를 모두 사용하는것이 아니라 단지 crop을 한 버전에 불과하게 된다.

다시 이전예제로 돌아가 지금까지 배운내용으로 확인을 해보자.

cv2.VideoCapture('nvarguscamerasrc sensor-id=0 \ #Properties for nvarguscamerasrc
! video/x-raw(memory:NVMM), width=3264, height=2464, framerate=21/1,format=NV12 \ #Caps for nvarguscamerasrc
! nvvidconv flip-method=0 \ #Properties for nvvidconv
! video/x-raw, width=1920, height=1080, format=BGRx\ #Caps for nvvidconv
! videoconvert ! video/x-raw, format=BGR \ #Caps for videoconvert
! appsink')
  • nvarguscamerasrc
    • prop : sensor-id를 설정하여 카메라를 선택한다.
    • caps : 해상도와 format을 선택한다. 반드시 최대 해상도로 설정하도록 한다
  • nvvidconv
    • prop : flip-method를 통해 회전을 어떻게 할것인지 결정한다.
    • caps : videoconvert에 입력으로 집어넣기 위해 nvmm메모리에서 video/x-raw로 메모리를 전환하고, 해상도와 format을 바꾼다.
  • videoconvert
    • no prop
    • caps : appsink에서 요구하는 BGR형식으로 변환한다.
  • appsink : appsink는 현재 app에서 기본적으로 가능한 format으로 데이터를 dump시키는 sink이다. 여기에서는 app이 openCV이므로, openCV에 맞게 전달해준다는 의미

이렇게 전체적인 퍼즐을 맞춰가면서, appsink에 도달하게 된다면 cv2에서 사용가능한 stream이 완성된다.

추가 내용 improving image

  • nvarguscamerasrc
    이어지는 강의의 후속편에서 어떻게 해야 이미지가 더욱 선명하게 보이는지 property를 설정하는 부분이 나온다. Improving image from cam link (ee-mode & ee-strength, wbmode, tnr-mode & tnr-strength 등등..)
  • videobalance
    brightness, saturation등 이미지 미세조정에 사용된다.
cv2.VideoCapture('nvarguscamerasrc sensor-id=0 tnr-mode=2 wbmode=3\ #Properties for nvarguscamerasrc 
! video/x-raw(memory:NVMM), width=3264, height=2464, framerate=21/1,format=NV12 \ #Caps for nvarguscamerasrc
! nvvidconv flip-method=0 \ #Properties for nvvidconv
! video/x-raw, width=1920, height=1080, format=BGRx\ #Caps for nvvidconv
! videoconvert ! video/x-raw, format=BGR \ #Caps for videoconvert
! videobalance contrast=1.5 saturation=? brightness=-.2 \ #video improving
! appsink')

강의를 다듣고 나니 왜 gstreamer명령어가 길어지는지 알꺼같다..

1개의 댓글

comment-user-thumbnail
2022년 8월 26일

감사합니다. 덕분에, 차근차근 예제 따라하면서 인자를 어떻게 넣어야 제가 원하는데로 사용할 수 있는지 배우고 있습니다!

gstreamer 버전 차이 때문일 수 있지만, 작성해주신 example 중에서 audio-x-raw,format=U8 인자를 명령어 입력했을 때, "no element : 'audio-x-raw'"가 나오더라구요.

그래서 gst-inspect 했을 때 나온 것처럼 audio/x-raw로 하니깐 작동을 해서..참고하시면 좋을 것 같습니다!!

답글 달기

관련 채용 정보