It will be used by avplay.tags/n1.0
| @@ -171,19 +171,6 @@ typedef struct FilterGraph { | |||
| int nb_outputs; | |||
| } 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 { | |||
| int file_index; | |||
| AVStream *st; | |||
| @@ -449,135 +436,6 @@ static void reset_options(OptionsContext *o) | |||
| 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 | |||
| * allowed formats, | |||
| @@ -37,6 +37,7 @@ | |||
| #include "libavutil/avassert.h" | |||
| #include "libavutil/avstring.h" | |||
| #include "libavutil/mathematics.h" | |||
| #include "libavutil/imgutils.h" | |||
| #include "libavutil/parseutils.h" | |||
| #include "libavutil/pixdesc.h" | |||
| #include "libavutil/eval.h" | |||
| @@ -1041,3 +1042,132 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) | |||
| } | |||
| 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; | |||
| } | |||
| } | |||
| @@ -383,4 +383,46 @@ void exit_program(int ret); | |||
| */ | |||
| 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 */ | |||