Libav 0.7.1
|
00001 /* 00002 * Copyright (c) 2010 Brandon Mintern 00003 * Copyright (c) 2007 Bobby Bingham 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00028 #include "libavutil/pixdesc.h" 00029 #include "avfilter.h" 00030 00031 typedef struct { 00032 int factor, fade_per_frame; 00033 unsigned int frame_index, start_frame, stop_frame; 00034 int hsub, vsub, bpp; 00035 } FadeContext; 00036 00037 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) 00038 { 00039 FadeContext *fade = ctx->priv; 00040 unsigned int nb_frames; 00041 char in_out[4]; 00042 00043 if (!args || 00044 sscanf(args, " %3[^:]:%u:%u", in_out, &fade->start_frame, &nb_frames) != 3) { 00045 av_log(ctx, AV_LOG_ERROR, 00046 "Expected 3 arguments '(in|out):#:#':'%s'\n", args); 00047 return AVERROR(EINVAL); 00048 } 00049 00050 nb_frames = nb_frames ? nb_frames : 1; 00051 fade->fade_per_frame = (1 << 16) / nb_frames; 00052 if (!strcmp(in_out, "in")) 00053 fade->factor = 0; 00054 else if (!strcmp(in_out, "out")) { 00055 fade->fade_per_frame = -fade->fade_per_frame; 00056 fade->factor = (1 << 16); 00057 } else { 00058 av_log(ctx, AV_LOG_ERROR, 00059 "first argument must be 'in' or 'out':'%s'\n", in_out); 00060 return AVERROR(EINVAL); 00061 } 00062 fade->stop_frame = fade->start_frame + nb_frames; 00063 00064 av_log(ctx, AV_LOG_INFO, 00065 "type:%s start_frame:%d nb_frames:%d\n", 00066 in_out, fade->start_frame, nb_frames); 00067 return 0; 00068 } 00069 00070 static int query_formats(AVFilterContext *ctx) 00071 { 00072 const static enum PixelFormat pix_fmts[] = { 00073 PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV420P, 00074 PIX_FMT_YUV411P, PIX_FMT_YUV410P, 00075 PIX_FMT_YUVJ444P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ420P, 00076 PIX_FMT_YUV440P, PIX_FMT_YUVJ440P, 00077 PIX_FMT_RGB24, PIX_FMT_BGR24, 00078 PIX_FMT_NONE 00079 }; 00080 00081 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); 00082 return 0; 00083 } 00084 00085 static int config_props(AVFilterLink *inlink) 00086 { 00087 FadeContext *fade = inlink->dst->priv; 00088 const AVPixFmtDescriptor *pixdesc = &av_pix_fmt_descriptors[inlink->format]; 00089 00090 fade->hsub = pixdesc->log2_chroma_w; 00091 fade->vsub = pixdesc->log2_chroma_h; 00092 00093 fade->bpp = av_get_bits_per_pixel(pixdesc) >> 3; 00094 return 0; 00095 } 00096 00097 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) 00098 { 00099 FadeContext *fade = inlink->dst->priv; 00100 AVFilterBufferRef *outpic = inlink->cur_buf; 00101 uint8_t *p; 00102 int i, j, plane; 00103 00104 if (fade->factor < UINT16_MAX) { 00105 /* luma or rgb plane */ 00106 for (i = 0; i < h; i++) { 00107 p = outpic->data[0] + (y+i) * outpic->linesize[0]; 00108 for (j = 0; j < inlink->w * fade->bpp; j++) { 00109 /* fade->factor is using 16 lower-order bits for decimal 00110 * places. 32768 = 1 << 15, it is an integer representation 00111 * of 0.5 and is for rounding. */ 00112 *p = (*p * fade->factor + 32768) >> 16; 00113 p++; 00114 } 00115 } 00116 00117 if (outpic->data[1] && outpic->data[2]) { 00118 /* chroma planes */ 00119 for (plane = 1; plane < 3; plane++) { 00120 for (i = 0; i < h; i++) { 00121 p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane]; 00122 for (j = 0; j < inlink->w >> fade->hsub; j++) { 00123 /* 8421367 = ((128 << 1) + 1) << 15. It is an integer 00124 * representation of 128.5. The .5 is for rounding 00125 * purposes. */ 00126 *p = ((*p - 128) * fade->factor + 8421367) >> 16; 00127 p++; 00128 } 00129 } 00130 } 00131 } 00132 } 00133 00134 avfilter_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); 00135 } 00136 00137 static void end_frame(AVFilterLink *inlink) 00138 { 00139 FadeContext *fade = inlink->dst->priv; 00140 00141 avfilter_end_frame(inlink->dst->outputs[0]); 00142 00143 if (fade->frame_index >= fade->start_frame && 00144 fade->frame_index <= fade->stop_frame) 00145 fade->factor += fade->fade_per_frame; 00146 fade->factor = av_clip_uint16(fade->factor); 00147 fade->frame_index++; 00148 } 00149 00150 AVFilter avfilter_vf_fade = { 00151 .name = "fade", 00152 .description = NULL_IF_CONFIG_SMALL("Fade in/out input video"), 00153 .init = init, 00154 .priv_size = sizeof(FadeContext), 00155 .query_formats = query_formats, 00156 00157 .inputs = (AVFilterPad[]) {{ .name = "default", 00158 .type = AVMEDIA_TYPE_VIDEO, 00159 .config_props = config_props, 00160 .get_video_buffer = avfilter_null_get_video_buffer, 00161 .start_frame = avfilter_null_start_frame, 00162 .draw_slice = draw_slice, 00163 .end_frame = end_frame, 00164 .min_perms = AV_PERM_READ | AV_PERM_WRITE, 00165 .rej_perms = AV_PERM_PRESERVE, }, 00166 { .name = NULL}}, 00167 .outputs = (AVFilterPad[]) {{ .name = "default", 00168 .type = AVMEDIA_TYPE_VIDEO, }, 00169 { .name = NULL}}, 00170 };