Notice
Recent Posts
Recent Comments
Link
투케이2K
1042. (Android/Java) [간단 소스] 안드로이드 AWS WebRTC 뷰어에서 특정 비디오 코덱을 사용하도록 Video Factory 커스텀 설정 방법 본문
Android
1042. (Android/Java) [간단 소스] 안드로이드 AWS WebRTC 뷰어에서 특정 비디오 코덱을 사용하도록 Video Factory 커스텀 설정 방법
투케이2K 2025. 10. 21. 20:21728x90
반응형
[개발 환경 설정]
개발 툴 : AndroidStudio
개발 언어 : Java / Kotlin

[소스 코드]
// --------------------------------------------------------------------------------------
[개발 및 테스트 환경]
// --------------------------------------------------------------------------------------
- 언어 : Java / Kotlin
- 개발 툴 : AndroidStudio
- 기술 구분 : Android / Android / AWS / WebRTC / Viewer
- 사전) AWS KVS WebRTC 설명 :
>> WebRTC 란 웹, 애플리케이션, 디바이스 간 중간자 없이 오디오나 영상 미디어를 포착하고 실시간 스트림할 뿐 아니라, 임의의 데이터도 교환할 수 있도록 하는 기술입니다
>> WebRTC 는 간단한 API 를 통해 웹 브라우저, 모바일 애플리케이션 및 커넥티드 디바이스 간에 실시간 통신을 활성화할 수 있습니다
>> WebRTC 주요 용어 :
- SDP (Session Description Protocol) : 오디오/비디오 코덱, 해상도, 포트 등 스트리밍 정보를 담은 텍스트 포맷
- Offer / Answer : 통신 연결을 협상하기 위한 SDP 메시지 (초기 연결 설정)
- ICE (Interactive Connectivity Establishment) : NAT/P2P 환경에서도 연결 가능한 경로(IP, 포트 등)를 찾기 위한 기술
- Candidate : 가능한 연결 경로 (IP + Port 조합)
>> WebRTC [ICE] 연결 형태 :
- Relayed Address : TURN 서버가 패킷 릴레이를 위해 할당하는 주소
- Server Reflexive Address : NAT 가 매핑한 클라이언트의 공인망 (Public IP, Port)
- Local Address : 클라이언트의 사설주소 (Private IP, Port)
>> WebRTC STUN 및 TURN 서버 설명 :
- (같은 와이파이 망) STUN 서버는 HOST 를 거쳐 >> Server Reflexive Address 만을 응답하지만,
(릴레이서버 사용) TURN 서버는 Relayed Address와 Server Reflexive Address 를 모두 응답한다
- STUN, TURN 서버를 이용해 SDP Answer IP주소 를 취득 >> RTCPeerConnection Remote 연결 수행
>> WebRTC SDP 오퍼 생성 (뷰어) 및 응답 (마스터) 스트리밍 플로우 :
[Viewer → Signaling Server] -- SDP Offer --> [Master] : 뷰어는 마스터로 스트리밍 오퍼 신호 보낸다
[Master] -- SDP Answer --> [Viewer] : 마스터는 특정 뷰어의 오퍼 신호 확인 후 응답을 보낸다
[Viewer] -- ICE Candidate --> [Master] : 스트리밍을 할 수 있는 경로 확인
[Master] -- ICE Candidate --> [Viewer] : 스트리밍을 할 수 있는 경로 확인
P2P 연결 성립 → 스트리밍 시작
- 사전) 안드로이드 Build.gradle 설정 사항 :
android {
// [컴파일 버전]
compileSdk 34
// [Config 셋팅]
defaultConfig {
// ----------------------------
applicationId "com.example.javaproject" // 앱 아이디
// ----------------------------
versionCode 1 // 빌드 버전
// ----------------------------
versionName '1.0.1' // 빌드 네임
// ----------------------------
minSdk 24 // 최소 빌드 버전
// ----------------------------
targetSdk 34 // TODO 타겟 빌드 버전
// ----------------------------
}
// [컴파일 자바 버전 지정]
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// [아파치 http 사용 설정]
useLibrary ('org.apache.http.legacy')
}
dependencies {
implementation 'com.amazonaws:aws-android-sdk-iot:2.57.0'
implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.57.0'
implementation 'com.amazonaws:aws-android-sdk-kinesisvideo:2.57.0'
//implementation files('libs/google-webrtc-1.0.32006.aar')
implementation 'com.infobip:google-webrtc:1.0.0035529'
}
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[소스 코드]
// --------------------------------------------------------------------------------------
// ---------------------------------------------------
// TODO 인코더 : 비디오 코덱 H264만 사용하도록 설정
// ---------------------------------------------------
// TODO VP9 관련 코드가 포함된 DefaultVideoEncoderFactory를 그대로 사용하면 getSupportedCodecs() 호출 시 크래시가 발생할 수 있습니다.
// 이를 방지하려면 VP9을 제외한 코덱만 반환하도록 커스텀 팩토리를 구현하세요.
// ---------------------------------------------------
// 기본 인코더 팩토리 생성
DefaultVideoEncoderFactory defaultEncoderFactory =
new DefaultVideoEncoderFactory(
eglBase.getEglBaseContext(),
/* enableIntelVp8Encoder */ true,
/* enableH264HighProfile */ true
);
// H264만 필터링
encoderFactory = new VideoEncoderFactory() {
@Override
public VideoCodecInfo[] getSupportedCodecs() {
List<VideoCodecInfo> filtered = new ArrayList<>();
for (VideoCodecInfo codec : defaultEncoderFactory.getSupportedCodecs()) {
S_Log.d("KWON_TWOK", "VideoEncoderFactory :: getSupportedCodecs :: " + String.valueOf(codec.name) + " / " + codec.params.toString());
if ("H264".equalsIgnoreCase(codec.name)) { // 특정 코덱 필더링
filtered.add(codec); // Add Array
S_Log.w("KWON_TWOK", "VideoEncoderFactory :: Add H264 Codec" + String.valueOf(codec.name) + " / " + codec.params.toString());
}
}
return filtered.toArray(new VideoCodecInfo[0]);
}
@Override
public VideoEncoder createEncoder(VideoCodecInfo codecInfo) {
return defaultEncoderFactory.createEncoder(codecInfo);
}
};
// ---------------------------------------------------
// TODO 디코더 : 비디오 코덱 H264만 사용하도록 설정
// ---------------------------------------------------
// TODO 코덱 확인 시 H264가 없다면, WebRTC SDK가 빌드 시 libopenh264 또는 MediaCodec H264 를 포함하지 못한 것입니다.
// ---------------------------------------------------
// 기본 디코더 팩토리 생성
DefaultVideoDecoderFactory defaultDecoderFactory = new DefaultVideoDecoderFactory(eglBase.getEglBaseContext());
// H264만 필터링
decoderFactory = new VideoDecoderFactory() {
@Override
public VideoCodecInfo[] getSupportedCodecs() {
List<VideoCodecInfo> filtered = new ArrayList<>();
for (VideoCodecInfo codec : defaultDecoderFactory.getSupportedCodecs()) {
S_Log.d("KWON_TWOK", "VideoDecoderFactory :: getSupportedCodecs :: " + String.valueOf(codec.name) + " / " + codec.params.toString());
if ("H264".equalsIgnoreCase(codec.name)) { // 특정 코덱 필더링
filtered.add(codec); // Add Array
S_Log.w("KWON_TWOK", "VideoDecoderFactory :: Add H264 Codec" + String.valueOf(codec.name) + " / " + codec.params.toString());
}
}
return filtered.toArray(new VideoCodecInfo[0]);
}
@Override
public VideoDecoder createDecoder(VideoCodecInfo info) {
return defaultDecoderFactory.createDecoder(info);
}
};
// ---------------------------------------------------
// TODO [PeerConnectionFactory 생성]
// ---------------------------------------------------
String fieldTrials = "WebRTC-H264Simulcast/Enabled/" // H264 코덱에서 Simulcast 기능 활성화
+ "WebRTC-Video-BalancedDegradation/Enabled/" // 비디오 품질 저하 시 균형 잡힌 처리 방식 적용
+ "WebRTC-IncreasedReceivebuffers/Enabled/"; // 수신 버퍼 크기 증가 (영상 수신 안정성 향상)
PeerConnectionFactory.initialize(
PeerConnectionFactory.InitializationOptions.builder(A_Test_Native_Aws_WebRTC.this)
//.setFieldTrials(fieldTrials) // 필요시
.setEnableInternalTracer(true) // 디버깅용
.createInitializationOptions()
);
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
peerFactory = PeerConnectionFactory.builder()
.setOptions(options)
.setVideoEncoderFactory(encoderFactory)
.setVideoDecoderFactory(decoderFactory)
.createPeerConnectionFactory();
S_Log._W_(ACTIVITY_NAME + " :: initPeerConnectionFactory :: PeerConnectionFactory", new String[]{
"peerFactory :: " + String.valueOf(peerFactory == null ? "PeerConnectionFactory Is Null" : "PeerConnectionFactory Init Success")
});
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[참고 사이트]
// --------------------------------------------------------------------------------------
[업무 이슈] 안드로이드 슬러시 (특수 문자) 포함 JSON 정보 전달 시 자동으로 이스케이프 문자 처리되어 WIFI 접속 문제 발생 이슈
https://blog.naver.com/kkh0977/224019151434?trackingCode=blog_bloghome_searchlist
[자바스크립트 AWS WebRTC 실시간 동영상 재생 수행]
https://blog.naver.com/kkh0977/223170500993?trackingCode=blog_bloghome_searchlist
[Aws Kvs WebRTC 실시간 영상 재생 관련 구성 요소 및 용어 정리]
https://blog.naver.com/kkh0977/223858189791
[업무 이슈] AWS WebRTC 실시간 비디오 재생 시 Client 클라이언트 연결 접속 및 해제 상태 확인 이슈
https://blog.naver.com/kkh0977/223966952222
[Aws Kinesis Video Streams] WebRTC SDP 협상 과정 프로세스 정리 정리
https://blog.naver.com/kkh0977/224030054470
[Aws Kinesis Video Streams] WebRTC getSignalingChannelEndpoint HTTPS, WSS 사용 범위 정리
https://blog.naver.com/kkh0977/224035890592
[유틸 파일] unescapeString : 수동 이스케이프 문자 원복 수행
https://blog.naver.com/kkh0977/224019199327?trackingCode=blog_bloghome_searchlist
// --------------------------------------------------------------------------------------
728x90
반응형
'Android' 카테고리의 다른 글
Comments
