It will be used by avplay.tags/n1.0
| @@ -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, | ||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| @@ -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 */ | ||||