[FFmpeg-devel] [PATCH] lavfi/vf_extractplanes: set input formats to reduce conversions.
Nicolas George
nicolas.george at normalesup.org
Mon May 6 21:21:19 CEST 2013
Only accept formats that will not require color-space conversion
and with the same bit depth as actually available on input.
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
libavfilter/vf_extractplanes.c | 67 ++++++++++++++++++++++++++--------------
1 file changed, 44 insertions(+), 23 deletions(-)
Note tht for some reason, GBRP16?E are not considered valid output formats
for lsws, so handling RGB in 16 bpp will not work. But that is completely
unrelated.
diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c
index 028813a..373a789 100644
--- a/libavfilter/vf_extractplanes.c
+++ b/libavfilter/vf_extractplanes.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
@@ -33,6 +34,12 @@
#define PLANE_U 0x20
#define PLANE_V 0x40
+#define FLAG_DEPTH_8 0x10000
+#define FLAG_DEPTH_16LE 0x20000
+#define FLAG_DEPTH_16BE 0x40000
+#define FLAG_DEPTH_OTHER 0x80000
+#define FLAG_DEPTHS 0xF0000
+
typedef struct {
const AVClass *class;
int requested_planes;
@@ -56,6 +63,21 @@ static const AVOption extractplanes_options[] = {
AVFILTER_DEFINE_CLASS(extractplanes);
+static unsigned pix_fmt_to_bitmask(enum AVPixelFormat fmt)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
+ unsigned depth = desc->comp[0].depth_minus1 + 1;
+
+ return ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B :
+ PLANE_Y |
+ ((desc->nb_components > 2) ? PLANE_U|PLANE_V : 0)) |
+ ((desc->flags & PIX_FMT_ALPHA) ? PLANE_A : 0) |
+ (depth == 8 ? FLAG_DEPTH_8 :
+ depth == 16 ? (desc->flags & PIX_FMT_BE) ? FLAG_DEPTH_16BE :
+ FLAG_DEPTH_16LE :
+ FLAG_DEPTH_OTHER);
+}
+
static int query_formats(AVFilterContext *ctx)
{
static const enum AVPixelFormat in_pixfmts[] = {
@@ -77,42 +99,45 @@ static int query_formats(AVFilterContext *ctx)
AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE,
AV_PIX_FMT_GBRP,
AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRP16BE,
- AV_PIX_FMT_NONE,
};
static const enum AVPixelFormat out8_pixfmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
static const enum AVPixelFormat out16le_pixfmts[] = { AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_NONE };
static const enum AVPixelFormat out16be_pixfmts[] = { AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE };
const enum AVPixelFormat *out_pixfmts;
- const AVPixFmtDescriptor *desc;
- AVFilterFormats *avff;
- int i, depth = 0, be = 0;
+ AVFilterFormats *avff, *in_formats = NULL;
+ unsigned i, fmt_mask, max_fmt_mask = 0;
if (!ctx->inputs[0]->in_formats ||
!ctx->inputs[0]->in_formats->format_count) {
return AVERROR(EAGAIN);
}
- if (!ctx->inputs[0]->out_formats)
- ff_formats_ref(ff_make_format_list(in_pixfmts), &ctx->inputs[0]->out_formats);
-
avff = ctx->inputs[0]->in_formats;
- desc = av_pix_fmt_desc_get(avff->formats[0]);
- depth = desc->comp[0].depth_minus1;
- be = desc->flags & PIX_FMT_BE;
- for (i = 1; i < avff->format_count; i++) {
- desc = av_pix_fmt_desc_get(avff->formats[i]);
- if (depth != desc->comp[0].depth_minus1 ||
- be != (desc->flags & PIX_FMT_BE)) {
+ for (i = 0; i < avff->format_count; i++) {
+ fmt_mask = pix_fmt_to_bitmask(avff->formats[i]);
+ if ((fmt_mask & ~max_fmt_mask) && (max_fmt_mask & ~fmt_mask))
return AVERROR(EAGAIN);
- }
+ max_fmt_mask |= fmt_mask;
}
- if (depth == 7)
+ if ((max_fmt_mask & FLAG_DEPTH_8)) {
out_pixfmts = out8_pixfmts;
- else if (be)
+ } else if ((max_fmt_mask & FLAG_DEPTH_16BE)) {
out_pixfmts = out16be_pixfmts;
- else
+ } else if ((max_fmt_mask & FLAG_DEPTH_16BE)) {
out_pixfmts = out16le_pixfmts;
+ } else {
+ av_log(ctx, AV_LOG_ERROR, "No supported bit depth in input\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (!ctx->inputs[0]->out_formats) {
+ for (i = 0; i < FF_ARRAY_ELEMS(in_pixfmts); i++)
+ if (!(pix_fmt_to_bitmask(in_pixfmts[i]) & ~max_fmt_mask))
+ ff_add_format(&in_formats, in_pixfmts[i]);
+ av_assert0(in_formats);
+ ff_formats_ref(in_formats, &ctx->inputs[0]->out_formats);
+ }
for (i = 0; i < ctx->nb_outputs; i++)
ff_formats_ref(ff_make_format_list(out_pixfmts), &ctx->outputs[i]->in_formats);
@@ -123,13 +148,9 @@ static int config_input(AVFilterLink *inlink)
{
AVFilterContext *ctx = inlink->dst;
ExtractPlanesContext *e = ctx->priv;
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
int plane_avail, ret;
- plane_avail = ((desc->flags & PIX_FMT_RGB) ? PLANE_R|PLANE_G|PLANE_B :
- PLANE_Y |
- ((desc->nb_components > 2) ? PLANE_U|PLANE_V : 0)) |
- ((desc->flags & PIX_FMT_ALPHA) ? PLANE_A : 0);
+ plane_avail = pix_fmt_to_bitmask(inlink->format) & ~FLAG_DEPTHS;
if (e->requested_planes & ~plane_avail) {
av_log(ctx, AV_LOG_ERROR, "Requested planes not available.\n");
return AVERROR(EINVAL);
--
1.7.10.4
More information about the ffmpeg-devel
mailing list