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 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를 어떻게 적용하는지 살펴보자.
property parameter는 inspect에서 확인 할수 있다. 수많은 element property가 있지만 wave와 freq을 다음과 같이 입력하여 수정할 수 있다.
gst-launch-1.0 audiotestsrc wave=0 freq=800 ! alsasink
여기에서 주의해야할 문법은 property parameter사이에는 반드시 띄어쓰기(콤마(,)아님)를 한다. 또한 !를 기준으로 앞뒤에 띄어쓰기 한칸이 있어야 한다. 여기에서는 !다음에 바로 sink가 오므로, caps설정 없이 바로 alsasink로 데이터를 보내는 것을 확인할 수 있다.
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의 역할을 할 수 있다.
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를 쓰는법을 알아보자.
앞서 배웠던 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')
이렇게 전체적인 퍼즐을 맞춰가면서, appsink에 도달하게 된다면 cv2에서 사용가능한 stream이 완성된다.
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명령어가 길어지는지 알꺼같다..
감사합니다. 덕분에, 차근차근 예제 따라하면서 인자를 어떻게 넣어야 제가 원하는데로 사용할 수 있는지 배우고 있습니다!
gstreamer 버전 차이 때문일 수 있지만, 작성해주신 example 중에서 audio-x-raw,format=U8 인자를 명령어 입력했을 때, "no element : 'audio-x-raw'"가 나오더라구요.
그래서 gst-inspect 했을 때 나온 것처럼 audio/x-raw로 하니깐 작동을 해서..참고하시면 좋을 것 같습니다!!