2013-11-19 3 views
1

Я работаю над переводом библиотеки захвата с 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 (..). Это сделал трюк!

Благодарим за помощь!

+0

Я рад, что вы, наконец, нашли решение, фонд средств массовой информации может быть немного не стартером, и я знаю, что мне потребовался хороший день или два отладки, чтобы получить MFT только для правильной загрузки и регистрации. Вероятно, было бы лучше, если бы вы сами ответили на вопрос и приняли свой собственный ответ, поскольку мой действительно не отвечает на вопрос, кроме как очень смутно. – Mgetz

+0

Спасибо Mgetz, я последовал вашим советам и опубликовал новый ответ – skuallpa

ответ

0

Наконец-то возникла проблема: мне нужно было установить тип носителя на исходном считывателе напрямую, используя SourceReader-> SetCurrentMediaType (..). Это сделал трюк!

Благодарим за помощь!

0

Не зная, что такое дескриптор типа входного носителя, мы можем в основном только предполагать, но наиболее вероятный ответ заключается в том, что вы говорите, что можете обрабатывать поток, хотя MFT_INPUT_STREAM_WHOLE_SAMPLES не установлен на входном потоке.

Следующей наиболее вероятной причиной является interlacing, и в этом случае каждый кадр будет полным, но не полным разрешением, которое вы принимаете. Независимо от того, вы должны подтвердить свой дескриптор типа ENTIRE, прежде чем принимать его.

Смежные вопросы