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
