root/liboggz/trunk/src/tools/oggz-scan.c

Revision 3674, 9.5 kB (checked in by conrad, 5 months ago)

add -? option to all tools, which simply prints out all possible
options, and nothing else (for shell completion).

Line 
1 /*
2    Copyright (C) 2003 Commonwealth Scientific and Industrial Research
3    Organisation (CSIRO) Australia
4
5    Redistribution and use in source and binary forms, with or without
6    modification, are permitted provided that the following conditions
7    are met:
8
9    - Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
12    - Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16    - Neither the name of CSIRO Australia nor the names of its
17    contributors may be used to endorse or promote products derived from
18    this software without specific prior written permission.
19
20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
24    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "config.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #ifndef WIN32
40 #include <strings.h>
41 #endif
42
43 #include <getopt.h>
44 #include <errno.h>
45
46 #ifdef HAVE_INTTYPES_H
47 #  include <inttypes.h>
48 #else
49 #  define PRId64 "I64d"
50 #endif
51
52 #include <oggz/oggz.h>
53 #include "oggz_tools.h"
54
55 /* #define DEBUG */
56
57 #ifdef WIN32                                                                   
58 #define strcasecmp _stricmp
59 #endif
60
61 typedef struct {
62   OggzReadPacket read_packet;
63   int clipcount;
64   int pktssincekey;
65   int granuleshift;
66   int keyframes;
67   int cmml;
68   int html;
69 } OSData;
70
71 static char * progname;
72 static FILE * outfile = NULL;
73
74 #define HTML_HEAD "<html>\n<head>\n<title>OGGZ_SCAN OUTPUT</title>\n</head>\n\n<body>\n<h1>OGGZ_SCAN OUTPUT for %s</h1>\n\n"
75
76 #define HTML_END "<hr/>\n</body>\n</html>"
77
78 #define HTML_CLIP "<p>Clip No %i\tat t=%lf.</p>\n\n"
79
80
81 #define CMML_HEAD "<cmml>\n<stream>\n<import src=\"%s\"/>\n</stream>\n\n<head>\n<title>OGGZ_SCAN OUTPUT for %s</title>\n</head>\n\n"
82
83 #define CMML_END "</cmml>"
84
85 #define CMML_CLIP "<clip id=\"clip-%i\" start=\"%lf\">\n<desc>Enter description.</desc>\n</clip>\n\n"
86
87 static void
88 usage (char * progname)
89 {
90   printf ("Usage: %s [options] filename\n", progname);
91   printf ("Scan an Ogg file and output characteristic landmarks.\n");
92   printf ("\nOutput options\n");
93   printf ("  -o filename, --output filename\n");
94   printf ("                         Specify output filename\n");
95   printf ("  -f format, --format format\n");
96   printf ("                         Specify output format. Supported formats are plain,\n");
97   printf ("                         cmml, and html. (Default: plain)\n");
98   printf ("\nFeature options\n");
99   printf ("  -k, --keyframe         Display timestamps of unforced theora keyframes\n");
100   printf ("\nMiscellaneous options\n");
101   printf ("  -h, --help             Display this help and exit\n");
102   printf ("  -v, --version          Output version information and exit\n");
103   printf ("\n");
104   printf ("Please report bugs to <ogg-dev@xiph.org>\n");
105 }
106
107 static int
108 filter_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
109 {
110   OSData * osdata = (OSData *) user_data;
111   const char * ident;
112
113   /* set scanning callback for keyframe calculation on theora pages only */
114   if (osdata->keyframes && ogg_page_bos ((ogg_page *)og)) {
115     ident = ot_page_identify (oggz, og, NULL);
116     if (ident && (strcasecmp ("theora", ident) == 0)) {
117        oggz_set_read_callback (oggz, serialno, osdata->read_packet, osdata);
118     }
119   }
120
121   return OGGZ_CONTINUE;
122 }
123
124 static int
125 read_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
126 {
127   OSData * osdata = (OSData *) user_data;
128   double time_offset;
129
130   /* calculate granuleshift for theora track */
131   if (osdata->granuleshift == 0) {
132     osdata->granuleshift = 1 << oggz_get_granuleshift (oggz, serialno);
133     osdata->granuleshift--;
134 #ifdef DEBUG
135     fprintf(outfile, "Granuleshift = %d\n", osdata->granuleshift);
136 #endif
137   }
138
139   /* don't do anything on bos page */
140   if (op->b_o_s) {
141     return OGGZ_CONTINUE;
142   }
143
144   /* calculate the keyframes if requested */
145   if (osdata->keyframes) {
146     /* increase number of packets seen since the last intra frame */
147     osdata->pktssincekey++;
148
149     /* does the current packet contain a keyframe? */
150     if(!(op->packet[0] & 0x80) /* data packet */ &&
151        !(op->packet[0] & 0x40) /* intra frame */ ) {
152       ogg_int64_t units;
153
154 #ifdef DEBUG
155       fprintf(outfile, "Keyframe found: packetno=%" PRId64
156               "\t pktssincekey=%d\n", op->packetno, osdata->pktssincekey);
157 #endif
158
159       /* if the keyframe is on the granuleshift position, ignore it */
160       if (osdata->pktssincekey >= osdata->granuleshift) {
161         osdata->pktssincekey=0;
162         return OGGZ_CONTINUE;
163       }
164       osdata->pktssincekey=0;
165
166       /* new shot boundary found: calculate time */
167       units = oggz_tell_units (oggz);
168       if (units == -1) {
169         time_offset = oggz_tell(oggz);
170       } else {
171         time_offset = (double)units / 1000.0;
172       }
173
174       /* output in requested format */
175       if (osdata->html) {
176         fprintf(outfile, HTML_CLIP, osdata->clipcount, time_offset);
177       }
178       if (osdata->cmml) {
179         fprintf(outfile, CMML_CLIP, osdata->clipcount, time_offset);
180       }
181       osdata->clipcount++;
182       if (!osdata->html && !osdata->cmml) {
183         ot_fprint_time (outfile, time_offset);
184         fputc ('\n', outfile);
185       }
186     }
187   }
188
189 #ifdef DEBUG
190   fprintf (outfile, "%ld bytes pktno=%" PRId64 "\n", op->bytes, op->packetno);
191 #endif
192
193   return OGGZ_CONTINUE;
194 }
195
196 int
197 main (int argc, char ** argv)
198 {
199   int show_version = 0;
200   int show_help = 0;
201   int output_cmml = 0;
202   int output_html = 0;
203   int scan_keyframes = 0;
204
205   OSData * osdata = NULL;
206   OGGZ * oggz;
207   char * infilename = NULL, * outfilename = NULL;
208   int i;
209
210   char * optstring = "f:khvo:";
211
212 #ifdef HAVE_GETOPT_LONG
213   static struct option long_options[] = {
214     {"output",   required_argument, 0, 'o'},
215     {"format",   required_argument, 0, 'f'},
216     {"keyframe", no_argument, 0, 'k'},
217     {"help",     no_argument, 0, 'h'},
218     {"version",  no_argument, 0, 'v'},
219     {0,0,0,0}
220   };
221 #endif
222
223   progname = argv[0];
224
225   if (argc < 2) {
226     usage (progname);
227     return (1);
228   }
229
230   if (!strncmp (argv[1], "-?", 2)) {
231 #ifdef HAVE_GETOPT_LONG
232     ot_print_options (long_options, optstring);
233 #else
234     ot_print_short_options (optstring);
235 #endif
236     exit (0);
237   }
238
239   while (1) {
240 #ifdef HAVE_GETOPT_LONG
241     i = getopt_long(argc, argv, optstring, long_options, NULL);
242 #else
243     i = getopt (argc, argv, optstring);
244 #endif
245     if (i == -1) break;
246     if (i == ':') {
247       usage (progname);
248       goto exit_err;
249     }
250
251     switch (i) {
252     case 'f': /* format */
253       if (!strcmp (optarg, "cmml")) {
254         output_cmml = 1;
255         output_html = 0;
256       } else if (!strcmp (optarg, "html")) {
257         output_cmml = 0;
258         output_html = 1;
259       } else {
260         output_cmml = 0;
261         output_html = 0;
262       }
263       break;
264     case 'w': /* html */
265       output_html = 1;
266       break;
267     case 'k': /* keyframe */
268       scan_keyframes = 1;
269       break;
270     case 'h': /* help */
271       show_help = 1;
272       break;
273     case 'v': /* version */
274       show_version = 1;
275       break;
276     case 'o': /* output */
277       outfilename = optarg;
278       break;
279     default:
280       break;
281     }
282   }
283
284   if (show_version) {
285     printf ("%s version " VERSION "\n", progname);
286   }
287
288   if (show_help) {
289     usage (progname);
290   }
291
292   if (show_version || show_help) {
293     goto exit_ok;
294   }
295
296   if (optind >= argc) {
297     usage (progname);
298     goto exit_err;
299   }
300
301   infilename = argv[optind++];
302
303   if (outfilename == NULL) {
304     outfile = stdout;
305   } else {
306     outfile = fopen (outfilename, "wb");
307     if (outfile == NULL) {
308       fprintf (stderr, "%s: unable to open output file %s\n",
309                progname, outfilename);
310       goto exit_err;
311     }
312   }
313
314   errno = 0;
315
316   if (strcmp (infilename, "-") == 0) {
317     oggz = oggz_open_stdio (stdin, OGGZ_READ|OGGZ_AUTO);
318   } else {
319     oggz = oggz_open (infilename, OGGZ_READ|OGGZ_AUTO);
320   }
321
322   if (oggz == NULL) {
323     if (errno == 0) {
324       fprintf (stderr, "%s: %s: error opening input file\n",
325               progname, infilename);
326     } else {
327       fprintf (stderr, "%s: %s: %s\n",
328                progname, infilename, strerror (errno));
329     }
330     goto exit_err;
331   }
332
333   /* init osdata */
334   osdata = malloc (sizeof (OSData));
335   memset (osdata, 0, sizeof (OSData));
336   osdata->read_packet = read_packet;
337   if (scan_keyframes) osdata->keyframes = 1;
338   if (output_cmml)    osdata->cmml = 1;
339   if (output_html)    osdata->html = 1;
340
341   /* set up the right filters on the tracks */
342   oggz_set_read_page (oggz, -1, filter_page, osdata);
343
344   /* correct output format */
345   if (output_html) {
346     fprintf(outfile, HTML_HEAD, infilename);
347   }
348   if (output_cmml) {
349     fprintf(outfile, CMML_HEAD, infilename, infilename);
350   }
351
352   oggz_run_set_blocksize (oggz, 1024*1024);
353   oggz_run (oggz);
354
355   /* finish output */
356   if (output_html) {
357     fprintf(outfile, HTML_END);
358   }
359   if (output_cmml) {
360     fprintf(outfile, CMML_END);
361   }
362
363   oggz_close (oggz);
364
365 exit_ok:
366   free(osdata);
367   exit(0);
368
369 exit_err:
370   free(osdata);
371   exit(1);
372 }
Note: See TracBrowser for help on using the browser.