FFMPEG Seeking приносит аудио артефакты - PullRequest
6 голосов
/ 03 ноября 2011

Я реализую аудио декодер, используя ffmpeg.Хотя чтение аудио и даже поиск уже работает, я не могу найти способ очистить буферы после поиска, поэтому у меня нет артефактов, когда приложение начинает читать аудио сразу после поиска.

avcodec_flush_buffers непохоже что-то влияет на внутренние буферы.Эта проблема возникает со всеми декодерами (mp3, aac, wma, ...), кроме PCM / WAV (который не использует внутренние буферы для хранения данных для декодирования, поскольку звук не сжат).

КодФрагмент прост:

av_seek_frame(audioFilePack->avContext, audioFilePack->stream, posInTimeFrame, AVSEEK_FLAG_ANY);
avcodec_flush_buffers(audioFilePack->avContext->streams[audioFilePack->stream]->codec);

Объяснение:

audioFilePack->avContext = FormatContext
audioFilePack->stream = Stream Position (also used to read audio packets)
audioFilePack->avContext->streams[audioFilePack->stream]->codec = CodecContext for the codec used

Любые идеи о том, что я должен делать, чтобы я мог искать и не получить остаточного звука?Спасибо!

Ответы [ 2 ]

3 голосов
/ 24 апреля 2012

Это ошибка в ffmpeg. Внутренние буферы не очищаются, и поэтому, когда вы получаете пакет / кадр после очистки, вы получаете данные перед поиском. Похоже, что это исправлено с 3-16-12, так что вы можете включить это исправление самостоятельно или обновить ffmpeg.

http://permalink.gmane.org/gmane.comp.video.libav.devel/23455

В качестве обновления приведенная выше ошибка действительно является проблемой, но есть и вторая ошибка, в частности, с AAC.

По состоянию на пять месяцев назад другой пользователь обнаружил эту ошибку, и она была исправлена. https://ffmpeg.org/trac/ffmpeg/ticket/420

Исправление было добавлено в aacdec.c функцию сброса, которая очищает его внутренние буферы. Проблема в том, что в aacdec.c определены два декодера, и только один получил указатель на функцию очистки. Если вы используете другой (более распространенный) декодер, он все равно не будет очищен должным образом.

Если вы в состоянии собрать ffmpeg самостоятельно, исправление заключается в добавлении .flush = flush, внизу определения AVCodec ff_aac_decoder (который находится внизу файла.)

Я сообщу ребятам из ffmpeg, так что, надеюсь, он может быть включен в основную ветку.

2 голосов
/ 11 ноября 2011

Я никогда не писал аудиоплеер с возможностью поиска, но я подозреваю, что это происходит так. Каждый пакет аудио декодируется во фрагмент оригинальной звуковой волны. Обычно эти фрагменты последовательно примыкают друг к другу, и в результате получается непрерывная волна, которая слышится как звук без артефактов. При поиске вы заставляете два фрагмента из разных частей файла примыкать друг к другу. Это обычно вносит разрыв в результирующую звуковую волну, которую ухо воспринимает как щелчок или треск или как вы называете это (я предполагаю) артефакт.

Вот более конкретный пример. Предположим, что вы проиграли первые 25 пакетов аудио, прежде чем искать. Допустим, пакет 25 декодируется в волну, последняя выборка которой составляет 12345. В то время как пакет 25 визуализируется в динамик, вы стремитесь к пакету 66. Допустим, первая выборка пакета 66 имеет значение -23456. Таким образом, цифровой аудиопоток перепрыгивает с 12345 до -23456 по поиску. Это огромный разрыв, и он будет звучать как поп.

Я думаю, что одним из решений является захват одного дополнительного пакета перед началом поиска (пакет 26 в моем примере), декодирование его в автономный буфер, применение затухания и затем помещение его в очередь воспроизведения. После того, как вы ищете нужное место, возьмите первый пакет (66 в моем примере), декодируйте его в другой автономный буфер, примените эффект постепенного появления, а затем поместите его в очередь воспроизведения. Это должно обеспечить плавные звуковые волны и поиск без артефактов.

Если вы умны, вы можете сделать постепенное или постепенное исчезновение настолько коротким или длинным, насколько вы хотите. Я думаю, что только несколько миллисекунд должно быть достаточно для предотвращения артефактов. Вы можете даже применить перекрестное затухание от старых и новых пакетов. Также может быть достаточно просто записать последнее значение выборки в последнем пакете перед поиском и постепенно понизить его до нуля в течение нескольких выборок, вместо того, чтобы сразу же обнулять его. Это может быть проще, чем декодировать дополнительный пакет.

Это мое предположение о том, как можно решить эту проблему. Это явно решаемая проблема, поэтому я рекомендую вам также взглянуть на аудиоплееры с открытым исходным кодом и посмотреть, как они реализуют поиск. Такие программы, как Audacity, Totem, Banshee, RhythmBox, Amarok или VLC, или фреймворки, такие как GStreamer, могут быть хорошими примерами для изучения. Если вы обнаружите, что они используют известные методы, пожалуйста, сообщите о теме здесь. Я думаю, что люди захотят узнать, кто они. Удачи!

...