호환 미디어 트랜스코딩

Android 12에서 도입된 호환 미디어 트랜스코딩은 기기가 앱과의 호환성을 유지하면서 HEVC와 같은 동영상 캡처에 저장용량 효율성이 높은 최신 미디어 형식을 사용할 수 있는 기능입니다. 이 기능을 사용하면 기기 제조업체에서 AVC 대신 HEVC를 기본적으로 사용하여 동영상 화질을 향상하면서 저장용량 및 대역폭 요구사항을 줄일 수 있습니다. 호환 미디어 트랜스코딩이 사용 설정된 기기의 경우 Android는 HEVC나 HDR을 지원하지 않는 앱에서 동영상이 열릴 때 이 형식으로 녹화된 동영상(최대 길이 1분)을 자동으로 변환할 수 있습니다. 이를 통해 동영상이 기기에서 최신 형식으로 캡처될 때도 앱이 작동할 수 있습니다.

호환 미디어 트랜스코딩 기능은 기본적으로 사용 중지되어 있습니다. 미디어 트랜스코딩을 요청하려면 앱에서 미디어 기능을 선언해야 합니다. 미디어 기능 선언에 관한 자세한 내용은 Android 개발자 사이트의 호환 미디어 트랜스코딩을 참고하세요.

작동 방식

호환 미디어 트랜스코딩 기능은 두 가지 주요 부분으로 구성됩니다.

  • 미디어 프레임워크의 트랜스코딩 서비스: 이러한 서비스는 짧은 지연 시간과 고화질 변환을 위해 하드웨어를 사용하여 파일을 한 형식에서 다른 형식으로 변환합니다. 여기에는 트랜스코딩 API, 트랜스코딩 서비스, 맞춤 필터용 OEM 플러그인, 하드웨어가 포함됩니다. 자세한 내용은 아키텍처 개요를 참고하세요.
  • 미디어 제공업체의 호환 미디어 트랜스코딩 기능: 미디어 제공업체에서 찾을 수 있는 이 구성요소는 미디어 파일에 액세스하는 앱을 가로채 앱의 선언된 기능에 기반하여 원본 파일 또는 트랜스코딩된 파일을 제공합니다. 앱이 미디어 파일 형식을 지원하는 경우 특별한 처리가 필요하지 않습니다. 앱이 이 형식을 지원하지 않으면 프레임워크에서는 앱이 파일에 액세스 할 때 AVC와 같은 이전 형식으로 파일을 변환합니다.

그림 1은 미디어 트랜스코딩 프로세스의 개요를 보여줍니다.

호환 미디어 트랜스코딩 프로세스

그림 1. 호환 미디어 트랜스코딩 개요

지원되는 형식

호환 미디어 트랜스코딩 기능은 다음과 같은 형식 변환을 지원합니다.

  • HEVC(8비트)에서 AVC로: 코덱 변환은 mediacodec 디코더 하나와 mediacode 인코더 하나를 연결하여 실행됩니다.
  • HDR10+(10비트)에서 AVC(SDR)로: HDR에서 SDR로의 변환은 mediacodec 인스턴스와 디코더 인스턴스의 공급업체 플러그인 후크를 사용하여 실행됩니다. 자세한 내용은 HDR에서 SDR로 인코딩을 참고하세요.

지원되는 콘텐츠 소스

호환 미디어 트랜스코딩 기능은 기본 외부 볼륨의 DCIM/Camera/ 폴더에 저장된 기본 OEM 카메라 앱이 생성한 기기 내 미디어를 지원합니다. 이 기능은 보조 저장소의 미디어는 지원하지 않습니다. 이메일이나 SD 카드를 통해 기기에 전달된 콘텐츠는 지원되지 않습니다.

앱은 다양한 파일 경로에 기반하여 파일에 액세스합니다. 다음은 트랜스코딩이 사용 설정되거나 우회되는 파일 경로를 설명합니다.

  • 트랜스코딩이 사용 설정됨

    • MediaStore API를 통한 앱 액세스
    • 자바, 네이티브 코드 등 직접 파일 경로 API를 통한 앱 액세스
    • 저장소 액세스 프레임워크(SAF)를 통한 앱 액세스
    • OS 공유 시트 인텐트를 통한 앱 액세스. MediaStore URI에만 적용됩니다.
    • 휴대전화에서 PC로 MTP/PTP 파일 전송
  • 트랜스코딩이 우회됨

    • SD 카드를 꺼내 기기에서 파일 전송
    • Nearby Share나 블루투스 전송과 같은 옵션을 사용하여 기기에서 기기로 파일 전송

트랜스코딩용 맞춤 파일 경로 추가

기기 제조업체는 DCIM/ 디렉터리에 미디어 트랜스코딩용 파일 경로를 추가할 수 있습니다(선택사항). DCIM/ 디렉터리 외부의 모든 경로는 거부됩니다. 이러한 파일 경로를 추가하려면 이동통신사 요구사항 또는 현지 규정을 충족해야 할 수도 있습니다.

파일 경로를 추가하려면 트랜스코딩 경로 런타임 리소스 오버레이(RRO), config_supported_transcoding_relative_paths를 사용합니다. 다음은 파일 경로를 추가하는 방법의 예입니다.

<string-array name="config_supported_transcoding_relative_paths" translatable="false">
    <item>DCIM/JCF/</item>
</string-array>

구성된 파일 경로를 확인하려면 다음을 사용하세요.

adb shell dumpsys activity provider com.google.android.providers.media.module/com.android.providers.media.MediaProvider | head -n 20

아키텍처 개요

이 섹션에서는 미디어 트랜스코딩 기능의 아키텍처를 설명합니다.

media-transcoding-architecture

그림 2. 미디어 트랜스코딩 아키텍처

미디어 트랜스코딩 아키텍처는 다음 구성요소로 이루어집니다.

  • MediaTranscodingManager system API: 클라이언트가 MediaTranscoding 서비스와 통신할 수 있는 인터페이스입니다. MediaProvider 모듈에서 이 API를 사용합니다.
  • MediaTranscodingService: 클라이언트 연결을 관리하고 트랜스코딩 요청을 예약하며 TranscodingSessions의 기록을 관리하는 네이티브 서비스입니다.
  • MediaTranscoder: 트랜스코딩을 실행하는 네이티브 라이브러리입니다. 이 라이브러리는 모듈과 호환되도록 미디어 프레임워크 NDK에 기반합니다.

호환 미디어 트랜스코딩 기능은 서비스와 미디어 트랜스코더에서 모두 트랜스코딩 측정항목을 기록합니다. 클라이언트 측과 서비스 측 코드는 시기적절한 버그 수정과 업데이트를 허용하도록 MediaProvider 모듈에 있습니다.

파일 액세스

호환 미디어 트랜스코딩은 범위 지정 저장소에 사용되는 Filesystem in Userspace(FUSE) 파일 시스템에 기반합니다. FUSE를 사용하면 MediaProvider 모듈이 사용자 공간의 파일 작업을 검사하고, 액세스 권한을 허용하거나 거부, 수정하는 정책에 따라 파일 액세스를 관리할 수 있습니다.

앱이 파일에 액세스하려고 하면 FUSE 데몬이 앱의 파일 읽기 액세스 권한을 가로챕니다. 앱이 최신 형식(예: HEVC)을 지원하면 원본 파일이 반환됩니다. 앱에서 이 형식을 지원하지 않으면 파일은 이전 형식(예: AVC)으로 트랜스코딩되거나 트랜스코딩된 버전이 사용 가능한 경우 캐시에서 반환됩니다.

트랜스코딩된 파일 요청

호환 미디어 트랜스코딩 기능은 기본적으로 사용 중지되어 있습니다. 즉, 기기에서 HEVC를 지원하면 Android는 파일을 트랜스코딩하지 않습니다. 단, 앱에서 매니페스트 파일이나 강제 트랜스코딩 목록에 지정한 경우는 예외입니다.

앱은 다음 옵션을 사용하여 트랜스코딩된 애셋을 요청할 수 있습니다.

  • 매니페스트 파일에서 지원되지 않는 형식을 선언합니다. 자세한 내용은 리소스에서 기능 선언, 코드에서 기능 선언을 참고하세요.
  • MediaProvider 모듈에 포함된 강제 트랜스코딩 목록에 앱을 추가합니다. 이렇게 하면 매니페스트 파일을 업데이트하지 않은 앱의 트랜스코딩이 사용 설정됩니다. 앱이 지원되지 않는 형식으로 매니페스트 파일을 업데이트하면 강제 트랜스코딩 목록에서 삭제되어야 합니다. 기기 제조업체는 패치를 제출하거나 버그를 신고하여 강제 트랜스코딩 목록에 추가하거나 목록에서 삭제할 앱을 지정할 수 있습니다. Android팀은 정기적으로 목록을 검토하여 목록에서 앱을 삭제할 수 있습니다.
  • 런타임에 앱 호환성 프레임워크로 지원되는 형식을 사용 중지합니다. 사용자도 설정에서 각 앱에 관해 이를 사용 중지할 수 있습니다.
  • openTypedAssetFileDescriptor API를 사용하여 지원되지 않는 형식을 명시적으로 지정하면서 MediaStore로 파일을 엽니다.

USB 전송(기기에서 PC로)의 경우 트랜스코딩이 기본적으로 사용 중지되어 있지만 사용자는 그림 3과 같이 USB 환경설정 설정 화면의 동영상을 AVC로 변환 전환 버튼으로 트랜스코딩을 사용하도록 선택할 수 있습니다.

미디어 트랜스코딩을 사용하도록 전환

그림 3. USB 환경설정 화면에서 미디어 트랜스코딩을 사용하도록 전환

트랜스코딩된 파일 요청 제한사항

트랜스코딩 요청으로 인해 시스템 리소스가 장시간 잠기지 않도록 트랜스코딩 세션을 요청하는 앱은 다음과 같이 제한됩니다.

  • 연속 세션 10회
  • 총 실행 시간 3분

앱이 이러한 제한사항을 모두 초과하면 프레임워크에서 원본 파일 설명자를 반환합니다.

기기 요구사항

호환 미디어 트랜스코딩 기능을 지원하려면 기기가 다음 요구사항을 충족해야 합니다.

  • 기기의 네이티브 카메라 앱에 HEVC 인코딩이 기본적으로 사용 설정되어 있습니다.
  • (HDR에서 SDR로의 트랜스코딩을 지원하는 기기) 기기가 HDR 동영상 캡처를 지원합니다.

기기의 미디어 트랜스코딩 성능을 보장하려면 동영상 하드웨어와 저장소 읽기/쓰기 액세스 성능을 최적화해야 합니다. 미디어 코덱이 1과 같은 우선순위로 구성된 경우 코덱은 가능한 최대 처리량으로 작동해야 합니다. 트랜스코딩 성능은 최소 200fps를 달성하는 것이 좋습니다. 하드웨어 성능을 테스트하려면 frameworks/av/media/libmediatranscoding/transcoder/benchmark에서 미디어 트랜스코더 벤치마크를 실행하세요.

유효성 검사

호환 미디어 트랜스코딩 기능을 확인하려면 다음 CTS 테스트를 실행하세요.

  • android.media.mediatranscoding.cts
  • android.mediaprovidertranscode.cts

전역적으로 미디어 트랜스코딩 사용 설정

트랜스코딩을 통해 미디어 트랜스코딩 프레임워크나 앱 동작을 테스트하려면 호환 미디어 트랜스코딩 기능을 전역적으로 사용 설정하거나 사용 중지하면 됩니다. 설정 > 시스템 > 개발자 > 미디어 트랜스코딩 개발자 옵션 페이지에서 트랜스코딩 기본값 재정의 전환 버튼을 사용으로 설정하고 트랜스코딩 사용 설정 전환 버튼을 사용이나 사용 중지로 설정합니다. 이 설정이 사용 설정되면 개발 중인 앱을 제외한 앱의 백그라운드에서 미디어 트랜스코딩이 발생할 수도 있습니다.

트랜스코딩 상태 확인

테스트하는 동안 다음 ADB 셸 명령어를 사용하여 현재 및 이전 트랜스코딩 세션을 비롯한 트랜스코딩 상태를 확인할 수 있습니다.

adb shell dumpsys media.transcoding

동영상 길이 제한 연장

테스트를 위해 다음 명령어를 사용하여 트랜스코딩의 1분 동영상 길이 제한을 연장할 수 있습니다. 이 명령어를 실행하면 재부팅해야 할 수도 있습니다.

adb shell device_config put storage_native_boot transcode_max_duration_ms <LARGE_NUMBER_IN_MS>

AOSP 소스 및 참조

다음은 호환 미디어 트랜스코딩과 관련된 AOSP 소스 코드입니다.

HDR에서 SDR로 인코딩

HDR에서 SDR로의 인코딩을 지원하려면 기기 제조업체에서 /platform/frameworks/av/media/codec2/hidl/plugin/에 있는 AOSP 샘플 Codec 2.0 필터 플러그인을 사용하면 됩니다. 이 섹션에서는 필터 플러그인 작동 방식과 플러그인 구현 방법, 플러그인 테스트 방법을 설명합니다.

기기에 HDR에서 SDR로의 인코딩을 지원하는 플러그인이 포함되어 있지 않으면 HDR 동영상에 액세스하는 앱은 매니페스트에 선언된 앱의 미디어 기능과 관계없이 원본 파일 설명자를 가져옵니다.

작동 방식

이 섹션에서는 일반적인 Codec 2.0 필터 플러그인의 동작을 설명합니다.

배경

Android에서는 Codec 2.0 인터페이스와 android::hardware::media::c2android.hardware.media.c2 HAL 인터페이스 사이에 적응 레이어 구현을 제공합니다. 필터 플러그인의 경우 AOSP에는 디코더를 필터 플러그인과 함께 래핑하는 래퍼 메커니즘이 포함되어 있습니다. MediaCodec은 이러한 래핑된 구성요소를 필터링 기능이 있는 디코더로 인식합니다.

개요

FilterWrapper 클래스는 공급업체 코덱을 가져오고 래핑된 코덱을 다시 media.c2 적응 레이어에 반환합니다. FilterWrapper 클래스는 FilterWrapper::Plugin API를 통해 libc2filterplugin.so를 로드하고 플러그인에서 사용 가능한 필터를 기록합니다. 만들 때 FilterWrapper는 사용 가능한 모든 필터를 인스턴스화합니다. 버퍼를 변경하는 필터만 시작할 때 시작됩니다.

필터 플러그인 아키텍처

그림 1. 필터 플러그인 아키텍처

필터 플러그인 인터페이스

