Вопрос или проблема
У меня есть приложение для декодирования аудио, написанное с использованием 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, что создает путаницу между двумя разными реализациями декодеров.
Решение проблемы
-
Проверьте конфигурацию:
Убедитесь, что FFmpeg был правильно скомпилирован с поддержкой libfdk_aac. Вы уже разместили вывод конфигурации. Важно обратить внимание на наличие параметров--enable-libfdk_aac
и--enable-nonfree
, что указывает на то, что ваша сборка действительно поддерживает эту библиотеку. -
Идентификация кодека:
В вашем коде вы пытаетесь найти декодер с помощью имени"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);
-
Выбор декодера:
Изменение свойстваcontext->codec_id
наAV_CODEC_ID_AAC
не гарантирует, что будет использоваться именно libfdk_aac. Тем не менее, это позволит вам избежать прямого указания имени, что может снизить вероятность сбоя. -
Дебелизируйте настройки FFmpeg:
Если указанные шаги не решают аналогичную проблему, вы можете дополнительно изучить:- Убедитесь, что у вас установлены последние версии библиотек и FFmpeg. Более новые версии могут устранить подобные конфликты.
- Используйте
av_log_set_level(AV_LOG_DEBUG);
для получения более детальной информации о том, какие кодеки выбирает FFmpeg.
Заключение
Для обеспечения использования libfdk_aac в приложении, важно корректно настроить контекст кодека и убедиться в наличии необходимых библиотек во время компиляции. Используя указанные здесь шаги, вы сможете избежать возникновения проблем с выбором декодера и улучшить качество обработки звука в вашем приложении. Обязательно протестируйте код после внесения изменений и следите за выводом отладочной информации для устранения возможных ошибок.