• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavfilter/libmpcodecs/vf_screenshot.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of MPlayer.
00003  *
00004  * MPlayer is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * MPlayer is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License along
00015  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #include "config.h"
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #if HAVE_MALLOC_H
00024 #include <malloc.h>
00025 #endif
00026 #include <string.h>
00027 #include <inttypes.h>
00028 
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <unistd.h>
00032 
00033 #include "mp_msg.h"
00034 
00035 #include "img_format.h"
00036 #include "mp_image.h"
00037 #include "vf.h"
00038 #include "vf_scale.h"
00039 
00040 #include "libswscale/swscale.h"
00041 #include "libavcodec/avcodec.h"
00042 
00043 struct vf_priv_s {
00044     int frameno;
00045     char fname[102];
00050     int shot, store_slices;
00051     int dw, dh, stride;
00052     uint8_t *buffer;
00053     struct SwsContext *ctx;
00054     AVCodecContext *avctx;
00055     uint8_t *outbuffer;
00056     int outbuffer_size;
00057 };
00058 
00059 //===========================================================================//
00060 
00061 static int config(struct vf_instance *vf,
00062                   int width, int height, int d_width, int d_height,
00063                   unsigned int flags, unsigned int outfmt)
00064 {
00065     vf->priv->ctx=sws_getContextFromCmdLine(width, height, outfmt,
00066                                  d_width, d_height, IMGFMT_RGB24);
00067 
00068     vf->priv->outbuffer_size = d_width * d_height * 3 * 2;
00069     vf->priv->outbuffer = realloc(vf->priv->outbuffer, vf->priv->outbuffer_size);
00070     vf->priv->avctx->width = d_width;
00071     vf->priv->avctx->height = d_height;
00072     vf->priv->avctx->pix_fmt = PIX_FMT_RGB24;
00073     vf->priv->avctx->compression_level = 0;
00074     vf->priv->dw = d_width;
00075     vf->priv->dh = d_height;
00076     vf->priv->stride = (3*vf->priv->dw+15)&~15;
00077 
00078     free(vf->priv->buffer); // probably reconfigured
00079     vf->priv->buffer = NULL;
00080 
00081     return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00082 }
00083 
00084 static void write_png(struct vf_priv_s *priv)
00085 {
00086     char *fname = priv->fname;
00087     FILE * fp;
00088     AVFrame pic;
00089     int size;
00090 
00091     fp = fopen (fname, "wb");
00092     if (fp == NULL) {
00093         mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname);
00094         return;
00095     }
00096 
00097     pic.data[0] = priv->buffer;
00098     pic.linesize[0] = priv->stride;
00099     size = avcodec_encode_video(priv->avctx, priv->outbuffer, priv->outbuffer_size, &pic);
00100     if (size > 0)
00101         fwrite(priv->outbuffer, size, 1, fp);
00102 
00103     fclose (fp);
00104 }
00105 
00106 static int fexists(char *fname)
00107 {
00108     struct stat dummy;
00109     if (stat(fname, &dummy) == 0) return 1;
00110     else return 0;
00111 }
00112 
00113 static void gen_fname(struct vf_priv_s* priv)
00114 {
00115     do {
00116         snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno);
00117     } while (fexists(priv->fname) && priv->frameno < 100000);
00118     if (fexists(priv->fname)) {
00119         priv->fname[0] = '\0';
00120         return;
00121     }
00122 
00123     mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname);
00124 
00125 }
00126 
00127 static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi)
00128 {
00129     uint8_t *dst[MP_MAX_PLANES] = {NULL};
00130     int dst_stride[MP_MAX_PLANES] = {0};
00131 
00132     dst_stride[0] = priv->stride;
00133     if (!priv->buffer)
00134         priv->buffer = av_malloc(dst_stride[0]*priv->dh);
00135 
00136     dst[0] = priv->buffer;
00137     sws_scale(priv->ctx, mpi->planes, mpi->stride, 0, priv->dh, dst, dst_stride);
00138 }
00139 
00140 static void start_slice(struct vf_instance *vf, mp_image_t *mpi)
00141 {
00142     vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
00143         mpi->type, mpi->flags, mpi->width, mpi->height);
00144     if (vf->priv->shot) {
00145         vf->priv->store_slices = 1;
00146         if (!vf->priv->buffer)
00147             vf->priv->buffer = av_malloc(vf->priv->stride*vf->priv->dh);
00148     }
00149 
00150 }
00151 
00152 static void draw_slice(struct vf_instance *vf, unsigned char** src,
00153                        int* stride, int w,int h, int x, int y)
00154 {
00155     if (vf->priv->store_slices) {
00156         uint8_t *dst[MP_MAX_PLANES] = {NULL};
00157         int dst_stride[MP_MAX_PLANES] = {0};
00158         dst_stride[0] = vf->priv->stride;
00159         dst[0] = vf->priv->buffer;
00160         sws_scale(vf->priv->ctx, src, stride, y, h, dst, dst_stride);
00161     }
00162     vf_next_draw_slice(vf,src,stride,w,h,x,y);
00163 }
00164 
00165 static void get_image(struct vf_instance *vf, mp_image_t *mpi)
00166 {
00167     // FIXME: should vf.c really call get_image when using slices??
00168     if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
00169       return;
00170     vf->dmpi= vf_get_image(vf->next, mpi->imgfmt,
00171                            mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height);
00172 
00173     mpi->planes[0]=vf->dmpi->planes[0];
00174     mpi->stride[0]=vf->dmpi->stride[0];
00175     if(mpi->flags&MP_IMGFLAG_PLANAR){
00176         mpi->planes[1]=vf->dmpi->planes[1];
00177         mpi->planes[2]=vf->dmpi->planes[2];
00178         mpi->stride[1]=vf->dmpi->stride[1];
00179         mpi->stride[2]=vf->dmpi->stride[2];
00180     }
00181     mpi->width=vf->dmpi->width;
00182 
00183     mpi->flags|=MP_IMGFLAG_DIRECT;
00184 
00185     mpi->priv=(void*)vf->dmpi;
00186 }
00187 
00188 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
00189 {
00190     mp_image_t *dmpi = (mp_image_t *)mpi->priv;
00191 
00192     if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
00193       dmpi = vf->dmpi;
00194     else
00195     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
00196         dmpi=vf_get_image(vf->next,mpi->imgfmt,
00197                                     MP_IMGTYPE_EXPORT, 0,
00198                                     mpi->width, mpi->height);
00199         vf_clone_mpi_attributes(dmpi, mpi);
00200         dmpi->planes[0]=mpi->planes[0];
00201         dmpi->planes[1]=mpi->planes[1];
00202         dmpi->planes[2]=mpi->planes[2];
00203         dmpi->stride[0]=mpi->stride[0];
00204         dmpi->stride[1]=mpi->stride[1];
00205         dmpi->stride[2]=mpi->stride[2];
00206         dmpi->width=mpi->width;
00207         dmpi->height=mpi->height;
00208     }
00209 
00210     if(vf->priv->shot) {
00211         if (vf->priv->shot==1)
00212             vf->priv->shot=0;
00213         gen_fname(vf->priv);
00214         if (vf->priv->fname[0]) {
00215             if (!vf->priv->store_slices)
00216               scale_image(vf->priv, dmpi);
00217             write_png(vf->priv);
00218         }
00219         vf->priv->store_slices = 0;
00220     }
00221 
00222     return vf_next_put_image(vf, dmpi, pts);
00223 }
00224 
00225 static int control (vf_instance_t *vf, int request, void *data)
00226 {
00231     if(request==VFCTRL_SCREENSHOT) {
00232         if (data && *(int*)data) { // repeated screenshot mode
00233             if (vf->priv->shot==2)
00234                 vf->priv->shot=0;
00235             else
00236                 vf->priv->shot=2;
00237         } else { // single screenshot
00238             if (!vf->priv->shot)
00239                 vf->priv->shot=1;
00240         }
00241         return CONTROL_TRUE;
00242     }
00243     return vf_next_control (vf, request, data);
00244 }
00245 
00246 
00247 //===========================================================================//
00248 
00249 static int query_format(struct vf_instance *vf, unsigned int fmt)
00250 {
00251     switch(fmt){
00252     case IMGFMT_YV12:
00253     case IMGFMT_I420:
00254     case IMGFMT_IYUV:
00255     case IMGFMT_UYVY:
00256     case IMGFMT_YUY2:
00257     case IMGFMT_BGR32:
00258     case IMGFMT_BGR24:
00259     case IMGFMT_BGR16:
00260     case IMGFMT_BGR15:
00261     case IMGFMT_BGR12:
00262     case IMGFMT_RGB32:
00263     case IMGFMT_RGB24:
00264     case IMGFMT_Y800:
00265     case IMGFMT_Y8:
00266     case IMGFMT_YVU9:
00267     case IMGFMT_IF09:
00268     case IMGFMT_444P:
00269     case IMGFMT_422P:
00270     case IMGFMT_411P:
00271         return vf_next_query_format(vf, fmt);
00272     }
00273     return 0;
00274 }
00275 
00276 static void uninit(vf_instance_t *vf)
00277 {
00278     avcodec_close(vf->priv->avctx);
00279     av_freep(&vf->priv->avctx);
00280     if(vf->priv->ctx) sws_freeContext(vf->priv->ctx);
00281     av_free(vf->priv->buffer);
00282     free(vf->priv->outbuffer);
00283     free(vf->priv);
00284 }
00285 
00286 static int vf_open(vf_instance_t *vf, char *args)
00287 {
00288     vf->config=config;
00289     vf->control=control;
00290     vf->put_image=put_image;
00291     vf->query_format=query_format;
00292     vf->start_slice=start_slice;
00293     vf->draw_slice=draw_slice;
00294     vf->get_image=get_image;
00295     vf->uninit=uninit;
00296     vf->priv=malloc(sizeof(struct vf_priv_s));
00297     vf->priv->frameno=0;
00298     vf->priv->shot=0;
00299     vf->priv->store_slices=0;
00300     vf->priv->buffer=0;
00301     vf->priv->outbuffer=0;
00302     vf->priv->ctx=0;
00303     vf->priv->avctx = avcodec_alloc_context();
00304     avcodec_register_all();
00305     if (avcodec_open(vf->priv->avctx, avcodec_find_encoder(CODEC_ID_PNG))) {
00306         mp_msg(MSGT_VFILTER, MSGL_FATAL, "Could not open libavcodec PNG encoder\n");
00307         return 0;
00308     }
00309     return 1;
00310 }
00311 
00312 
00313 const vf_info_t vf_info_screenshot = {
00314     "screenshot to file",
00315     "screenshot",
00316     "A'rpi, Jindrich Makovicka",
00317     "",
00318     vf_open,
00319     NULL
00320 };
00321 
00322 //===========================================================================//

Generated on Wed Apr 11 2012 07:31:36 for FFmpeg by  doxygen 1.7.1