[MPlayer-dev-eng] [patch][rfc] screenshot

Arpi arpi at mplayerhq.hu
Mon Jul 4 04:10:17 CEST 2005


Hi,

I needed a screenshot feature, to print frames from a video...
so i implemented it. actually first i did RTFA, and found an
ugly hack, refused on this list. i tried to do the right way,
although i had no time to do whole clean implementation, with
support for all colorspaces, filename as parameter etc...
do it if you want, and commit if you want. here is it:
(try with -vop scale,screenshot,scale  and press 's' while playing
and gui disabled, otherwise 's' is mapped for gui's stop...)

note: mplayer already has half support for screenshot:
's' was mapped to MP_CMD_SCREENSHOT, and this command was
mapped to VOCTRL_SCREENSHOT, but it was not implemented
in any vo driver... anyway it should be in vf, not vo,
so i done it in a filter... it has fallback to vo, if no
filter responding to this command.


vf_screenshot.c:
---------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include <png.h>

#include "../config.h"
#include "../mp_msg.h"

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"

#include "../libvo/fastmemcpy.h"
#include "../postproc/rgb2rgb.h"

struct vf_priv_s {
    int frameno;
    int shot;
};

//===========================================================================//

static int config(struct vf_instance_s* vf,
        int width, int height, int d_width, int d_height,
	unsigned int flags, unsigned int outfmt){
    return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
}


static int put_image(struct vf_instance_s* vf, mp_image_t *mpi){
    mp_image_t *dmpi;
    int bpp=mpi->bpp/8;
    int w,h,x,y,shrink_by;

    dmpi=vf_get_image(vf->next,mpi->imgfmt,
	MP_IMGTYPE_EXPORT, 0,
	mpi->w, mpi->h);

    dmpi->planes[0]=mpi->planes[0];
    dmpi->planes[1]=mpi->planes[1];
    dmpi->planes[2]=mpi->planes[2];
    dmpi->stride[0]=mpi->stride[0];
    dmpi->stride[1]=mpi->stride[1];
    dmpi->stride[2]=mpi->stride[2];
    dmpi->width=mpi->width;
    dmpi->height=mpi->height;

  if(vf->priv->shot){
    vf->priv->shot=0;

// ------------------------ write to PNG --------------------------
    char fname[102];
    FILE * fp;
    png_structp png_ptr;
    png_infop info_ptr;
    snprintf (fname, 100, "shot%04d.png", ++vf->priv->frameno);
    mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",fname);

    png_ptr = png_create_write_struct
       (PNG_LIBPNG_VER_STRING, NULL,
        NULL, NULL);
    info_ptr = png_create_info_struct(png_ptr);
    fp=NULL;

    if (setjmp(png_ptr->jmpbuf)) {
//	if(verbose > 1) printf("PNG Internal error!\n");    
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
        return 0;
    }

    fp = fopen (fname, "wb");
    if (fp == NULL) {
	printf("\nPNG Error opening %s for writing!\n", fname);
       	return 0;
    }
    
    png_init_io(png_ptr, fp);
    png_set_compression_level(png_ptr, 0);

    png_set_IHDR(png_ptr, info_ptr, mpi->width, mpi->height,
//       8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
       8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
       PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    png_write_info(png_ptr, info_ptr);
    
    png_set_bgr(png_ptr);

    png_byte *row_pointers[mpi->height];
    int k;
    for ( k = 0; k <mpi->height; k++ ){
	unsigned char* s=mpi->planes[0] + mpi->stride[0]*k;
	row_pointers[k] = s;
    }

    png_write_image(png_ptr, row_pointers);
    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    
    fclose (fp);

// -------------------------------------------------------------
  }

    return vf_next_put_image(vf,dmpi);
}

int control (vf_instance_t *vf, int request, void *data){
    if(request==VFCTRL_SCREENSHOT) {
	vf->priv->shot=1;
        return CONTROL_TRUE;
    }
    return vf_next_control (vf, request, data);
}


//===========================================================================//

static int query_format(struct vf_instance_s* vf, unsigned int fmt){
    switch(fmt){
	case IMGFMT_BGR24:
//	case IMGFMT_RGB24:
//	case IMGFMT_BGR32:
//	case IMGFMT_RGB32:
		return vf_next_query_format(vf, fmt);
    }
    return 0;
}

static int open(vf_instance_t *vf, char* args){
    vf->config=config;
    vf->control=control;
    vf->put_image=put_image;
    vf->query_format=query_format;
    vf->priv=malloc(sizeof(struct vf_priv_s));
    vf->priv->frameno=0;
    vf->priv->shot=0;
    return 1;
}

vf_info_t vf_info_screenshot = {
    "screenshot to file",
    "screenshot",
    "A'rpi",
    "",
    open,
    NULL
};

//===========================================================================//



and the patch:


? libmpcodecs/vf_screenshot.c
Index: mplayer.c
===================================================================
RCS file: /cvsroot/mplayer/main/mplayer.c,v
retrieving revision 1.854
diff -u -r1.854 mplayer.c
--- mplayer.c	3 Jul 2005 10:09:09 -0000	1.854
+++ mplayer.c	4 Jul 2005 02:02:42 -0000
@@ -3566,7 +3566,11 @@
       }    
       break;
     case MP_CMD_SCREENSHOT :
-      if(vo_config_count) video_out->control(VOCTRL_SCREENSHOT, NULL);
+      if(vo_config_count){
+	mp_msg(MSGT_CPLAYER,MSGL_INFO,"sending VFCTRL_SCREENSHOT!\n");
+	if(CONTROL_OK!=((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SCREENSHOT, 0))
+	video_out->control(VOCTRL_SCREENSHOT, NULL);
+      }
       break;
     case MP_CMD_VF_CHANGE_RECTANGLE:
 	set_rectangle(sh_video, cmd->args[0].v.i, cmd->args[1].v.i);
Index: libmpcodecs/Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/Makefile,v
retrieving revision 1.144
diff -u -r1.144 Makefile
--- libmpcodecs/Makefile	19 Jun 2005 22:52:55 -0000	1.144
+++ libmpcodecs/Makefile	4 Jul 2005 02:02:43 -0000
@@ -112,6 +112,7 @@
              vf_rotate.c \
              vf_sab.c \
              vf_scale.c \
+	     vf_screenshot.c \
              vf_smartblur.c \
              vf_softpulldown.c \
              vf_softskip.c \
Index: libmpcodecs/vf.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/vf.c,v
retrieving revision 1.115
diff -u -r1.115 vf.c
--- libmpcodecs/vf.c	8 Jun 2005 15:29:26 -0000	1.115
+++ libmpcodecs/vf.c	4 Jul 2005 02:02:43 -0000
@@ -97,6 +97,7 @@
 extern vf_info_t vf_info_divtc;
 extern vf_info_t vf_info_harddup;
 extern vf_info_t vf_info_softskip;
+extern vf_info_t vf_info_screenshot;
 
 // list of available filters:
 static vf_info_t* filter_list[]={
@@ -183,6 +184,7 @@
     &vf_info_divtc,
     &vf_info_harddup,
     &vf_info_softskip,
+    &vf_info_screenshot,
     NULL
 };
 
Index: libmpcodecs/vf.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/vf.h,v
retrieving revision 1.27
diff -u -r1.27 vf.h
--- libmpcodecs/vf.h	1 Mar 2005 20:21:58 -0000	1.27
+++ libmpcodecs/vf.h	4 Jul 2005 02:02:43 -0000
@@ -74,6 +74,7 @@
 #define VFCTRL_DUPLICATE_FRAME 11 /* For encoding - encode zero-change frame */
 #define VFCTRL_SKIP_NEXT_FRAME 12 /* For encoding - drop the next frame that passes thru */
 #define VFCTRL_FLUSH_FRAMES    13 /* For encoding - flush delayed frames */
+#define VFCTRL_SCREENSHOT      14
 
 #include "vfcap.h"
 



A'rpi / MPlayer, Astral & ESP-team

--
Girls are like internet domain names, the ones I like are already taken.




More information about the MPlayer-dev-eng mailing list