mirror of https://github.com/FFmpeg/FFmpeg.git
parent
04cc4d0550
commit
0c59d40ae0
7 changed files with 309 additions and 14 deletions
@ -0,0 +1,189 @@ |
||||
/*
|
||||
* This file is part of FFmpeg. |
||||
* |
||||
* Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com> |
||||
* |
||||
* FFmpeg is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* FFmpeg is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
#include "framepool.h" |
||||
#include "libavutil/avassert.h" |
||||
#include "libavutil/buffer.h" |
||||
#include "libavutil/frame.h" |
||||
#include "libavutil/imgutils.h" |
||||
#include "libavutil/mem.h" |
||||
#include "libavutil/pixfmt.h" |
||||
|
||||
struct FFVideoFramePool { |
||||
|
||||
int width; |
||||
int height; |
||||
int format; |
||||
int align; |
||||
int linesize[4]; |
||||
AVBufferPool *pools[4]; |
||||
|
||||
}; |
||||
|
||||
FFVideoFramePool *ff_video_frame_pool_init(AVBufferRef* (*alloc)(int size), |
||||
int width, |
||||
int height, |
||||
enum AVPixelFormat format, |
||||
int align) |
||||
{ |
||||
int i, ret; |
||||
FFVideoFramePool *pool; |
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); |
||||
|
||||
if (!desc) |
||||
return NULL; |
||||
|
||||
pool = av_mallocz(sizeof(FFVideoFramePool)); |
||||
if (!pool) |
||||
return NULL; |
||||
|
||||
pool->width = width; |
||||
pool->height = height; |
||||
pool->format = format; |
||||
pool->align = align; |
||||
|
||||
if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) { |
||||
goto fail; |
||||
} |
||||
|
||||
if (!pool->linesize[0]) { |
||||
for(i = 1; i <= align; i += i) { |
||||
ret = av_image_fill_linesizes(pool->linesize, pool->format, |
||||
FFALIGN(pool->width, i)); |
||||
if (ret < 0) { |
||||
goto fail; |
||||
} |
||||
if (!(pool->linesize[0] & (pool->align - 1))) |
||||
break; |
||||
} |
||||
|
||||
for (i = 0; i < 4 && pool->linesize[i]; i++) { |
||||
pool->linesize[i] = FFALIGN(pool->linesize[i], pool->align); |
||||
} |
||||
} |
||||
|
||||
for (i = 0; i < 4 && pool->linesize[i]; i++) { |
||||
int h = FFALIGN(pool->height, 32); |
||||
if (i == 1 || i == 2) |
||||
h = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); |
||||
|
||||
pool->pools[i] = av_buffer_pool_init(pool->linesize[i] * h + 16 + 16 - 1, |
||||
alloc); |
||||
if (!pool->pools[i]) |
||||
goto fail; |
||||
} |
||||
|
||||
if (desc->flags & AV_PIX_FMT_FLAG_PAL || |
||||
desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { |
||||
pool->pools[1] = av_buffer_pool_init(AVPALETTE_SIZE, alloc); |
||||
if (!pool->pools[1]) |
||||
goto fail; |
||||
} |
||||
|
||||
return pool; |
||||
|
||||
fail: |
||||
ff_video_frame_pool_uninit(&pool); |
||||
return NULL; |
||||
} |
||||
|
||||
int ff_video_frame_pool_get_config(FFVideoFramePool *pool, |
||||
int *width, |
||||
int *height, |
||||
enum AVPixelFormat *format, |
||||
int *align) |
||||
{ |
||||
if (!pool) |
||||
return AVERROR(EINVAL); |
||||
|
||||
*width = pool->width; |
||||
*height = pool->height; |
||||
*format = pool->format; |
||||
*align = pool->align; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
AVFrame *ff_video_frame_pool_get(FFVideoFramePool *pool) |
||||
{ |
||||
int i; |
||||
AVFrame *frame; |
||||
const AVPixFmtDescriptor *desc; |
||||
|
||||
frame = av_frame_alloc(); |
||||
if (!frame) { |
||||
return NULL; |
||||
} |
||||
|
||||
desc = av_pix_fmt_desc_get(pool->format); |
||||
if (!desc) { |
||||
goto fail; |
||||
} |
||||
|
||||
frame->width = pool->width; |
||||
frame->height = pool->height; |
||||
frame->format = pool->format; |
||||
|
||||
for (i = 0; i < 4; i++) { |
||||
frame->linesize[i] = pool->linesize[i]; |
||||
if (!pool->pools[i]) |
||||
break; |
||||
|
||||
frame->buf[i] = av_buffer_pool_get(pool->pools[i]); |
||||
if (!frame->buf[i]) { |
||||
goto fail; |
||||
} |
||||
|
||||
frame->data[i] = frame->buf[i]->data; |
||||
} |
||||
|
||||
if (desc->flags & AV_PIX_FMT_FLAG_PAL || |
||||
desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) { |
||||
enum AVPixelFormat format = |
||||
pool->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : pool->format; |
||||
|
||||
av_assert0(frame->data[1] != NULL); |
||||
if (avpriv_set_systematic_pal2((uint32_t *)frame->data[1], format) < 0) { |
||||
goto fail; |
||||
} |
||||
} |
||||
|
||||
frame->extended_data = frame->data; |
||||
|
||||
return frame; |
||||
fail: |
||||
av_frame_free(&frame); |
||||
return NULL; |
||||
} |
||||
|
||||
void ff_video_frame_pool_uninit(FFVideoFramePool **pool) |
||||
{ |
||||
int i; |
||||
|
||||
if (!pool || !*pool) |
||||
return; |
||||
|
||||
for (i = 0; i < 4; i++) { |
||||
av_buffer_pool_uninit(&(*pool)->pools[i]); |
||||
} |
||||
|
||||
av_freep(pool); |
||||
} |
@ -0,0 +1,84 @@ |
||||
/*
|
||||
* This file is part of FFmpeg. |
||||
* |
||||
* Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com> |
||||
* |
||||
* FFmpeg is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* FFmpeg is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with FFmpeg; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
#ifndef AVUTIL_FRAME_POOL_H |
||||
#define AVUTIL_FRAME_POOL_H |
||||
|
||||
#include "libavutil/buffer.h" |
||||
#include "libavutil/frame.h" |
||||
|
||||
/**
|
||||
* Video frame pool. This structure is opaque and not meant to be accessed |
||||
* directly. It is allocated with ff_video_frame_pool_init() and freed with |
||||
* ff_video_frame_pool_uninit(). |
||||
*/ |
||||
typedef struct FFVideoFramePool FFVideoFramePool; |
||||
|
||||
/**
|
||||
* Allocate and initialize a video frame pool. |
||||
* |
||||
* @param alloc a function that will be used to allocate new frame buffers when |
||||
* the pool is empty. May be NULL, then the default allocator will be used |
||||
* (av_buffer_alloc()). |
||||
* @param width width of each frame in this pool |
||||
* @param height height of each frame in this pool |
||||
* @param format format of each frame in this pool |
||||
* @param align buffers alignement of each frame in this pool |
||||
* @return newly created video frame pool on success, NULL on error. |
||||
*/ |
||||
FFVideoFramePool *ff_video_frame_pool_init(AVBufferRef* (*alloc)(int size), |
||||
int width, |
||||
int height, |
||||
enum AVPixelFormat format, |
||||
int align); |
||||
|
||||
/**
|
||||
* Deallocate the video frame pool. It is safe to call this function while |
||||
* some of the allocated video frame are still in use. |
||||
* |
||||
* @param pool pointer to the video frame pool to be freed. It will be set to NULL. |
||||
*/ |
||||
void ff_video_frame_pool_uninit(FFVideoFramePool **pool); |
||||
|
||||
/**
|
||||
* Get the video frame pool configuration. |
||||
* |
||||
* @param width width of each frame in this pool |
||||
* @param height height of each frame in this pool |
||||
* @param format format of each frame in this pool |
||||
* @param align buffers alignement of each frame in this pool |
||||
* @return 0 on success, a negative AVERROR otherwise. |
||||
*/ |
||||
int ff_video_frame_pool_get_config(FFVideoFramePool *pool, |
||||
int *width, |
||||
int *height, |
||||
enum AVPixelFormat *format, |
||||
int *align); |
||||
|
||||
/**
|
||||
* Allocate a new AVFrame, reussing old buffers from the pool when available. |
||||
* This function may be called simultaneously from multiple threads. |
||||
* |
||||
* @return a new AVFrame on success, NULL on error. |
||||
*/ |
||||
AVFrame *ff_video_frame_pool_get(FFVideoFramePool *pool); |
||||
|
||||
|
||||
#endif /* AVUTIL_FRAME_POOL_H */ |
Loading…
Reference in new issue