libavcodec을 사용하여 AAC로 오디오를 인코딩하십시오
-
18-09-2019 - |
문제
Libavcodec (3/3/10 기준 최신 Git)을 사용하여 원시 PCM을 AAC (LibFAAC 지원 활성화)로 인코딩합니다. 나는 avcodec_encode_audio를 매번 codec_context-> frame_size 샘플로 반복적으로 호출하여 이것을합니다. 처음 네 번의 전화는 성공적으로 반환되지만 다섯 번째 전화는 결코 돌아 오지 않습니다. GDB를 사용하여 파손되면 스택이 손상되었습니다.
Audacity를 사용하여 PCM 데이터를 .wav 파일로 내보내면 명령 줄 ffmpeg를 사용하여 아무런 문제없이 AAC로 변환 할 수 있으므로 내가 잘못하고있는 일이라고 확신합니다.
나는 내 문제를 복제하는 작은 테스트 프로그램을 작성했습니다. 여기에서 사용할 수있는 파일에서 테스트 데이터를 읽습니다.http://birdie.protoven.com/audio.pcm (~ 2 초의 서명 16 비트 LE PCM)
FAAC를 직접 사용하면 모든 것이 작동 할 수 있지만 비디오를 인코딩하고 MP4에 둘 다 글을 쓰기 때문에 Libavcodec을 사용할 수 있다면 코드가 약간 더 깨끗합니다.
FFMPEG 버전 정보 :
FFmpeg version git-c280040, Copyright (c) 2000-2010 the FFmpeg developers
built on Mar 3 2010 15:40:46 with gcc 4.4.1
configuration: --enable-libfaac --enable-gpl --enable-nonfree --enable-version3 --enable-postproc --enable-pthreads --enable-debug=3 --enable-shared
libavutil 50.10. 0 / 50.10. 0
libavcodec 52.55. 0 / 52.55. 0
libavformat 52.54. 0 / 52.54. 0
libavdevice 52. 2. 0 / 52. 2. 0
libswscale 0.10. 0 / 0.10. 0
libpostproc 51. 2. 0 / 51. 2. 0
내 코덱 컨텍스트에서 설정하지 않거나 잘못 설정하지 않습니까? 모든 도움이 감사합니다!
내 테스트 코드는 다음과 같습니다.
#include <stdio.h>
#include <libavcodec/avcodec.h>
void EncodeTest(int sampleRate, int channels, int audioBitrate,
uint8_t *audioData, size_t audioSize)
{
AVCodecContext *audioCodec;
AVCodec *codec;
uint8_t *buf;
int bufSize, frameBytes;
avcodec_register_all();
//Set up audio encoder
codec = avcodec_find_encoder(CODEC_ID_AAC);
if (codec == NULL) return;
audioCodec = avcodec_alloc_context();
audioCodec->bit_rate = audioBitrate;
audioCodec->sample_fmt = SAMPLE_FMT_S16;
audioCodec->sample_rate = sampleRate;
audioCodec->channels = channels;
audioCodec->profile = FF_PROFILE_AAC_MAIN;
audioCodec->time_base = (AVRational){1, sampleRate};
audioCodec->codec_type = CODEC_TYPE_AUDIO;
if (avcodec_open(audioCodec, codec) < 0) return;
bufSize = FF_MIN_BUFFER_SIZE * 10;
buf = (uint8_t *)malloc(bufSize);
if (buf == NULL) return;
frameBytes = audioCodec->frame_size * audioCodec->channels * 2;
while (audioSize >= frameBytes)
{
int packetSize;
packetSize = avcodec_encode_audio(audioCodec, buf, bufSize, (short *)audioData);
printf("encoder returned %d bytes of data\n", packetSize);
audioData += frameBytes;
audioSize -= frameBytes;
}
}
int main()
{
FILE *stream = fopen("audio.pcm", "rb");
size_t size;
uint8_t *buf;
if (stream == NULL)
{
printf("Unable to open file\n");
return 1;
}
fseek(stream, 0, SEEK_END);
size = ftell(stream);
fseek(stream, 0, SEEK_SET);
buf = (uint8_t *)malloc(size);
fread(buf, sizeof(uint8_t), size, stream);
fclose(stream);
EncodeTest(32000, 2, 448000, buf, size);
}
해결책
비트 전송률이 386000 미만이면 문제가 사라지는 것 같습니다. FAAC를 직접 사용하는 것보다 비트 전송기에서 더 높은 인코딩 할 수 있으므로 왜 이것이 왜 이것이인지 확실하지 않습니다. 그러나 128000은 내 목적에 충분하기 때문에 앞으로 나아갈 수 있습니다.
다른 팁
AAC 형식으로 압축하려고 시도하고 있습니다. 인코딩에 다른 문제가 있습니다. FFMPEG (2.8.0)의 마지막 개정에는 몇 가지 기능이 있습니다. 먼저 샘플 형식이 지원되었는지 확인 했습니까? 내 버전에서 유일하게 지원되는 형식은 av_sample_fmt_fltp입니다. 형식 검사는 예입니다.
/ *주어진 샘플 형식은 인코더 */ int check_sample_fmt (avcodec *codec, enum avsampleformat sample_fmt) {const enum avsample format *p = codec-> sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
지원되는 형식을 관찰하면 AV_SAMPLE_FMT_FLTP 만 AAC Codec에 의해 지원됩니다. swresample (제안 된대로)을 사용하여 Planare Float 형식으로 변환하거나 손으로 할 수 있습니다. Codec을 개방하기 위해 엄격한 Sperimental 옵션이있는 AVCODEC_OPEN2를 사용해야합니다. 문안 인사