Skip to content

Commit

Permalink
upipe_ffmt: add format conversion for hardware surfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
nto authored and cmassiot committed Feb 19, 2024
1 parent b81f6af commit 8a9ab6d
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 38 deletions.
85 changes: 59 additions & 26 deletions include/upipe-av/upipe_av_pixfmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ static inline int upipe_av_pixfmt_to_flow_def(enum AVPixelFormat pix_fmt,
return uref_flow_set_def(flow_def, UREF_PIC_FLOW_DEF);
}

/** @This finds the appropriate av pixel format according to the flow
/** @This finds the appropriate software av pixel format according to the flow
* definition, and creates a mapping system for planes.
*
* @param flow_def flow definition
Expand All @@ -192,9 +192,9 @@ static inline int upipe_av_pixfmt_to_flow_def(enum AVPixelFormat pix_fmt,
* was found
*/
static inline enum AVPixelFormat
upipe_av_pixfmt_from_flow_def(struct uref *flow_def,
const enum AVPixelFormat *pix_fmts,
const char *chroma_p[UPIPE_AV_MAX_PLANES])
upipe_av_sw_pixfmt_from_flow_def(struct uref *flow_def,
const enum AVPixelFormat *pix_fmts,
const char *chroma_p[UPIPE_AV_MAX_PLANES])
{
static const enum AVPixelFormat supported_fmts[] = {
AV_PIX_FMT_YUVA420P,
Expand Down Expand Up @@ -253,28 +253,6 @@ static inline enum AVPixelFormat
-1
};

const char *surface_type;
if (ubase_check(uref_pic_flow_get_surface_type(flow_def, &surface_type))) {
if (ubase_ncmp(surface_type, "av."))
return AV_PIX_FMT_NONE;

enum AVPixelFormat pix_fmt = av_get_pix_fmt(surface_type + 3);
if (pix_fmts == NULL) {
chroma_p[0] = NULL;
return pix_fmt;
}

while (*pix_fmts != -1) {
if (*pix_fmts == pix_fmt) {
chroma_p[0] = NULL;
return pix_fmt;
}
pix_fmts++;
}

return AV_PIX_FMT_NONE;
}

if (pix_fmts == NULL)
pix_fmts = supported_fmts;

Expand All @@ -301,6 +279,61 @@ static inline enum AVPixelFormat
return AV_PIX_FMT_NONE;
}

/** @This returns the appropriate hardware av pixel format according to the
* flow definition.
*
* @param flow_def flow definition
* @return selected pixel format, or AV_PIX_FMT_NONE if no compatible pixel
* format was found
*/
static inline enum AVPixelFormat
upipe_av_hw_pixfmt_from_flow_def(struct uref *flow_def)
{
const char *surface_type;

if (ubase_check(uref_pic_flow_get_surface_type(flow_def, &surface_type)))
if (!ubase_ncmp(surface_type, "av."))
return av_get_pix_fmt(surface_type + 3);

return AV_PIX_FMT_NONE;
}

/** @This finds the appropriate av pixel format according to the flow
* definition, and creates a mapping system for planes.
*
* @param flow_def flow definition
* @param pix_fmts allowed pixel formats, terminated by -1 (or NULL for any)
* @param chroma_map av plane number vs. chroma map
* @return selected pixel format, or AV_PIX_FMT_NONE if no compatible pixel
* format was found
*/
static inline enum AVPixelFormat
upipe_av_pixfmt_from_flow_def(struct uref *flow_def,
const enum AVPixelFormat *pix_fmts,
const char *chroma_p[UPIPE_AV_MAX_PLANES])
{
enum AVPixelFormat pix_fmt = upipe_av_hw_pixfmt_from_flow_def(flow_def);

if (pix_fmt != AV_PIX_FMT_NONE) {
if (pix_fmts == NULL) {
chroma_p[0] = NULL;
return pix_fmt;
}

while (*pix_fmts != -1) {
if (*pix_fmts == pix_fmt) {
chroma_p[0] = NULL;
return pix_fmt;
}
pix_fmts++;
}

return AV_PIX_FMT_NONE;
}

return upipe_av_sw_pixfmt_from_flow_def(flow_def, pix_fmts, chroma_p);
}

#ifdef __cplusplus
}
#endif
Expand Down
7 changes: 4 additions & 3 deletions include/upipe-av/upipe_avfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct upipe_mgr *upipe_avfilt_mgr_alloc(void);
enum upipe_avfilt_mgr_command {
UPIPE_AVFILT_MGR_SENTINEL = UPIPE_MGR_CONTROL_LOCAL,

/** gets the pixel format name from flow def (struct uref *, const char **) */
/** gets the pixel format name from flow def (struct uref *, const char **, bool) */
UPIPE_AVFILT_MGR_GET_PIXFMT_NAME
};

