This is my WIP patch for GSoC and I worked on transformations involved in encoding/decoding FLIF images. I have created a module under libavcodec and as guided by my mentors I have tried to use pixel data from AVFrame structs. Module covers all the chunks of code for YCoCg Transformation that will be used in final encoder/decoder. Necessary structs and methods have been made as suggested by my mentors. The module compiles/builds successfully. Also I have attached a small code 'transformtest.c' which I wrote for testing the implementation of pixel transformation. The variable AVFrame::data[] is of type uint8_t* and I was initially unaware of this so I stored the YCoCg values in 'data'. So the negative values which were the output of transformation of RGB -> YCoCg were not stored properly and thats where the output is wrong. Just wanted to ask, if I should be using some other structs for storing the YCoCg values and not AVFrame, because AVFrame seems to be the standard struct in FFmpeg where the raw media resides. Attaching some testcases of RGB and its corresponding YCoCg values for testing purposes.
Thanks Kartik K. Khullar
#include "transformflif16.h" int process(Transform transform, AVFrame *frame, int p){ switch(transform.transform_number){ case 1: //Transform number for YCoCg transformation is 1 officially. if(!transform.done){ TransformYCoCg transformYCoCg = initYCoCg(frame, p); if(!processYCoCg(frame)) transform.done = 1; return 0; } break; /* Rest of the cases will be implemented here. */ default: break; } return 0; } TransformYCoCg initYCoCg(AVFrame *frame, int p){ TransformYCoCg transform; transform.num_planes = p; transform.ranges = getRanges(transform.num_planes, frame); transform.origmax4 = max(transform.ranges[0].max, transform.ranges[1].max, transform.ranges[2].max)/4 -1; for(p=0; p<transform.num_planes; p++){ transform.ranges[p].max = max_range_YCoCg(p, transform.origmax4); transform.ranges[p].min = min_range_YCoCg(p, transform.origmax4); } return transform; } int processYCoCg(AVFrame *frame){ int r, c; ColorVal R,G,B,Y,Co,Cg; //Assuming all the channels will have same width and height int height = frame[0].height; int width = frame[0].width; for (r=0; r<height; r++) { for (c=0; c<width; c++) { R = frame->data[0][r*width + c]; G = frame->data[1][r*width + c]; B = frame->data[2][r*width + c]; Y = (((R + B)>>1) + G)>>1; Co = R - B; Cg = G - ((R + B)>>1); frame->data[0][r*width + c] = Y; frame->data[1][r*width + c] = Co; frame->data[2][r*width + c] = Cg; } } return 0; } int invProcessYCoCg(AVFrame *frame){ int r, c; ColorVal R,G,B,Y,Co,Cg; //Assuming all the channels will have same width and height int height = frame[0].height; int width = frame[0].width; for (r=0; r<height; r++) { for (c=0; c<width; c++) { Y = frame->data[0][r*width + c]; Co= frame->data[1][r*width + c]; Cg= frame->data[2][r*width + c]; R = Co + Y + ((1-Cg)>>1) - (Co>>1); G = Y - ((-Cg)>>1); B = Y + ((1-Cg)>>1) - (Co>>1); frame->data[0][r*width + c] = R; frame->data[1][r*width + c] = G; frame->data[2][r*width + c] = B; } } return 0; } ColorRanges* getRanges(int p, AVFrame *frame){ ColorRanges ranges[p]; int i, c, r, width, height; uint8_t min, max; for(i=0; i<p; i++){ width = frame[p].width; height = frame[p].height; min = frame->data[p][0]; max = frame->data[p][0]; for(r=0; r<frame[p].height; r++){ for(c=0; c<frame[p].width; r++){ if(min > frame->data[p][r*width + c]) min = frame->data[p][r*width + c]; if(max < frame->data[p][r*width + c]) max = frame->data[p][r*width + c]; } } ranges[p].min = min; ranges[p].max = max; } return ranges; } int max(int a, int b, int c){ if(a > b){ if(a > c) return a; else return c; } else return b; } int min(int a, int b){ if(a < b) return a; else return b; } int get_min_y(int origmax4){ return 0; } int get_max_y(int origmax4){ return 4*origmax4-1; } int get_min_co(int origmax4, int yval){ int newmax = 4*origmax4 - 1; if (yval < origmax4-1) return -3 - 4*yval; else if (yval >= 3*origmax4) return 4*(yval - newmax); else return -newmax; } int get_max_co(int origmax4, int yval){ int newmax = 4*origmax4 - 1; if (yval < origmax4-1) return 3 + 4*yval; else if (yval >= 3*origmax4) return 4*(newmax - yval); else return newmax; } int get_min_cg(int origmax4, int yval, int coval){ int newmax = 4*origmax4 - 1; if (yval < origmax4-1) return -2 - 2*yval; else if (yval >= 3*origmax4) return -2*(newmax-yval) + 2*((abs(coval)+1)/2); else{ return min(2*yval + 1, 2*newmax - 2*yval - 2*abs(coval)+1)/2; } } int get_max_cg(int origmax4, int yval, int coval){ int newmax = 4*origmax4 - 1; if (yval < origmax4-1) return 1 + 2*yval - 2*(abs(coval)/2); else if (yval >= 3*origmax4) return 2 * (newmax-yval); else return min(2*(yval- newmax), -2*yval - 1 + 2*(abs(coval)/2)); } int min_range_YCoCg(int p, int origmax4){ switch(p){ case 0: return 0; case 1: return -4*origmax4+1; case 2: return -4*origmax4+1; default: return 0; break; } } int max_range_YCoCg(int p, int origmax4){ switch(p){ case 0: return 0; case 1: return 4*origmax4+1; case 2: return 4*origmax4+1; default: return 0; break; } } ColorRanges crangeYCoCg(int p, ColorVal* prevPlanes, TransformYCoCg transform){ ColorRanges crange; switch(p){ case 0: crange.min = get_min_y(transform.origmax4); crange.max = get_max_y(transform.origmax4); break; case 1: crange.min = get_min_co(transform.origmax4, prevPlanes[0]); crange.max = get_max_co(transform.origmax4, prevPlanes[0]); break; case 2: crange.min = get_min_cg(transform.origmax4, prevPlanes[0], prevPlanes[1]); crange.max = get_max_cg(transform.origmax4, prevPlanes[0], prevPlanes[1]); break; default: break; } return crange; }
#include <stdint.h> #include "../libavutil/frame.h" typedef int32_t ColorVal; typedef struct ColorRanges{ ColorVal min, max; }ColorRanges; typedef struct Transform{ char* desc; int transform_number; uint8_t done; }Transform; typedef struct TransformYCoCg{ int origmax4; ColorRanges *ranges; int num_planes; }TransformYCoCg; ColorRanges* getRanges(int p, AVFrame *frame); int getmax(ColorRanges* ranges, int p); int max_range_YCoCg(int p, int origmax4); int min_range_YCoCg(int p, int origmax4); int get_min_y(int); int get_max_y(int orgimax4); int get_min_co(int orgimax4, int yval); int get_max_co(int orgimax4, int yval); int get_min_cg(int orgimax4, int yval, int coval); int get_max_cg(int orgimax4, int yval, int coval); int min(int, int); int max(int, int, int); ColorRanges crangesYCoCg(int p, ColorVal* prevPlanes, TransformYCoCg transform); int process(Transform transform, AVFrame *frame, int p); TransformYCoCg initYCoCg(AVFrame *frame, int p); int processYCoCg(AVFrame *frame); int invProcessYCoCg(AVFrame *frame);
#include "transformflif16.h" int main(){ AVFrame frame; frame.height = 1; frame.width = 214; int i, j; for(i=0; i<3; i++){ frame.data[i] = (uint8_t*)malloc(214*sizeof(uint8_t)); } for(i=0; i<214; i++){ for(j=0; j<3; j++){ scanf("%d", &frame.data[j][i]); } } processYCoCg(&frame); printf("\n\n YCoCg Values ------> \n\n"); for(i=0; i<214; i++){ for(j=0; j<3; j++){ printf("%d ", frame.data[j][i]); } printf("\n"); } return 0; }
RGB
Description: Binary data
YCoCg
Description: Binary data
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".