Добавление звука и входного звука в Media Foundation Sink Writer

Я могу создать файл mp4 с помощью своего приложения для записи экрана, но оно только захватывает экран и не имеет звука. Теперь я хочу, чтобы запись также выводила звук. Я хочу закодировать звук, исходящий от компьютера, который является прямым звуком, и смешать его со звуком, исходящим от микрофона. Я использую SharDX и mediafoundation.net Ниже мой код, как я инициализирую аудиоустройство в SharDX

        var audioDevices = SharpDX.DirectSound.DirectSoundCapture.GetDevices();
        SharpDX.DirectSound.DirectSound dxSoundCapture = new SharpDX.DirectSound.DirectSound(audioDevices.First().DriverGuid);

и ниже показано, как я инициализирую медиатип для аудио в mediafoundation.

    IMFMediaType audioTypeIn = null;
IMFMediaType audioTypeOut = null;

// Create the Audio input type 
if (Succeeded(hr)) hr = (int)MFExtern.MFCreateMediaType(out audioTypeOut);
if (Succeeded(hr)) hr = (int)audioTypeOut.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Audio);
if (Succeeded(hr)) hr = (int)audioTypeOut.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.AAC);
if (Succeeded(hr)) hr = (int)audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_NUM_CHANNELS, 2);
if (Succeeded(hr)) hr = (int)audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
if (Succeeded(hr)) hr = (int)audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
if (Succeeded(hr)) hr = (int)audioTypeOut.SetUINT32(MFAttributesClsid.MF_MT_ALL_SAMPLES_INDEPENDENT, 1);
if (Succeeded(hr)) hr = (int)sinkWriter.AddStream(audioTypeOut, out streamAudIndex);

// Create the Audio input type 
if (Succeeded(hr)) hr = (int)MFExtern.MFCreateMediaType(out audioTypeIn);
if (Succeeded(hr)) hr = (int)audioTypeIn.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Audio);
if (Succeeded(hr)) hr = (int)audioTypeIn.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MFMediaType.PCM);
if (Succeeded(hr)) hr = (int)audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_NUM_CHANNELS, 2);
if (Succeeded(hr)) hr = (int)audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
if (Succeeded(hr)) hr = (int)audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
if (Succeeded(hr)) hr = (int)audioTypeIn.SetUINT32(MFAttributesClsid.MF_MT_ALL_SAMPLES_INDEPENDENT, 1);
if (Succeeded(hr)) hr = (int)sinkWriter.SetInputMediaType(streamAudIndex, audioTypeIn, null);

Мой вопрос заключается в том, как я могу предоставить звуковой образец для моего синкрайтера? В моем видео я в основном использую текстуру 2d из SharpDX и делаю из нее буфер сэмплов.


person kripto    schedule 16.06.2017    source источник


Ответы (1)


Вы готовите Sink Writer к приему аудиопотока PCM со следующей конфигурацией: 44100 отсчетов/с, стерео, 16 бит/отсчет.

Вы должны либо получить образцы медиа с соответствующими данными, либо создать их самостоятельно, используя MFCreateSample и друзей. См. также Работа с образцами мультимедиа в MSDN.

Получив образец мультимедиа, IMFSinkWriter::WriteSample отправляет его на кодирование .

person Roman R.    schedule 16.06.2017
comment
Создание буфера памяти увеличит использование процессора моим приложением. Я хотел бы знать, возможно ли напрямую передавать звуки в синкрайтер без буфера памяти, как я сделал в своей текстуре 2d. Я использовал MFCreateVideoSampleFromSurface для создания семпла и MFCreateDXGISurfaceBuffer для получения медиабуфера и записи его в стокрайтер. - person kripto; 16.06.2017
comment
Вы не должны беспокоиться об этом, на самом деле. Здесь дело даже не в аспекте видео и аудио, а в том, что кодирование программного обеспечения и ваше потребление через SharpDX с его накладными расходами превращают MFCreateSample в почти нулевой вызов затрат. - person Roman R.; 16.06.2017
comment
Я попробовал ваше предложение, но я не знаю, как передать данные с моего устройства на сток. есть ли простой способ сделать это в медиафонде? - person kripto; 22.06.2017
comment
Привет, Роман, я искал в Интернете, и я был так удивлен, что ссылка, которую я искал, была на этом веб-сайте. alax.info и я увидел, что вы были автором. Я видел одну из ваших статей, которая находится на alax.info/blog/1716. Я полагал, что приложение написано используя C ++ и мог записывать звук. Исходный код недоступен на вашем сайте, и мне интересно, планируете ли вы выпустить его в образовательных целях. это моя электронная почта, кстати. [email protected] Спасибо. - person kripto; 27.06.2017
comment
Код был перепрофилирован для другого проекта, поэтому исходный код недоступен. Извини за это! - person Roman R.; 27.06.2017
comment
а ну понятно. Спасибо. - person kripto; 27.06.2017
comment
Привет, Роман, извините, что беспокою вас снова, но это касается вашего сообщения в блоге здесь alax.info/blog/1716. Ваше приложение прекращает запись, когда я запускаю приложение в полноэкранном режиме. У вас есть идеи, как записывать также экран, когда я запускаю какое-либо приложение в полноэкранном режиме? Спасибо - person kripto; 23.10.2017
comment
@kripto: просто через некоторое время запустите еще один сеанс дублирования рабочего стола, и вы снова получите видеопоток. Поместить его более плавно в один и тот же непрерывный файл сложнее, но также возможно, если вы разработаете соответствующий слой склеивания между Desktop Duplication и MF Media Sink. - person Roman R.; 23.10.2017
comment
Спасибо за ответ, я уже пробовал. Но я все еще получаю Устройство было потеряно. Я использую D3DSurface и передаю его Sinkwriter. Я также попытался повторно инициализировать свое устройство D3D, когда оно обнаруживает, что устройство было потеряно, но моя запись останавливается. - person kripto; 24.10.2017
comment
Это та же ошибка, с которой я сталкиваюсь. github.com/sharpdx/SharpDX/issues/798 - person kripto; 27.10.2017
comment
Привет, Роман, ты прямо сейчас я могу записывать в полноэкранном режиме, но он создает другой файл. Моя запись теперь создает новый файл каждый раз, когда она переключается в полноэкранный и не полноэкранный режим. Я сейчас выясняю, как происходит склеивание, или у вас есть идея продолжить запись, не создавая несколько файлов. - person kripto; 03.11.2017
comment
@kripto: вы сами решаете, когда начинать новый файл. Пока вы используете один и тот же экземпляр IMFSinkWriter, вы продолжаете работать с одним и тем же файлом. - person Roman R.; 03.11.2017
comment
Благодарю за ваш ответ. Кстати, я использую attribute.SetUnknown(MFAttributesClsid.MF_SINK_WRITER_D3D_MANAGER, m_pDeviceManager); и моя проблема заключается в том, что после перехода в полноэкранный режим d3ddevice будет повторно инициализирован, чтобы дубликат вывода снова работал, и я не знаю, как я могу снова связать новый d3dManager с IMFSinkwriter. - person kripto; 07.11.2017
comment
Привет, Роман, есть ли способ скопировать ресурс текстуры2d в другую текстуру2d с другой шириной и высотой? как это d3dDevice.ImmediateContext.CopyResource (originalTexture2d, resizedTexture2d); Потому что мне нужно иметь согласованный размер texture2d, прежде чем передать его синкрайтеру. - person kripto; 20.11.2017