Hi Hendrik,

Many thanks to the detailed explanation. I applied the x-direction
shift code. The program works as I wanted. I attached the related code
here. Please let me know if you see any places I can optimize it
further.

The avframe pointer copy helps in later avframe data memory release
because the original data pointers have been altered. Is it why you
copied the avframe pointer first?

The memory access error I got before was actually caused by double
memory release.

...
/*Alloc. the target frame with 640X480 res.*/
AVFrame* picture_final  = alloc_target_frame(PIX_FMT_YUV420P, 640, 480);
AVFrame* picture_final_copy  = picture_final;
..

/*Get the sws context that would scale src. images from 640x480 to 320x480*/
img_convert_ctx = sws_getContext(640, 480, PIX_FMT_YUV420P, 320, 480,
ist->st->codec->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);

/*scale the first image to left half of target frame*/
if ( sws_scale(img_convert_ctx, picture1->data, picture1->linesize, 0,
480, picture_final->data, picture_final->linesize) < 0 )
{
}

/*Apply the x shift in target frame*/
picture_final->data[0] += picture_final->linesize[0] / 2;
picture_final->data[1] += picture_final->linesize[1] / 2;
picture_final->data[2] += picture_final->linesize[2] / 2;

/*Scale the second image  half of the target frame*/
if ( sws_scale(img_convert_ctx, pictur2->data, picture2->linesize, 0,
480, picture_final->data, picture_final->linesize) < 0 )
{
}
...
av_free(picture_final_copy->data[0]);
av_free(picture_final_copy);

Best Regards,
Ke


