Перейти к содержимому
Compvision.ru
Vicul

Конвертор формата BGR24 to YUYV

Recommended Posts

Работаю с программой, где я принимаю фреймы в 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;


}


Поделитесь идеями?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ну как бы сдвиг указателя явно где то неправильный.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

это понятно, что не правильный, только вот где?

Вот здесь я заполняю 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);



Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Со сдвигом разобрался, дело в том, что в приемном модуле у меня кодек был установлен как RAWVIDEO и заголовки типа BITMAP... там не нужны, потому все сдвигалось на размер этих заголовков.

Но теперь проблема чисто opencv, изображение на выходе идет с синими лицами. С помощью cvSaveImage() определил, что bgr кадр поступает в конвертор c нормальными цветами,

а вот на выходе идет уже с искажением на синий цвет.

Где копать? коды конвертора в первом посте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А если заменить cvCvtColor(&RgbImg, pYuvImg, CV_BGR2YCrCb) на cvCvtColor(&RgbImg, pYuvImg, CV_RGB2YCrCb)?

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Блин заработало!!!

Дай Бог тебе здоровья и удачи.

Полдня сидел, чуть себе резьбу не сорвал.

Не понятно, почему CV_RGB2YCrC, ведь на вход у меня поступает bgr?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я как-то столкнулся с похожей проблемой в IPP'шных кодеках. Так и не понял в чём дело. Специально для них писал функцию на ассемблере для быстрой смены каналов местами.

В твоём конкретном случае, чувствую, тоже надо разбираться отдельно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

значит буду капать дальше,

спасибо за помощь!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×