Установить атрибуты через ICodecAPI для кодера IMFSinkWriter H.264 - PullRequest
1 голос
/ 03 июня 2019

Я пытаюсь настроить атрибуты кодера H.264, созданные с помощью ActivateObject (), путем получения к нему интерфейса ICodecAPI. Хотя я не получаю ошибок, мои настройки не учитываются.

Код работает под Windows 10.

Я копирую код, который использую для создания IMFSinkWriter, и получаю приведенный ниже ICodecAPI. Обработка ошибок не показана, но ошибки не выдаются.

Я прочитал эту ветку , которая подразумевает, что настройка кодировщика, используемого IMFSinkWriter, может быть невозможна, но поскольку в документации MSDN нет заявления, которое я хотел бы услышать, если кому-то удалось использовать ICodecAPI с IMFSinkWritter.

Если это невозможно, каков будет путь? Мне нужно кодировать в H.264 и поток в MP4. Я хочу изменить GOP, Qp, CABAC и т. Д., Что, по-видимому, невозможно из-за типа носителя. Я должен быть в состоянии создать кодировщик отдельно и подключить его к средству записи файлов MP4? Любые указатели о том, как это сделать, приветствуются ...

hr = encoderToOpen.activate->ActivateObject(__uuidof(IMFTransform), (LPVOID *)&encoderTransform);
hr = encoderTransform->GetAttributes(&attributes);
hr = attributes->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
hr = MFCreateSinkWriterFromURL(fileName, NULL, attributes, &encoder);

// Initialise outputMediaType (code not shown)

hr = encoder->AddStream(outputMediaType, &streamIndex);
hr = encoder->SetInputMediaType(streamIndex, sourceMediaType, NULL);

// Retrieve the ICodecAPI
ICodecAPI *codecApi;
streamIndex = 0;
hr = encoder->GetServiceForStream(streamIndex, GUID_NULL, __uuidof(ICodecAPI), (LPVOID*)&codecApi);

VARIANT v;
hr = codecApi->GetValue(&CODECAPI_AVEncCommonQuality, &v);
v.vt = VT_UI4;
v.ulVal = 8;
hr = codecApi->SetValue(&CODECAPI_AVEncMPVGOPSize, &v);

// Start encoding (code not shown)

1 Ответ

0 голосов
/ 05 июня 2019

Sink Writer от Media Foundation - это упрощенный API, в котором вопрос конфигурации энкодера упущен. Фундаментальная проблема здесь заключается в том, что у вас нет MFT кодировщика, и вы получаете к нему доступ через голову автора, тогда поведение кодировщиков при изменении настроек после того, как все настроено, зависит от реализации, которая в случае кодировщика зависит от конкретной реализации поставщика. и может варьироваться в зависимости от оборудования.

Более надежный вариант - напрямую управлять кодированием MFT и снабжать Sink Writer уже закодированным видео.

Ваша потенциальная уловка, чтобы заставить вещи работать с меньшими усилиями, - это также извлечь и очистить IMFTransform кодировщика, а затем вернуть обратно типы входных / выходных носителей после того, как вы закончили с ICodecAPI обновлением. Сдвигая типы носителей, вы предлагаете, чтобы кодировщик перенастроил внутренние компоненты, и он сделал бы это уже с вашими настройками. Обратите внимание, что это, вообще говоря, может иметь побочные проблемы.

Эта хитрость работает для некоторых параметров ICodecAPI (например, CODECAPI_AVEncCommonQualityVsSpeed) и только для кодера h.264 от Microsoft. Не влияет на CODECAPI_AVEncH264CABACEnable. Документ действительно предназначен для кодировщика Microsoft и не является универсальным API. Я использую кодеки QuickSync и NVidia. Знаете ли вы, настраиваются ли они через ICodecAPI, если я создаю MFT самостоятельно?

Поставляемые поставщиком кодировщики подпадают под требования Сертифицированный аппаратный кодировщик , поэтому они должны поддерживать значения ICodecAPI, указанные в статье MSDN. Важно то, что не определен порядок вызовов конфигурации. Если вы сами управляете кодировщиком, вы должны выполнить настройку ICodecAPI перед настройкой типов носителей. В сценарии Sink Writer он уже настроил типы носителей, после чего вы переходите к тонкой настройке. Следовательно, мое предложение об уловке включает в себя часть сброса существующих типов носителей. Поскольку этот трюк чувствителен к деталям реализации, я бы посоветовал получить текущие типы носителей, затем очистить их на MFT, выполнить ICodecAPI и вернуть типы. Я предполагаю, что это должно работать в большем количестве сценариев, а не только в кодировщике MS. Все же это все еще остается ненадежным взломом.

IMO Реализация кодировщика Nvidia ужасна (наихудшая среди поставщиков), Intel лучше, но у нее все еще есть свои проблемы. Опять же, IMO, MFT предоставляются только для того, чтобы соответствовать минимальным требованиям сертификации для аппаратного кодирования видео, и по этой причине их реализация плохо согласована. Различные программные пакеты предпочитают реализовывать кодирование видео через SDK производителя, а не через интерфейс Media Foundation Transform. В одном из проектов я также пропустил идею использования MFT для кодирования и реализовал свои собственные MFT поверх SDK поставщиков.

Будет ли подход фабрики классов в этом посте работать с IMFSinkWriter? Это позволит избежать написания слишком большого количества кода ...

Полагаю, да, это должно сработать, хотя я чувствую, что это не очень приятная работа - исправлять это таким образом. Также вам может понадобиться принять во внимание поддержку кодеров HW, потому что Sink Writer также имеет тенденцию использовать аппаратное кодирование в некоторых случаях, включая сценарий, когда ему предоставляется устройство DXGI.

Еще один вид взлома, который похож, но, возможно, немного менее навязчив (хотя в его реализации вам нужно было бы лучше понять внутреннее устройство), заключается в переопределении конкретных CLSID кодировщика поставщика в пределах области инициализации Sink Writer. Существует всего три кодера (AMD, Intel, Nvidia; хорошо, четвертый от Shanghai Zhaoxin Semiconductor, но он не очень популярен), и их CLSID известны. Если вы умно CoRegisterClassObject, вы можете подключить MFT-инстанцирование, чтобы Media Foundation решал, какой кодировщик выбрать. Это просто еще одна идея, поэтому она может зависеть от того, что лучше всего делать, от других факторов.

...