Commit e15546b2 authored by Thomas Guillem's avatar Thomas Guillem

chroma: cvpx: use copy helper instead of sub filters

parent 3980ea2c
......@@ -119,6 +119,7 @@ if HAVE_TVOS
libcvpx_plugin_la_CFLAGS = $(AM_CFLAGS) -mtvos-version-min=10.2
endif
libcvpx_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(chromadir)' -Wl,-framework,Foundation -Wl,-framework,VideoToolbox -Wl,-framework,CoreMedia -Wl,-framework,CoreVideo
libcvpx_plugin_la_LIBADD = libchroma_copy.la
EXTRA_LTLIBRARIES += libcvpx_plugin.la
chroma_LTLIBRARIES += $(LTLIBcvpx)
......
......@@ -36,6 +36,7 @@
#include <vlc_picture.h>
#include <vlc_modules.h>
#include "../codec/vt_utils.h"
#include "../video_chroma/copy.h"
static int Open(vlc_object_t *);
static void Close(vlc_object_t *);
......@@ -50,7 +51,12 @@ struct filter_sys_t
CVPixelBufferPoolRef pool;
union
{
filter_t *p_sw_filter;
struct
{
video_format_t fmt;
copy_cache_t cache;
bool has_cache;
} sw;
#if !TARGET_OS_IPHONE
VTPixelTransferSessionRef vttransfer;
#endif
......@@ -75,19 +81,63 @@ vlc_module_end ()
static picture_t *CVPX_TO_SW_Filter(filter_t *p_filter, picture_t *src)
{
filter_sys_t *p_sys = p_filter->p_sys;
picture_t *src_sw =
cvpxpic_create_mapped(&p_filter->fmt_out.video, cvpxpic_get_ref(src),
true);
cvpxpic_create_mapped(&p_sys->sw.fmt, cvpxpic_get_ref(src), true);
if (!src_sw)
{
picture_Release(src);
return NULL;
}
picture_CopyProperties(src_sw, src);
picture_Release(src);
return src_sw;
}
static picture_t *CVPX_TO_SW_I420_Filter(filter_t *p_filter, picture_t *src)
{
filter_sys_t *p_sys = p_filter->p_sys;
picture_t *src_sw = CVPX_TO_SW_Filter(p_filter, src);
if (!src_sw)
return NULL;
picture_t *dst = filter_NewPicture(p_filter);
if (!dst)
{
picture_Release(src_sw);
return NULL;
}
const uint8_t *src_planes[2] = { src_sw->p[0].p_pixels,
src_sw->p[1].p_pixels };
const size_t src_pitches[2] = { src_sw->p[0].i_pitch,
src_sw->p[1].i_pitch };
switch (p_filter->fmt_in.video.i_chroma)
{
case VLC_CODEC_CVPX_NV12:
assert(dst->format.i_chroma == VLC_CODEC_I420);
Copy420_SP_to_P(dst, src_planes, src_pitches, src_sw->format.i_visible_height,
&p_sys->sw.cache);
break;
case VLC_CODEC_CVPX_P010:
assert(dst->format.i_chroma == VLC_CODEC_I420_10L);
Copy420_16_SP_to_P(dst, src_planes, src_pitches, src_sw->format.i_visible_height,
6, &p_sys->sw.cache);
break;
default:
vlc_assert_unreachable();
}
picture_CopyProperties(dst, src_sw);
picture_Release(src_sw);
return dst;
}
static picture_t *SW_TO_CVPX_Filter(filter_t *p_filter, picture_t *src)
{
filter_sys_t *p_sys = p_filter->p_sys;
......@@ -101,7 +151,7 @@ static picture_t *SW_TO_CVPX_Filter(filter_t *p_filter, picture_t *src)
/* Allocate a CPVX backed picture mapped for read/write */
picture_t *mapped_dst =
cvpxpic_create_mapped(&p_filter->fmt_in.video, cvpx, false);
cvpxpic_create_mapped(&p_sys->sw.fmt, cvpx, false);
CFRelease(cvpx);
if (!mapped_dst)
{
......@@ -109,6 +159,54 @@ static picture_t *SW_TO_CVPX_Filter(filter_t *p_filter, picture_t *src)
return NULL;
}
const uint8_t *src_planes[3] = { src->p[0].p_pixels,
src->p[1].p_pixels,
src->p[2].p_pixels };
const size_t src_pitches[3] = { src->p[0].i_pitch,
src->p[1].i_pitch,
src->p[2].i_pitch };
#define DO(x, planes, pitches) \
x(mapped_dst, planes, pitches, src->format.i_visible_height, &p_sys->sw.cache)
#define DO_S(x, planes, pitches, shift) \
x(mapped_dst, planes, pitches, src->format.i_visible_height, shift, &p_sys->sw.cache)
switch (p_filter->fmt_out.video.i_chroma)
{
case VLC_CODEC_CVPX_NV12:
if (p_filter->fmt_in.video.i_chroma == VLC_CODEC_I420)
DO(Copy420_P_to_SP, src_planes, src_pitches);
else
{
assert(p_filter->fmt_in.video.i_chroma == VLC_CODEC_NV12);
DO(Copy420_SP_to_SP, src_planes, src_pitches);
}
break;
case VLC_CODEC_CVPX_P010:
if (p_filter->fmt_in.video.i_chroma == VLC_CODEC_I420_10L)
DO_S(Copy420_16_P_to_SP, src_planes, src_pitches, -6);
else
{
assert(p_filter->fmt_in.video.i_chroma == VLC_CODEC_P010);
DO(Copy420_SP_to_SP, src_planes, src_pitches);
}
break;
case VLC_CODEC_CVPX_I420:
assert(p_filter->fmt_in.video.i_chroma == VLC_CODEC_I420);
DO(Copy420_P_to_P, src_planes, src_pitches);
break;
case VLC_CODEC_CVPX_UYVY:
assert(p_filter->fmt_in.video.i_chroma == VLC_CODEC_UYVY);
DO(CopyPacked, src_planes[0], src_pitches[0]);
break;
case VLC_CODEC_CVPX_BGRA:
assert(p_filter->fmt_in.video.i_chroma == VLC_CODEC_BGRA);
DO(CopyPacked, src_planes[0], src_pitches[0]);
break;
default:
vlc_assert_unreachable();
}
/* Allocate a CVPX picture without any context */
picture_t *dst = picture_NewFromFormat(&p_filter->fmt_out.video);
if (!dst)
......@@ -118,11 +216,6 @@ static picture_t *SW_TO_CVPX_Filter(filter_t *p_filter, picture_t *src)
return NULL;
}
/* Copy pixels to the CVPX backed picture. Don't use picture_CopyPixels()
* since we want to handle the context ourself. */
for( int i = 0; i < src->i_planes ; i++ )
plane_CopyPixels( mapped_dst->p+i, src->p+i );
/* Attach the CVPX to a new opaque picture */
cvpxpic_attach(dst, cvpxpic_get_ref(mapped_dst));
......@@ -134,76 +227,15 @@ static picture_t *SW_TO_CVPX_Filter(filter_t *p_filter, picture_t *src)
return dst;
}
static picture_t *CVPX_TO_I420_Filter(filter_t *p_filter, picture_t *src)
{
filter_sys_t *p_sys = p_filter->p_sys;
filter_t *p_sw_filter = p_sys->p_sw_filter;
assert(p_sw_filter != NULL);
picture_t *dst = NULL;
picture_t *src_sw =
cvpxpic_create_mapped(&p_sw_filter->fmt_in.video, cvpxpic_get_ref(src),
true);
if (!src_sw)
{
picture_Release(src);
return NULL;
}
picture_CopyProperties(src_sw, src);
picture_Release(src);
dst = p_sw_filter->pf_video_filter(p_sw_filter, src_sw);
return dst;
}
static picture_t *SW_buffer_new(filter_t *p_filter)
{
return picture_NewFromFormat( &p_filter->fmt_out.video );
}
static picture_t *CVPX_buffer_new(filter_t *p_sw_filter)
{
filter_t *p_filter = p_sw_filter->owner.sys;
filter_sys_t *p_sys = p_filter->p_sys;
CVPixelBufferRef cvpx = cvpxpool_new_cvpx(p_sys->pool);
if (cvpx == NULL)
return NULL;
picture_t *pic =
cvpxpic_create_mapped(&p_sw_filter->fmt_out.video, cvpx, false);
CFRelease(cvpx);
return pic;
}
static picture_t *I420_TO_CVPX_Filter(filter_t *p_filter, picture_t *src)
{
filter_sys_t *p_sys = p_filter->p_sys;
filter_t *p_sw_filter = p_sys->p_sw_filter;
picture_t *sw_dst = p_sw_filter->pf_video_filter(p_sw_filter, src);
if (sw_dst == NULL)
return NULL;
return cvpxpic_unmap(sw_dst);
}
static void Close(vlc_object_t *obj)
{
filter_t *p_filter = (filter_t *)obj;
filter_sys_t *p_sys = p_filter->p_sys;
if (p_sys->p_sw_filter != NULL)
{
module_unneed(p_sys->p_sw_filter, p_sys->p_sw_filter->p_module);
vlc_object_release(p_sys->p_sw_filter);
}
if (p_sys->pool != NULL)
CVPixelBufferPoolRelease(p_sys->pool);
if (p_sys->sw.has_cache)
CopyCleanCache(&p_sys->sw.cache);
free(p_sys);
}
......@@ -215,58 +247,60 @@ static int Open(vlc_object_t *obj)
|| p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width)
return VLC_EGENERIC;
#define CASE_CVPX_INPUT(x) \
video_format_t sw_fmt;
#define CASE_CVPX_INPUT(x, i420_fcc) \
case VLC_CODEC_CVPX_##x: \
if (p_filter->fmt_out.video.i_chroma == VLC_CODEC_##x) { \
sw_fmt = p_filter->fmt_out.video; \
if (p_filter->fmt_out.video.i_chroma == VLC_CODEC_##x) \
p_filter->pf_video_filter = CVPX_TO_SW_Filter; \
} else if (p_filter->fmt_out.video.i_chroma == VLC_CODEC_I420) {\
p_filter->pf_video_filter = CVPX_TO_I420_Filter; \
i_sw_filter_in_chroma = VLC_CODEC_##x; \
i_sw_filter_out_chroma = VLC_CODEC_I420; \
sw_filter_owner.video.buffer_new = SW_buffer_new; \
else if (i420_fcc != 0 && p_filter->fmt_out.video.i_chroma == i420_fcc) { \
p_filter->pf_video_filter = CVPX_TO_SW_I420_Filter; \
sw_fmt.i_chroma = VLC_CODEC_##x; \
b_need_cache = true; \
} else return VLC_EGENERIC; \
b_need_pool = false;
#define CASE_CVPX_OUTPUT(x) \
#define CASE_CVPX_OUTPUT(x, i420_fcc) \
case VLC_CODEC_CVPX_##x: \
sw_fmt = p_filter->fmt_in.video; \
if (p_filter->fmt_in.video.i_chroma == VLC_CODEC_##x) { \
p_filter->pf_video_filter = SW_TO_CVPX_Filter; \
} else if (p_filter->fmt_in.video.i_chroma == VLC_CODEC_I420) {\
p_filter->pf_video_filter = I420_TO_CVPX_Filter; \
i_sw_filter_in_chroma = VLC_CODEC_I420; \
i_sw_filter_out_chroma = VLC_CODEC_##x; \
sw_filter_owner.sys = p_filter; \
sw_filter_owner.video.buffer_new = CVPX_buffer_new; \
} \
else if (i420_fcc != 0 && p_filter->fmt_in.video.i_chroma == i420_fcc) { \
p_filter->pf_video_filter = SW_TO_CVPX_Filter; \
sw_fmt.i_chroma = VLC_CODEC_##x; \
} else return VLC_EGENERIC; \
b_need_cache = true; \
b_need_pool = true;
bool b_need_pool;
vlc_fourcc_t i_sw_filter_in_chroma = 0, i_sw_filter_out_chroma = 0;
filter_owner_t sw_filter_owner = {};
bool b_need_pool = false;
bool b_need_cache = false;
unsigned i_cache_pixel_bytes = 1;
switch (p_filter->fmt_in.video.i_chroma)
{
CASE_CVPX_INPUT(NV12)
CASE_CVPX_INPUT(NV12, VLC_CODEC_I420)
break;
CASE_CVPX_INPUT(P010)
CASE_CVPX_INPUT(P010, VLC_CODEC_I420_10L)
i_cache_pixel_bytes = 2;
break;
CASE_CVPX_INPUT(UYVY)
CASE_CVPX_INPUT(UYVY, 0)
break;
CASE_CVPX_INPUT(I420)
CASE_CVPX_INPUT(I420, 0)
break;
CASE_CVPX_INPUT(BGRA)
CASE_CVPX_INPUT(BGRA, 0)
break;
default:
switch (p_filter->fmt_out.video.i_chroma)
{
CASE_CVPX_OUTPUT(NV12)
CASE_CVPX_OUTPUT(NV12, VLC_CODEC_I420)
break;
CASE_CVPX_OUTPUT(P010)
CASE_CVPX_OUTPUT(P010, VLC_CODEC_I420_10L)
i_cache_pixel_bytes = 2;
break;
CASE_CVPX_OUTPUT(UYVY)
CASE_CVPX_OUTPUT(UYVY, 0)
break;
CASE_CVPX_OUTPUT(I420)
CASE_CVPX_OUTPUT(I420, 0)
break;
CASE_CVPX_OUTPUT(BGRA)
CASE_CVPX_OUTPUT(BGRA, 0)
break;
default:
return VLC_EGENERIC;
......@@ -278,35 +312,20 @@ static int Open(vlc_object_t *obj)
if (unlikely(!p_sys))
return VLC_ENOMEM;
p_sys->p_sw_filter = NULL;
p_sys->pool = NULL;
p_sys->sw.fmt = sw_fmt;
p_sys->sw.has_cache = false;
if (b_need_pool
&& (p_sys->pool = cvpxpool_create(&p_filter->fmt_out.video, 3)) == NULL)
goto error;
if (i_sw_filter_in_chroma != 0)
if (b_need_cache)
{
filter_t *p_sw_filter = vlc_object_create(p_filter, sizeof(filter_t));
if (unlikely(p_sw_filter == NULL))
goto error;
p_sw_filter->fmt_in = p_filter->fmt_in;
p_sw_filter->fmt_out = p_filter->fmt_out;
p_sw_filter->fmt_in.i_codec = p_sw_filter->fmt_in.video.i_chroma
= i_sw_filter_in_chroma;
p_sw_filter->fmt_out.i_codec = p_sw_filter->fmt_out.video.i_chroma
= i_sw_filter_out_chroma;
p_sw_filter->owner = sw_filter_owner;
p_sw_filter->p_module = module_need(p_sw_filter, "video converter",
NULL, false);
if (p_sw_filter->p_module == NULL)
{
vlc_object_release(p_sw_filter);
unsigned i_cache_width = p_filter->fmt_in.video.i_width * i_cache_pixel_bytes;
if (CopyInitCache(&p_sys->sw.cache, i_cache_width) != VLC_SUCCESS)
goto error;
}
p_sys->p_sw_filter = p_sw_filter;
p_sys->sw.has_cache = true;
}
return VLC_SUCCESS;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment