1/* 2 * Copyright (c) 2010 Bobby Bingham 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 * aspect ratio modification video filters 24 */ 25 26#include "libavutil/mathematics.h" 27#include "avfilter.h" 28 29typedef struct { 30 AVRational aspect; 31} AspectContext; 32 33static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) 34{ 35 AspectContext *aspect = ctx->priv; 36 double ratio; 37 int64_t gcd; 38 char c = 0; 39 40 if (args) { 41 if (sscanf(args, "%d:%d%c", &aspect->aspect.num, &aspect->aspect.den, &c) != 2) 42 if (sscanf(args, "%lf%c", &ratio, &c) == 1) 43 aspect->aspect = av_d2q(ratio, 100); 44 45 if (c || aspect->aspect.num <= 0 || aspect->aspect.den <= 0) { 46 av_log(ctx, AV_LOG_ERROR, 47 "Invalid string '%s' for aspect ratio.\n", args); 48 return AVERROR(EINVAL); 49 } 50 51 gcd = av_gcd(FFABS(aspect->aspect.num), FFABS(aspect->aspect.den)); 52 if (gcd) { 53 aspect->aspect.num /= gcd; 54 aspect->aspect.den /= gcd; 55 } 56 } 57 58 if (aspect->aspect.den == 0) 59 aspect->aspect = (AVRational) {0, 1}; 60 61 av_log(ctx, AV_LOG_INFO, "a:%d/%d\n", aspect->aspect.num, aspect->aspect.den); 62 return 0; 63} 64 65static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) 66{ 67 AspectContext *aspect = link->dst->priv; 68 69 picref->video->pixel_aspect = aspect->aspect; 70 avfilter_start_frame(link->dst->outputs[0], picref); 71} 72 73#if CONFIG_SETDAR_FILTER 74/* for setdar filter, convert from frame aspect ratio to pixel aspect ratio */ 75static int setdar_config_props(AVFilterLink *inlink) 76{ 77 AspectContext *aspect = inlink->dst->priv; 78 AVRational dar = aspect->aspect; 79 80 av_reduce(&aspect->aspect.num, &aspect->aspect.den, 81 aspect->aspect.num * inlink->h, 82 aspect->aspect.den * inlink->w, 100); 83 84 av_log(inlink->dst, AV_LOG_INFO, "w:%d h:%d -> dar:%d/%d sar:%d/%d\n", 85 inlink->w, inlink->h, dar.num, dar.den, aspect->aspect.num, aspect->aspect.den); 86 87 inlink->sample_aspect_ratio = aspect->aspect; 88 89 return 0; 90} 91 92AVFilter avfilter_vf_setdar = { 93 .name = "setdar", 94 .description = NULL_IF_CONFIG_SMALL("Set the frame display aspect ratio."), 95 96 .init = init, 97 98 .priv_size = sizeof(AspectContext), 99 100 .inputs = (AVFilterPad[]) {{ .name = "default", 101 .type = AVMEDIA_TYPE_VIDEO, 102 .config_props = setdar_config_props, 103 .get_video_buffer = avfilter_null_get_video_buffer, 104 .start_frame = start_frame, 105 .end_frame = avfilter_null_end_frame }, 106 { .name = NULL}}, 107 108 .outputs = (AVFilterPad[]) {{ .name = "default", 109 .type = AVMEDIA_TYPE_VIDEO, }, 110 { .name = NULL}}, 111}; 112#endif /* CONFIG_SETDAR_FILTER */ 113 114#if CONFIG_SETSAR_FILTER 115/* for setdar filter, convert from frame aspect ratio to pixel aspect ratio */ 116static int setsar_config_props(AVFilterLink *inlink) 117{ 118 AspectContext *aspect = inlink->dst->priv; 119 120 inlink->sample_aspect_ratio = aspect->aspect; 121 122 return 0; 123} 124 125AVFilter avfilter_vf_setsar = { 126 .name = "setsar", 127 .description = NULL_IF_CONFIG_SMALL("Set the pixel sample aspect ratio."), 128 129 .init = init, 130 131 .priv_size = sizeof(AspectContext), 132 133 .inputs = (AVFilterPad[]) {{ .name = "default", 134 .type = AVMEDIA_TYPE_VIDEO, 135 .config_props = setsar_config_props, 136 .get_video_buffer = avfilter_null_get_video_buffer, 137 .start_frame = start_frame, 138 .end_frame = avfilter_null_end_frame }, 139 { .name = NULL}}, 140 141 .outputs = (AVFilterPad[]) {{ .name = "default", 142 .type = AVMEDIA_TYPE_VIDEO, }, 143 { .name = NULL}}, 144}; 145#endif /* CONFIG_SETSAR_FILTER */ 146 147