- Adroid Camera2API 및 MediaCodec을 사용하여 H264 형식으로 카메라 이미지 전송
8108 단어 AndroidCamera2API
개요
다음 기사에서 Android 단말기의 화면을 H264 형식으로 전송합니다.
그러면 멜라의 화면도 전송할 수 있겠지, 내가 한번 해봤어.
Android 화면을 컴퓨터에 미러링하는 소프트웨어 만들기
다음 그림과 같이 Android 터미널을 서버로 H264를 통해 전송합니다.
ffplay를 클라이언트 응용 프로그램으로 사용합니다.
ffplay는 FFmpeg 라이브러리를 사용하는 미디어 플레이어입니다.
ffplay Documentation
MediaCodec
미디어 인코딩은 저급 영상이나 오디오 인코더의 일종이다
디코더를 제공하는 클래스입니다.
비디오 인코더는 다음과 같은 형식에 대응한다.
H264 형식으로 카메라 이미지 전송
응용 프로그램은 다음 그림의 구조입니다.
MediaCodec을 사용하여 H264 형식 만들기
다음 내용을 참조했습니다.
모두 Surface 입력입니다.
Camera22에서 Surface 입력이 실패했습니다.
Buffer 를 입력합니다.
reference : getInputBuffer
MediaCodec의 사용 방법은 리셋을 사용하는 비동기형과 리셋을 사용하지 않는 동기형 두 가지가 있다.
비동기식은 매우 느리다.
onInputBufferAvailable 및 onOutputBufferAvailable
만약 같은 라인에서 처리한다면, 마치 한 라인을 처리할 때 다른 라인을 막는 것 같다.
동기화
Android MediaCodec slower in async-mode than in synchronous mode?
reference : MediaCodec.Callback
미디어 Codec의 Buffer 입력 및 Buffer 출력
Buffer 입력은 카메라에서 이미지 데이터를 준비하는 곳입니다.
입력 버퍼 가져오기
// 画像データ
byte[] frame;
long timestamp;
ByteBuffer inputBuffer = null;
int index = -1;
try {
index = mediaCodec.dequeueInputBuffer(INPUT_TIMEOUT);
if (index>=0) {
inputBuffer = mediaCodec.getInputBuffer(index);
}
} catch (IllegalStateException e) {
}
if(inputBuffer == null) return;
int size = frame.length;
inputBuffer.clear();
inputBuffer.put(frame, 0 ,size);
mediaCodec.queueInputBuffer(index, 0, size, timestamp, 0);
Buffer 출력에 트리거되지 않은 이벤트무한 순환으로 처리하다.
데이터가 준비되어도
출력 버퍼에서 바이트 열을 가져옵니다.
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
// outputBuffer を取得する
int index = -1;
ByteBuffer outputBuffer = null;
try {
// timeout: 500ms
index = mediaCodec.dequeueOutputBuffer(bufferInfo, 500000);
if (index >= 0) {
outputBuffer = mCodec.getOutputBuffer(index);
}
} catch (IllegalStateException e) {
}
if(outputBuffer == null) return null;
// バイト列を取得する
int size = bufferInfo.size ;
byte[] outData = new byte[size];
outputBuffer.position(0);
outputBuffer.get(outData);
mediaCodec.releaseOutputBuffer(index, false);
ImageFormatConverter
ImageReader 출력은 YUV420_888 형식.
미디어코덱의 입력은 YUV420Planar 형식입니다.
이미지 형식을 변환합니다.
인터넷을 찾아보니 고전하는 것 같다.
오랜만입니다. 환경 설정과 빌딩을 지나는 데 많은 시간이 걸렸습니다.
프로젝트는 카메라에서 파일로 내보내기 위한 데모입니다.
최소한의 필요한 곳을 제시하다
나는 안드로이드 뱅크를 만들었다.
프로젝트는 여기 있습니다.
https://github.com/ohwada/Android_Samples/tree/master/ImageFormatConverter
서버에서 이미지 전송
포트 번호를 지정하여 ServerSocket을 생성합니다.
클라이언트의 연결을 기다립니다.
연결 후 MediaCodec를 시작합니다.
H264 바이트 문자열을 연속으로 보냅니다.
ffplay로 재생하기
ffplay를 다운로드합니다.
Download ffplay
명령줄에서 실행합니다.
동작을 확인하다.
버전 표시
$ ffplay -version
비디오 파일 재생
$ffplay 파일 경로
Android 터미널에서 비디오 스트림 재생
$ ffplay -i tcp://IP주소: 포트/
이미지 크기
미디어코덱의 이미지 크기를 입력하려면 다음과 같이 하십시오.
미디어 형식인 #createVideoFormat에서 지정한 내용 크기보다 작거나 같아야 합니다.
크면 버퍼 오버플로우가 돼요.
이미지 센서와 동일한 이미지 크기
일반적으로 꺼내서 축소합니다.
도로가 멀어 보이기 때문에 YUV420Planar 형식의 축소
ImageReader를 생성할 때 필요한 크기를 지정하는 방법입니다.
공식 문서에 따르면 추천하는 해상도는 다음과 같다.
컴퓨터 모니터에 익숙한 VGA 사이즈(640x480)는 컴퓨터에서 재생하면 이렇게 큰 사이즈를 원합니다.
유형
해상도
종횡비
비고
SD(저화질)
176 x 144
1.22
SD(고화질)
480 x 360
1.33
HD 720p
1280 x 720
1.77
모델에 의존
guide : Supported media formats - Video support
아래 글에 따르면 FullHD(1920×1080) 30fps 정도면 문제가 없을 것 같습니다.
넥서스 5로 해봤어요.
VGA(640x480) 10fps 및 HD(1920×960)10fps는 모두 ffplay로 순조롭게 재생할 수 있다.
미디어코드의 한계에 대해 알아봤습니다.
이미지의 크기에 따라 재생성된 이미지에 이상한 것이 있습니다.
이미지는 SD(고화질) 480x360에서만 녹색으로 바뀝니다.
비디오 인코더 유형
위에서 말한 바와 같이 ffplay로 순조롭게 재생할 수 있다
공식 문서에 따르면 Android 7.0 이후는 임의(optional)
쓰지 말라는 거지.
SoftMPEG4Encoder: Failed to initialize the encoder
[OMX.google.h263.encoder] ERROR(0x80001001)
ffplay에서 다음 오류가 발생했습니다.
새로운 형식과 H264와 같은 정도의 품질이기 때문에.
대응하지 않은 것 같습니다
wikipedia : VP8
샘플 코드가github에 발표되었습니다.
https://github.com/ohwada/Android_Samples/tree/master/Camera222
Reference
이 문제에 관하여(- Adroid Camera2API 및 MediaCodec을 사용하여 H264 형식으로 카메라 이미지 전송), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ohwada/items/dd69fdd5297e042d237d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)