Кодировать аудио в aac с помощью libavcodec
Я использую libavcodec (последний git от 3/3/10) для кодирования raw pcm aac
(поддерживается поддержка libfaac). Я делаю это, вызывая avcodec_encode_audio
повторно с помощью codec_context- > frame_size образцов каждый раз. Первые четыре
звонки возвращаются успешно, но пятый вызов никогда не возвращается. Когда я использую gdb
чтобы сломаться, стек поврежден.
Если я использую смелость для экспорта данных pcm в файл .wav, тогда я могу использовать
командной строки ffmpeg для преобразования в aac без каких-либо проблем, поэтому я уверен, что это
что-то я делаю неправильно.
Я написал небольшую тестовую программу, которая дублирует мою проблему. Он читает
тестовые данные из файла, которые доступны здесь:
http://birdie.protoven.com/audio.pcm (~ 2 секунды подписанного 16 бит LE pcm)
Я могу заставить все это работать, если я использую FAAC напрямую, но код будет немного чище, если бы я мог просто использовать libavcodec, поскольку я также кодирую видео и записываю оба в mp4.
Информация о версии 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);
}
Ответы
Ответ 1
Проблема, кажется, исчезает, если бит бит меньше 386000. Не знаю, почему это так, поскольку я могу кодировать на битрейтах выше, чем при использовании FAAC напрямую. Но 128000 достаточно хорош для моих целей, поэтому я могу двигаться вперед.
Ответ 2
Я пытаюсь сжать в формате aac слишком много других проблем в кодировке. В последней версии ffmpeg (2.8.0) есть некоторые особенности. Во-первых, вы проверили, поддерживается ли формат выборки? В моей версии поддерживается только формат AV_SAMPLE_FMT_FLTP. Проверка формата приведена в примере:
/* убедитесь, что данный формат образца поддерживается кодером */
int check_sample_fmt (кодек AVCodec *, перечисление AVSampleFormat sample_fmt)
{ const enum AVSampleFormat * p = codec- > sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
Если вы наблюдаете поддерживаемые форматы, только AV_SAMPLE_FMT_FLTP поддерживается кодеком AAC. Вы должны использовать swresample (как предложено) для преобразования в плавающем формате planare, или вы можете сделать это вручную.
Вы должны использовать avcodec_open2 с опциями строгого спермы, чтобы открыть кодек.
рассматривает