Принудите ffmpeg использовать libfdk_aac вместо родного декодера aac через C API

Вопрос или проблема

У меня есть приложение для декодирования аудио, написанное с использованием C API ffmpeg. Оно декодирует сжатое аудио и преобразует его в нес signes 32-разрядные PCM данные. У меня есть libfdk_aac, связанная с ffmpeg, и ffmpeg скомпилирован из исходников согласно инструкциям, представленным в https://trac.ffmpeg.org/wiki/CompilationGuide/Centos.

Однако, похоже, что даже если я специально прошу ffmpeg найти и использовать libfdk_aac, он переключается обратно на свое родное aac-реализацию. Например, как видно в фрагменте кода и его выводах ниже, вывод переменной “codec” показывает libfdk_aac с кодом кодека: 86018 (который происходит от перечисления AVCodecID, определенного в codec_id.h). Вывод переменной “context” показывает, что он все еще использует родное aac-реализацию с кодом кодека 86018.

const AVCodec* codec = avcodec_find_decoder_by_name("libfdk_aac");
fprintf(stderr, "Codec id: %d, name %s , long_name: %s \n", codec->id, codec->name, codec->long_name );
AVCodecContext* context = avcodec_alloc_context3(codec);

int ret = avcodec_open2(context, codec, NULL);
fprintf(stderr, "From context: Codec id: %d, name %s , long_name: %s \n", context->codec_id, context->codec_descriptor->name, context->codec_descriptor->long_name);

Вывод для вышеуказанного:

Codec id: 86018, name libfdk_aac , long_name: Fraunhofer FDK AAC 
From context: Codec id: 86018, name aac , long_name: AAC (Advanced Audio Coding) 

При просмотре codec_id.h и его перечисления AVCodecID мы видим, что AV_CODEC_ID_AAC соответствует ID 86018 и для libfdk_aac не определено перечисление.

    enum AVCodecID
    {
        // ..
        AV_CODEC_ID_AAC, // -> 86018
        AV_CODEC_ID_AC3, // -> 86019
    };

Не могли бы вы сообщить мне, как заставить ffmpeg использовать библиотеку декодера libfdk_aac вместо его родной реализации?

Я использую ffmpeg 5.1, и вот вывод конфигурации, который показывает, что libfdk_aac и nonfree включены. Я запускаю это на Fedora 40 с ядром Linux 6.10.9-200.fc40.x86_64.

ffmpeg version N-110004-g1231003c3c Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 13 (GCC)
  configuration: --prefix=~/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I~/ffmpeg_build/include --extra-ldflags=-L~/ffmpeg_build/lib --extra-libs=-lpthread --extra-libs=-lm --bindir=~/bin --enable-libfdk_aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree --enable-openssl --enable-demuxer=spdif --enable-decoder=dolby_e --enable-decoder=ac3 --enable-gpl --enable-decoder=eac3 --enable-indev=alsa --enable-outdev=alsa --enable-libsrt --enable-nonfree --enable-openssl
  libavutil      58.  3.100 / 58.  3.100
  libavcodec     60.  6.101 / 60.  6.101
  libavformat    60.  4.100 / 60.  4.100
  libavdevice    60.  2.100 / 60.  2.100
  libavfilter     9.  4.100 /  9.  4.100
  libswscale      7.  2.100 /  7.  2.100
  libswresample   4. 11.100 /  4. 11.100
  libpostproc    57.  2.100 / 57.  2.100
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

Ответ или решение

Чтобы заставить FFmpeg использовать декодер libfdk_aac вместо его встроенного декодера AAC, необходимо учесть несколько важных аспектов. Ваша ситуация подразумевает, что, несмотря на использование правильного идентификатора кодека, FFmpeg переключается на собственный декодер. Это происходит потому, что FFmpeg использует лишь один идентификатор кодека для AAC, что создает путаницу между двумя разными реализациями декодеров.

Решение проблемы

  1. Проверьте конфигурацию:
    Убедитесь, что FFmpeg был правильно скомпилирован с поддержкой libfdk_aac. Вы уже разместили вывод конфигурации. Важно обратить внимание на наличие параметров --enable-libfdk_aac и --enable-nonfree, что указывает на то, что ваша сборка действительно поддерживает эту библиотеку.

  2. Идентификация кодека:
    В вашем коде вы пытаетесь найти декодер с помощью имени "libfdk_aac". Однако FFmpeg автоматически выбирает кодек на основе идентификатора, как вы заметили. Используйте следующий подход для создания контекста кодека:

    const AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
    if (!codec) {
       fprintf(stderr, "Codec not found\n");
       return -1; // Обработка ошибки
    }
    
    AVCodecContext* context = avcodec_alloc_context3(codec);
    if (!context) {
       fprintf(stderr, "Could not allocate codec context\n");
       return -1; // Обработка ошибки
    }
    
    // Установите флаг использования libfdk_aac
    context->codec_type = AVMEDIA_TYPE_AUDIO;
    context->codec_id = AV_CODEC_ID_AAC; // Использование идентификатора AAC для контекста
    
    // Откройте декодер
    int ret = avcodec_open2(context, codec, NULL);
    if (ret < 0) {
       fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
       return -1; // Обработка ошибки
    }
    
    fprintf(stderr, "Using codec: id = %d, name = %s\n", context->codec_id, context->codec_descriptor->name);
  3. Выбор декодера:
    Изменение свойства context->codec_id на AV_CODEC_ID_AAC не гарантирует, что будет использоваться именно libfdk_aac. Тем не менее, это позволит вам избежать прямого указания имени, что может снизить вероятность сбоя.

  4. Дебелизируйте настройки FFmpeg:
    Если указанные шаги не решают аналогичную проблему, вы можете дополнительно изучить:

    • Убедитесь, что у вас установлены последние версии библиотек и FFmpeg. Более новые версии могут устранить подобные конфликты.
    • Используйте av_log_set_level(AV_LOG_DEBUG); для получения более детальной информации о том, какие кодеки выбирает FFmpeg.

Заключение

Для обеспечения использования libfdk_aac в приложении, важно корректно настроить контекст кодека и убедиться в наличии необходимых библиотек во время компиляции. Используя указанные здесь шаги, вы сможете избежать возникновения проблем с выбором декодера и улучшить качество обработки звука в вашем приложении. Обязательно протестируйте код после внесения изменений и следите за выводом отладочной информации для устранения возможных ошибок.

Оцените материал
Добавить комментарий

Капча загружается...