diff --git a/modules/hw/mmal/Makefile.am b/modules/hw/mmal/Makefile.am index 2a0dba7572..1dd7aa25ed 100644 --- a/modules/hw/mmal/Makefile.am +++ b/modules/hw/mmal/Makefile.am @@ -11,7 +11,7 @@ libmmal_vout_plugin_la_LDFLAGS = $(AM_LDFLAGS) -lm libmmal_vout_plugin_la_LIBADD = $(LIBS_mmal) mmal_LTLIBRARIES = libmmal_vout_plugin.la -libmmal_codec_plugin_la_SOURCES = codec.c mmal_picture.c mmal_picture.h \ +libmmal_codec_plugin_la_SOURCES = codec.c subpic.c subpic.h mmal_picture.c mmal_picture.h \ mmal_cma.c mmal_cma.h libmmal_codec_plugin_la_CFLAGS = $(AM_CFLAGS) libmmal_codec_plugin_la_LDFLAGS = $(AM_LDFLAGS) diff --git a/modules/hw/mmal/codec.c b/modules/hw/mmal/codec.c index f56b6fa2f8..7ff3dd5d3c 100644 --- a/modules/hw/mmal/codec.c +++ b/modules/hw/mmal/codec.c @@ -59,6 +59,10 @@ #define MMAL_RESIZE_TEXT N_("Use mmal resizer rather than hvs.") #define MMAL_RESIZE_LONGTEXT N_("Use mmal resizer rather than isp. This uses less gpu memory than the ISP but is slower.") +#define MMAL_ISP_NAME "mmal-isp" +#define MMAL_ISP_TEXT N_("Use mmal isp rather than hvs.") +#define MMAL_ISP_LONGTEXT N_("Use mmal isp rather than Hardware Video Scaler. This may be faster but has no blend.") + static int OpenDecoder(vlc_object_t *); static void CloseDecoder(vlc_object_t *); static int OpenConverter(vlc_object_t *); @@ -82,6 +86,7 @@ vlc_module_begin() add_shortcut("mmal_converter") set_capability( "video converter", 900 ) add_bool(MMAL_RESIZE_NAME, /* default */ false, MMAL_RESIZE_TEXT, MMAL_RESIZE_LONGTEXT, /* advanced option */ false) + add_bool(MMAL_ISP_NAME, /* default */ false, MMAL_ISP_TEXT, MMAL_ISP_LONGTEXT, /* advanced option */ false) set_callbacks(OpenConverter, CloseConverter) vlc_module_end() @@ -792,6 +797,7 @@ static void pic_fifo_put(pic_fifo_t * const pf, picture_t * pic) typedef enum filter_resizer_e { FILTER_RESIZER_RESIZER, FILTER_RESIZER_ISP, + FILTER_RESIZER_HVS, } filter_resizer_t; typedef struct conv_frame_stash_s @@ -1042,6 +1048,13 @@ static void conv_flush(filter_t * p_filter) converter_sys_t * const sys = p_filter->p_sys; unsigned int i; + if (sys->resizer_type == FILTER_RESIZER_HVS) + { + for (i = 0; i != SUBS_MAX; ++i) { + hw_mmal_subpic_flush(sys->subs + i); + } + } + if (sys->input != NULL && sys->input->is_enabled) mmal_port_disable(sys->input); @@ -1182,6 +1195,23 @@ static picture_t *conv_filter(filter_t *p_filter, picture_t *p_pic) if (!sys->needs_copy_in) msg_Dbg(p_filter, "No context"); } + else if (sys->resizer_type == FILTER_RESIZER_HVS) + { + unsigned int sub_no = 0; + + for (sub_no = 0; sub_no != SUBS_MAX; ++sub_no) { + int rv; + if ((rv = hw_mmal_subpic_update(VLC_OBJECT(p_filter), + hw_mmal_pic_sub_buf_get(p_pic, sub_no), + sys->subs + sub_no, + &p_pic->format, + &sys->output->format->es->video.crop, + frame_seq)) == 0) + break; + else if (rv < 0) + goto fail; + } + } else { unsigned int sub_no = 0; @@ -1359,6 +1389,13 @@ static void CloseConverter(vlc_object_t * obj) if (sys->component && sys->component->is_enabled) mmal_component_disable(sys->component); + if (sys->resizer_type == FILTER_RESIZER_HVS) + { + for (size_t i = 0; i != SUBS_MAX; ++i) { + hw_mmal_subpic_close(sys->subs + i); + } + } + if (sys->out_pool) { if (sys->is_sliced) @@ -1406,12 +1443,14 @@ static int OpenConverter(vlc_object_t * obj) const MMAL_FOURCC_T enc_out = vlc_to_mmal_video_fourcc(&p_filter->fmt_out.video); const MMAL_FOURCC_T enc_in = filter_enc_in(&p_filter->fmt_in.video); bool use_resizer; + bool use_isp; // At least in principle we should deal with any mmal format as input if (enc_in == 0 || enc_out == 0) return VLC_EGENERIC; use_resizer = var_InheritBool(p_filter, MMAL_RESIZE_NAME); + use_isp = var_InheritBool(p_filter, MMAL_ISP_NAME); retry: // ** Make more generic by checking supported encs @@ -1421,13 +1460,25 @@ retry: // If resizer selected then just give up if (use_resizer) return VLC_EGENERIC; + // otherwise downgrade HVS to ISP + use_isp = true; + } + // HVS can't do I420 + if (enc_out == MMAL_ENCODING_I420) { + use_isp = true; } // Only HVS can deal with SAND30 if (enc_in == MMAL_ENCODING_YUV10_COL) { - if (use_resizer) + if (use_isp || use_resizer) return VLC_EGENERIC; } + + if (use_resizer) { + // use resizer overrides use_isp + use_isp = false; + } + // Check we have a sliced version of the fourcc if we want the resizer if (use_resizer && pic_to_slice_mmal_fourcc(enc_out) == 0) { return VLC_EGENERIC; @@ -1461,15 +1512,26 @@ retry: sys->component_name = MMAL_COMPONENT_DEFAULT_RESIZER; sys->out_port_cb_fn = slice_output_port_cb; } - else { + else if (use_isp) { sys->resizer_type = FILTER_RESIZER_ISP; sys->is_sliced = false; // Copy directly into filter picture sys->component_name = MMAL_COMPONENT_ISP_RESIZER; sys->out_port_cb_fn = conv_output_port_cb; + } else { + sys->resizer_type = FILTER_RESIZER_HVS; + sys->is_sliced = false; // Copy directly into filter picture + sys->component_name = MMAL_COMPONENT_HVS; + sys->out_port_cb_fn = conv_output_port_cb; } status = mmal_component_create(sys->component_name, &sys->component); if (status != MMAL_SUCCESS) { + if (!use_isp && !use_resizer) { + msg_Warn(p_filter, "Failed to rcreate HVS resizer - retrying with ISP"); + CloseConverter(obj); + use_isp = true; + goto retry; + } msg_Err(p_filter, "Failed to create MMAL component %s (status=%"PRIx32" %s)", MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); goto fail; @@ -1528,6 +1590,18 @@ retry: goto fail; } + if (sys->resizer_type == FILTER_RESIZER_HVS) + { + unsigned int i; + for (i = 0; i != SUBS_MAX; ++i) { + if (hw_mmal_subpic_open(VLC_OBJECT(p_filter), sys->subs + i, sys->component->input[i + 1], -1, i + 1) != MMAL_SUCCESS) + { + msg_Err(p_filter, "Failed to open subpic %d", i); + goto fail; + } + } + } + p_filter->pf_video_filter = conv_filter; p_filter->pf_flush = conv_flush; // video_drain NIF in filter structure diff --git a/modules/hw/mmal/subpic.c b/modules/hw/mmal/subpic.c index 1d8662f029..00365b6912 100644 --- a/modules/hw/mmal/subpic.c +++ b/modules/hw/mmal/subpic.c @@ -38,7 +38,7 @@ static bool cmp_rect(const MMAL_RECT_T * const a, const MMAL_RECT_T * const b) return a->x == b->x && a->y == b->y && a->width == b->width && a->height == b->height; } -static void hw_mmal_subpic_flush(subpic_reg_stash_t * const sub) +void hw_mmal_subpic_flush(subpic_reg_stash_t * const sub) { if (sub->port != NULL && sub->port->is_enabled) mmal_port_disable(sub->port); diff --git a/modules/hw/mmal/subpic.h b/modules/hw/mmal/subpic.h index b33475b4b4..3eb3a1aa20 100644 --- a/modules/hw/mmal/subpic.h +++ b/modules/hw/mmal/subpic.h @@ -42,6 +42,8 @@ int hw_mmal_subpic_update(vlc_object_t * const p_filter, const MMAL_RECT_T * const scale_out, const uint64_t pts); +void hw_mmal_subpic_flush(subpic_reg_stash_t * const spe); + void hw_mmal_subpic_close(subpic_reg_stash_t * const spe); // If display id is -1 it will be unset