Vicul 0 Жалоба Опубликовано April 16, 2012 Работаю с программой, где я принимаю фреймы в BGR24 формате и передаю их в модуль, собранный на кодах FFMPEG, который передает их на тв сайт по RTMP протоколу. Все работает нормально, но возникла необходимость передавать фреймы не в BGR24, а в YUYV (YUY2), т.е, нужен конвертор BGR24 -> YUYV. Нашел коды на openCV, немного подправил их и получил одну фигню - концовка кадра почему то оказалась вначале, см. приатаченный файл. Не могу понять, где хомутнул, вот коды конвертора typedef struct _typeYUYV { char Y0; char U0; char Y1; char V0; } _typeYUYV; typedef enum _typeFormat { _NONE = 0, _UYVY, _YUYV } int ConvertBGRTo(char* pSrcBuf, size_t nSrcBufSize, _typeFormat nFormatType, char* pDstBuf, size_t& nDstBufSize, int outX, int outY) { int nRes = NO_ERROR; // Create IplImage for given BMP int nStep = outX*3; IplImage RgbImg; cvInitImageHeader( &RgbImg, cvSize(outX, outY), IPL_DEPTH_8U, 3 ); cvSetData( &RgbImg, (char*)pSrcBuf, nStep ); // Convert RGB24 to YUV (YCrCb) IplImage* pYuvImg = cvCloneImage(&RgbImg); cvCvtColor(&RgbImg,pYuvImg, CV_BGR2YCrCb); char* pDstBufEndPos = pDstBuf + nDstBufSize; for(int nCurYPos = outY - 1; nCurYPos > 0; nCurYPos--) { _typeYUV* pSrcBufCurPos = (_typeYUV*)(pYuvImg->imageData + nCurYPos * nStep); char* pSrcBufEndPos = (char*)pSrcBufCurPos + nStep; for(;(char*)pSrcBufCurPos < pSrcBufEndPos;) { _typeYUYV YUYV = { pSrcBufCurPos[0].Y, pSrcBufCurPos[0].U, pSrcBufCurPos[1].Y, pSrcBufCurPos[0].V }; if((pDstBuf + sizeof(_typeYUYV)) > pDstBufEndPos) break; memcpy(pDstBuf,&YUYV,sizeof(_typeYUYV)); pDstBuf += sizeof(_typeYUYV); if((char*)(pSrcBufCurPos + 2) > pSrcBufEndPos) break; pSrcBufCurPos += 2; } } cvReleaseImage(&pYuvImg); return nRes; } Поделитесь идеями? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано April 16, 2012 Прикрепленный файл Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 17, 2012 ну как бы сдвиг указателя явно где то неправильный. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано April 17, 2012 это понятно, что не правильный, только вот где? Вот здесь я заполняю BITMAPINFOHEADER в FFMPEG модуле для YUYV (аналог YUY2), может здесь я что то намутил? struct VIDEOSTRUCT { uint32_t lBufSize; uint32_t iWidth; uint32_t iHeight; int64_t iTime; uint8_t* pBuf; }; ....... list<VIDEOSTRUCT>::iterator delIter = VideoBuf.begin(); int headersSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); int bufSize = headersSize + delIter->lBufSize; PBYTE data = new BYTE [bufSize]; if (data != NULL) { BITMAPFILEHEADER* pbfHeader; BITMAPINFOHEADER* pbmiHeader; pbfHeader = (BITMAPFILEHEADER *)(data); pbfHeader->bfType = ('M' << CHAR_BIT) | 'B' ; //'MB'; pbfHeader->bfSize = bufSize; pbfHeader->bfOffBits = headersSize; pbfHeader->bfReserved1 = pbfHeader->bfReserved2 = 0; uint8_t* pData; pData = data + headersSize; pbmiHeader = (BITMAPINFOHEADER *)(pData - sizeof(BITMAPINFOHEADER)); pbmiHeader->biBitCount = 16; pbmiHeader->biWidth = delIter->iWidth; pbmiHeader->biHeight = delIter->iHeight; pbmiHeader->biPlanes = 1; pbmiHeader->biSize = sizeof(BITMAPINFOHEADER); pbmiHeader->biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');//MAKEFOURCC('Y', 'U', 'Y', 'V');//MAKEFOURCC('Y', 'U', 'Y', 'V');//BI_RGB; pbmiHeader->biClrImportant = pbmiHeader->biClrUsed = pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0; pbmiHeader->biSizeImage = DIBSIZE(*pbmiHeader); Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано April 19, 2012 Со сдвигом разобрался, дело в том, что в приемном модуле у меня кодек был установлен как RAWVIDEO и заголовки типа BITMAP... там не нужны, потому все сдвигалось на размер этих заголовков. Но теперь проблема чисто opencv, изображение на выходе идет с синими лицами. С помощью cvSaveImage() определил, что bgr кадр поступает в конвертор c нормальными цветами, а вот на выходе идет уже с искажением на синий цвет. Где копать? коды конвертора в первом посте. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 19, 2012 А если заменить cvCvtColor(&RgbImg, pYuvImg, CV_BGR2YCrCb) на cvCvtColor(&RgbImg, pYuvImg, CV_RGB2YCrCb)? 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано April 19, 2012 Блин заработало!!! Дай Бог тебе здоровья и удачи. Полдня сидел, чуть себе резьбу не сорвал. Не понятно, почему CV_RGB2YCrC, ведь на вход у меня поступает bgr? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 19, 2012 Я как-то столкнулся с похожей проблемой в IPP'шных кодеках. Так и не понял в чём дело. Специально для них писал функцию на ассемблере для быстрой смены каналов местами. В твоём конкретном случае, чувствую, тоже надо разбираться отдельно. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Vicul 0 Жалоба Опубликовано April 19, 2012 значит буду капать дальше, спасибо за помощь! Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах