Кодировать аудио в aac с помощью libavcodec - PullRequest
13 голосов
/ 09 марта 2010

Я использую libavcodec (последний git от 3/3/10) для кодирования необработанного 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 напрямую, но код был бы немного чище, если бы я мог просто использовать 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);
}

Ответы [ 2 ]

4 голосов
/ 04 июня 2010

Проблема, похоже, исчезнет, ​​если битрейт меньше 386000. Не уверен, почему это так, поскольку я могу кодировать на битрейтах выше, чем при использовании FAAC напрямую. Но 128000 достаточно для моих целей, поэтому я могу двигаться вперед.

0 голосов
/ 22 октября 2015

Я пытаюсь сжать в формате 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;

}

Если вы наблюдаете поддерживаемые форматы, только кодек AAC поддерживает только AV_SAMPLE_FMT_FLTP. Вы должны использовать swresample (как предложено), чтобы конвертировать в формате float planare, или вы можете сделать это вручную. Вы должны использовать avcodec_open2 с опциями строго sperimental, чтобы открыть кодек. С уважением

...