FilterPlugin.h 인터페이스는 필터를 노출하도록 다음 API를 정의합니다.

  • std::shared_ptr<C2ComponentStore>getComponentStore()

    필터가 포함된 C2ComponentStore 객체를 반환합니다. 이는 공급업체의 Codec 2.0 구현에서 노출하는 것과는 별개입니다. 일반적으로 이 저장소에는 FilterWrapper 클래스에서 사용되는 필터만 포함됩니다.

  • bool describe(C2String name, Descriptor *desc)

    C2ComponentStore에서 사용할 수 있는 것 외에 필터를 설명합니다. 다음 설명이 정의됩니다.

    • controlParam: 필터의 동작을 제어하는 매개변수입니다. 예를 들어 HDR에서 SDR로의 톤 매퍼의 경우 제어 매개변수는 타겟 전송 함수입니다.
    • affectedParams: 필터링 작업으로 영향을 받는 매개변수입니다. 예를 들어 HDR에서 SDR로의 톤 매퍼의 경우 영향을 받는 매개변수는 색상 측면입니다.
  • bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf)

    필터 구성요소가 버퍼를 변경하면 true를 반환합니다. 예를 들어 타겟 전송 함수가 SDR이고 입력 전송 함수가 HDR(HLG 또는 PQ)이면 톤 매핑 필터는 true를 반환합니다.

FilterWrapper 세부정보

이 섹션에서는 FilterWrapper 클래스의 세부정보를 설명합니다.

생성

래핑된 구성요소는 생성 시 기본 디코더와 정의된 모든 필터를 인스턴스화합니다.

쿼리와 구성

래핑된 구성요소는 필터 설명에 따라 쿼리 또는 구성 요청에서 수신 매개변수를 분리합니다. 예를 들어 필터 제어 매개변수의 구성은 상응하는 필터로 라우팅되고 필터의 영향을 받는 매개변수가 쿼리에 표시됩니다(영향을 받지 않는 매개변수가 있는 디코더에서 읽는 대신).

쿼리와 구성

그림 2. 쿼리와 구성

시작

시작 시 래핑된 구성요소는 디코더와 버퍼를 변경하는 모든 필터를 시작합니다. 사용 설정된 필터가 없으면 래핑된 구성요소는 디코더와 패스 스루 버퍼를 시작하고 디코더 자체에 명령어를 전송합니다.

버퍼 처리

버퍼 처리

그림 3. 버퍼 처리

래핑된 디코더의 큐에 추가된 버퍼는 기본 디코더로 이동합니다. 래핑된 구성요소는 onWorkDone_nb() 콜백을 통해 디코더에서 출력 버퍼를 가져온 다음 필터의 큐에 추가합니다. 마지막 필터의 최종 출력 버퍼가 클라이언트에 보고됩니다.

이 버퍼 처리가 작동하려면 프레임워크 출력이 예상 블록 풀에서 버퍼링되도록 래핑된 구성요소가 C2PortBlockPoolsTuning을 마지막 필터로 구성해야 합니다.

중지, 재설정, 해제

중지 시 래핑된 구성요소는 시작되고 사용 설정된 모든 필터와 디코더를 중지합니다. 재설정 및 해제 시 모든 구성요소는 사용 설정 여부와 관계없이 재설정되거나 해제됩니다.

샘플 필터 플러그인 구현

플러그인을 사용하려면 다음을 실행하세요.

  1. FilterPlugin 인터페이스를 라이브러리에서 구현하여 /vendor/lib[64]/libc2filterplugin.so.에 배치합니다.
  2. 필요한 경우 mediacodec.te에 권한을 추가합니다.
  3. 조정 레이어를 Android 12로 업데이트하고 media.c2 서비스를 다시 빌드합니다.

플러그인 테스트

샘플 플러그인을 테스트하려면 다음을 실행하세요.

  1. 기기를 다시 빌드하고 플래시합니다.
  2. 다음 명령어를 사용하여 샘플 플러그인을 빌드합니다.

    m sample-codec2-filter-plugin
    
  3. 기기를 다시 마운트하고 코덱 서비스에서 인식하도록 공급업체 플러그인의 이름을 바꿉니다.

    adb root
    adb remount
    adb reboot
    adb wait-for-device
    adb root
    adb remount
    adb
    push /out/target/<...>/lib64/sample-codec2-filter-plugin.so \
    
    /vendor/lib64/libc2filterplugin.so
    adb push
    /out/target/<...>/lib/sample-codec2-filter-plugin.so \
    
    /vendor/lib/libc2filterplugin.so
    adb reboot