mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-29 22:00:58 +02:00
avtools: move buffer management code from avconv to cmdutils.
It will be used by avplay.
This commit is contained in:
parent
3ffa233595
commit
d55c2e05b5
142
avconv.c
142
avconv.c
@ -171,19 +171,6 @@ typedef struct FilterGraph {
|
|||||||
int nb_outputs;
|
int nb_outputs;
|
||||||
} FilterGraph;
|
} FilterGraph;
|
||||||
|
|
||||||
typedef struct FrameBuffer {
|
|
||||||
uint8_t *base[4];
|
|
||||||
uint8_t *data[4];
|
|
||||||
int linesize[4];
|
|
||||||
|
|
||||||
int h, w;
|
|
||||||
enum PixelFormat pix_fmt;
|
|
||||||
|
|
||||||
int refcount;
|
|
||||||
struct FrameBuffer **pool; ///< head of the buffer pool
|
|
||||||
struct FrameBuffer *next;
|
|
||||||
} FrameBuffer;
|
|
||||||
|
|
||||||
typedef struct InputStream {
|
typedef struct InputStream {
|
||||||
int file_index;
|
int file_index;
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
@ -449,135 +436,6 @@ static void reset_options(OptionsContext *o)
|
|||||||
init_opts();
|
init_opts();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_buffer(FrameBuffer **pool, AVCodecContext *s, FrameBuffer **pbuf)
|
|
||||||
{
|
|
||||||
FrameBuffer *buf = av_mallocz(sizeof(*buf));
|
|
||||||
int i, ret;
|
|
||||||
const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1;
|
|
||||||
int h_chroma_shift, v_chroma_shift;
|
|
||||||
int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1
|
|
||||||
int w = s->width, h = s->height;
|
|
||||||
|
|
||||||
if (!buf)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
|
|
||||||
if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
|
|
||||||
w += 2*edge;
|
|
||||||
h += 2*edge;
|
|
||||||
}
|
|
||||||
|
|
||||||
avcodec_align_dimensions(s, &w, &h);
|
|
||||||
if ((ret = av_image_alloc(buf->base, buf->linesize, w, h,
|
|
||||||
s->pix_fmt, 32)) < 0) {
|
|
||||||
av_freep(&buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/* XXX this shouldn't be needed, but some tests break without this line
|
|
||||||
* those decoders are buggy and need to be fixed.
|
|
||||||
* the following tests fail:
|
|
||||||
* cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit
|
|
||||||
*/
|
|
||||||
memset(buf->base[0], 128, ret);
|
|
||||||
|
|
||||||
avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
|
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
|
|
||||||
const int h_shift = i==0 ? 0 : h_chroma_shift;
|
|
||||||
const int v_shift = i==0 ? 0 : v_chroma_shift;
|
|
||||||
if (s->flags & CODEC_FLAG_EMU_EDGE)
|
|
||||||
buf->data[i] = buf->base[i];
|
|
||||||
else
|
|
||||||
buf->data[i] = buf->base[i] +
|
|
||||||
FFALIGN((buf->linesize[i]*edge >> v_shift) +
|
|
||||||
(pixel_size*edge >> h_shift), 32);
|
|
||||||
}
|
|
||||||
buf->w = s->width;
|
|
||||||
buf->h = s->height;
|
|
||||||
buf->pix_fmt = s->pix_fmt;
|
|
||||||
buf->pool = pool;
|
|
||||||
|
|
||||||
*pbuf = buf;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_buffer_pool(FrameBuffer **pool)
|
|
||||||
{
|
|
||||||
FrameBuffer *buf = *pool;
|
|
||||||
while (buf) {
|
|
||||||
*pool = buf->next;
|
|
||||||
av_freep(&buf->base[0]);
|
|
||||||
av_free(buf);
|
|
||||||
buf = *pool;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unref_buffer(FrameBuffer *buf)
|
|
||||||
{
|
|
||||||
FrameBuffer **pool = buf->pool;
|
|
||||||
|
|
||||||
av_assert0(buf->refcount);
|
|
||||||
buf->refcount--;
|
|
||||||
if (!buf->refcount) {
|
|
||||||
buf->next = *pool;
|
|
||||||
*pool = buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int codec_get_buffer(AVCodecContext *s, AVFrame *frame)
|
|
||||||
{
|
|
||||||
FrameBuffer **pool = s->opaque;
|
|
||||||
FrameBuffer *buf;
|
|
||||||
int ret, i;
|
|
||||||
|
|
||||||
if (!*pool && (ret = alloc_buffer(pool, s, pool)) < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
buf = *pool;
|
|
||||||
*pool = buf->next;
|
|
||||||
buf->next = NULL;
|
|
||||||
if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) {
|
|
||||||
av_freep(&buf->base[0]);
|
|
||||||
av_free(buf);
|
|
||||||
if ((ret = alloc_buffer(pool, s, &buf)) < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
buf->refcount++;
|
|
||||||
|
|
||||||
frame->opaque = buf;
|
|
||||||
frame->type = FF_BUFFER_TYPE_USER;
|
|
||||||
frame->extended_data = frame->data;
|
|
||||||
frame->pkt_pts = s->pkt ? s->pkt->pts : AV_NOPTS_VALUE;
|
|
||||||
frame->width = buf->w;
|
|
||||||
frame->height = buf->h;
|
|
||||||
frame->format = buf->pix_fmt;
|
|
||||||
frame->sample_aspect_ratio = s->sample_aspect_ratio;
|
|
||||||
|
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
|
|
||||||
frame->base[i] = buf->base[i]; // XXX h264.c uses base though it shouldn't
|
|
||||||
frame->data[i] = buf->data[i];
|
|
||||||
frame->linesize[i] = buf->linesize[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void codec_release_buffer(AVCodecContext *s, AVFrame *frame)
|
|
||||||
{
|
|
||||||
FrameBuffer *buf = frame->opaque;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
|
|
||||||
frame->data[i] = NULL;
|
|
||||||
|
|
||||||
unref_buffer(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void filter_release_buffer(AVFilterBuffer *fb)
|
|
||||||
{
|
|
||||||
FrameBuffer *buf = fb->priv;
|
|
||||||
av_free(fb);
|
|
||||||
unref_buffer(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a function for building a string containing a list of
|
* Define a function for building a string containing a list of
|
||||||
* allowed formats,
|
* allowed formats,
|
||||||
|
130
cmdutils.c
130
cmdutils.c
@ -37,6 +37,7 @@
|
|||||||
#include "libavutil/avassert.h"
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
#include "libavutil/mathematics.h"
|
#include "libavutil/mathematics.h"
|
||||||
|
#include "libavutil/imgutils.h"
|
||||||
#include "libavutil/parseutils.h"
|
#include "libavutil/parseutils.h"
|
||||||
#include "libavutil/pixdesc.h"
|
#include "libavutil/pixdesc.h"
|
||||||
#include "libavutil/eval.h"
|
#include "libavutil/eval.h"
|
||||||
@ -1041,3 +1042,132 @@ void *grow_array(void *array, int elem_size, int *size, int new_size)
|
|||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int alloc_buffer(FrameBuffer **pool, AVCodecContext *s, FrameBuffer **pbuf)
|
||||||
|
{
|
||||||
|
FrameBuffer *buf = av_mallocz(sizeof(*buf));
|
||||||
|
int i, ret;
|
||||||
|
const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1;
|
||||||
|
int h_chroma_shift, v_chroma_shift;
|
||||||
|
int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1
|
||||||
|
int w = s->width, h = s->height;
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
if (!(s->flags & CODEC_FLAG_EMU_EDGE)) {
|
||||||
|
w += 2*edge;
|
||||||
|
h += 2*edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
avcodec_align_dimensions(s, &w, &h);
|
||||||
|
if ((ret = av_image_alloc(buf->base, buf->linesize, w, h,
|
||||||
|
s->pix_fmt, 32)) < 0) {
|
||||||
|
av_freep(&buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/* XXX this shouldn't be needed, but some tests break without this line
|
||||||
|
* those decoders are buggy and need to be fixed.
|
||||||
|
* the following tests fail:
|
||||||
|
* cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit
|
||||||
|
*/
|
||||||
|
memset(buf->base[0], 128, ret);
|
||||||
|
|
||||||
|
avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
|
||||||
|
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
|
||||||
|
const int h_shift = i==0 ? 0 : h_chroma_shift;
|
||||||
|
const int v_shift = i==0 ? 0 : v_chroma_shift;
|
||||||
|
if (s->flags & CODEC_FLAG_EMU_EDGE)
|
||||||
|
buf->data[i] = buf->base[i];
|
||||||
|
else
|
||||||
|
buf->data[i] = buf->base[i] +
|
||||||
|
FFALIGN((buf->linesize[i]*edge >> v_shift) +
|
||||||
|
(pixel_size*edge >> h_shift), 32);
|
||||||
|
}
|
||||||
|
buf->w = s->width;
|
||||||
|
buf->h = s->height;
|
||||||
|
buf->pix_fmt = s->pix_fmt;
|
||||||
|
buf->pool = pool;
|
||||||
|
|
||||||
|
*pbuf = buf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codec_get_buffer(AVCodecContext *s, AVFrame *frame)
|
||||||
|
{
|
||||||
|
FrameBuffer **pool = s->opaque;
|
||||||
|
FrameBuffer *buf;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
if (!*pool && (ret = alloc_buffer(pool, s, pool)) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
buf = *pool;
|
||||||
|
*pool = buf->next;
|
||||||
|
buf->next = NULL;
|
||||||
|
if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) {
|
||||||
|
av_freep(&buf->base[0]);
|
||||||
|
av_free(buf);
|
||||||
|
if ((ret = alloc_buffer(pool, s, &buf)) < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
buf->refcount++;
|
||||||
|
|
||||||
|
frame->opaque = buf;
|
||||||
|
frame->type = FF_BUFFER_TYPE_USER;
|
||||||
|
frame->extended_data = frame->data;
|
||||||
|
frame->pkt_pts = s->pkt ? s->pkt->pts : AV_NOPTS_VALUE;
|
||||||
|
frame->width = buf->w;
|
||||||
|
frame->height = buf->h;
|
||||||
|
frame->format = buf->pix_fmt;
|
||||||
|
frame->sample_aspect_ratio = s->sample_aspect_ratio;
|
||||||
|
|
||||||
|
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) {
|
||||||
|
frame->base[i] = buf->base[i]; // XXX h264.c uses base though it shouldn't
|
||||||
|
frame->data[i] = buf->data[i];
|
||||||
|
frame->linesize[i] = buf->linesize[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unref_buffer(FrameBuffer *buf)
|
||||||
|
{
|
||||||
|
FrameBuffer **pool = buf->pool;
|
||||||
|
|
||||||
|
av_assert0(buf->refcount);
|
||||||
|
buf->refcount--;
|
||||||
|
if (!buf->refcount) {
|
||||||
|
buf->next = *pool;
|
||||||
|
*pool = buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void codec_release_buffer(AVCodecContext *s, AVFrame *frame)
|
||||||
|
{
|
||||||
|
FrameBuffer *buf = frame->opaque;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++)
|
||||||
|
frame->data[i] = NULL;
|
||||||
|
|
||||||
|
unref_buffer(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void filter_release_buffer(AVFilterBuffer *fb)
|
||||||
|
{
|
||||||
|
FrameBuffer *buf = fb->priv;
|
||||||
|
av_free(fb);
|
||||||
|
unref_buffer(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_buffer_pool(FrameBuffer **pool)
|
||||||
|
{
|
||||||
|
FrameBuffer *buf = *pool;
|
||||||
|
while (buf) {
|
||||||
|
*pool = buf->next;
|
||||||
|
av_freep(&buf->base[0]);
|
||||||
|
av_free(buf);
|
||||||
|
buf = *pool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
42
cmdutils.h
42
cmdutils.h
@ -383,4 +383,46 @@ void exit_program(int ret);
|
|||||||
*/
|
*/
|
||||||
void *grow_array(void *array, int elem_size, int *size, int new_size);
|
void *grow_array(void *array, int elem_size, int *size, int new_size);
|
||||||
|
|
||||||
|
typedef struct FrameBuffer {
|
||||||
|
uint8_t *base[4];
|
||||||
|
uint8_t *data[4];
|
||||||
|
int linesize[4];
|
||||||
|
|
||||||
|
int h, w;
|
||||||
|
enum PixelFormat pix_fmt;
|
||||||
|
|
||||||
|
int refcount;
|
||||||
|
struct FrameBuffer **pool; ///< head of the buffer pool
|
||||||
|
struct FrameBuffer *next;
|
||||||
|
} FrameBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a frame from the pool. This is intended to be used as a callback for
|
||||||
|
* AVCodecContext.get_buffer.
|
||||||
|
*
|
||||||
|
* @param s codec context. s->opaque must be a pointer to the head of the
|
||||||
|
* buffer pool.
|
||||||
|
* @param frame frame->opaque will be set to point to the FrameBuffer
|
||||||
|
* containing the frame data.
|
||||||
|
*/
|
||||||
|
int codec_get_buffer(AVCodecContext *s, AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback to be used for AVCodecContext.release_buffer along with
|
||||||
|
* codec_get_buffer().
|
||||||
|
*/
|
||||||
|
void codec_release_buffer(AVCodecContext *s, AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback to be used for AVFilterBuffer.free.
|
||||||
|
* @param fb buffer to free. fb->priv must be a pointer to the FrameBuffer
|
||||||
|
* containing the buffer data.
|
||||||
|
*/
|
||||||
|
void filter_release_buffer(AVFilterBuffer *fb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free all the buffers in the pool. This must be called after all the
|
||||||
|
* buffers have been released.
|
||||||
|
*/
|
||||||
|
void free_buffer_pool(FrameBuffer **pool);
|
||||||
#endif /* LIBAV_CMDUTILS_H */
|
#endif /* LIBAV_CMDUTILS_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user