1/* 2 * Copyright (c) 2009 Stefano Sabatini 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21/** 22 * @file 23 * pixdesc test filter 24 */ 25 26#include "libavutil/common.h" 27#include "libavutil/pixdesc.h" 28#include "avfilter.h" 29#include "internal.h" 30#include "video.h" 31 32typedef struct PixdescTestContext { 33 const AVPixFmtDescriptor *pix_desc; 34 uint16_t *line; 35} PixdescTestContext; 36 37static av_cold void uninit(AVFilterContext *ctx) 38{ 39 PixdescTestContext *priv = ctx->priv; 40 av_freep(&priv->line); 41} 42 43static int config_props(AVFilterLink *inlink) 44{ 45 PixdescTestContext *priv = inlink->dst->priv; 46 47 priv->pix_desc = av_pix_fmt_desc_get(inlink->format); 48 49 av_freep(&priv->line); 50 if (!(priv->line = av_malloc_array(sizeof(*priv->line), inlink->w))) 51 return AVERROR(ENOMEM); 52 53 return 0; 54} 55 56static int filter_frame(AVFilterLink *inlink, AVFrame *in) 57{ 58 PixdescTestContext *priv = inlink->dst->priv; 59 AVFilterLink *outlink = inlink->dst->outputs[0]; 60 AVFrame *out; 61 int i, c, w = inlink->w, h = inlink->h; 62 const int cw = FF_CEIL_RSHIFT(w, priv->pix_desc->log2_chroma_w); 63 const int ch = FF_CEIL_RSHIFT(h, priv->pix_desc->log2_chroma_h); 64 65 out = ff_get_video_buffer(outlink, outlink->w, outlink->h); 66 if (!out) { 67 av_frame_free(&in); 68 return AVERROR(ENOMEM); 69 } 70 71 av_frame_copy_props(out, in); 72 73 for (i = 0; i < 4; i++) { 74 const int h1 = i == 1 || i == 2 ? ch : h; 75 if (out->data[i]) { 76 uint8_t *data = out->data[i] + 77 (out->linesize[i] > 0 ? 0 : out->linesize[i] * (h1-1)); 78 memset(data, 0, FFABS(out->linesize[i]) * h1); 79 } 80 } 81 82 /* copy palette */ 83 if (priv->pix_desc->flags & AV_PIX_FMT_FLAG_PAL || 84 priv->pix_desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) 85 memcpy(out->data[1], in->data[1], AVPALETTE_SIZE); 86 87 for (c = 0; c < priv->pix_desc->nb_components; c++) { 88 const int w1 = c == 1 || c == 2 ? cw : w; 89 const int h1 = c == 1 || c == 2 ? ch : h; 90 91 for (i = 0; i < h1; i++) { 92 av_read_image_line(priv->line, 93 (void*)in->data, 94 in->linesize, 95 priv->pix_desc, 96 0, i, c, w1, 0); 97 98 av_write_image_line(priv->line, 99 out->data, 100 out->linesize, 101 priv->pix_desc, 102 0, i, c, w1); 103 } 104 } 105 106 av_frame_free(&in); 107 return ff_filter_frame(outlink, out); 108} 109 110static const AVFilterPad avfilter_vf_pixdesctest_inputs[] = { 111 { 112 .name = "default", 113 .type = AVMEDIA_TYPE_VIDEO, 114 .filter_frame = filter_frame, 115 .config_props = config_props, 116 }, 117 { NULL } 118}; 119 120static const AVFilterPad avfilter_vf_pixdesctest_outputs[] = { 121 { 122 .name = "default", 123 .type = AVMEDIA_TYPE_VIDEO, 124 }, 125 { NULL } 126}; 127 128AVFilter ff_vf_pixdesctest = { 129 .name = "pixdesctest", 130 .description = NULL_IF_CONFIG_SMALL("Test pixel format definitions."), 131 .priv_size = sizeof(PixdescTestContext), 132 .uninit = uninit, 133 .inputs = avfilter_vf_pixdesctest_inputs, 134 .outputs = avfilter_vf_pixdesctest_outputs, 135}; 136