Thanks a lot. I'm still not used to the new API, so I used the avpicture_*
functions.


2014-04-14 15:01 GMT+03:00 wm4 <[email protected]>:

> On Mon, 14 Apr 2014 13:20:31 +0300
> Ondřej Perutka <[email protected]> wrote:
>
> > Sorry, the attachment was probably filtered out by the mailing list. Here
> > is the code:
> >
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <time.h>
> > #include "libswscale/swscale.h"
> > #include "libavutil/pixfmt.h"
> > #include "libavutil/frame.h"
> > #include "libavcodec/avcodec.h"
> > #include <sys/mman.h>
> >
> > #define PADDING 8
> > #define PAGE_SIZE 0x1000
> > #define PAGE_MASK (PAGE_SIZE - 1)
> >
> > void * alloc_frame(int w, int h, int pf, AVFrame **frame) {
> >     /* get required buffer size + PADDING */
> >     int size = avpicture_get_size(pf, w, h) + PADDING;
> >     /* allocate buffer (make some space for additional locked page) */
> >     uint8_t *data = av_malloc(size + 2 * PAGE_SIZE);
> >     /* get address of the first byte after the padding */
> >     uint8_t *nextByte = data + size;
> >     /* compute offset for the buffer alignment */
> >     unsigned int offset = PAGE_SIZE - ((uint64_t)nextByte & PAGE_MASK);
> >     AVFrame *result;
> >
> >     /* get address of the next page after the padding */
> >     uint8_t *nextPage = (uint64_t)nextByte & ~PAGE_MASK;
> >     if (((uint64_t)nextByte & PAGE_MASK) != 0)
> >         nextPage += PAGE_SIZE;
> >
> >     /* lock the next page */
> >     mprotect(nextPage, PAGE_SIZE, PROT_NONE);
> >
> >     /* allocate a new frame and fill it with aligned data */
> >     result = av_frame_alloc();
> >     avpicture_fill(result, data + offset, pf, w, h);
> >
> >     /* print some info */
> >     printf("buffer: [0x%016lx, 0x%016lx]\n",
> >         (uint64_t)(data + offset),                      /* first byte */
> >         (uint64_t)(data + offset + size - PADDING));    /* last byte + 1
> */
> >     printf("trap address: 0x%016lx\n", (uint64_t)(nextPage));
> >     printf("img size: [%d, %d]\n", w, h);
> >
> >     *frame = result;
> >     return data;
> > }
>
> You probably do this to create a guard page, but normally you should
> use av_frame_get_buffer() to allocate an image.
>
> > void free_frame(void *buffer, AVFrame** frame) {
> >     av_free(buffer);
> >     av_frame_free(frame);
> > }
>
> And if you use av_frame_get_buffer(), av_frame_free() will actually
> free the image.
>
> > int main(void) {
> >     int srcW = 1280;
> >     int srcH = 536;
> >     int dstW, dstH;
> >     int srcPF = AV_PIX_FMT_YUV420P;
> >     int dstPF = AV_PIX_FMT_BGRA;
> >
> >     AVFrame *f1;
> >     void *buffer1 = alloc_frame(srcW, srcH, srcPF, &f1);
> >
> >     int n = 1000;
> >
> >     AVFrame *f2;
> >     void *buffer2;
> >     struct SwsContext *sc;
> >
> >     srand(time(NULL));
> >
> >     while (n-- > 0) {
> >         /* make some random output dimensions */
> >         dstW = 736 + (rand() % 400) - 200;
> >         dstH = 308 + (rand() % 400) - 200;
> >
> >         /* allocate output frame and scale context */
> >         buffer2 = alloc_frame(dstW, dstH, dstPF, &f2);
> >         sc = sws_getCachedContext(NULL, srcW, srcH, srcPF,
> >             dstW, dstH, dstPF, SWS_BICUBIC, NULL, NULL, NULL);
> >
> >         sws_scale(sc, f1->data, f1->linesize, 0, srcH,
> >             f2->data, f2->linesize);
> >
> >         /* free the scale context and the output frame */
> >         sws_freeContext(sc);
> >         free_frame(buffer2, &f2);
> >     }
> >
> >     free_frame(buffer1, &f1);
> >
> >     return 0;
> > }
> >
>
> I can reproduce your problems, but didn't find the cause. The following
> code works just fine, so I assume the avpicture_ crap is to blame, and
> the fact that you try aliasing AVFrame with AVPicture (which I think is
> allowed, but probably still causes problems). I'd suggest you use
> AVFrames natively instead.
>
> The following code works, and passes valgrind without errors:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <time.h>
> #include "libswscale/swscale.h"
> #include "libavutil/pixfmt.h"
> #include "libavutil/frame.h"
>
> AVFrame *alloc_frame(int w, int h, int pf) {
>     AVFrame *result = av_frame_alloc();
>     result->format = pf;
>     result->width = w;
>     result->height = h;
>     av_frame_get_buffer(result, 32); // misses error check
>     return result;
> }
>
> void free_frame(AVFrame** frame) {
>     av_frame_free(frame);
> }
>
> int main(void) {
>     int srcW = 1280;
>     int srcH = 536;
>     int dstW, dstH;
>     int srcPF = AV_PIX_FMT_YUV420P;
>     int dstPF = AV_PIX_FMT_BGRA;
>     int p, y;
>
>     AVFrame *f1 = alloc_frame(srcW, srcH, srcPF);
>     // avoid valgrind errors (YUV420P specific code)
>     for (p = 0; p < 3; p++) {
>         for (y = 0; y < f1->height / (p ? 2 : 1); y++)
>             memset(f1->data[p] + f1->linesize[p] * y, 0, f1->linesize[p]);
>     }
>
>     int n = 1000;
>
>     AVFrame *f2;
>     struct SwsContext *sc;
>
>     srand(time(NULL));
>
>     while (n-- > 0) {
>         /* make some random output dimensions */
>         dstW = 736 + (rand() % 400) - 200;
>         dstH = 308 + (rand() % 400) - 200;
>
>         /* allocate output frame and scale context */
>         f2 = alloc_frame(dstW, dstH, dstPF);
>         sc = sws_getCachedContext(NULL, srcW, srcH, srcPF,
>             dstW, dstH, dstPF, SWS_BICUBIC, NULL, NULL, NULL);
>
>         sws_scale(sc, f1->data, f1->linesize, 0, srcH,
>             f2->data, f2->linesize);
>
>         /* free the scale context and the output frame */
>         sws_freeContext(sc);
>         free_frame(&f2);
>     }
>
>     free_frame(&f1);
>
>     return 0;
> }
>
>
> _______________________________________________
> libav-api mailing list
> [email protected]
> https://lists.libav.org/mailman/listinfo/libav-api
>
_______________________________________________
libav-api mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-api

Reply via email to