1 /* ------------------------------------------------------------------------- */
2 
3 /*
4  * md5sum video output driver
5  *
6  * Copyright (C) 2004, 2005, 2006 Ivo van Poorten
7  *
8  * This file is part of MPlayer.
9  *
10  * MPlayer is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * MPlayer is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 /* ------------------------------------------------------------------------- */
26 
27 /* Global Includes */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 
34 /* ------------------------------------------------------------------------- */
35 
36 /* Local Includes */
37 
38 #include "config.h"
39 #include "subopt-helper.h"
40 #include "mp_msg.h"
41 #include "video_out.h"
42 #define NO_DRAW_FRAME
43 #define NO_DRAW_SLICE
44 #include "video_out_internal.h"
45 #include "mp_core.h"			/* for exit_player() */
46 #include "help_mp.h"
47 #include "libavutil/md5.h"
48 
49 /* ------------------------------------------------------------------------- */
50 
51 /* Info */
52 
53 static const vo_info_t info=
54 {
55 	"md5sum of each frame",
56 	"md5sum",
57 	"Ivo van Poorten (ivop@euronet.nl)",
58 	""
59 };
60 
61 const LIBVO_EXTERN (md5sum)
62 
63 /* ------------------------------------------------------------------------- */
64 
65 /* Global Variables */
66 
67 char *md5sum_outfile = NULL;
68 
69 struct AVMD5 *md5_context;
70 FILE *md5sum_fd;
71 int framenum = 0;
72 
73 /* ------------------------------------------------------------------------- */
74 
75 /** \brief An error occured while writing to a file.
76  *
77  * The program failed to write data to a file.
78  * It displays a message and exits the player.
79  *
80  * \return nothing It does not return.
81  */
82 
md5sum_write_error(void)83 static void md5sum_write_error(void) {
84     mp_msg(MSGT_VO, MSGL_ERR, MSGTR_ErrorWritingFile, info.short_name);
85     exit_player(EXIT_ERROR);
86 }
87 
88 /* ------------------------------------------------------------------------- */
89 
90 /** \brief Pre-initialisation.
91  *
92  * This function is called before initialising the video output driver. It
93  * parses all suboptions and sets variables accordingly. If an error occurs
94  * (like an option being out of range, not having any value or an unknown
95  * option is stumbled upon) the player will exit. It also sets default
96  * values if necessary.
97  *
98  * \param arg   A string containing all the suboptions passed to the video
99  *              output driver.
100  *
101  * \return 0    All went well.
102  */
103 
preinit(const char * arg)104 static int preinit(const char *arg)
105 {
106     const opt_t subopts[] = {
107         {"outfile",     OPT_ARG_MSTRZ,    &md5sum_outfile,   NULL},
108         {NULL, 0, NULL, NULL}
109     };
110 
111     mp_msg(MSGT_VO, MSGL_V, "%s: %s\n", info.short_name,
112            "Parsing suboptions.");
113 
114     md5sum_outfile = strdup("md5sums");
115     if (subopt_parse(arg, subopts) != 0) {
116         return -1;
117     }
118 
119     mp_msg(MSGT_VO, MSGL_V, "%s: outfile --> %s\n", info.short_name,
120                                                             md5sum_outfile);
121 
122     mp_msg(MSGT_VO, MSGL_V, "%s: %s\n", info.short_name,
123            "Suboptions parsed OK.");
124     return 0;
125 }
126 
127 /* ------------------------------------------------------------------------- */
128 
129 /** \brief Configure the video output driver.
130  *
131  * This functions configures the video output driver. It opens the output
132  * file to which this driver will write all the MD5 sums. If something
133  * goes wrong, the player will exit.
134  *
135  *  \return 0             All went well.
136  */
137 
config(uint32_t width,uint32_t height,uint32_t d_width,uint32_t d_height,uint32_t flags,char * title,uint32_t format)138 static int config(uint32_t width, uint32_t height, uint32_t d_width,
139                        uint32_t d_height, uint32_t flags, char *title,
140                        uint32_t format)
141 {
142     if (vo_config_count > 0 ) { /* Already configured */
143         return 0;
144     }
145 
146     if (strcmp(md5sum_outfile, "-") == 0)
147         md5sum_fd = stdout;
148     else
149     if ( (md5sum_fd = fopen(md5sum_outfile, "w") ) == NULL ) {
150         mp_msg(MSGT_VO, MSGL_ERR, "\n%s: %s\n", info.short_name,
151                 MSGTR_VO_CantCreateFile);
152         mp_msg(MSGT_VO, MSGL_ERR, "%s: %s: %s\n",
153                 info.short_name, MSGTR_VO_GenericError, strerror(errno) );
154         exit_player(EXIT_ERROR);
155     }
156 
157     md5_context = av_md5_alloc();
158 
159     return 0;
160 }
161 
162 /* ------------------------------------------------------------------------- */
163 
164 /** \brief Write MD5 sum to output file.
165  *
166  * This function writes an ASCII representation of a 16-byte hexadecimal
167  * MD5 sum to our output file. The file descriptor is a global variable.
168  *
169  * \param md5sum Sixteen bytes that represent an MD5 sum.
170  *
171  * \return None     The player will exit if a write error occurs.
172  */
173 
md5sum_output_sum(unsigned char * md5sum)174 static void md5sum_output_sum(unsigned char *md5sum) {
175     int i;
176 
177     for(i=0; i<16; i++) {
178         if ( fprintf(md5sum_fd, "%02x", md5sum[i]) < 0 ) md5sum_write_error();
179     }
180     if ( fprintf(md5sum_fd, " frame%08d\n", framenum) < 0 )
181         md5sum_write_error();
182 
183     framenum++;
184 }
185 
186 /* ------------------------------------------------------------------------- */
187 
draw_image(mp_image_t * mpi)188 static uint32_t draw_image(mp_image_t *mpi)
189 {
190     unsigned char md5sum[16];
191     uint32_t w = mpi->w;
192     uint32_t h = mpi->h;
193     uint8_t *rgbimage = mpi->planes[0];
194     uint8_t *planeY = mpi->planes[0];
195     uint8_t *planeU = mpi->planes[1];
196     uint8_t *planeV = mpi->planes[2];
197     uint32_t strideY = mpi->stride[0];
198     uint32_t strideU = mpi->stride[1];
199     uint32_t strideV = mpi->stride[2];
200 
201     unsigned int i;
202 
203     if (mpi->flags & MP_IMGFLAG_PLANAR) { /* Planar */
204         if (mpi->flags & MP_IMGFLAG_YUV) { /* Planar YUV */
205             av_md5_init(md5_context);
206             for (i=0; i<h; i++) {
207                 av_md5_update(md5_context, planeY + i * strideY, w);
208             }
209             w = w / 2;
210             h = h / 2;
211             for (i=0; i<h; i++) {
212                 av_md5_update(md5_context, planeU + i * strideU, w);
213             }
214             for (i=0; i<h; i++) {
215                 av_md5_update(md5_context, planeV + i * strideV, w);
216             }
217             av_md5_final(md5_context, md5sum);
218             md5sum_output_sum(md5sum);
219             return VO_TRUE;
220         } else { /* Planar RGB */
221             return VO_FALSE;
222         }
223     } else { /* Packed */
224         if (mpi->flags & MP_IMGFLAG_YUV) { /* Packed YUV */
225 
226             return VO_FALSE;
227         } else { /* Packed RGB */
228             av_md5_sum(md5sum, rgbimage, mpi->w * (mpi->bpp >> 3) * mpi->h);
229             md5sum_output_sum(md5sum);
230             return VO_TRUE;
231         }
232     }
233 
234     return VO_FALSE;
235 }
236 
237 /* ------------------------------------------------------------------------- */
238 
query_format(uint32_t format)239 static int query_format(uint32_t format)
240 {
241     switch (format) {
242         case IMGFMT_RGB24:
243         case IMGFMT_YV12:
244             return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VOCAP_NOSLICES;
245         default:
246             return 0;
247     }
248 }
249 
250 /* ------------------------------------------------------------------------- */
251 
control(uint32_t request,void * data)252 static int control(uint32_t request, void *data)
253 {
254     switch (request) {
255         case VOCTRL_QUERY_FORMAT:
256             return query_format(*((uint32_t*)data));
257         case VOCTRL_DRAW_IMAGE:
258             return draw_image(data);
259     }
260     return VO_NOTIMPL;
261 }
262 
263 /* ------------------------------------------------------------------------- */
264 
uninit(void)265 static void uninit(void)
266 {
267     free(md5sum_outfile);
268     md5sum_outfile = NULL;
269     if (md5sum_fd && md5sum_fd != stdout) fclose(md5sum_fd);
270     av_freep(&md5_context);
271 }
272 
273 /* ------------------------------------------------------------------------- */
274 
check_events(void)275 static void check_events(void)
276 {
277 }
278 
279 /* ------------------------------------------------------------------------- */
280 
draw_osd(void)281 static void draw_osd(void)
282 {
283 }
284 
285 /* ------------------------------------------------------------------------- */
286 
flip_page(void)287 static void flip_page (void)
288 {
289 }
290