📌 요약
GStreamer 공식 튜토리얼 basic-tutorial-5.c가 Wayland 기본 환경에서 Gdk-CRITICAL assertion을 띄우고 GTK 창과 영상이 분리되어 출력됩니다.
원인은 GTK_WINDOW_XID()를 컴파일 타임 매크로로만 분기하고 런타임 백엔드 검사를 하지 않기 때문입니다.
🖥 환경
| 항목 |
값 |
| 장비 |
Raspberry Pi |
| OS |
Raspberry Pi OS (Debian 13 trixie), 2025-12-04 이미지 |
| 커널 |
6.12.75+rpt-rpi-v8 (aarch64) |
| 컴포지터 |
labwc 0.9.2 (Wayland) — Pi OS 현재 기본 |
| GTK |
3.x (X11 + Wayland 백엔드 동시 빌드) |
| GStreamer |
1.x |
| 대상 소스 |
basic-tutorial-5.c |
🔁 재현 절차
gcc basic-tutorial-5.c -o basic-tutorial-5 \
`pkg-config --cflags --libs gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0`
./basic-tutorial-5
기대 동작
GTK 창의 drawing area 안에 sintel_trailer-480p.webm 영상이 합성되어 재생.
실제 동작
(basic-tutorial-5:5860): Gdk-CRITICAL **: gdk_x11_window_get_xid:
assertion 'GDK_IS_X11_WINDOW (window)' failed
- GTK 창 내부는 검은 배경으로 남음
xvimagesink가 자체 창을 새로 띄워 영상을 그 바깥에 출력 → GUI와 영상이 분리
🔍 원인 분석
realize_cb()에서 윈도우 핸들 획득이 컴파일 타임 매크로로만 분기되어 있습니다:
#if defined (GDK_WINDOWING_X11)
window_handle = GDK_WINDOW_XID (window); // ← X11 전용 API
#endif
라즈베리파이 OS를 포함한 대부분의 배포판 GTK3는 X11과 Wayland 백엔드를 동시에 활성화해 빌드되어
GDK_WINDOWING_X11 매크로가 항상 정의됩니다. 하지만 런타임 세션이 Wayland(labwc)면 GdkWindow는
Wayland 윈도우 객체이므로:
GDK_WINDOW_XID() 내부의 GDK_IS_X11_WINDOW() 검사가 실패 → assertion 경고
- 반환된 핸들이 유효하지 않음 →
gst_video_overlay_set_window_handle()에 쓰레기 값 전달
xvimagesink가 자체 fallback 창을 생성 → GUI/영상 분리
즉 튜토리얼 코드가 GTK3 X11을 전용으로 사용한다고 가정하고 작성된 것이 근본 원인입니다.
🩹 우회 방안
XWayland(X11 호환 레이어)로 강제:
GDK_BACKEND=x11 DISPLAY=:0 ./basic-tutorial-5
GDK_BACKEND=x11 : GTK가 X11 경로 선택 (튜토리얼 코드의 가정과 일치)
DISPLAY=:0 : 라즈베리파이 본체 모니터의 XWayland 인스턴스 지정
이 설정으로 실행 시 autovideosink가 xvimagesink를 선택해 정상 합성됨을 확인.
🧪 파이프라인 분석 (부가 조사)
playbin이 런타임에 자동 조립하는 실제 파이프라인(덤프 기반):
GstPlayBin
├── GstURIDecodeBin
│ ├── GstSoupHTTPSrc
│ ├── GstTypeFindElement (감지: video/webm)
│ └── GstDecodeBin
│ ├── GstMatroskaDemux
│ ├── GstMultiQueue
│ ├── GstVP8Dec ← video decoder
│ └── GstVorbisDec ← audio decoder
├── GstStreamSynchronizer
├── GstInputSelector × 2
└── GstPlaySink
├── (vbin) GstQueue → GstVideoConvert → GstVideoScale → GstXvImageSink
└── (abin) GstQueue → GstAudioConvert → GstAudioResample → GstVolume → GstPulseSink
앱이 명시적으로 생성한 엘리먼트는 playbin 하나뿐이며, 나머지는 URI와 시스템
환경(XWayland/PulseAudio)에 따라 자동 autoplug됨.
📚 학습 포인트
- 컴포지터/디스플레이 서버 개념: X11 → Wayland 전환,
Xorg vs Wayland 컴포지터(labwc)의 역할
차이
- XWayland: wlroots 컴포지터의 lazy-start 호환 레이어.
/tmp/.X11-unix/X0 소켓은 미리 떠 있지만
XWayland 프로세스는 X11 클라이언트가 붙는 순간에만 spawn
- GTK 백엔드 선택:
GDK_BACKEND 환경변수로 런타임 강제 가능
- GStreamer
playbin: 단일 엘리먼트로 보이지만 내부에서 src→demux→decode→sink 체인을 자동 조립.
직접 작성한 파이프라인(libcamerasrc ! videoconvert ! v4l2h264enc ! fakesink)과 개념은 동일하나
포맷이 가변일 때 쓰는 고수준 헬퍼
GstVideoOverlay 인터페이스: GUI 창의 네이티브 핸들(XID/HWND/wl_surface)을 싱크에 전달해 외부
윈도우 위에 합성하도록 지시
- 컴파일 타임 vs 런타임 분기: 다중 백엔드를 동시 빌드하는 환경에서는 #if defined만으로는 부족하며 GDK_IS_*_WINDOW() 런타임 검사가 필수
✅ 체크리스트
해당 이슈는 Claude(LLM)의 도움을 받아 원인 분석과 초안 작성을 진행하였습니다.
📌 요약
GStreamer 공식 튜토리얼
basic-tutorial-5.c가 Wayland 기본 환경에서Gdk-CRITICALassertion을 띄우고 GTK 창과 영상이 분리되어 출력됩니다.원인은
GTK_WINDOW_XID()를 컴파일 타임 매크로로만 분기하고 런타임 백엔드 검사를 하지 않기 때문입니다.🖥 환경
6.12.75+rpt-rpi-v8(aarch64)basic-tutorial-5.c🔁 재현 절차
gcc basic-tutorial-5.c -o basic-tutorial-5 \ `pkg-config --cflags --libs gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0` ./basic-tutorial-5기대 동작
GTK 창의 drawing area 안에
sintel_trailer-480p.webm영상이 합성되어 재생.실제 동작
xvimagesink가 자체 창을 새로 띄워 영상을 그 바깥에 출력 → GUI와 영상이 분리🔍 원인 분석
realize_cb()에서 윈도우 핸들 획득이 컴파일 타임 매크로로만 분기되어 있습니다:라즈베리파이 OS를 포함한 대부분의 배포판 GTK3는 X11과 Wayland 백엔드를 동시에 활성화해 빌드되어
GDK_WINDOWING_X11매크로가 항상 정의됩니다. 하지만 런타임 세션이 Wayland(labwc)면GdkWindow는Wayland 윈도우 객체이므로:
GDK_WINDOW_XID()내부의GDK_IS_X11_WINDOW()검사가 실패 → assertion 경고gst_video_overlay_set_window_handle()에 쓰레기 값 전달xvimagesink가 자체 fallback 창을 생성 → GUI/영상 분리즉 튜토리얼 코드가 GTK3 X11을 전용으로 사용한다고 가정하고 작성된 것이 근본 원인입니다.
🩹 우회 방안
XWayland(X11 호환 레이어)로 강제:
GDK_BACKEND=x11: GTK가 X11 경로 선택 (튜토리얼 코드의 가정과 일치)DISPLAY=:0: 라즈베리파이 본체 모니터의 XWayland 인스턴스 지정이 설정으로 실행 시
autovideosink가xvimagesink를 선택해 정상 합성됨을 확인.🧪 파이프라인 분석 (부가 조사)
playbin이 런타임에 자동 조립하는 실제 파이프라인(덤프 기반):앱이 명시적으로 생성한 엘리먼트는
playbin하나뿐이며, 나머지는 URI와 시스템환경(XWayland/PulseAudio)에 따라 자동 autoplug됨.
📚 학습 포인트
Xorgvs Wayland 컴포지터(labwc)의 역할차이
/tmp/.X11-unix/X0소켓은 미리 떠 있지만XWayland 프로세스는 X11 클라이언트가 붙는 순간에만 spawn
GDK_BACKEND환경변수로 런타임 강제 가능playbin: 단일 엘리먼트로 보이지만 내부에서 src→demux→decode→sink 체인을 자동 조립.직접 작성한 파이프라인(
libcamerasrc ! videoconvert ! v4l2h264enc ! fakesink)과 개념은 동일하나포맷이 가변일 때 쓰는 고수준 헬퍼
GstVideoOverlay인터페이스: GUI 창의 네이티브 핸들(XID/HWND/wl_surface)을 싱크에 전달해 외부윈도우 위에 합성하도록 지시
✅ 체크리스트
GDK_BACKEND=x11 DISPLAY=:0)해당 이슈는 Claude(LLM)의 도움을 받아 원인 분석과 초안 작성을 진행하였습니다.