Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * This file is part of FFmpeg.
- *
- * Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /**
- * @file
- * XBR Filter is used for depixelization of image.
- * This is based on Hyllian's 2xBR shader.
- * 2xBR Filter v0.2.5
- * Reference : http://board.byuu.org/viewtopic.php?f=10&t=2248
- */
- #include "libavutil/opt.h"
- #include "libavutil/avassert.h"
- #include "libavutil/pixdesc.h"
- #include "internal.h"
- typedef struct {
- uint32_t rgbtoyuv[1<<24];
- } xBRContext;
- /**
- * Calculates the weight of difference of the pixels, by transforming these
- * pixels into their Y'UV parts. It then uses the threshold used by HQx filters:
- * 48*Y + 7*U + 6*V, to give it those smooth looking edges.
- **/
- static int d(AVFrame *in,int x1,int y1,int x2,int y2,const uint32_t *r2y){
- #define YMASK 0xff0000
- #define UMASK 0x00ff00
- #define VMASK 0x0000ff
- int r1 = *(in->data[0] + y1 * in->linesize[0] + x1*3);
- int g1 = *(in->data[0] + y1 * in->linesize[0] + x1*3 + 1);
- int b1 = *(in->data[0] + y1 * in->linesize[0] + x1*3 + 2);
- int r2 = *(in->data[0] + y2 * in->linesize[0] + x2*3);
- int g2 = *(in->data[0] + y2 * in->linesize[0] + x2*3 + 1);
- int b2 = *(in->data[0] + y2 * in->linesize[0] + x2*3 + 2);
- printf("entered\n");
- uint32_t c1 = (r1 | g1<<8 | b1<<16);
- uint32_t c2 = (r2 | g2<<8 | b2<<16);
- uint32_t yuv1 = r2y[c1 & 0xffffff];
- uint32_t yuv2 = r2y[c2 & 0xffffff];
- return abs((yuv1 & YMASK) - (yuv2 & YMASK)) > (48 << 16) ||
- abs((yuv1 & UMASK) - (yuv2 & UMASK)) > ( 7 << 8) ||
- abs((yuv1 & VMASK) - (yuv2 & VMASK)) > ( 6 << 0);
- }
- /**
- * Mixes a pixel A, with pixel B, with B's transperancy set to 'a'
- * In other words, A is a solid color (bottom) and B is a transparent color (top)
- **/
- static int mix(AVFrame *in,int x1,int y1,int x2,int y2,int a,int color){
- int col1,col2;
- col1 = *(in->data[0] + y1 * in->linesize[0] + x1*3 + color);
- col2 = *(in->data[0] + y2 * in->linesize[0] + x2*3 + color);
- return (a*col2 + (2-a)*col1)/2;
- };
- /**
- * Fills the output matrix
- **/
- static void fill(AVFrame *in,AVFrame *out,int u,int v,int x,int y,int mode,int new_x,int new_y){
- int r,g,b;
- /*mix colors if they are not on boundary*/
- if(mode!=0 && u>=0 && v>=0 && u<in->width && v<in->height){
- r = mix(in,u,v,x,y,1,0);
- g = mix(in,u,v,x,y,1,1);
- b = mix(in,u,v,x,y,1,2);
- } else{
- r = *(in->data[0] + y*in->linesize[0] + x*3);
- g = *(in->data[0] + y*in->linesize[0] + x*3 + 1);
- b = *(in->data[0] + y*in->linesize[0] + x*3 + 2);
- }
- /*Insert blended color into scaledImageData*/
- *(out->data[0] + (new_y)*out->linesize[0] + (new_x)*3) = r;
- *(out->data[0] + (new_y)*out->linesize[0] + (new_x)*3 + 1) = g;
- *(out->data[0] + (new_y)*out->linesize[0] + (new_x)*3 + 2) = b;
- return;
- }
- /**
- * Applies the xBR filter rules.
- **/
- static void apply_edge_detection_rules(AVFrame *in,AVFrame *out,int x,int y,const uint32_t *r2y){
- /* Matrix: (10 is 0,0 i.e: current pixel)
- -2 | -1| 0| +1| +2 (x)
- ______________________________
- -2 | [A1][B1][C1]
- -1 | [A0][ A][ B][ C][C4]
- 0 | [D0][ D][ E][ F][F4]
- +1 | [G0][ G][ H][ I][I4]
- +2 | [G5][H5][I5]
- |(y)|
- */
- /*Cached Pixel Weight Difference*/
- int d_E_D = d(in, x, y, x-1, y, r2y);
- int d_E_B = d(in, x, y, x, y-1, r2y);
- int d_E_F = d(in, x, y, x+1, y, r2y);
- int d_E_H = d(in, x, y, x, y+1, r2y);
- int d_E_G = d(in, x, y, x-1, y+1, r2y);
- int d_E_C = d(in, x, y, x+1, y-1, r2y);
- int d_A_D0 = d(in, x-1, y-1, x-2, y, r2y);
- int d_A_B1 = d(in, x-1, y-1, x, y-2, r2y);
- int d_D_B = d(in, x-1, y, x, y-1, r2y);
- int d_D_H = d(in, x-1, y, x, y+1, r2y);
- int d_D_A0 = d(in, x-1, y, x-2, y-1, r2y);
- int d_B_F = d(in, x, y-1, x+1, y, r2y);
- int d_B_A1 = d(in, x, y-1, x-1, y-2, r2y);
- int d_E_A = d(in, x, y, x-1, y-1, r2y);
- int d_E_I = d(in, x, y, x+1, y+1, r2y);
- int d_C_F4 = d(in, x+1, y-1, x+2, y, r2y);
- int d_C_B1 = d(in, x+1, y-1, x, y-2, r2y);
- int d_F_H = d(in, x+1, y, x, y+1, r2y);
- int d_F_C4 = d(in, x+1, y, x+2, y-1, r2y);
- int d_B_C1 = d(in, x, y-1, x+1, y-2, r2y);
- int d_G_D0 = d(in, x-1, y+1, x-2, y, r2y);
- int d_G_H5 = d(in, x-1, y+1, x, y+2, r2y);
- int d_H_G5 = d(in, x, y+1, x-1, y+2, r2y);
- int d_D_G0 = d(in, x-1, y, x-2, y+1, r2y);
- int d_I_F4 = d(in, x+1, y+1, x+2, y, r2y);
- int d_I_H5 = d(in, x+1, y+1, x, y+2, r2y);
- int d_H_I5 = d(in, x, y+1, x+1, y+2, r2y);
- int d_H_I4 = d(in, x, y+1, x+2, y+1, r2y);
- /**
- * Note: On reading edge detection rules
- *
- * Each edge rule is an if..else statement, everytime on else, the
- * current pixel color pointed to by matrix[0] is used to color it's edge.
- *
- * Each if statement checks wether the sum of weight difference on the left is
- * lesser than that of the right weight differece.
- */
- /**
- * Top Left Edge Detection Rule
- **/
- if ((d_E_G+d_E_C+d_A_D0+d_A_B1+(4*d_D_B)) < (d_D_H+d_D_A0+d_B_F+d_B_A1+(4*d_E_A))){
- // Figure what color to blend with current pixel -->10
- if(d_E_D <= d_E_B)
- fill(in,out,x-1,y,x,y,1,x*2,y*2);
- else
- fill(in,out,x,y-1,x,y,1,x*2,y*2);
- } else{
- /*Insert current pixel color into scaledImageData*/
- fill(in,out,x,y,x,y,0,x*2,y*2);
- }
- /**
- * Top Right Edge Detection Rule
- **/
- if ((d_E_I+d_E_A+d_C_F4+d_C_B1+(4*d_B_F)) < (d_F_H+d_F_C4+d_D_B+d_B_C1+(4*d_E_C))){
- // Figure what color to blend with current pixel --> 10
- if(d_E_B <= d_E_F)
- fill(in,out,x,y-1,x,y,1,(x*2)+1,y*2);
- else
- fill(in,out,x+1,y,x,y,1,(x*2)+1,y*2);
- } else{
- /*Insert current pixel color into scaledImageData*/
- fill(in,out,x,y,x,y,0,(x*2)+1,y*2);
- }
- /**
- * Bottom Left Edge Detection Rule
- **/
- if ((d_E_A+d_E_I+d_G_D0+d_G_H5+(4*d_D_H)) < (d_D_B+d_D_G0+d_F_H+d_H_G5+(4*d_E_G))){
- // Figure what color to blend with current pixel --> 10
- if(d_E_D <= d_E_H)
- fill(in,out,x-1,y,x,y,1,x*2,(y*2)+1);
- else
- fill(in,out,x,y+1,x,y,1,x*2,(y*2)+1);
- } else{
- /*Insert current pixel color into scaledImageData*/
- fill(in,out,x,y,x,y,0,x*2,(y*2)+1);
- }
- /**
- * Bottom Right Edge Detection Rule
- **/
- if ((d_E_C+d_E_G+d_I_F4+d_I_H5+(4*d_F_H)) < (d_D_H+d_H_I5+d_H_I4+d_B_F+(4*d_E_I))){
- // Figure what color to blend with current pixel --> 10
- if(d_E_F <= d_E_H)
- fill(in,out,x+1,y,x,y,1,(x*2)+1,(y*2)+1);
- else
- fill(in,out,x,y+1,x,y,1,(x*2)+1,(y*2)+1);
- } else{
- /*Insert current pixel color into scaledImageData*/
- fill(in,out,x,y,x,y,0,(x*2)+1,(y*2)+1);
- }
- }
- static int config_output(AVFilterLink *outlink)
- {
- AVFilterContext *ctx = outlink->src;
- AVFilterLink *inlink = ctx->inputs[0];
- outlink->w = inlink->w * 2 ;
- outlink->h = inlink->h * 2 ;
- return 0;
- }
- static int query_formats(AVFilterContext *ctx)
- {
- static const enum AVPixelFormat pix_fmts[] = {
- AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,AV_PIX_FMT_NONE,
- };
- ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
- return 0;
- }
- static int filter_frame(AVFilterLink *inlink, AVFrame *in)
- {
- AVFilterContext *ctx = inlink->dst;
- AVFilterLink *outlink = ctx->outputs[0];
- int i,j;
- xBRContext *xBR = ctx->priv;
- printf("declaring xBR\n");
- const uint32_t *r2y = xBR->rgbtoyuv;
- AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
- if (!out) {
- av_frame_free(&in);
- return AVERROR(ENOMEM);
- }
- av_frame_copy_props(out, in);
- for(i=0;i<inlink->w;i++)
- for(j=0;j<inlink->h;j++)
- apply_edge_detection_rules(in,out,i,j,r2y);
- out->width = outlink->w;
- out->height = outlink->h;
- av_frame_free(&in);
- return ff_filter_frame(outlink, out);
- }
- static int init(AVFilterContext *ctx)
- {
- xBRContext *xbr = ctx->priv;
- printf("init-entering\n");
- uint32_t c;
- int bg, rg, g;
- for (bg=-255; bg<256; bg++) {
- for (rg=-255; rg<256; rg++) {
- const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
- const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
- int startg = FFMAX3(-bg, -rg, 0);
- int endg = FFMIN3(255-bg, 255-rg, 255);
- uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
- c = bg + (rg<<16) + 0x010101 * startg;
- for (g = startg; g <= endg; g++) {
- printf("Value of c :");
- printf("%" PRIu32 "\n",c);
- xbr->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v;
- c+= 0x010101;
- }
- }
- }
- printf("init-leaving\n");
- return 0;
- }
- static const AVFilterPad xbr_inputs[] = {
- {
- .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .filter_frame = filter_frame,
- },
- { NULL }
- };
- static const AVFilterPad xbr_outputs[] = {
- {
- .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .config_props = config_output,
- },
- { NULL }
- };
- AVFilter ff_vf_xbr = {
- .name = "xbr",
- .description = NULL_IF_CONFIG_SMALL("Scale the input by 2 using xbr algorithm."),
- .inputs = xbr_inputs,
- .outputs = xbr_outputs,
- .query_formats = query_formats,
- .init = init,
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement