Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- Close
- mutex
- go언어
- Callback
- Sync
- Golang
- windows
- 책
- File
- Linux
- json
- API
- GO 언어
- C
- window
- install
- write
- 영화
- go
- c++
- http
- JavaScript
- 리뷰
- range
- bitcoin
- channel
- tcp
- FOR
- Python
- package
Archives
- Today
- Total
Code Habit
fdk-aac decoder 본문
압축(인코딩)된 aac데이터를 fdk-aac 라이브러리를 사용하여 decode 하는 예제이다. 결과물은 pcm 데이터로 저장되며 audacity uitl 등을 통해 decode된 음원을 재생해 볼 수 있다.
- FDKAACDecoder.h
#include "aacdecoder_lib.h"
class CFDKAACDecoder
{
public:
CFDKAACDecoder();
~CFDKAACDecoder();
bool Initialize();
void Destroy();
int Decode(BYTE* pBuffer, UINT nBufSize);
private:
HANDLE_AACDECODER m_hDecoder;
BOOL m_bInitialized;
CStreamInfo m_stream_info;
};
- FDKAACDecoder.cpp
#include "FDKAACDecoder.h"
#pragma comment(lib, "libfdk-aac.dll.a")
CFDKAACDecoder::CFDKAACDecoder()
:m_hDecoder(NULL)
,m_bInitialized(FALSE)
{
memset(&m_stream_info, 0, sizeof(CStreamInfo));
}
CFDKAACDecoder::~CFDKAACDecoder()
{
}
bool CFDKAACDecoder::Initialize()
{
// decoder를 오픈하고 핸들을 반환 받는다.
m_hDecoder = aacDecoder_Open(TT_MP4_ADTS, 1);
if (NULL == m_hDecoder) {
OutputDebugString(L"Failed to aacDecoder_Open()");
return false;
}
// 디코드 설정을 셋팅하는 함수로
// 여기서는 따로 셋팅할 값이 없어 default 값 설정을 한다.
AAC_DECODER_ERROR err = aacDecoder_SetParam(m_hDecoder, AAC_PCM_OUTPUT_INTERLEAVED, 1);
if (AAC_DEC_OK != err) {
OutputDebugString(L"Failed to aacDecoder_SetParam");
return false;
}
return true;
}
void CFDKAACDecoder::Destroy()
{
// 디코드 닫고 핸들 반환
if (NULL != m_hDecoder) {
aacDecoder_Close(m_hDecoder);
m_hDecoder = NULL;
}
}
int CFDKAACDecoder::Decode(BYTE* pBuffer, UINT nBufSize)
{
// In
UINT nValid = nBufSize;
// Out
UINT nPcmPktSize = 0;
INT_PCM vOutBuffer[8192] = { 0, };
// (처음 한번) 디코드 하기전에 패킷 사이즈를 알 수 없어 처음에는 넉넉히 버퍼 크기를 정하고
// 이 후는 아래와 같이 디코드 때 가져온 헤더 정보를 토대로 사이즈를 정해준다.
// framesize * channel 수 * 2byte(16bit)
if (TRUE == m_bInitialized) {
nPcmPktSize = m_stream_info.frameSize * m_stream_info.numChannels * sizeof(SHORT);
}
else {
nPcmPktSize = 8192;
}
// decode 할 버퍼를 채운다.
// 채울 수 있는 만큼 채우고 남은 버퍼 사이즈를 nValid로 반환해준다.
// ** 다음 버퍼를 채울때 nValid만큼 남은 버퍼를 앞에 붙여줘야 한다 !
AAC_DECODER_ERROR err = AAC_DEC_OK;
err = aacDecoder_Fill(m_hDecoder, &pBuffer, &nBufSize, &nValid);
if (AAC_DEC_OK != err) {
OutputDebugString(L"Failed to aacDecoder_Fill()");
return -1;
}
int n = 100;
while (1) {
// aacDecoder_Fill에서 채워진 버퍼를 nPcmPktSize만큼 디코드 한다.
// 채워진 버퍼를 여러번 돌며 디코드 하며 완료되면 AAC_DEC_NOT_ENOUGH_BITS를 리턴한다.
err = aacDecoder_DecodeFrame(m_hDecoder, (INT_PCM*)vOutBuffer, nPcmPktSize, 0);
if (AAC_DEC_NOT_ENOUGH_BITS == err) {
return nValid; // 채워진 버퍼 모두 처리. -> 정상 리턴
}
if (AAC_DEC_OK != err) {
OutputDebugString(L"Failed to aacDecoder_DecodeFrame()");
return -1;
}
// 스트림 정보 저장 ( 초기 한번만 )
if (false == m_bInitialized) {
CStreamInfo* pStream_info = aacDecoder_GetStreamInfo(m_hDecoder);
memcpy_s(&m_stream_info, sizeof(CStreamInfo), pStream_info, sizeof(CStreamInfo));
m_bInitialized = true;
}
// debug : 파일 쓰기
FILE* pFile = NULL;
errno_t err = _tfopen_s(&pFile, _T("TEST.pcm"), _T("ab+"));
if (err) {
return -1;
}
if (!pFile) {
return -1;
}
fwrite(vOutBuffer, 1, m_stream_info.numChannels * 2 * m_stream_info.frameSize, pFile);
if (fclose(pFile)) {
}
// 행 방지
--n;
if (0 > n) {
break;
}
}
return -1;
}
'libfdk-aac.dll.a', 'aacdecoder_lib.h' 는 fdk-aac 라이브러리를 빌드하거나 가져온 헤더파일로 아래 사이트를 참고하면 된다.