Я работаю над переводом библиотеки захвата с DirectShow на MediaFoundation. Библиотека захвата, похоже, работала неплохо, но у меня возникла проблема с интегрированной веб-камерой на планшете с 32-разрядной версией Windows 8.Media Foundation onReadSample неправильный размер возвращаемого образца
При перечислении формат захвата (как объяснено в Media Foundation documentation), я получил следующий поддерживаемый формат камеры:
- 0: MFVideoFormat_NV12, разрешение: 448x252, фреймрейт: 30000x1001
- 1: MFVideoFormat_YUY2, разрешение: 448x252, частота кадров: 30000x1001
- 2: MFVideoFormat_NV12, разрешение: 640x360, частота кадров: 30000x1001
- 3: MFVideoFormat_YUY2, разрешение: 640x360, частота кадров: 30000x1001
- 4: MFVideoFormat_NV12, разрешение: 640x480, частота кадров: 30000x1001
- 5: MFVideoFormat_YUY2, разрешение: 640x480, частота кадров: 30000x1001
Я тогда установить формат захвата, в этом случае, по одному индексу 5, используя следующая функция, как описано в примере:
hr = pHandler->SetCurrentMediaType(pType);
Эта функция выполнена без ошибок. Таким образом, камера должна быть сконфигурирована для захвата в YUY2 с разрешением 640 * 480.
В onReadSample callback, я должен получить образец с буфером размера:
640 * 480 * sizeof(unsigned char) * 2 = 614400 //YUY2 is encoded on 2 bytes
Тем не менее, я получил образец с буфером размером 169344. Здесь ниже является частью функции обратного вызова.
HRESULT SourceReader::OnReadSample(
HRESULT hrStatus,
DWORD dwStreamIndex,
DWORD dwStreamFlags,
LONGLONG llTimeStamp,
IMFSample *pSample // Can be NULL
)
{
EnterCriticalSection(&m_critsec);
if (pSample)
{
DWORD expectedBufferSize = 640*480*1*2; // = 614400 (hard code for the example)
IMFMediaBuffer* buffer = NULL;
hr = pSample->ConvertToContiguousBuffer(&buffer);
if (FAILED(hr))
{
//...
goto done;
}
DWORD byteLength = 0;
BYTE* pixels = NULL;
hr = buffer->Lock(&pixels, NULL, &byteLength);
//byteLength is 169344 instead of 614400
if (byteLength > 0 && byteLength == expectedBufferSize)
{
//do someting with the image, but never comes here because byteLength is wrong
}
//...
Любой совет, почему я получаю образец размером 169344?
Заранее спасибо
Спасибо Mgetz за ваш ответ.
Я проверил значение типа медиафайла MF_MT_INTERLACE_MODE и выяснилось, что видеопоток содержит прогрессивные кадры. Значение MF_MT_INTERLACE_MODE возвращает MFVideoInterlace_Progressive.
hr = pHandler->SetCurrentMediaType(m_pType);
if(FAILED(hr)){
//
}
else
{
//get info about interlacing
UINT32 interlaceFormat = MFVideoInterlace_Unknown;
m_pType->GetUINT32(MF_MT_INTERLACE_MODE, &interlaceFormat);
//...
Таким образом, видеопоток не чересстрочный. Я снова проверил в onReadSample значение MFSampleExtension_Interlaced, чтобы увидеть, является ли образец чересстрочным или нет, и кажется, что образец чересстрочный.
if (pSample && m_bCapture)
{
//check if interlaced
UINT32 isSampleInterlaced = 0;
pSample->GetUINT32(MFSampleExtension_Interlaced, &isSampleInterlaced);
if(isSampleInterlaced)
{
//enters here
}
Как возможно, что поток является прогрессивным и что образец чересстрочный? Я дважды проверял значение MF_MT_INTERLACE_MODE в обратном вызове onReadSample, и он по-прежнему дает мне значение MFT_INPUT_STREAM_WHOLE_SAMPLES.
Что касается вашего первого предложения, я не смог заставить флаг MFT_INPUT_STREAM_WHOLE_SAMPLES во входном потоке.
Заранее спасибо
Я до сих пор сталкиваются с проблемой, и я в настоящее время расследование на различных потоков, доступных.
Согласно документации, каждый источник мультимедиа предоставляет дескриптор представления, из которого мы можем получить доступные потоки. Чтобы получить дескриптор представления, мы должны назвать:
HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
Я затем запросить потоки, доступные с помощью IMFPresentationDescriptor :: функция GetStreamDescriptorCount:
DWORD nbrStream;
pPD->GetStreamDescriptorCount(&nbrStream);
При запросе этой информации на лобовом веб на качестве ACER планшета с окнами 8, я получил три потока. Я зациклился на этих потоках, попросил их MediaTypeHandler и проверил MajorType. Три потока имеют для основного типа: MFMediaType_Video, поэтому все потоки являются потоками видео. При перечислении типа носителя, доступного в разных потоках, я получил, что все потоки поддерживают захват на 640x480. (некоторые из потоков имеют более доступные типы носителей).
Я проверил, чтобы выбрать каждый из различных потоков и соответствующего типа формата (рамки не возвращать какую-либо ошибки), но я до сих пор не получаю правильный образец в функции обратного вызова ...
Любых консультаций для продвижения по этому вопросу?
Наконец нашел вопрос: я должен был установить тип носителя на читателя источника напрямую, используя SourceReader-> SetCurrentMediaType (..). Это сделал трюк!
Благодарим за помощь!
Я рад, что вы, наконец, нашли решение, фонд средств массовой информации может быть немного не стартером, и я знаю, что мне потребовался хороший день или два отладки, чтобы получить MFT только для правильной загрузки и регистрации. Вероятно, было бы лучше, если бы вы сами ответили на вопрос и приняли свой собственный ответ, поскольку мой действительно не отвечает на вопрос, кроме как очень смутно. – Mgetz
Спасибо Mgetz, я последовал вашим советам и опубликовал новый ответ – skuallpa