Hi Mark,
On Tue, Aug 30, 2011 at 1:05 AM, Mark Kenna
<[email protected]> wrote:
> On 26/08/2011 23:40, Ronald S. Bultje wrote:
>> On Fri, Aug 26, 2011 at 6:15 AM, Mark Kenna
>> <[email protected]> wrote:
>>> I have 4 AVFrames holding YUV420p data and I want to join them together
>>> into
>>> a single AVFrame for encoding, in effect tiling the output like so:
>>>
>>> [ ][ ]
>>> [ ][ ]
>>>
>>> Is LibAv able to do this without first converting to RGB and splicing
>>> them
>>> together?
>>
>> I don't think you ever need to convert to RGB.
>>
>> You can't splice them together. However, you can make it easier. That
>> is, implement your own get_buffer callback and allocate one big buffer
>> with double strides and set offsets correctly so it puts it exactly at
>> these positions. (I hope that makes sense, I can provide more detail
>> if that is confusing.)
>
> I think I know where you are coming from but can you explain in more detail
> just to be sure? Perhaps some sample code if there is any?
I don't have any sample code, but let me explain with a little more detail.
Step 1: implement a get_buffer callback in your application. This
means that when Libav tries to decode a frame, it doesn't put it in
its own buffer, but uses your application's buffer allocation
mechanism instead. (This is AVCodecContext->get_buffer.)
Step 2: (this requires that you know which buffers are to be placed in
which order, but I assume you know that already.) using your own
get_buffer callback, don't allocate one buffer per frame, but instead
one 2x2-sized buffer per 4 frames. This means, that when you fill the
AVFrame.data[]/linesize[] of the buffer, you don't av_malloc() buffers
for each, but rather a buffer that is twice the width and twice the
height of the picture to be decoded.
So instead of:
static int my_get_buffer(...)
{
buffer->data[0] = av_malloc(height * buffer->linesize[0]);
// etc. for data[1]/[2]
}
you do:
static int my_get_buffer(...)
{
if (need_new_cache_buffer) {
cache_buffer[0] = av_malloc(buffer->linesize[0] * 2 * height * 2);
// etc. for cache_buffer[1]/[2]
}
// int position = 0 for topleft, 1 for top right, 2 for bottom
left, 3 for bottom right
buffer->data[0] = cache_buffer[0] + ((position & 1) + position &
2) * height) * buffer->linesize[0];
// etc. for data[1]/[2]
}
what will happen now is that the data is automatically filled into the
relevant regions of the output buffer, no need to memcpy() after
decoding.
A few warnings:
- you're required to use CODEC_FLAG_EMU_EDGE (in
AVCodecContext->flags), else you'll get weird borders around your
image. Assure linesize[0] == width.
- this doesn't work if your h264 picture has weird cropping parameters
(unlikely, but just to be sure)
HTH,
Ronald
_______________________________________________
libav-api mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-api