Expand All @@ -118,10 +118,11 @@ enum upipe_avfilt_mgr_command {
*/
static inline int upipe_avfilt_mgr_get_pixfmt_name(struct upipe_mgr *mgr,
struct uref *flow_def,
const char **name)
const char **name,
bool software)
{
return upipe_mgr_control(mgr, UPIPE_AVFILT_MGR_GET_PIXFMT_NAME,
UPIPE_AVFILT_SIGNATURE, flow_def, name);
UPIPE_AVFILT_SIGNATURE, flow_def, name, software);
}

#ifdef __cplusplus
Expand Down
10 changes: 7 additions & 3 deletions lib/upipe-av/upipe_avfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -2695,10 +2695,12 @@ static void upipe_avfilt_free(struct upipe *upipe)
* @return an error code
*/
static int _upipe_avfilt_mgr_get_pixfmt_name(struct uref *flow_def,
const char **name_p)
const char **name_p,
bool software)
{
const char *chroma_map[UPIPE_AV_MAX_PLANES];
enum AVPixelFormat pix_fmt =
enum AVPixelFormat pix_fmt = software ?
upipe_av_sw_pixfmt_from_flow_def(flow_def, NULL, chroma_map) :
upipe_av_pixfmt_from_flow_def(flow_def, NULL, chroma_map);

const char *name = av_get_pix_fmt_name(pix_fmt);
Expand Down Expand Up @@ -2726,7 +2728,9 @@ static int upipe_avfilt_mgr_control(struct upipe_mgr *mgr,
UBASE_SIGNATURE_CHECK(args, UPIPE_AVFILT_SIGNATURE)
struct uref *flow_def = va_arg(args, struct uref *);
const char **name_p = va_arg(args, const char **);
return _upipe_avfilt_mgr_get_pixfmt_name(flow_def, name_p);
bool software = va_arg(args, int);
return _upipe_avfilt_mgr_get_pixfmt_name(flow_def, name_p,
software);
default:
return UBASE_ERR_UNHANDLED;
}
Expand Down
24 changes: 18 additions & 6 deletions lib/upipe-filters/upipe_filter_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,11 @@ static int upipe_ffmt_check_flow_format(struct upipe *upipe,
const char *pix_fmt_in = "unknown";
const char *pix_fmt_out = "unknown";
upipe_avfilt_mgr_get_pixfmt_name(ffmt_mgr->avfilter_mgr,
flow_def, &pix_fmt_in);
flow_def, &pix_fmt_in,
true);
upipe_avfilt_mgr_get_pixfmt_name(ffmt_mgr->avfilter_mgr,
flow_def_dup, &pix_fmt_out);
flow_def_dup, &pix_fmt_out,
true);
upipe_notice_va(upipe, "need format conversion %s → %s",
pix_fmt_in, pix_fmt_out);
}
Expand Down Expand Up @@ -421,7 +423,10 @@ static int upipe_ffmt_check_flow_format(struct upipe *upipe,

const char *pix_fmt = NULL;
upipe_avfilt_mgr_get_pixfmt_name(ffmt_mgr->avfilter_mgr,
flow_def_dup, &pix_fmt);
flow_def_dup, &pix_fmt, false);
const char *pix_fmt_sw = NULL;
upipe_avfilt_mgr_get_pixfmt_name(ffmt_mgr->avfilter_mgr,
flow_def_dup, &pix_fmt_sw, true);

char filters[512];
int pos = 0;
Expand All @@ -432,15 +437,22 @@ static int upipe_ffmt_check_flow_format(struct upipe *upipe,
str_cat("scale,format=nv12,hwupload,");
if (need_deint)
str_cat("deinterlace_vaapi=auto=1,");
if (need_scale)
str_cat("scale_vaapi=w=%"PRIu64":h=%"PRIu64",", hsize, vsize);
if (need_scale || need_format) {
str_cat("scale_vaapi=");
if (need_scale)
str_cat("w=%"PRIu64":h=%"PRIu64, hsize, vsize);
if (need_scale && need_format)
str_cat(":");
if (need_format)
str_cat("format=%s", pix_fmt_sw);
str_cat(",");
}
if (!hw_out) {
str_cat("hwmap=mode=read+direct,format=nv12,");
if (pix_fmt != NULL && strcmp(pix_fmt, "nv12"))
str_cat("scale,format=%s,", pix_fmt);
} else if (pic_qsv_out && (need_deint || need_scale || pic_vaapi_in))
str_cat("hwmap=derive_device=qsv,format=qsv");

#undef str_cat

if (filters[pos - 1] == ',')
Expand Down

0 comments on commit 8a9ab6d

Please sign in to comment.