본문 바로가기
프로젝트/원격 제어 프로그램

비동기 GPU 인코딩에서 peer가 바뀌던 문제, 프레임에 소유자를 심다

by iwbap 2026. 10. 18.
728x90
반응형

원격 제어 프로그램의 GPU H.264 송출을 점검하며 비동기 시작 시점의 peer 식별 문제를 수정했다. 정지 화면 보완 범위도 조정했지만, NVIDIA 현장의 해결 여부는 아직 확인하지 못했다.

비동기 GPU 인코더 시작 시 전역 peer 힌트 대신 프레임에 소유자를 심어 MFT를 연다는 문구와 정지 화면 화질 보완·QP 가드 흐름을 담은 대표 이미지
전역 peer 추정 대신 프레임에 소유자를 심고, 정지 화면 보완과 QP 가드를 좁힌 기록

비동기 InitEncode가 놓친 소유자

WebRTC의 InitEncode는 비동기로 실행되므로 이 단계에는 담당 peer가 확정되지 않았다. 기존에는 프로세스 전역의 active peer 힌트를 이용해 소유자를 추정했다.

이 힌트의 스코프가 인코더 태스크보다 먼저 끝나면 다른 peer의 MaxQP가 묶일 위험이 있었다. 소유자가 없는 인코더 하나에 peer를 임의 연결하던 예외 처리도 제거했다.

소유 프레임이 도착한 뒤 MFT를 열었다

캡처 프레임에 peer ID와 정지 보완 플래그를 담는 불변 wrapper를 도입했다. 자르기와 크기 조정 후에도 동일 정보를 유지하도록 새 wrapper로 감쌌다.

이제 InitEncode에서는 비트레이트와 FPS만 기록하고 MFT를 곧바로 열지 않는다. 첫 소유 프레임으로 실제 owner를 확인한 뒤 MFT를 열며, 이후 소유자가 다르면 소프트웨어로 전환한다.

아래는 핵심 분기만 남긴 단순화한 예시다. 실제 코드에는 진단 로그와 fallback 사유 기록이 더 붙어 있다.

if (!opened_) {
    if (!hardware_->Open(width_, height_, fps_, bitrate_, owner))
        return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
    opened_ = true;
    owner_ = owner;
} else if (owner != owner_) {
    return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
}

peer별 품질 요청은 큐에 남겨 최초 MFT 초기화 시 적용하도록 했다. 전역 힌트로 소유자를 추정하던 경로는 더 이상 사용하지 않게 했다.

동시 연결 3개로 로컬 시험했을 때, 최초 MFT의 소유 peer와 요청 MaxQP가 일치했다. NV12/I420 전환과 해상도 재초기화 후에도 최신 설정이 남았다.

수정 전에는 InitEncode가 비동기로 돌 때 프로세스 전역 active peer 힌트로 소유자를 추정해 스코프가 먼저 끝나면 다른 peer의 MaxQP가 묶일 수 있었고, 수정 후에는 캡처 프레임에 peer ID와 정지 보완 플래그를 심은 불변 wrapper로 crop/scale 뒤에도 소유자를 유지한 채 첫 owned 프레임에서야 MFT를 여는 구조를 비교한 도식

정지 화면 보완은 세 모드에 적용했다

기존에는 성능 모드의 정지 화면 보완이 꺼져 있었다. 이번에는 성능·균형·품질 모드 모두 refineWhenStill을 켜도록 바꿨다.

모드별 인코더 정책은 품질·속도 우선값과 MaxQP 상한의 조합이다. 성능 25/40, 균형 50/32, 품질 75/24이며, 이번에 바뀐 것은 성능 모드의 정지 보완 여부 하나뿐이다.

다만 상한은 예전과 같다. 8회 / 2초를 넘기면 멈춘다. 연속 30FPS 재전송이나 무제한 키프레임 요청은 넣지 않았다. 보완 프레임에는 표시 플래그를 붙여, 인코더 쪽이 일반 움직임과 구분할 수 있게 했다.

성능·균형·품질 세 모드 모두 정지 화면 보완을 켜되 기존처럼 8회 또는 2초 상한에서 멈추고 연속 30FPS 재전송이나 무제한 키프레임 요청은 넣지 않는 정지 화면 화질 보완 흐름을 나타낸 도식

높은 QP가 이어질 때만 소프트웨어로

정지 보완인데도 보고 QP가 요청 상한보다 크게 남는 경우가 있다. 그때만 탈출구를 두었다. 비트레이트 예산이 2Mbps 이상인 정지 보완에서, 보고 QP가 요청 MaxQP+6을 넘는 프레임이 4회 연속이면 그 인코더만 WebRTC 소프트웨어로 넘긴다.

비트레이트 예산 2Mbps 이상인 정지 보완에서 보고 QP가 요청 MaxQP+6을 넘는 프레임이 4회 연속일 때만 해당 GPU 인코더를 WebRTC 소프트웨어 fallback으로 넘기고, 한 번 높은 QP·QP 미확인·이동 장면·저대역폭만으로는 GPU를 끄지 않는 RefinementQualityGuard 조건을 나타낸 도식

  • 한 번 높은 QP만으로는 GPU를 끄지 않는다.
  • QP 미확인 프레임도 단독으로 전환 조건이 되지 않는다.
  • 이동 장면이나 저대역폭만으로 GPU를 끄지 않는다.

보고 QP가 유효하고 요청 MaxQP가 1~51 범위일 때만 위 조건을 판정한다. 이 임계값은 초기 보수 정책이므로 NVIDIA 실사용 시험이 더 필요하다.

GPU 인코더 설정과 종료 순서를 다룬 이전 글은 H.264 MaxQP와 GPU 인코더 종료 기록에서 볼 수 있다. 이번 수정에서는 그때 다듬은 종료 확인 절차를 실패한 텍스처 인코더 정리에도 그대로 썼다.

실패한 텍스처 MFT를 먼저 정리했다

공유 텍스처 MFT가 실패하면 이전 세션을 종료·초기화한 뒤 packed 경로로 재시도하게 했다. 실패한 비동기 세션의 늦은 출력이 다음 결과에 섞이는 위험을 막기 위한 변경이었다.

Host 단위 시험은 264개가 통과했고, AMD 장치의 로컬 인코딩·전환 경로도 시험했다. Intel UHD PC 한 대에서 돌린 1080×1920 세로 화면 재생 회귀 시험에서는 진단상 손상 프레임이 0이었다.

여기서 손상은 샘플 픽셀 차이가 45를 넘는 비율이 10%를 초과한 프레임을 뜻한다. 따라서 진단상 손상 0을 무손실 압축이나 압축 오차 0으로 읽으면 안 되고, 전체 화질이 좋아졌다는 보증도 아니다. 깨진 프레임이 섞이지 않았다는 회귀 확인 정도로 봐야 한다.

검증을 마치며 남긴 과제

  • 비동기 프레임의 소유자는 전역 힌트가 아닌 프레임 정보로 식별했다.
  • 정지 보완을 세 모드에 적용하되 기존 횟수·시간 상한을 지켰다.
  • 소프트웨어 전환은 정해진 조건에서 해당 인코더에만 적용했다.

NVIDIA 문제 기기의 직접 검증과 장시간 고QP 상황의 안정성은 아직 확인하지 못했다. 운영 배포나 설치 변경도 하지 않아 기존 운영 릴리스는 그대로 남아 있다.

MFT의 기본 구조와 처리 방식은 Microsoft Media Foundation Transforms 공식 문서를 참고했다. 이번 작업은 현장 해결 확정보다 소유자 추적과 실패 처리 경로를 정리한 작업이었다.

728x90
반응형