lavfi: add error handling to start_frame().
[libav.git] / libavfilter / vf_pixdesctest.c
1 /*
2 * Copyright (c) 2009 Stefano Sabatini
3 *
4 * This file is part of Libav.
5 *
6 * Libav 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 * Libav 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 Libav; 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/pixdesc.h"
27 #include "avfilter.h"
28 #include "internal.h"
29 #include "video.h"
30
31 typedef struct {
32 const AVPixFmtDescriptor *pix_desc;
33 uint16_t *line;
34 } PixdescTestContext;
35
36 static av_cold void uninit(AVFilterContext *ctx)
37 {
38 PixdescTestContext *priv = ctx->priv;
39 av_freep(&priv->line);
40 }
41
42 static int config_props(AVFilterLink *inlink)
43 {
44 PixdescTestContext *priv = inlink->dst->priv;
45
46 priv->pix_desc = &av_pix_fmt_descriptors[inlink->format];
47
48 if (!(priv->line = av_malloc(sizeof(*priv->line) * inlink->w)))
49 return AVERROR(ENOMEM);
50
51 return 0;
52 }
53
54 static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
55 {
56 PixdescTestContext *priv = inlink->dst->priv;
57 AVFilterLink *outlink = inlink->dst->outputs[0];
58 AVFilterBufferRef *outpicref;
59 int i, ret = 0;
60
61 outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE,
62 outlink->w, outlink->h);
63 if (!outpicref)
64 return AVERROR(ENOMEM);
65
66 avfilter_copy_buffer_ref_props(outpicref, picref);
67
68 for (i = 0; i < 4; i++) {
69 int h = outlink->h;
70 h = i == 1 || i == 2 ? h>>priv->pix_desc->log2_chroma_h : h;
71 if (outpicref->data[i]) {
72 uint8_t *data = outpicref->data[i] +
73 (outpicref->linesize[i] > 0 ? 0 : outpicref->linesize[i] * (h-1));
74 memset(data, 0, FFABS(outpicref->linesize[i]) * h);
75 }
76 }
77
78 /* copy palette */
79 if (priv->pix_desc->flags & PIX_FMT_PAL ||
80 priv->pix_desc->flags & PIX_FMT_PSEUDOPAL)
81 memcpy(outpicref->data[1], outpicref->data[1], 256*4);
82
83 ret = ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0));
84 if (ret < 0) {
85 avfilter_unref_bufferp(&outpicref);
86 return ret;
87 }
88
89 outlink->out_buf = outpicref;
90 return 0;
91 }
92
93 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
94 {
95 PixdescTestContext *priv = inlink->dst->priv;
96 AVFilterBufferRef *inpic = inlink->cur_buf;
97 AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf;
98 int i, c, w = inlink->w;
99
100 for (c = 0; c < priv->pix_desc->nb_components; c++) {
101 int w1 = c == 1 || c == 2 ? w>>priv->pix_desc->log2_chroma_w : w;
102 int h1 = c == 1 || c == 2 ? h>>priv->pix_desc->log2_chroma_h : h;
103 int y1 = c == 1 || c == 2 ? y>>priv->pix_desc->log2_chroma_h : y;
104
105 for (i = y1; i < y1 + h1; i++) {
106 av_read_image_line(priv->line,
107 inpic->data,
108 inpic->linesize,
109 priv->pix_desc,
110 0, i, c, w1, 0);
111
112 av_write_image_line(priv->line,
113 outpic->data,
114 outpic->linesize,
115 priv->pix_desc,
116 0, i, c, w1);
117 }
118 }
119
120 ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir);
121 }
122
123 AVFilter avfilter_vf_pixdesctest = {
124 .name = "pixdesctest",
125 .description = NULL_IF_CONFIG_SMALL("Test pixel format definitions."),
126
127 .priv_size = sizeof(PixdescTestContext),
128 .uninit = uninit,
129
130 .inputs = (const AVFilterPad[]) {{ .name = "default",
131 .type = AVMEDIA_TYPE_VIDEO,
132 .start_frame = start_frame,
133 .draw_slice = draw_slice,
134 .config_props = config_props,
135 .min_perms = AV_PERM_READ, },
136 { .name = NULL}},
137
138 .outputs = (const AVFilterPad[]) {{ .name = "default",
139 .type = AVMEDIA_TYPE_VIDEO, },
140 { .name = NULL}},
141 };