8. Compress Offload
8.1 Compress Offload 개요
Compress Offload API는 압축된 오디오 스트림 (MP3, AAC, FLAC 등)을 DSP에 직접 전송하여 CPU 사용률을 낮춥니다. 모바일/임베디드 플랫폼에서 배터리 수명 연장에 효과적입니다.
/* include/sound/compress_driver.h */
struct snd_compr *compr;
int err = snd_compress_new(card, 0, SND_COMPRESS_PLAYBACK, "compress", &compr);
compr->ops = &my_compr_ops;
/* Compress ops */
struct snd_compr_ops {
int (*open)(struct snd_compr_stream *stream);
int (*free)(struct snd_compr_stream *stream);
int (*set_params)(struct snd_compr_stream *stream,
struct snd_compr_params *params);
int (*get_params)(struct snd_compr_stream *stream,
struct snd_codec *params);
int (*trigger)(struct snd_compr_stream *stream, int cmd);
int (*pointer)(struct snd_compr_stream *stream,
struct snd_compr_tstamp *tstamp);
int (*copy)(struct snd_compr_stream *stream,
char __user *buf, size_t count);
int (*get_caps)(struct snd_compr_stream *stream,
struct snd_compr_caps *caps);
int (*get_codec_caps)(struct snd_compr_stream *stream,
struct snd_compr_codec_caps *codec);
};
ASLA Compress Offload는 오디오 데이터를 디코딩(압축 해제)하는 무거운 작업을 메인 CPU가 아닌, 오디오 하드웨어 내부에 있는 DSP(Digital Signal Processor)에 통째로 맡기는 기술입니다.
일반적으로 임베디드 시스템이나 스마트폰의 배터리 효율을 극대화하기 위해 사용됩니다.
1. 일반 모드 vs. Compress Offload 모드
일반 오디오 재생 (PCM)
메인 CPU가 MP3나 AAC 같은 압축 파일을 읽어서 직접 PCM(원시 데이터)으로 풉니다. 그 후 ALSA PCM 인터페이스를 통해 하드웨어로 전달합니다. CPU가 계속 일을 해야 하므로 전력 소모가 큽니다.
Compress Offload 재생
CPU는 MP3/AAC 데이터를 압축된 상태 그대로 하드웨어 버퍼에 밀어 넣기만 합니다. 실제 소리로 만드는 복잡한 계산은 하드웨어 전용 DSP가 담당합니다. CPU는 데이터를 던져준 뒤 Sleep(수면) 상태에 들어갈 수 있어 전력을 획기적으로 아낍니다.
2. 주요 장점
• 저전력 소모 (Low Power): CPU 사용량을 최소화하여 모바일 기기의 음악 재생 시간을 늘려줍니다.
• 시스템 부하 감소: CPU가 다른 복잡한 작업을 처리하는 동안에도 오디오 재생이 끊길 위험이 줄어듭니다.
• DSP 기능 활용: 하드웨어 DSP에 내장된 이퀄라이저, 가상 서라운드 등의 효과를 압축 해제 단계에서 바로 적용할 수 있습니다.
3. 기술적 특징 (API)
이 인터페이스는 일반적인 read/write와는 조금 다른 흐름을 가집니다.
• 비표준 포맷 지원: PCM 데이터가 아니므로 샘플링 레이트, 비트레이트, 코덱 정보(MP3, AAC, FLAC 등)를 명시적으로 전달해야 합니다.
• 대용량 버퍼: CPU가 오래 쉴 수 있도록 보통 일반 PCM 버퍼보다 훨씬 큰 버퍼를 사용합니다.
• Gapless 재생: 곡과 곡 사이의 무음 구간 없이 자연스럽게 넘어가기 위한 메타데이터 처리를 지원합니다.
4. 코드 수준에서의 접근
Compress Offload는 ALSA의 일반 라이브러리가 아닌 tinycompress라는 별도의 경량 라이브러리를 주로 사용합니다.
// 장치 열기 (카드 번호, 장치 번호, 모드 등)
struct compress *compress = compress_open(card, device, flags, &config);
// 코덱 설정 (예: MP3)
struct snd_codec codec;
codec.id = SND_AUDIOCODEC_MP3;
compress_set_codec_params(compress, &codec);
// 압축된 데이터 전송
compress_write(compress, compressed_buffer, size);
5. 실무에서의 위치
• Android: 안드로이드 오디오 프레임워크(Audio HAL)는 배터리 절약을 위해 이 Compress Offload 기능을 적극적으로 사용합니다.
• Embedded Linux: 인포테인먼트 시스템이나 저전력 미디어 플레이어 설계 시 핵심 기능으로 들어갑니다.
요약하자면
Compress Offload는 "압축 해제 업무를 CPU에서 DSP로 **이관(Offload)**하여 전력 효율을 높이는 기술"입니다.
혹시 이 기술이 적용된 시스템에서 오디오가 끊기거나(Underrun) 하는 이슈를 해결하는 방법이 궁금하신가요?
8.2 Compress Ops 구현
static int my_compr_set_params(struct snd_compr_stream *stream,
struct snd_compr_params *params)
{
struct snd_codec *codec = ¶ms->codec;
/* DSP에 코덱 파라미터 설정 */
switch (codec->id) {
case SND_AUDIOCODEC_MP3:
my_dsp_set_codec(CODEC_MP3, codec->bit_rate);
break;
case SND_AUDIOCODEC_AAC:
my_dsp_set_codec(CODEC_AAC, codec->bit_rate);
break;
default:
return -EINVAL;
}
return 0;
}
static int my_compr_copy(struct snd_compr_stream *stream,
char __user *buf, size_t count)
{
/* 압축 데이터를 DSP 링 버퍼로 복사 */
return my_dsp_write_compressed(stream, buf, count);
}
8.3 지원 코덱 포맷
사용자 공간은 tinycompress 라이브러리를 통해 compress 디바이스에 접근합니다.
#define SND_AUDIOCODEC_PCM 1
#define SND_AUDIOCODEC_MP3 2
#define SND_AUDIOCODEC_AMR 3
#define SND_AUDIOCODEC_AMRWB 4
#define SND_AUDIOCODEC_AMRWBPLUS 5
#define SND_AUDIOCODEC_AAC 6
#define SND_AUDIOCODEC_WMA 7
#define SND_AUDIOCODEC_REAL 8
#define SND_AUDIOCODEC_VORBIS 9
#define SND_AUDIOCODEC_FLAC 10
#define SND_AUDIOCODEC_IEC61937 11 /* S/PDIF passthrough */
#define SND_AUDIOCODEC_G723_1 12
#define SND_AUDIOCODEC_G729 13
#define SND_AUDIOCODEC_BESPOKE 14 /* 벤더 전용 */