diff options
author | wm4 <wm4@nowhere> | 2012-12-22 21:46:53 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-01-13 20:04:10 +0100 |
commit | 1f32250629c990859b0f6a7d70bcbe3bd2d6afae (patch) | |
tree | bd4b294ace0079f594611c93f0865f2efce7e622 /video/decode | |
parent | 1b9d4a771a27d6017d826ed03dfbbc7ee976bf77 (diff) | |
download | mpv-1f32250629c990859b0f6a7d70bcbe3bd2d6afae.tar.bz2 mpv-1f32250629c990859b0f6a7d70bcbe3bd2d6afae.tar.xz |
vd_lavc: make non-reference frames writeable
This allows avoiding a copy.
The logic about using the AVFrame.reference field if buffer hints are
not available is similar to mplayer-svn's direct rendering code. This is
needed because h264 decoding doesn't set buffer hints.
<wm4> michaelni: couldn't it set buffer hints from AVFrame.reference then?
<michaelni> i see no reason ATM why that wouldnt be possible
OK...
Diffstat (limited to 'video/decode')
-rw-r--r-- | video/decode/lavc_dr1.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/video/decode/lavc_dr1.c b/video/decode/lavc_dr1.c index 34aad2e030..e81b723a70 100644 --- a/video/decode/lavc_dr1.c +++ b/video/decode/lavc_dr1.c @@ -48,6 +48,7 @@ typedef struct FrameBuffer { int h, w; int pix_fmt; + int used_by_decoder, needed_by_decoder; int refcount; struct FramePool *pool; struct FrameBuffer *next; @@ -155,6 +156,15 @@ int mp_codec_get_buffer(AVCodecContext *s, AVFrame *frame) frame->type = FF_BUFFER_TYPE_USER; frame->extended_data = frame->data; + buf->used_by_decoder = buf->needed_by_decoder = 1; + if (frame->buffer_hints & FF_BUFFER_HINTS_VALID) { + buf->needed_by_decoder = + (frame->buffer_hints & FF_BUFFER_HINTS_PRESERVE) || + (frame->buffer_hints & FF_BUFFER_HINTS_REUSABLE); + } else { + buf->needed_by_decoder = !!frame->reference; + } + 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]; @@ -192,7 +202,12 @@ void mp_buffer_unref(struct FrameBuffer *buf) bool mp_buffer_is_unique(struct FrameBuffer *buf) { - return buf->refcount == 1; + int refcount = buf->refcount; + // Decoder has a reference, but doesn't want to use it. (ffmpeg has no good + // way of transferring frame ownership to the user.) + if (buf->used_by_decoder && !buf->needed_by_decoder) + refcount--; + return refcount == 1; } void mp_codec_release_buffer(AVCodecContext *s, AVFrame *frame) @@ -205,6 +220,8 @@ void mp_codec_release_buffer(AVCodecContext *s, AVFrame *frame) return; } + buf->used_by_decoder = buf->needed_by_decoder = 0; + for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++) frame->data[i] = NULL; |