|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
||||||||||||||||
Конвертация аудио сэмплов wasapi в AVFrame FFmpeg и C++04.02.2021, 04:10. Показов 4008. Ответов 17
Задача заключается в следующем, необходимо аудио сэмплы, которые захватываются с помощью WASAPI записать в аудио файл ac3 с помощью FFmpeg. Сэмплы захватываются в виде BYTE *, их нужно сначала конвертировать в AVFrame и в дальнейшем с помощью функции av_interleaved_write_frame записать в файл.
WASAPI пишет семплы в формате, значения структуры WAVEFORMATEXTENSIBLE:
Вот код WASAPI по захвату сэмплов (сэмплы пишутся в вектор m_curAudioData):
0
|
||||||||||||||||
| 04.02.2021, 04:10 | |
|
Ответы с готовыми решениями:
17
Ffmpeg сохранить AVFrame в .bmp или .jpg ffmpeg конвертация файла Перекодирование аудио ffmpeg |
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
|
| 04.02.2021, 11:35 | |
|
Серега_123, так вопрос то ваш в чём заключается? Очень уж размытая формулировка.
Вы не смогли разобрать исходный формат указанный в WAVEFORMATEXTENSIBLE? Или не знаете функции конвертирования звука между разными некомпрессированными форматами (swr_convert)?
0
|
|
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
|
| 04.02.2021, 11:50 [ТС] | |
|
Ygg, прошу прощения, что из поста непонятно что я хотел. Я буду очень признателен за минимально работающий пример метода, который бы принимал на вход данные этого формата в виде байтов, а отдавал AVFrame готовый к записи в файл ac3 с помощью av_interleaved_write_frame.
Что то типа такого: PCM2AC3(BYTE * data, AVFrame * frame); Как то так
0
|
|
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
|
| 04.02.2021, 12:16 | |
|
Серега_123, если вы смогли интерпретировать исходный формат, то не могли бы вы его озвучить? Ваша интерпретации дампа памяти структуры отображает GUID не в лучшем виде и её сложно анализировать. Полагаю, что GUID соответствует KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ("00000003-0000-0010-8000-00aa00389b71").
0
|
|
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
||||||
| 04.02.2021, 13:32 [ТС] | ||||||
|
Ygg, Так, ну я распечатал формат таким образом:
что то в документации я его найти не могу Возможно неверно распечатал. нагуглил: IEEE floating-point audio {00000003-0000-0010-8000-00AA00389B71} (MEDIASUBTYPE_IEEE_FLOAT) 0x0003 (WAVE_FORMAT_IEEE_FLOAT)
1
|
||||||
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
|
| 04.02.2021, 13:50 | |
|
Значит WASAPI отдаёт вам стерео (nChannels=2) в формате float. В терминологии ffmpeg данный формат называется AV_SAMPLE_FMT_FLT. Если кодек ac3 требует на вход данные исключительно в формате AV_SAMPLE_FMT_FLTP, то исходные данные нужно преобразовать.
Названия форматов отличаются одной буквой 'P' в конце. Наличие этой буквы означает планарный формат. У вас стерео, т.е. два канала звука. При непланарном представлении семплы каналов перемежаются и лежат в одном буфере. Первым идёт семпл левого канала, дальше первый семпл правого канала, затем второй семпл левого канала и так далее. При планарном представлении внутри AVFrame создаются два буфера и каждый из них содержит семплы только одного канала.
0
|
|
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
|
| 04.02.2021, 14:00 [ТС] | |
|
Ygg, Т.е. мне один буфер надо разделить на два? нечетные в один буфер, четные в другой. На выходе получится два буфера? Это через цикл я так понимаю.
0
|
|
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
||||||||||||
| 04.02.2021, 14:14 | ||||||||||||
|
Преобразование средствами ffmpeg выполняется в два этапа. Сперва нужно подготовить контекст, указать какой формат в какой вы хотите преобразовывать. Затем уже для преобразования используется этот контекст и буфера с данными. Подготовку контекста можно найти в исходниках различных примеров, например тут:
0
|
||||||||||||
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
|
| 04.02.2021, 14:19 [ТС] | |
|
Ygg, Это ужасные примеры. Из них вообще ничего непонятно.... имена переменных просто одна буква
. Т.е. контекста должно быть два, один формата на входе, второй формата на выходе?
0
|
|
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
||||||||||||
| 04.02.2021, 14:50 | ||||||||||||
0
|
||||||||||||
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
|
| 04.02.2021, 16:54 [ТС] | |
|
Ygg, У меня еще такой вопрос: я правильно понял, что контекст один? Т.е. мы не настраиваем два контекста входящий и исходящий, а по сути настраиваем один исходящий контекст? Или это контекст стрима?
UPD: кажется я понял, это контекст преобразования. Т.е. это не исходящий контекст AVCodecContext, а SwrContext
1
|
|
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
|
| 04.02.2021, 17:08 | |
|
Серега_123, контекст для преобразования звука из одного формата в другой формат один SwrContext.
В ffmpeg всё в основном делается через контексты. Одни контексты для кодирования, другие для чтения файлов, третьи для преобразований форматов. Контексты как хендлы в windows. Есть хендл окна и есть функции для работы с окном, в которые передаётся этот хендл. Есть хендл файла, а есть функции для работы с файлами, в которые передаётся этот хендл. Для C++ привычнее было бы объединить данные с функциями в класс, тогда можно было бы вызывать сразу функции контекста. Но вот почему-то разработчиками был избран иной путь, который ближе к языку C.
0
|
|
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
|||||||||||
| 05.02.2021, 08:24 [ТС] | |||||||||||
|
Ygg, я вчера по примерам накидал метод. Не могли бы вы код ревью его провести, на ошибки указать, советы дать. Это прототип, который не работает:
Вот сам метод:
Вроде же логика верная. В чем ошибка? Что то тут наверное надо делать с разделением буфера?
0
|
|||||||||||
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
|
| 05.02.2021, 10:07 | |
|
Серега_123, я не настолько профи, что бы выявить все ошибки по фрагменту кода. По хорошему, нужно иметь возможность всё это запускать и отлаживать. Могу указать на основные неточности, которые сходу бросаются в глаза.
Основная ошибка, судя по вашему описанию и коду, в отсутствии результирующих буферов. При вызове swr_convert указатели буферов pFLTPAudioFrame->data[0] и pFLTPAudioFrame->data[1] должны быть не нулевыми.AVFrame - это структура для хранения видео кадра или набора звуковых семплов. Структура содержит большое количество описательных полей, но сама не является буфером для данных. Память под буфер выделяется динамически и указатели хранятся в массиве data. Массив используется для хранения нескольких буферов при планарных форматах. data[0] - буфер первого плана, data[1] - буфер второго плана и так далее.Так как код ориентирован на C, то структура не имеет конструктора и деструктора. Вместо конструктора выступает функция av_frame_alloc. Эта функция выделяет память под структуру и инициализирует поля структуры значениями по умолчанию. Создать буфера на этом этапе нельзя, так как размеры буферов и их количество определяются форматом и прочими параметрами, которые пока не заданы. Для кадра исходного формата вы вызываете функцию av_samples_fill_arrays, полагаю она и производит инициализацию буферов и копирование в них данных. Для кадра выходного формата ничего по созданию буферов не вызывается.Вторая возможная проблема заключается в том, что кодек может требовать определенное количество семплов на свой вход. Это количество записано в одном из полей кодека, сейчас точно не вспомню его названия. Возможно, что перед вызовом функции кодирования вам придётся ещё бить кадры на требуемое количество семплов. Если семплов мало, то их нужно накапливать. Если семплов много, то обрезать и излишки откладывать до следующего раза. Делать подобное можно с помощью специального буфера или же воспользоваться для накопления контекстом преобразования, он содержит в себе буфер и может накапливать данные. Функция av_rescale_rnd вам скорее всего не нужна. Она используется при изменении частоты дискретизации. При этом получается, что исходное количество семплов преобразуется в другое количество семплов. Если же вы сохраняете частоту дискретизации, то количество семплов до и после преобразования у вас будет одинаковым.Цикл do с 60 строки по 77 сделан не к месту. Это так называемый цикл выталкивания, который должен запускаться один раз после того как все входные данные будут прочитаны и отправлены в энкодер. Кодеки могут задерживать данные в себе. К примеру, вы помещаете в кодек первый свой фрагмент данных, кодек говорит ok, но никаких данных не отдаёт (gotOutput=0). Вы помещаете в кодек второй фрагмет данных, кодек говорит ok и отдаёт вам данные соответствующие первому фрагменту. Возникает такой временной сдвиг между входом и выходом. В конце, когда больше уже нет новых фрагментов для передачи их кодеку, кодек содержит в себе ещё некоторое количество задержанных данных. Эти данные нужно из него вытолкнуть. Для этого вызывают функцию кодирования avcodec_encode_audio2, но вместо исходного фрагмента данных передаёт в неё нулевой указатель. Выталкивание повторяют до тех пор, пока функция кодирования возвращает данные.
0
|
|
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
|
| 05.02.2021, 15:09 [ТС] | |
|
Ygg, Мне конечно неловко просить Вас. Я сегодня снова весь день просидел с задачей и не смог добиться результата. Зашел в тупик. Если у вас есть возможность помочь мне с доработкой моего прототипа, я был бы вам очень благодарен.
0
|
|
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
||||||
| 06.02.2021, 08:36 [ТС] | ||||||
|
Ygg, Вот прототип. Я прошу у вас помощи в его доработке, т.е. как я сам зашел в тупик
Ygg, Если поможете написать, о цене можем договориться.
0
|
||||||
|
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,109
|
||||||
| 06.02.2021, 09:23 | ||||||
|
Вот пример нужного вам преобразования, кодирования и записи в файл.
1
|
||||||
|
3 / 3 / 0
Регистрация: 24.02.2017
Сообщений: 140
|
|
| 06.02.2021, 10:50 [ТС] | |
|
Ygg, Вы человек ЧЕЛОВЕЧИЩЕ. Спасибо Вам. Пусть в этом году Вам очень сильно повезет)
0
|
|
| 06.02.2021, 10:50 | |
|
Помогаю со студенческими работами здесь
18
Конвертация файлов через ffmpeg
Av_read_frame и avformat_open_input для аудио по сети (FFMPEG) Конвертация фрейма HEVC в h264 по средствам C API фреймворка ffMpeg Пакетная конвертация через ffmpeg кодеком xvid в заданный размер не работает Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога
Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
|
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование
. \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json>
Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом.
# Check if. . .
|
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так:
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347
Основана на STM32F303RBT6.
На борту пять. . .
|
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
|
|
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу,
и светлой Луне.
В мире
покоя нет
и люди
не могут жить в тишине.
А жить им немного лет.
|
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила»
«Время-Деньги»
«Деньги -Пуля»
|
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога
Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога
Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
|