root/liboggz/trunk/src/tools/oggz_tools.c

Revision 3831, 11.6 kB (checked in by oggk, 3 weeks ago)

s/int64_t/ogg_int64_t/

because all compilers less C99 equal than others.

Line 
1 /*
2   Copyright (C) 2005 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 #include <getopt.h>
39
40 #include <oggz/oggz.h>
41
42 #include "dirac.h"
43 #include "oggz_tools_dirac.h"
44
45 #if defined (WIN32) || defined (__EMX__)
46 #include <fcntl.h>
47 #include <io.h>
48 #define snprintf _snprintf
49 #endif
50
51 #ifdef HAVE_INTTYPES_H
52 #  include <inttypes.h>
53 #else
54 #  define PRId64 "I64d"
55 #endif
56
57
58 static  ogg_uint32_t
59 _le_32 (ogg_uint32_t i)
60 {
61    ogg_uint32_t ret=i;
62 #ifdef WORDS_BIGENDIAN
63    ret =  (i>>24);
64    ret += (i>>8) & 0x0000ff00;
65    ret += (i<<8) & 0x00ff0000;
66    ret += (i<<24);
67 #endif
68    return ret;
69 }
70
71 static  ogg_uint16_t
72 _be_16 (ogg_uint16_t s)
73 {
74   unsigned short ret=s;
75 #ifndef WORDS_BIGENDIAN
76   ret = (s>>8) & 0x00ffU;
77   ret += (s<<8) & 0xff00U;
78 #endif
79   return ret;
80 }
81
82 static  ogg_uint32_t
83 _be_32 (ogg_uint32_t i)
84 {
85    ogg_uint32_t ret=i;
86 #ifndef WORDS_BIGENDIAN
87    ret =  (i>>24);
88    ret += (i>>8) & 0x0000ff00;
89    ret += (i<<8) & 0x00ff0000;
90    ret += (i<<24);
91 #endif
92    return ret;
93 }
94
95 static  ogg_int64_t
96 _le_64 (ogg_int64_t l)
97 {
98   ogg_int64_t ret=l;
99   unsigned char *ucptr = (unsigned char *)&ret;
100 #ifdef WORDS_BIGENDIAN
101   unsigned char temp;
102
103   temp = ucptr [0] ;
104   ucptr [0] = ucptr [7] ;
105   ucptr [7] = temp ;
106
107   temp = ucptr [1] ;
108   ucptr [1] = ucptr [6] ;
109   ucptr [6] = temp ;
110
111   temp = ucptr [2] ;
112   ucptr [2] = ucptr [5] ;
113   ucptr [5] = temp ;
114
115   temp = ucptr [3] ;
116   ucptr [3] = ucptr [4] ;
117   ucptr [4] = temp ;
118
119 #endif
120   return (*(ogg_int64_t *)ucptr);
121 }
122
123 #define INT32_LE_AT(x) _le_32((*(ogg_int32_t *)(x)))
124 #define INT16_BE_AT(x) _be_16((*(ogg_uint16_t *)(x)))
125 #define INT32_BE_AT(x) _be_32((*(ogg_int32_t *)(x)))
126 #define INT64_LE_AT(x) _le_64((*(ogg_int64_t *)(x)))
127
128 typedef char * (* OTCodecInfoFunc) (unsigned char * data, long n);
129
130 static char *
131 ot_theora_info (unsigned char * data, long len)
132 {
133   char * buf;
134   int width, height;
135
136   if (len < 41) return NULL;
137
138   buf = malloc (80);
139
140   width = INT16_BE_AT(&data[15]);
141   height = INT16_BE_AT(&data[18]);
142
143   snprintf (buf, 80,
144             "\tVideo-Framerate: %.3f fps\n"
145             "\tVideo-Width: %d\n\tVideo-Height: %d\n",
146             (double)INT32_BE_AT(&data[22])/ (double)INT32_BE_AT(&data[26]),
147             width, height);
148
149   return buf;
150 }
151
152 static char *
153 ot_vorbis_info (unsigned char * data, long len)
154 {
155   char * buf;
156
157   if (len < 30) return NULL;
158
159   buf = malloc (60);
160
161   snprintf (buf, 60,
162             "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
163             INT32_LE_AT(&data[12]), (int)(data[11]));
164
165   return buf;
166 }
167
168 static char *
169 ot_speex_info (unsigned char * data, long len)
170 {
171   char * buf;
172
173   if (len < 68) return NULL;
174
175   buf = malloc (60);
176
177   snprintf (buf, 60,
178             "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
179             INT32_LE_AT(&data[36]), INT32_LE_AT(&data[48]));
180
181   return buf;
182 }
183
184 static char *
185 ot_celt_info (unsigned char * data, long len)
186 {
187   char * buf;
188
189   if (len < 56) return NULL;
190
191   buf = malloc (60);
192
193   snprintf (buf, 60,
194             "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
195             INT32_LE_AT(&data[40]), INT32_LE_AT(&data[44]));
196
197   return buf;
198 }
199
200 static char *
201 ot_flac_info (unsigned char * data, long len)
202 {
203   char * buf;
204   int n;
205   int version_major, version_minor;
206   int samplerate;
207   int channels;
208
209   if (len < 30) return NULL;
210
211   buf = malloc (120);
212
213   version_major = data[5];
214   version_minor = data[6];
215
216   samplerate = (ogg_int64_t) (data[27] << 12) | (data[28] << 4) |
217                ((data[29] >> 4)&0xf);
218   channels = 1 + ((data[29] >> 1)&0x7);
219
220   n = snprintf (buf, 120,
221             "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
222             samplerate, channels);
223
224   snprintf (buf+n, 120-n,
225             "\tFLAC-Ogg-Mapping-Version: %d.%d\n",
226             version_major, version_minor);
227
228   return buf;
229 }
230
231 static char *
232 ot_oggpcm2_info (unsigned char * data, long len)
233 {
234   char * buf;
235
236   if (len < 28) return NULL;
237
238   buf = malloc (60);
239
240   snprintf (buf, 60,
241             "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
242             INT32_BE_AT(&data[16]), (int)data[21]);
243
244   return buf;
245 }
246
247 static char *
248 ot_kate_info (unsigned char * data, long len)
249 {
250   char * buf;
251
252   static const size_t KATE_INFO_BUFFER_LEN =
253     1 /* tab */
254   +18 /* "Content-Language: " */
255   +15 /* 15 chars + NUL for language */
256    +1 /* \n */
257    +1 /* tab */
258   +18 /* "Content-Category: " */
259   +15 /* 15 chars + NUL for category */
260    +1 /* \n */
261    +1;/* terminating NUL */
262
263   if (len < 64) return NULL;
264
265   buf = malloc (KATE_INFO_BUFFER_LEN);
266
267   /* Are these headers coming from some standard ? If so, need to find what should these be for Kate */
268   snprintf (buf, KATE_INFO_BUFFER_LEN,
269             "\tContent-Language: %s\n"
270             "\tContent-Category: %s\n",
271             &data[32], &data[48]);
272
273 #undef KATE_INFO_BUFFER_LEN
274
275   return buf;
276 }
277
278 static char *
279 ot_dirac_info (unsigned char * data, long len)
280 {
281   char * buf;
282   dirac_info *info;
283
284   /* read in useful bits from sequence header */
285   if (len < 24) return NULL;
286
287   buf = malloc (80);
288   info = malloc(sizeof(dirac_info));
289
290   dirac_parse_info(info, data, len);
291
292   snprintf (buf, 80,
293             "\tVideo-Framerate: %.3f fps\n"
294             "\tVideo-Width: %d\n\tVideo-Height: %d\n",
295             (double)info->fps_numerator/ (double)info->fps_denominator,
296             info->width, info->height);
297
298   free(info);
299
300   return buf;
301 }
302
303
304 static char *
305 ot_skeleton_info (unsigned char * data, long len)
306 {
307   char * buf;
308   double pres_n, pres_d, pres;
309   double base_n, base_d, base;
310
311   if (len < 64L) return NULL;
312
313   buf = malloc (60);
314
315   pres_n = (double)INT64_LE_AT(&data[12]);
316   pres_d = (double)INT64_LE_AT(&data[20]);
317   if (pres_d != 0.0) {
318     pres = pres_n / pres_d;
319   } else {
320     pres = 0.0;
321   }
322
323   base_n = (double)INT64_LE_AT(&data[28]);
324   base_d = (double)INT64_LE_AT(&data[36]);
325   if (base_d != 0.0) {
326     base = base_n / base_d;
327   } else {
328     base = 0.0;
329   }
330
331   snprintf (buf, 60,
332             "\tPresentation-Time: %.3f\n\tBasetime: %.3f\n", pres, base);
333
334   return buf;
335 }
336
337 static const OTCodecInfoFunc codec_ident[] = {
338   ot_theora_info,
339   ot_vorbis_info,
340   ot_speex_info,
341   ot_oggpcm2_info,
342   NULL,             /* CMML */
343   NULL,             /* ANNODEX */
344   ot_skeleton_info,
345   NULL,             /* FLAC0 */
346   ot_flac_info,     /* FLAC */
347   NULL,             /* ANXDATA */
348   ot_celt_info,     /* CELT */
349   ot_kate_info,     /* KATE */
350   ot_dirac_info,    /* BBCD */
351   NULL              /* UNKNOWN */
352 };
353
354 const char *
355 ot_page_identify (OGGZ *oggz, const ogg_page * og, char ** info)
356 {
357   const char * ret = NULL;
358   int serial_no;
359   int content;
360
361   /*
362    * identify stream content using oggz_stream_get_content, identify
363    * stream content name using oggz_stream_get_content_type
364    */
365
366   serial_no = ogg_page_serialno((ogg_page *)og);
367
368   content = oggz_stream_get_content(oggz, serial_no);
369   if (content == OGGZ_ERR_BAD_SERIALNO) return NULL;
370
371   ret = oggz_stream_get_content_type(oggz, serial_no);
372
373   if (info != NULL)
374   {
375     if (codec_ident[content] != NULL)
376     {
377       *info = codec_ident[content](og->body, og->body_len);
378     }
379   }
380
381   return ret;
382 }
383
384 /*
385  * Print a number of bytes to 3 significant figures
386  * using standard abbreviations (GB, MB, kB, byte[s])
387  */
388 int
389 ot_fprint_bytes (FILE * stream, long nr_bytes)
390 {
391   if (nr_bytes > (1L<<30)) {
392     return fprintf (stream, "%0.3f GB",
393                    (double)nr_bytes / (1024.0 * 1024.0 * 1024.0));
394   } else if (nr_bytes > (1L<<20)) {
395     return fprintf (stream, "%0.3f MB",
396                    (double)nr_bytes / (1024.0 * 1024.0));
397   } else if (nr_bytes > (1L<<10)) {
398     return fprintf (stream, "%0.3f kB",
399                    (double)nr_bytes / (1024.0));
400   } else if (nr_bytes == 1) {
401     return fprintf (stream, "1 byte");
402   } else {
403     return fprintf (stream, "%ld bytes", nr_bytes);
404   }
405 }
406
407 /*
408  * Print a bitrate to 3 significant figures
409  * using quasi-standard abbreviations (Gbps, Mbps, kbps, bps)
410  */
411 int
412 ot_print_bitrate (long bps)
413 {
414   if (bps > (1000000000L)) {
415     return printf ("%0.3f Gbps",
416                    (double)bps / (1000.0 * 1000.0 * 1000.0));
417   } else if (bps > (1000000L)) {
418     return printf ("%0.3f Mbps",
419                    (double)bps / (1000.0 * 1000.0));
420   } else if (bps > (1000L)) {
421     return printf ("%0.3f kbps",
422                    (double)bps / (1000.0));
423   } else {
424     return printf ("%ld bps", bps);
425   }
426 }
427
428 int
429 ot_fprint_time (FILE * stream, double seconds)
430 {
431   int hrs, min;
432   double sec;
433   char * sign;
434
435   sign = (seconds < 0.0) ? "-" : "";
436
437   if (seconds < 0.0) seconds = -seconds;
438
439   hrs = (int) (seconds/3600.0);
440   min = (int) ((seconds - ((double)hrs * 3600.0)) / 60.0);
441   sec = seconds - ((double)hrs * 3600.0)- ((double)min * 60.0);
442
443   return fprintf (stream, "%s%02d:%02d:%06.3f", sign, hrs, min, sec);
444 }
445
446 void
447 ot_dirac_gpos_parse (ogg_int64_t iframe, ogg_int64_t pframe,
448                      struct ot_dirac_gpos * dg)
449 {
450   dg->pt = (iframe + pframe) >> 9;
451   dg->dist = ((iframe & 0xff) << 8) | (pframe & 0xff);
452   dg->delay = pframe >> 9;
453   dg->dt = (ogg_int64_t)dg->pt - dg->delay;
454 }
455
456 int
457 ot_fprint_granulepos (FILE * stream, OGGZ * oggz, long serialno,
458                       ogg_int64_t granulepos)
459 {
460   int ret, granuleshift = oggz_get_granuleshift (oggz, serialno);
461
462   if (granuleshift < 1) {
463     ret = fprintf (stream, "%" PRId64, granulepos);
464   } else {
465     ogg_int64_t iframe, pframe;
466     iframe = granulepos >> granuleshift;
467     pframe = granulepos - (iframe << granuleshift);
468
469     if (oggz_stream_get_content (oggz, serialno) != OGGZ_CONTENT_DIRAC) {
470       ret = fprintf (stream, "%" PRId64 "|%" PRId64, iframe, pframe);
471     } else {
472       struct ot_dirac_gpos dg;
473       ot_dirac_gpos_parse (iframe, pframe, &dg);
474       ret = fprintf (stream,
475                      "(pt:%u,dt:%" PRId64 ",dist:%hu,delay:%hu)",
476                      dg.pt, dg.dt, dg.dist, dg.delay);
477     }
478
479 }
480
481   return ret;
482 }
483
484 void
485 ot_init (void)
486 {
487 #ifdef _WIN32
488   /* We need to set stdin/stdout to binary mode on Win32 */
489
490   _setmode( _fileno( stdin ), _O_BINARY );
491   _setmode( _fileno( stdout ), _O_BINARY );
492 #endif
493 #ifdef __EMX__
494   /* We need to set stdin/stdout to binary mode on OS/2*/
495
496   setmode( fileno( stdin ), O_BINARY );
497   setmode( fileno( stdout ), O_BINARY );
498 #endif
499 }
500
501 void
502 ot_print_short_options (char * optstring)
503 {
504   char *c;
505
506   for (c=optstring; *c; c++) {
507     if (*c != ':') printf ("-%c ", *c);
508   }
509
510   printf ("\n");
511 }
512
513 #ifdef HAVE_GETOPT_LONG
514 void
515 ot_print_options (struct option long_options[], char * optstring)
516 {
517   int i;
518   for (i=0; long_options[i].name != NULL; i++)  {
519     printf ("--%s ", long_options[i].name);
520   }
521
522   ot_print_short_options (optstring);
523 }
524 #endif
525
Note: See TracBrowser for help on using the browser.