[RFC] Frame rotation by 90 degree
Hi All, I am new to this mailing list. My problem is to rotate a frame by 90, 180 and 270 degrees by adding/changing in FFMPEG code. For 180 degree rotation, I got the vf_vflip.c file under the libavfilter folder, which does the flipping, that means 180 degree rotation. But for 90 and 270 degree rotation we need to add in the ffmpeg code base. For this purpose, I thought that vf_vflip.c would be the starting point to proceed. And I got that, the fliping part is done inside the start_frame() function of the vf_Vflip.c (am I wrong...?). static void start_frame(AVFilterLink *link, AVFilterPicRef *picref) { FlipContext *flip = link->dst->priv; AVFilterPicRef *ref2 = avfilter_ref_pic(picref, ~0); int i; ref2->data[0] += (ref2->h-1) * ref2->linesize[0]; ref2->linesize[0] = -ref2->linesize[0]; for(i = 1; i < 4; i ++) { if(ref2->data[i]) { ref2->data[i] += ((ref2->h >> flip->vsub)-1) * ref2->linesize[i]; ref2->linesize[i] = -ref2->linesize[i]; } } avfilter_start_frame(link->dst->outputs[0], ref2); } In the above code width becomes the negative of of the existing width, but what's the use of the two lines below ... if(ref2->data[i]) { ref2->data[i] += ((ref2->h >> flip->vsub)-1) * ref2->linesize[i]; ref2->linesize[i] = -ref2->linesize[i]; } This algorithm is not clear to me. So my understanding for implementing rotation, is to add code in the start_frame() function. I need to rotate the frame in Y,U and V plane separately. But I saw that linesize[1] and linesize[2] does not represent the width of the frame exactly and I am confused about the exact rotation algorithm. For rotation in the Y plane, according to my understanding the rotation algorithm will be as follows --- void rotatePicture(AVFrame *fPicture, int w, int h, AVCodecContext *enc){ int i = 0, index, ai = 0, wi, hi ; uint8_t *arr = av_malloc(w*h * sizeof(uint8_t)); uint8_t *arr1 = NULL; uint8_t *arr2 = NULL; memset(arr, 0, w*h*sizeof(uint8_t)); // this is ONLY for the Y component for(wi = 0; wi <= w-1; wi++){ for(hi = h - 1; hi >= 0; hi--){ //arr[ai++] = fPicture->data[0][hi*w + wi]; arr[ai++] = 0; } } What do you think - is it correct... ? And then what will be for U and V plane...? Please suggest... Thanks in Advance... Thanks and Regards Tilak *-- tilak
On 3 Dec 2007 07:18:11 -0000 "Tilak Adhya" <tilakadhya@rediffmail.com> wrote:
Hi All,
I am new to this mailing list. My problem is to rotate a frame by 90, 180 and 270 degrees by adding/changing in FFMPEG code. For 180 degree rotation, I got the vf_vflip.c file under the libavfilter folder, which does the flipping, that means 180 degree rotation. But for 90
No. vf_vflip mirrors the image, which is not the same as a 180 degree rotation. In a rotation, the top-left corner would end up in the bottom-right. With vf_vflip, it ends up in the bottom-left. This is a very special case and can be accomplished simply by changing the pointer to the beginning of the frame data, and by negating the linesize. This does not generalize to other rotations, which will require that you copy data around.
and 270 degree rotation we need to add in the ffmpeg code base. For this purpose, I thought that vf_vflip.c would be the starting point to proceed. And I got that, the fliping part is done inside the start_frame() function of the vf_Vflip.c (am I wrong...?).
Yes, it is. But that will not work for true rotation because the image data is not available at that point. You need to process it either in draw_slice() (preferred) or in end_frame().
static void start_frame(AVFilterLink *link, AVFilterPicRef *picref) { FlipContext *flip = link->dst->priv; AVFilterPicRef *ref2 = avfilter_ref_pic(picref, ~0); int i;
ref2->data[0] += (ref2->h-1) * ref2->linesize[0]; ref2->linesize[0] = -ref2->linesize[0]; for(i = 1; i < 4; i ++) { if(ref2->data[i]) { ref2->data[i] += ((ref2->h >> flip->vsub)-1) * ref2->linesize[i]; ref2->linesize[i] = -ref2->linesize[i]; } }
avfilter_start_frame(link->dst->outputs[0], ref2); }
In the above code width becomes the negative of of the existing width, but what's the use of the two lines below ...
if(ref2->data[i]) { ref2->data[i] += ((ref2->h >> flip->vsub)-1) * ref2->linesize[i]; ref2->linesize[i] = -ref2->linesize[i]; }
This algorithm is not clear to me.
This changes the pointer to the image data to point to the last row of the original image. This, along with the negated width causes the image to be flipped.
So my understanding for implementing rotation, is to add code in the start_frame() function. I need to rotate the frame in Y,U and V plane separately. But I saw that linesize[1] and linesize[2] does not represent the width of the frame exactly and I am confused about the exact rotation algorithm. For rotation in the Y plane, according to my understanding the rotation algorithm will be as follows ---
void rotatePicture(AVFrame *fPicture, int w, int h, AVCodecContext *enc){ int i = 0, index, ai = 0, wi, hi ; uint8_t *arr = av_malloc(w*h * sizeof(uint8_t)); uint8_t *arr1 = NULL; uint8_t *arr2 = NULL; memset(arr, 0, w*h*sizeof(uint8_t));
// this is ONLY for the Y component for(wi = 0; wi <= w-1; wi++){ for(hi = h - 1; hi >= 0; hi--){ //arr[ai++] = fPicture->data[0][hi*w + wi]; arr[ai++] = 0; } }
There are functions already available for allocating a new frame. In particular, if you are implementing this as a libavfilter, just make sure your output dimensions are set right, and you can call avfilter_get_video_buffer()
What do you think - is it correct... ? And then what will be for U and V plane...?
I believe someone on ffmpeg-devel already answered this ...
Please suggest...
Thanks in Advance...
Thanks and Regards Tilak
*-- tilak
-- Bobby Bingham Never trust atoms. Or anything made of atoms. このメールは再利用されたバイトでできている。
Hi Bobby Bingham wrote:
On 3 Dec 2007 07:18:11 -0000 "Tilak Adhya" <tilakadhya@rediffmail.com> wrote:
Hi All,
I am new to this mailing list. My problem is to rotate a frame by 90, 180 and 270 degrees by adding/changing in FFMPEG code. For 180 degree rotation, I got the vf_vflip.c file under the libavfilter folder, which does the flipping, that means 180 degree rotation. But for 90
[...]
This is a very special case and can be accomplished simply by changing the pointer to the beginning of the frame data, and by negating the linesize. This does not generalize to other rotations, which will require that you copy data around.
[...]
Please suggest...
Continuing what Bobby said about vflip, maybe it would be a good idea to use as a base not vf_vflip.c but instead vf_negate.c (which do modify the frame data). You can first do a filter that only work with videos with square dimensions and then generalize. -Vitor
Hi Tilak Adhya wrote:
Hi All,
I am new to this mailing list. My problem is to rotate a frame by 90,
ffmpeg -vfilters rot90 -i input.avi output.avi -Vitor
participants (4)
-
Bobby Bingham -
Tilak Adhya -
Vitor -
Vitor Sessak