Re[2]: Проблема с GDI
От: klex  
Дата: 12.01.07 07:04
Оценка:
Здравствуйте, andrey.viktorov, Вы писали:

AV>Возникла идея: поставить у ISampleGrabber'а, который хватает битмапы, в AM_MEDIA_TYPE нужный формат битмапа и попробовать установить соединение между пинами в таком формате. Такое возможно? В общем, было бы просто супер, если можно это сделать средствами DirectShow. А нужно сделать следующее : есть семпл определённой длины и ширины, его необходимо подогонать в окно 320х240 не изменяя пропорций (если один из размеров получаются меньше, то оставшееся пространство забивается чёрными пикселями и получаются аля полосы как широкоформатном видео).


Не все так просто как кажеться. Да, конечно возможно, либо используй PushSource Filter для поставки видеокадров. Если хочешь в реальном времени про GDI забудь. Сейчас занимаюсь аналогичной задачей, не знаю получиться ли в реальном времени, но чувствую что — нет, вот откуда такие мысли. Сейчас я написал программу для генерации видеопотока но основе определенных спрайтов которые генерируються на отдельной машине. Потому что когда я попробовал рисовать прямо в буфер кадра, естественно производительность заставляла желать лучшего. После того как я начал генерировать спрайты на отдельной машине, попробовал опять посредством GDI составлять картинку из спрайтов, но опять таки получались довольно приличные тормоза, но уже меньше ) Решил делать посредством memcpy(pSample, pBackBuf, _screenSize), просто у меня задачка еще свзана с тем что аппаратное обеспечение очень специализированное и аппаратное ускорение графики как таковое отсутствует.

Я делаю:

hr = m_pIPushSource->GetFrameBuffer(&pSample);
if (SUCCEEDED(hr))
{
  hr = pSample->GetPointer(&pBuffer);
  cbBuffer = pSample->GetActualDataLength();
  if (pamt && pvih)
    WriteBuffer(pBuffer); // тут внутри memcpy про который я говорил выше
  if (SUCCEEDED(m_pIPushSource->Deliver(pSample)))
  {
    m_FrameCount += 1;
    pBuffer = NULL;
  }
...
}


Далее, функция DrawBackBuffer примерно следующего содержания, вызываеться в WriteBuffer перед memcpy(...):

byte* DrawBackBuffer(byte* pScreen)
{
...
int _size = dwWidth*dwHeight*4 + (dwWidth*4*400); // специфика такая, бэкбуфер должен быть больше рабочего кадра, не имеет отношения к теме ;)
if(backbuf == NULL)
  backbuf = new byte[_size];
// дальше "рисуем"
  for(int i=0; i < m_vImages.size(); i++)
  {
...
    m_vImages[i]->LockBits(&rect, ImageLockModeRead,
                PixelFormat32bppRGB, &bitmapData);
    pixels = (unsigned char*)bitmapData.Scan0;
    DrawImage(x, calc_y, backbuf, pixels)
  }
...
  return backbuf+dwWidth*4*200;
}


Ну и DrawImage:

void DrawImage(..., u_char* src, u_char* dst)
{
...
  for(UINT i=0; i < s_height; i++)
  {
    UINT line = dwHeight - dst_y;
    UINT line_mem = (i+line)*(dst_width*4);
    memcpy((void*)&dst[line_mem + x_offs],
             (void*)&src[(s_height - 1 - i)*s_len], s_len);
  }
}


Все работет отлично. Теперь у меня появилась потребность ко всей этой каше еще подмешать видеопоток с масштабированием, какзлось бы все просто, действуем по аналогии, ан нет, после небольшого теста пришел к сомнению что получиться, а тест был следующий, я добавил функцию, TestMask(... u_char* buf) примерно следующего содержания:

TestMask(... u_char* buf)
{
  for(int i=0; i < dwHeight; i++)
  {
       for(int y=1; y < dwWidth; y++)
       {
           buf[i*(y+2)] = buf[i*(y+2)] && 0x0a;
       }
  }
}


И у меня стало видно подтормаживание видеопотока. Масштабирование планирую делать как нибудь так http://www.enlight.ru/demo/faq/smth.phtml?query=alg_scale_bitmap. Если интересно, сообщу о результатах позже, через пару-тройку дней.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.