Совсем запутался с этими кодеками... Нужно из RGB (или BGR) буфера с картинкой получить три плана Y, U, V, которые "ест" x264 энкодер. У меня ступор с порядком записи байт UV, помогите разобраться пожалуйста:
#define CLAMP(t) ((t>255)?255:((t<0)?0:t))
// RGB to YUV
#define GET_Y(R,G,B) CLAMP((( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16)
#define GET_U(R,G,B) CLAMP(((-38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128)
#define GET_V(R,G,B) CLAMP(((112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128)
unsigned int Capture::GrabPlanar(unsigned char **Y, unsigned char **U, unsigned char **V){
if(*Y != nullptr || *U != nullptr || *V != nullptr){return 0;}
unsigned char *frame = nullptr;
unsigned int width, height, plane_size = 0;
unsigned int size = GrabBitmap(&frame, width, height, 1);
if( size){ // I420 algorithm...
plane_size = width * height;
*Y = (unsigned char *)malloc(plane_size );
*U = (unsigned char *)malloc(plane_size >> 2);
*V = (unsigned char *)malloc(plane_size >> 2);
unsigned char R, G, B;
unsigned int iY, iU, iV;
iY = iU = iV = 0;
for(unsigned int i; i < size; i+=3){
R = frame[i ];
G = frame[i+1];
B = frame[i+2];
(*Y)[iY] = GET_Y(R,G,B);
// Не знаю что делать с индексами iU и iV
// там ведь буфер в 4 раза меньше, можно на ошибку сегментации нарваться...
// С какого смещения RGB считать U и V?
iY++;
}
}
if( frame != nullptr ){free(frame);}
return plane_size;
}
И правильно ли выделена память под компоненты? (взял инфо отсюда)
В общем, благодаря первому комментарию под вопросом родилось такое решение
void Capture::BitmapToPlanar(unsigned char *src, unsigned char **Y, unsigned char **U, unsigned char **V, unsigned int width, unsigned int height){
unsigned char pix_buf[3];
int pix_avg[3];
unsigned int pix_pos[4], i, uvi = 0;
for(unsigned int h = 0; h < height; h+=2){
for(unsigned int w = 0; w < width; w+=2){
pix_avg[0] = pix_avg[1] = pix_avg[2] = 0;
pix_pos[0] = w + h * width;
pix_pos[1] = pix_pos[0] + 1;
pix_pos[2] = pix_pos[0] + width;
pix_pos[3] = pix_pos[1] + width;
i = pix_pos[0] * 3;
pix_buf[0] = src[i++];
pix_buf[1] = src[i++];
pix_buf[2] = src[i++];
pix_avg[0]+= pix_buf[0];
pix_avg[1]+= pix_buf[1];
pix_avg[2]+= pix_buf[2];
(*Y)[pix_pos[0]] = GET_Y(pix_buf[0],pix_buf[1],pix_buf[2]);
pix_buf[0] = src[i++];
pix_buf[1] = src[i++];
pix_buf[2] = src[i ];
pix_avg[0]+= pix_buf[0];
pix_avg[1]+= pix_buf[1];
pix_avg[2]+= pix_buf[2];
(*Y)[pix_pos[1]] = GET_Y(pix_buf[0],pix_buf[1],pix_buf[2]);
i = pix_pos[2] * 3;
pix_buf[0] = src[i++];
pix_buf[1] = src[i++];
pix_buf[2] = src[i++];
pix_avg[0]+= pix_buf[0];
pix_avg[1]+= pix_buf[1];
pix_avg[2]+= pix_buf[2];
(*Y)[pix_pos[2]] = GET_Y(pix_buf[0],pix_buf[1],pix_buf[2]);
pix_buf[0] = src[i++];
pix_buf[1] = src[i++];
pix_buf[2] = src[i ];
pix_avg[0]+= pix_buf[0];
pix_avg[1]+= pix_buf[1];
pix_avg[2]+= pix_buf[2];
(*Y)[pix_pos[3]] = GET_Y(pix_buf[0],pix_buf[1],pix_buf[2]);
pix_avg[0]/= 4;
pix_avg[1]/= 4;
pix_avg[2]/= 4;
(*U)[uvi] = GET_U(pix_avg[0],pix_avg[1],pix_avg[2]);
(*V)[uvi] = GET_V(pix_avg[0],pix_avg[1],pix_avg[2]);
uvi++;
}
}
}
которое, судя по всему, пришлось энкодеру по вкусу:
Повторяющийся код конечно режет глаза, но главное работает. Видео записал, цвета в порядке!
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Вопрос такой: как лучше произвольную(самую обычную) хранить матрицу? В виде массива указателей или цельным вектором?
// ConsoleApplication5cpp: определяет точку входа для консольного приложения
Мне нужно значение double перевести в строку с определенным количеством символов до и после запятойЯ использую функцию snprintf():
Вот пример реализации ОПЗ, возможно местами кривоКак из этого сделать бинарное дерево? У меня идея была построить двумерный массив и уже...