2010/3/15 Hendrik Jürgens <[email protected]>
>
> Hi,
>
> i've only copied the avframe to copy the pointers to the data and linesize 
> arrays. You also could only copy the two arrays in it. It's the same.
>
> To get a quick overview about the linsizes see this example.
> I have an memory block stored at the memory address 10000. The picture is 
> 120x60. So i need a block of 120*60 * 4bytes for an argb image.
> linesize for this example is 120 * 4bytes.
>
> 1st line:  10000              ARGB ARGB ARGB(...)
> 2nd line:  10000 + 120*4      ARGB ARGB ARGB(...)
> 3rd line:  10000 + 120*4 * 2  ARGB ARGB ARGB(...)
> 4th line:  10000 + 120*4 * 3  ARGB ARGB ARGB(...)
>
> The linepitch is added for every line. So you get a pointer on the start of 
> that line. This pitch can also get negative, then the startpointer for thsi 
> example is not 10000 anymore. Then its 38800 (10000 + 120*4 * 60). The 
> nextline then is 38800 - 120*4, and so on.
>
> if you now want to set a pixel in the firstline on the 6th position you have 
> to add 6 to the starting address of that row (10000 + 6) to get the memory 
> location of this actual pixel.
> To get the location of the 6th pixel in the 2nd row you simply add the 
> linepitch to the 6th pixel of the firstrow. So you get the folowing: 10000+6 
> + 120*4 and so on. This is the same for your YUV picture!
>
> So to get a shift in the x-direction, you simply need to add some to the 
> start pointers. so if you want to start at the half of your target image 
> simply add abs(linesize)/2 to it. Because linesize is the size of a full row. 
> For swscale this ist then an image with half width, nothing else. You only 
> have to make sure, that the swscale context will scale the image to this 
> smaller "virtual" image.
>
>
> I missed the negative linesizes in my example before, you have to caclulate 
> the absolute values for this. This could be what lead to the access violation 
> in your application. You also have to check, how large this array is. For RGB 
> mostly the first index is set in the array. For YUV data the first three 
> should be set.
>
> data[0] += abs(linesize[0]) / 2;
> data[1] += abs(linesize[1]) / 2;
> data[2] += abs(linesize[2]) / 2;
>
> I hope this made it clearer for you, what I ment in this example
>
> Best regards
> Hendrik
>
> Am 15.03.2010 05:24, schrieb Ke Yu:
>>
>> Thanks, Hendrik, for your generous help. I still don't quite
>> understand it here. What's the reason to copy the target avframe data?
>> After the data copying, can I still scale the second image onto the
>> same target avframe? Also, I don't understand the algorithm to add
>> linesize/2 to the data pointers. After doing that, it seems like I got
>> a memory access error when calling sws_scale.
>> Your way should be the ideal one to accomplish what I want. I just
>> need to get it done right. :)
>>
>> On 3/14/10, Hendrik Jürgens<[email protected]>  wrote:
>>>
>>> You simply have to adjust the data pointers of your target image, to scale
>>> the second input on it.
>>>
>>> Simply copy the data and linesize arrays.
>>> Then add linesize/2 to the data pointers. With this you get a shift in the x
>>> direction.
>>>
>>> i.e.
>>> avframecopy = avframe;
>>> avframecopy.data[0] += avframecopy.linesize[0] / 2;
>>> avframecopy.data[1] += avframecopy.linesize[1] / 2;
>>> avframecopy.data[2] += avframecopy.linesize[2] / 2;
>>>
>>> then you can scale your second image with a resolution of 320x480 on this
>>> "new" target.
>>>
>>> This should do the trick here.
>>>
>>> Please note, that this needs more rethinking, if your target resolution
>>> differs. But with yuv420 and 640x480 you shouldn't have a problem here.
>>>
>>> ________________________________________
>>> Von: [email protected] [[email protected]] im
>>> Auftrag von Ke Yu [[email protected]]
>>> Gesendet: Freitag, 12. März 2010 21:00
>>> An: Libav* user questions and discussions
>>> Betreff: Re: [libav-user] stitch avframes
>>>
>>> I think I figured out what you meant. Here's my understanding (my pixel_fmt
>>> is PIX_FMT_YUV420P):
>>> 1). concatenate each corresponding field in avframe->data with data from
>>> both src images (avframes);
>>> 2). double the value of each field in avframe->linesize;
>>> 3). sws_scale the avframe built with step 1) and 2) into the allocated
>>> avframe with res. 640x480.
>>>
>>> I'm trying it now. I'll let you know how it goes.
>>>
>>> Best Regards.
>>>
>>> On Fri, Mar 12, 2010 at 12:03 PM, Ke Yu<[email protected]>  wrote:
>>>
>>>> Thanks for the great idea. Following your suggestion, I scaled one of the
>>>> source images to the allocated dest. frame (640x480). It is fast! However,
>>>> I
>>>> could only scale the first src image to the left portion of the dest.
>>>> frame.
>>>> How can I scale the second src image to the right portion of the dest.
>>>> frame? sws_scale/sws_getContext only give sizes no location coordinates.
>>>> Is there a way with which I can specify the coordinates as well?
>>>>
>>>> Thanks again!
>>>>
>>>> 2010/3/12 Hendrik Jürgens<[email protected]>
>>>>
>>>> Am 12.03.2010 01:14, schrieb Stefano Sabatini:
>>>>>
>>>>> On date Thursday 2010-03-11 14:21:24 -0500, Ke Yu encoded:
>>>>>>
>>>>>>> Hi!
>>>>>>>
>>>>>>> I've got avframes from two udp multicast video streams. I would like to
>>>>>>> scale every avframe into half (only x coordinate, e.g.,
>>>>>>> 640x480->320x480) and stitch the two scaled avframes into one avframe
>>>>>>> with
>>>>>>> original size (e.g., 640x480). After that, I'll encode the generated
>>>>>>> avframes into one output video stream. My input video streams have the
>>>>>>> same
>>>>>>> encoding context. The frame rate is 30 fps. So I have about 33ms to
>>>>>>> finish
>>>>>>> the scaling and stitching. The performance is critical. I plan to use
>>>>>>> sws_scale to scale the avframe but don't know how to stitch two scaled
>>>>>>> avframes together. I prefer not to use a third party image lib.
>>>>>>>
>>>>>>> Can anyone help me to figure that out?
>>>>>>>
>>>>>>
>>>>>> Try with libavfilter+overlay, integration into main SVN pending.
>>>>>>
>>>>>> Regards.
>>>>>>
>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> You can allocate your AVFrame with the target resolution (640x480) and
>>>>> then let sws_scale the sourceimages directly onto this frame.
>>>>>
>>>>> You simply have to modify the data pointers and linepitches of yout
>>>>> AVFrame before giving them to sws_scale. If you don't need any
>>>>> transparency
>>>>> or some other fancy image stuff this should be the fastest way.
>>>>>
>>>>>
>>>>> Best regards
>>>>> Hendrik
>>>>>
>>>>> _______________________________________________
>>>>> libav-user mailing list
>>>>> [email protected]
>>>>> https://lists.mplayerhq.hu/mailman/listinfo/libav-user
>>>>>
>>>>
>>>>
>>> _______________________________________________
>>> libav-user mailing list
>>> [email protected]
>>> https://lists.mplayerhq.hu/mailman/listinfo/libav-user
>>> _______________________________________________
>>> libav-user mailing list
>>> [email protected]
>>> https://lists.mplayerhq.hu/mailman/listinfo/libav-user
>>>
>> _______________________________________________
>> libav-user mailing list
>> [email protected]
>> https://lists.mplayerhq.hu/mailman/listinfo/libav-user
>
> _______________________________________________
> libav-user mailing list
> [email protected]
> https://lists.mplayerhq.hu/mailman/listinfo/libav-user
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to