[vlc-devel] [PATCH 6/6] avcodec: pull the decoder picture_t only when the va has a picture to extract
Steve Lhomme
robux4 at gmail.com
Fri Oct 21 17:42:59 CEST 2016
From: Steve Lhomme <robUx4 at videolabs.io>
The va decoder is no longer provided a picture_t, the surface context is passed
when needed. This surface context is filled during vlc_va_Get().
picture_t->context is no longer filled before/after calling vlc_va_Extract().
The AVFrame->opaque is no longer a picture_t but the surface context.
--
replaces https://patches.videolan.org/patch/14764/
* vdpau needs the picture->context after the vlc_va_Extract() so that
VDPAU filters can work. *UNTESTED*
replaces https://patches.videolan.org/patch/14766/
* fixes picture_t handling wit no video acceleration
* fixes vdpau decoding by holding/releasing the surface reference when attached
to a picture_t
---
modules/codec/avcodec/d3d11va.c | 4 ++--
modules/codec/avcodec/directx_va.c | 7 +-----
modules/codec/avcodec/dxva2.c | 4 ++--
modules/codec/avcodec/va.h | 14 ++++++------
modules/codec/avcodec/vaapi.c | 9 +++-----
modules/codec/avcodec/vda.c | 11 +++-------
modules/codec/avcodec/video.c | 45 ++++++++++++++++++++------------------
modules/hw/vdpau/avcodec.c | 14 +++++++++---
8 files changed, 53 insertions(+), 55 deletions(-)
diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c
index da3b891..94a9311 100644
--- a/modules/codec/avcodec/d3d11va.c
+++ b/modules/codec/avcodec/d3d11va.c
@@ -245,11 +245,11 @@ static filter_t *CreateFilter( vlc_object_t *p_this, const es_format_t *p_fmt_in
return p_filter;
}
-static int Extract(vlc_va_t *va, picture_t *output, uint8_t *data)
+static int Extract(vlc_va_t *va, picture_t *output, void *data_context, uint8_t *data)
{
vlc_va_sys_t *sys = va->sys;
ID3D11VideoDecoderOutputView *src = (ID3D11VideoDecoderOutputView*)(uintptr_t)data;
- vlc_va_surface_t *surface = output->context;
+ vlc_va_surface_t *surface = data_context;
int ret = VLC_SUCCESS;
switch (output->format.i_chroma)
diff --git a/modules/codec/avcodec/directx_va.c b/modules/codec/avcodec/directx_va.c
index 4b145fe..5e67dd7 100644
--- a/modules/codec/avcodec/directx_va.c
+++ b/modules/codec/avcodec/directx_va.c
@@ -417,14 +417,9 @@ int directx_va_Get(vlc_va_t *va, directx_sys_t *dx_sys, void **data_context, uin
void directx_va_Release(void *opaque)
{
- picture_t *pic = opaque;
- vlc_va_surface_t *surface = pic->context;
+ vlc_va_surface_t *surface = opaque;
vlc_mutex_lock( surface->p_lock );
-
surface->refcount--;
- pic->context = NULL;
- picture_Release(pic);
-
vlc_mutex_unlock( surface->p_lock );
}
diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index 3001b6e..3d4b612 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -237,7 +237,7 @@ void SetupAVCodecContext(vlc_va_t *va)
sys->hw.workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
}
-static int Extract(vlc_va_t *va, picture_t *picture, uint8_t *data)
+static int Extract(vlc_va_t *va, picture_t *picture, void *data_context, uint8_t *data)
{
directx_sys_t *dx_sys = &va->sys->dx_sys;
LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)data;
@@ -269,7 +269,7 @@ static int Extract(vlc_va_t *va, picture_t *picture, uint8_t *data)
}
else if (va->sys->filter != NULL) {
va->sys->filter->owner.sys = picture;
- vlc_va_surface_t *surface = picture->context;
+ vlc_va_surface_t *surface = data_context;
picture_Hold( surface->p_pic );
va->sys->filter->pf_video_filter( va->sys->filter, surface->p_pic );
} else {
diff --git a/modules/codec/avcodec/va.h b/modules/codec/avcodec/va.h
index b1c9c20..ee74f8f 100644
--- a/modules/codec/avcodec/va.h
+++ b/modules/codec/avcodec/va.h
@@ -41,8 +41,8 @@ struct vlc_va_t {
void (*setup)(vlc_va_t *, vlc_fourcc_t *output);
#endif
int (*get)(vlc_va_t *, void **data_context, uint8_t **data);
- void (*release)(void *pic);
- int (*extract)(vlc_va_t *, picture_t *pic, uint8_t *data);
+ void (*release)(void *data_context);
+ int (*extract)(vlc_va_t *, picture_t *pic, void *data_context, uint8_t *data);
};
/**
@@ -87,15 +87,15 @@ static inline int vlc_va_Get(vlc_va_t *va, void **data_context, uint8_t **data)
* Releases a hardware surface from a libavcodec frame.
* The surface has been previously allocated with vlc_va_Get().
*
- * @param pic VLC picture being released [IN/OUT]
+ * @param data_context VLC structure being released [IN/OUT]
*
* @note This function needs not be reentrant. However it may be called
* concurrently with vlc_va_Get() and/or vlc_va_Extract() from other threads
* and other frames.
*/
-static inline void vlc_va_Release(vlc_va_t *va, picture_t *pic)
+static inline void vlc_va_Release(vlc_va_t *va, void *data_context)
{
- va->release(pic);
+ va->release(data_context);
}
/**
@@ -108,9 +108,9 @@ static inline void vlc_va_Release(vlc_va_t *va, picture_t *pic)
* @note This function needs not be reentrant, but it may run concurrently with
* vlc_va_Get() or vlc_va_Release() in other threads (with distinct frames).
*/
-static inline int vlc_va_Extract(vlc_va_t *va, picture_t *pic, uint8_t *data)
+static inline int vlc_va_Extract(vlc_va_t *va, picture_t *pic, void *data_context, uint8_t *data)
{
- return va->extract(va, pic, data);
+ return va->extract(va, pic, data_context, data);
}
/**
diff --git a/modules/codec/avcodec/vaapi.c b/modules/codec/avcodec/vaapi.c
index cd3ef4e..0e5008c 100644
--- a/modules/codec/avcodec/vaapi.c
+++ b/modules/codec/avcodec/vaapi.c
@@ -79,8 +79,9 @@ struct vlc_va_sys_t
VASurfaceID surfaces[32];
};
-static int Extract( vlc_va_t *va, picture_t *p_picture, uint8_t *data )
+static int Extract( vlc_va_t *va, picture_t *p_picture, void *data_context, uint8_t *data )
{
+ (void) data_context;
vlc_va_sys_t *sys = va->sys;
VASurfaceID surface = (VASurfaceID)(uintptr_t)data;
VAImage image;
@@ -169,8 +170,7 @@ static int Get( vlc_va_t *va, void **data_context, uint8_t **data )
static void Release( void *opaque )
{
- picture_t *pic = opaque;
- VASurfaceID *surface = pic->context;
+ VASurfaceID *surface = opaque;
vlc_va_sys_t *sys = (void *)((((uintptr_t)surface)
- offsetof(vlc_va_sys_t, surfaces)) & ~(sizeof (sys->surfaces) - 1));
unsigned i = surface - sys->surfaces;
@@ -179,9 +179,6 @@ static void Release( void *opaque )
assert(((sys->available >> i) & 1) == 0);
sys->available |= 1 << i;
vlc_mutex_unlock( &sys->lock );
-
- pic->context = NULL;
- picture_Release(pic);
}
static void Delete( vlc_va_t *va, AVCodecContext *avctx )
diff --git a/modules/codec/avcodec/vda.c b/modules/codec/avcodec/vda.c
index 97a9e2c..0db02b4 100644
--- a/modules/codec/avcodec/vda.c
+++ b/modules/codec/avcodec/vda.c
@@ -148,7 +148,7 @@ static int Open(vlc_va_t *va,
va->sys = sys;
va->description = (char *)"VDA";
va->get = Get;
- va->release = Release;
+ va->release = NULL;
va->extract = Extract;
return VLC_SUCCESS;
@@ -169,14 +169,9 @@ static int Get( vlc_va_t *va, void **data_context, uint8_t **data )
return VLC_SUCCESS;
}
-// Never called
-static void Release( void *opaque )
-{
- VLC_UNUSED(opaque);
-}
-
-static int Extract( vlc_va_t *va, picture_t *p_picture, uint8_t *data )
+static int Extract( vlc_va_t *va, picture_t *p_picture, void *data_context, uint8_t *data )
{
+ (void) data_context;
vlc_va_sys_t *sys = va->sys;
CVPixelBufferRef cv_buffer = (CVPixelBufferRef)data;
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 5b99732..d0dc7b1 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -954,8 +954,8 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
}
}
- picture_t *p_pic = frame->opaque;
- if( p_pic == NULL )
+ picture_t *p_pic = NULL;
+ if( frame->opaque == NULL )
{ /* When direct rendering is not used, get_format() and get_buffer()
* might not be called. The output video format must be set here
* then picture buffer can be allocated. */
@@ -976,8 +976,21 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
else
{
if( p_sys->p_va != NULL )
- vlc_va_Extract( p_sys->p_va, p_pic, AV_FRAME_SURFACE_DATA(frame) );
- picture_Hold( p_pic );
+ {
+ /* a picture_ has not been allocated yet, frame->opaque is meaningless */
+ p_pic = decoder_NewPicture(p_dec);
+ if( unlikely(p_pic==NULL) )
+ {
+ av_frame_free(&frame);
+ break;
+ }
+ vlc_va_Extract( p_sys->p_va, p_pic, AV_FRAME_SURFACE(frame), AV_FRAME_SURFACE_DATA(frame) );
+ }
+ else
+ {
+ p_pic = frame->opaque;
+ picture_Hold(p_pic);
+ }
}
if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den )
@@ -1117,34 +1130,24 @@ static void lavc_ReleaseFrame(void *opaque)
picture_Release(picture);
}
-static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
- picture_t *pic)
+static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame)
{
decoder_t *dec = ctx->opaque;
vlc_va_t *va = dec->p_sys->p_va;
- void *data_context;
- if (vlc_va_Get(va, &data_context, &AV_FRAME_SURFACE_DATA(frame)))
+ if (vlc_va_Get(va, &AV_FRAME_SURFACE(frame), &AV_FRAME_SURFACE_DATA(frame)))
{
msg_Err(dec, "hardware acceleration picture allocation failed");
- picture_Release(pic);
return -1;
}
- pic->context = data_context;
- AV_FRAME_SURFACE(frame) = AV_FRAME_SURFACE_DATA(frame);
-
- void (*release)(void *) = va->release;
- if (va->release == NULL)
- release = lavc_ReleaseFrame;
- frame->buf[0] = av_buffer_create(AV_FRAME_SURFACE_DATA(frame), 0, release, pic, 0);
+ frame->buf[0] = av_buffer_create(AV_FRAME_SURFACE_DATA(frame), 0, va->release, AV_FRAME_SURFACE(frame), 0);
if (unlikely(frame->buf[0] == NULL))
{
- release(pic);
return -1;
}
- frame->opaque = pic;
+ frame->opaque = AV_FRAME_SURFACE(frame);
assert(AV_FRAME_SURFACE(frame) != NULL);
return 0;
}
@@ -1258,13 +1261,13 @@ static int lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags)
}
post_mt(sys);
+ if (sys->p_va != NULL)
+ return lavc_va_GetFrame(ctx, frame);
+
pic = decoder_NewPicture(dec);
if (pic == NULL)
return -ENOMEM;
- if (sys->p_va != NULL)
- return lavc_va_GetFrame(ctx, frame, pic);
-
/* Some codecs set pix_fmt only after the 1st frame has been decoded,
* so we need to check for direct rendering again. */
int ret = lavc_dr_GetFrame(ctx, frame, pic);
diff --git a/modules/hw/vdpau/avcodec.c b/modules/hw/vdpau/avcodec.c
index 0be3500..b420f80 100644
--- a/modules/hw/vdpau/avcodec.c
+++ b/modules/hw/vdpau/avcodec.c
@@ -134,12 +134,20 @@ static int Lock(vlc_va_t *va, void **data_context, uint8_t **data)
return VLC_SUCCESS;
}
-static int Copy(vlc_va_t *va, picture_t *pic, uint8_t *data)
+static int Copy(vlc_va_t *va, picture_t *pic, void *data_context, uint8_t *data)
{
- (void) va; (void) pic; (void) data;
+ (void) va; (void) data;
+ vlc_vdp_video_field_t *field = data_context;
+ pic->context = vlc_vdp_video_copy(field);
return VLC_SUCCESS;
}
+static void Release(void *opaque)
+{
+ vlc_vdp_video_field_t *f = opaque;
+ DestroySurface(f);
+}
+
static int Open(vlc_va_t *va, AVCodecContext *avctx, enum PixelFormat pix_fmt,
const es_format_t *fmt, picture_sys_t *p_sys)
{
@@ -316,7 +324,7 @@ static int Open(vlc_va_t *va, AVCodecContext *avctx, enum PixelFormat pix_fmt,
va->description = infos;
va->get = Lock;
- va->release = NULL;
+ va->release = Release;
va->extract = Copy;
return VLC_SUCCESS;
--
2.7.4
More information about the vlc-devel
mailing list