vf_delogo.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright (C) 2002 Jindrich Makovicka <makovick@gmail.com>
  3. *
  4. * This file is part of MPlayer.
  5. *
  6. * MPlayer is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * MPlayer 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
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with MPlayer; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. */
  20. /* A very simple tv station logo remover */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <inttypes.h>
  25. #include <math.h>
  26. #include "mp_msg.h"
  27. #include "cpudetect.h"
  28. #include "img_format.h"
  29. #include "mp_image.h"
  30. #include "vf.h"
  31. #include "libvo/fastmemcpy.h"
  32. //===========================================================================//
  33. struct vf_priv_s {
  34. unsigned int outfmt;
  35. int xoff, yoff, lw, lh, band, show;
  36. };
  37. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  38. #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  39. static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height,
  40. int logo_x, int logo_y, int logo_w, int logo_h, int band, int show, int direct) {
  41. int y, x;
  42. int interp, dist;
  43. uint8_t *xdst, *xsrc;
  44. uint8_t *topleft, *botleft, *topright;
  45. int xclipl, xclipr, yclipt, yclipb;
  46. int logo_x1, logo_x2, logo_y1, logo_y2;
  47. xclipl = MAX(-logo_x, 0);
  48. xclipr = MAX(logo_x+logo_w-width, 0);
  49. yclipt = MAX(-logo_y, 0);
  50. yclipb = MAX(logo_y+logo_h-height, 0);
  51. logo_x1 = logo_x + xclipl;
  52. logo_x2 = logo_x + logo_w - xclipr;
  53. logo_y1 = logo_y + yclipt;
  54. logo_y2 = logo_y + logo_h - yclipb;
  55. topleft = src+logo_y1*srcStride+logo_x1;
  56. topright = src+logo_y1*srcStride+logo_x2-1;
  57. botleft = src+(logo_y2-1)*srcStride+logo_x1;
  58. if (!direct) memcpy_pic(dst, src, width, height, dstStride, srcStride);
  59. dst += (logo_y1+1)*dstStride;
  60. src += (logo_y1+1)*srcStride;
  61. for(y = logo_y1+1; y < logo_y2-1; y++)
  62. {
  63. for (x = logo_x1+1, xdst = dst+logo_x1+1, xsrc = src+logo_x1+1; x < logo_x2-1; x++, xdst++, xsrc++) {
  64. interp = ((topleft[srcStride*(y-logo_y-yclipt)]
  65. + topleft[srcStride*(y-logo_y-1-yclipt)]
  66. + topleft[srcStride*(y-logo_y+1-yclipt)])*(logo_w-(x-logo_x))/logo_w
  67. + (topright[srcStride*(y-logo_y-yclipt)]
  68. + topright[srcStride*(y-logo_y-1-yclipt)]
  69. + topright[srcStride*(y-logo_y+1-yclipt)])*(x-logo_x)/logo_w
  70. + (topleft[x-logo_x-xclipl]
  71. + topleft[x-logo_x-1-xclipl]
  72. + topleft[x-logo_x+1-xclipl])*(logo_h-(y-logo_y))/logo_h
  73. + (botleft[x-logo_x-xclipl]
  74. + botleft[x-logo_x-1-xclipl]
  75. + botleft[x-logo_x+1-xclipl])*(y-logo_y)/logo_h
  76. )/6;
  77. /* interp = (topleft[srcStride*(y-logo_y)]*(logo_w-(x-logo_x))/logo_w
  78. + topright[srcStride*(y-logo_y)]*(x-logo_x)/logo_w
  79. + topleft[x-logo_x]*(logo_h-(y-logo_y))/logo_h
  80. + botleft[x-logo_x]*(y-logo_y)/logo_h
  81. )/2;*/
  82. if (y >= logo_y+band && y < logo_y+logo_h-band && x >= logo_x+band && x < logo_x+logo_w-band) {
  83. *xdst = interp;
  84. } else {
  85. dist = 0;
  86. if (x < logo_x+band) dist = MAX(dist, logo_x-x+band);
  87. else if (x >= logo_x+logo_w-band) dist = MAX(dist, x-(logo_x+logo_w-1-band));
  88. if (y < logo_y+band) dist = MAX(dist, logo_y-y+band);
  89. else if (y >= logo_y+logo_h-band) dist = MAX(dist, y-(logo_y+logo_h-1-band));
  90. *xdst = (*xsrc*dist + interp*(band-dist))/band;
  91. if (show && (dist == band-1)) *xdst = 0;
  92. }
  93. }
  94. dst+= dstStride;
  95. src+= srcStride;
  96. }
  97. }
  98. static int config(struct vf_instance *vf,
  99. int width, int height, int d_width, int d_height,
  100. unsigned int flags, unsigned int outfmt){
  101. return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
  102. }
  103. static void get_image(struct vf_instance *vf, mp_image_t *mpi){
  104. if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
  105. if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
  106. // ok, we can do pp in-place (or pp disabled):
  107. vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
  108. mpi->type, mpi->flags, mpi->w, mpi->h);
  109. mpi->planes[0]=vf->dmpi->planes[0];
  110. mpi->stride[0]=vf->dmpi->stride[0];
  111. mpi->width=vf->dmpi->width;
  112. if(mpi->flags&MP_IMGFLAG_PLANAR){
  113. mpi->planes[1]=vf->dmpi->planes[1];
  114. mpi->planes[2]=vf->dmpi->planes[2];
  115. mpi->stride[1]=vf->dmpi->stride[1];
  116. mpi->stride[2]=vf->dmpi->stride[2];
  117. }
  118. mpi->flags|=MP_IMGFLAG_DIRECT;
  119. }
  120. static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
  121. mp_image_t *dmpi;
  122. if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
  123. // no DR, so get a new image! hope we'll get DR buffer:
  124. vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
  125. MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
  126. mpi->w,mpi->h);
  127. }
  128. dmpi= vf->dmpi;
  129. delogo(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h,
  130. vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show,
  131. mpi->flags&MP_IMGFLAG_DIRECT);
  132. delogo(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2,
  133. vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
  134. mpi->flags&MP_IMGFLAG_DIRECT);
  135. delogo(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2,
  136. vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
  137. mpi->flags&MP_IMGFLAG_DIRECT);
  138. vf_clone_mpi_attributes(dmpi, mpi);
  139. return vf_next_put_image(vf,dmpi, pts);
  140. }
  141. static void uninit(struct vf_instance *vf){
  142. if(!vf->priv) return;
  143. free(vf->priv);
  144. vf->priv=NULL;
  145. }
  146. //===========================================================================//
  147. static int query_format(struct vf_instance *vf, unsigned int fmt){
  148. switch(fmt)
  149. {
  150. case IMGFMT_YV12:
  151. case IMGFMT_I420:
  152. case IMGFMT_IYUV:
  153. return vf_next_query_format(vf,vf->priv->outfmt);
  154. }
  155. return 0;
  156. }
  157. static const unsigned int fmt_list[]={
  158. IMGFMT_YV12,
  159. IMGFMT_I420,
  160. IMGFMT_IYUV,
  161. 0
  162. };
  163. static int vf_open(vf_instance_t *vf, char *args){
  164. int res=0;
  165. vf->config=config;
  166. vf->put_image=put_image;
  167. vf->get_image=get_image;
  168. vf->query_format=query_format;
  169. vf->uninit=uninit;
  170. vf->priv=malloc(sizeof(struct vf_priv_s));
  171. memset(vf->priv, 0, sizeof(struct vf_priv_s));
  172. if (args) res = sscanf(args, "%d:%d:%d:%d:%d",
  173. &vf->priv->xoff, &vf->priv->yoff,
  174. &vf->priv->lw, &vf->priv->lh,
  175. &vf->priv->band);
  176. if (res != 5) {
  177. mp_msg(MSGT_VFILTER, MSGL_ERR, "deLogo: syntax is \"delogo=xoff:yoff:width:height:band\"\n");
  178. uninit(vf);
  179. return 0;
  180. }
  181. mp_msg(MSGT_VFILTER, MSGL_V, "delogo: %d x %d, %d x %d, band = %d\n",
  182. vf->priv->xoff, vf->priv->yoff,
  183. vf->priv->lw, vf->priv->lh,
  184. vf->priv->band);
  185. vf->priv->show = 0;
  186. if (vf->priv->band < 0) {
  187. vf->priv->band = 4;
  188. vf->priv->show = 1;
  189. }
  190. vf->priv->lw += vf->priv->band*2;
  191. vf->priv->lh += vf->priv->band*2;
  192. vf->priv->xoff -= vf->priv->band;
  193. vf->priv->yoff -= vf->priv->band;
  194. // check csp:
  195. vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
  196. if(!vf->priv->outfmt)
  197. {
  198. uninit(vf);
  199. return 0; // no csp match :(
  200. }
  201. return 1;
  202. }
  203. const vf_info_t vf_info_delogo = {
  204. "simple logo remover",
  205. "delogo",
  206. "Jindrich Makovicka, Alex Beregszaszi",
  207. "",
  208. vf_open,
  209. };
  210. //===========================================================================//