2017-03-13 4 views
2

안드로이드에서 그리고 특히 MediaCodec을 사용하여 카메라의 프레임 인코딩과 관련하여 그래픽 메모리 사용/흐름을 이해하려고합니다. 이를 위해서는 그래픽, OpenGL 및 안드로이드 용어/개념에 대해 잘 모르는 부분을 이해해야합니다. 나는 안드로이드 그래픽 아키텍처 자료, SO 질문 및 많은 소스를 읽었지 만 용어가 다른 맥락에서 다른 의미를 가지고있는 것 같기 때문에 여전히 혼란 스럽다.안드로이드 카메라 SurfaceTexture 및 MediaCodec 서피스 사용법 이해

나는 fadden의 사이트 here에서 CameraToMpegTest를 보았습니다. 내 구체적인 질문은 이 Camera::setPreviewTexture()과 함께 작동하는 방법입니다. OpenGL 텍스처가 생성 된 다음 SurfaceTexture 인 안드로이드를 생성하는 데 사용되어 setPreviewTexture()으로 전달 될 수 있습니다. 내 특정 질문 :

  1. setPreviewTexture()은 카메라에서 프레임이 이동하는 메모리 버퍼의 관점에서 실제로 무엇을합니까?
  2. 내 이해에서 OpenGL 텍스처는 GPU가 액세스 할 수있는 메모리 덩어리입니다. Android에서는 올바른 사용 플래그가있는 gralloc을 사용하여 할당해야합니다. SurfaceTexture의 Android 설명에 따르면 "주어진 OpenGL 텍스처로 이미지 스트리밍"을 할 수 있습니다 : https://developer.android.com/reference/android/graphics/SurfaceTexture.html#SurfaceTexture(int). SurfaceTexture은 OpenGL 텍스처 위에 무엇을합니까?
  3. MediaCodec::createInputSurface()은 Android Surface을 반환합니다. 내가 이해하기 때문에 안드로이드 Surface은 버퍼 대기열의 생산자 측을 나타내므로 다중 버퍼가 될 수 있습니다. API reference은 "서피스는 OpenGL ES와 같은 하드웨어 가속 API로 렌더링되어야합니다"라고 언급합니다. 카메라에서 캡처 한 프레임은 SurfaceTexture에서 인코더로 입력되는 Surface으로 어떻게 변환됩니까? CameraToMpegTest가 Surface을 사용하여 EGLSurface을 생성하지만 EGL에 대해 많이 알지 못해서이 부분을 얻지 못합니다.
  4. 누군가 "렌더링"사용법을 명확히 할 수 있습니까? "표면에 렌더링", "화면에 렌더링"등과 같은 것들을 볼 수 있습니다.

편집 : 나는 시도하고 더 나은 Camera::setPreviewTexture()의 내부 동작을 이해하고 좀 더 질문이 몇 가지 더 CameraServiceSurfaceTextureCameraClient::setPreviewTarget()의 코드로 파고

  1. : mstorsjo의 답변에 업을 따르십시오. SurfaceTextureBufferQueue을 만들고 CameraServiceIGraphicBufferProducer을 플랫폼 카메라 HAL 구현에 전달합니다. 그런 다음 카메라 HAL은 grloc 사용 플래그를 적절히 설정하고 (예 : GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_TEXTURE)이 BufferQueue에서 버퍼를 대기열에서 제외 할 수 있습니다. 따라서 카메라가 프레임을 캡쳐하는 버퍼는 grockoc 할당 된 버퍼이며 특별한 사용 플래그는 GRALLOC_USAGE_HW_TEXTURE입니다. GPU와 CPU가 동일한 메모리에 액세스 할 수 있도록 통합 메모리 아키텍처로 ARM 플랫폼에서 작업하므로 GRALLOC_USAGE_HW_TEXTURE 플래그가 버퍼가 할당되는 방식에 어떤 영향을 미칩니 까?
  2. SurfaceTexture의 OpenGL (ES) 부분은 주로 GLConsumer의 일부로 구현 된 것으로 보이며 마법은 updateTexImage() 인 것으로 보입니다. OpenGL (ES) 텍스처에 추가 버퍼가 할당되어 있습니까? 아니면 사용할 수있는 카메라로 채워진 동일한 gralloc 버퍼입니까? 카메라 픽셀 데이터를 gralloc 버퍼에서 OpenGL (ES) 텍스처로 가져 오기 위해 여기에서 발생해야하는 메모리 복사가 있습니까?나는 updateTexImage()이 무엇을하는지 이해하지 못한다.

답변

3
  1. 그것은 카메라 불투명 무늬로 대신 프로그램의 주소 공간 내에서 사용자 제공 완충액 (setPreviewCallback 또는 setPreviewCallbackWithBuffer를 사용하는 경우)에서 출력 된 프레임을 제공하는 것을 의미한다. 이 불투명 한 핸들 인 텍스처는 OpenGL 드로잉 내에서 사용할 수 있습니다.

  2. 거의. 이 경우, OpenGL 텍스처는 메모리의 물리적 덩어리가 아니라 EGL 컨텍스트 내의 다양한 메모리 덩어리에 대한 핸들입니다. 이 경우 샘플 코드 자체는 텍스처를 실제로 할당하거나 크기를 지정하지 않고 glGenTextures을 사용하여 텍스처의 "이름"/ 핸들 만 만듭니다. 기본적으로 정수입니다. 일반 OpenGL (ES) 내에서 OpenGL 함수를 사용하여 텍스처의 실제 저장소를 할당하고 내용으로 채 웁니다. 이 설정에서 SurfaceTexture은 텍스처로 데이터를 채우기 위해 Android 레벨 API/추상화를 제공합니다. 즉, 적절한 플래그로 저장소를 할당하고 크기 및 내용을 제공합니다. SurfaceTexture을 채울 수있는 다른 클래스에 전달할 수 있습니다. 데이터가있는 경우 (CameraSurfaceTexture을 직접 가져 오거나 Surface 클래스로 감싸서 다른 컨텍스트에서 사용할 수 있음). 이를 통해 원시 데이터 버퍼를 응용 프로그램의 프로세스에 전달하고 응용 프로그램에서 OpenGL로 업로드하지 않고도 OpenGL 텍스처를 효율적으로 내용으로 채울 수 있습니다.

  3. (응답 포인트 3과 4가 역순으로 정렬 됨) OpenGL (ES)은 그리기를위한 일반적인 API입니다. 보통/원래 설정에서 게임을 고려해보십시오. 게임 콘텐츠 (배경, 소도구, 액터 등)의 여러 부분에 대해 많은 질감을 가졌으므로 OpenGL API를 사용하여이를 화면에 그립니다. 텍스처는 화면에 그대로 복사되거나 삼각형으로 만들어진 3D 오브젝트로 감싸 여질 수 있습니다. 이것은 "렌더링"이라고 불리는 과정으로, 입력 텍스처와 삼각형 집합을 가져 와서 그립니다. 가장 간단한 경우에는 내용을 화면에 바로 표시합니다. GPU는 대개 다른 출력 버퍼에도 동일한 렌더링을 수행 할 수 있습니다. 게임에서 어떤 장면을 텍스처로 렌더링하고 최종 렌더링의 일부로 미리 렌더링 된 텍스처를 사용하여 실제로 화면에 표시되도록하는 것이 일반적입니다.

  4. EGL 컨텍스트는 카메라의 출력을 인코더 입력으로 전달하기 위해 생성됩니다. EGL 컨텍스트는 기본적으로 OpenGL 렌더링을 수행하기위한 컨텍스트입니다. 렌더링 대상은 인코더의 서피스입니다. 즉, OpenGL을 사용하여 그린 그래픽은 화면 대신 엔코더 입력 버퍼에서 끝납니다. 이제 OpenGL을 사용하여 그려지는 장면은 OpenGL 함수 호출 시퀀스 일 수 있으며 게임 장면을 인코더로 렌더링합니다. (이것은 Android 브레이크 아웃 게임 레코더 예제가하는 것입니다.) 컨텍스트 내에서 텍스처 핸들이 생성됩니다. 보통의 게임 그래픽 렌더링에서와 같이 디스크에서 피큐어를로드하여 내용으로 텍스처를 채우는 대신 으로 만들어 Camera이 카메라 그림으로 채울 수있게합니다. SurfaceTexture 클래스는 Camera이 콘텐츠를 업데이트 할 때 신호를 보내는 콜백을 제공합니다. 콜백이 수신되면 EGL 컨텍스트가 활성화되고 한 프레임이 EGL 컨텍스트 출력 대상 (인코더 입력)으로 렌더링됩니다. 렌더링 자체는 아무 것도하지 않지만 입력 텍스처를 그대로 출력으로 복사합니다.

이 모두 매우 로터리 들릴 수도 있지만, 몇 가지 혜택을 준다 : 잠재적으로 결코 응용 프로그램 코드 내에서 직접 처리하지 (할 필요가 없습니다 카메라 프레임의

  • 실제 원시 비트를 응용 프로그램의 프로세스 및 주소 공간 내에서).저해상도의 경우이 정도의 문제는 아니지만 고해상도의 경우 병목 현상이 발생합니다 (setPreviewCallback).
  • OpenGL에서 색상 조정과 다른 작업을 수행 할 수 있습니다. GPU 가속을 사용하면 거의 무료입니다.
+0

답변을 바탕으로 본래의 질문에 대한 후속 조치를 추가했습니다. –

+0

그 추가 질문에 대해서는 거의 논평 할 수 없습니다. 원래 질문은 API가 공개 안드로이드 API 관점에서 (내가 아는 것) 무엇을하는지에 대한 것이 었습니다. 후자의 질문은 플랫폼 구현 방법과 세부 사항에 관한 것입니다 플랫폼 구현 자와 관련이 있습니다. – mstorsjo

+1

마지막 질문에, 저는 SurfaceTexture가 실제로 하나 이상의 버퍼 세트가되어 소비자 (GL 컨텍스트)가 이전 프레임 렌더링을 유지하면서 생산자 (카메라)가 한 프레임을 쓸 수 있다고 예상합니다 . 'updateTexImage()'에서, 나는이 버퍼를 바꿀 것으로 예상한다. 그게 내 인상과 사용자의 관점에서 가정이지만, 나는 실제 구현을 모르겠습니다. – mstorsjo

관련 문제