[xiph-commits] r14860 - in trunk/vorbis-tools: . ogginfo

ivo at svn.xiph.org ivo at svn.xiph.org
Sat May 10 18:36:00 PDT 2008


Author: ivo
Date: 2008-05-10 18:35:59 -0700 (Sat, 10 May 2008)
New Revision: 14860

Modified:
   trunk/vorbis-tools/CHANGES
   trunk/vorbis-tools/configure.ac
   trunk/vorbis-tools/ogginfo/Makefile.am
   trunk/vorbis-tools/ogginfo/ogginfo2.c
Log:
Kate stream information support in ogginfo.  Patch by ogg.k.ogg.k.  Closes #1360.

Modified: trunk/vorbis-tools/CHANGES
===================================================================
--- trunk/vorbis-tools/CHANGES	2008-05-10 19:56:15 UTC (rev 14859)
+++ trunk/vorbis-tools/CHANGES	2008-05-11 01:35:59 UTC (rev 14860)
@@ -2,8 +2,9 @@
 
 * Fixed an error in configure.ac; --with-speex/flac work again (#1319)
 * Corrected problems in the Visual Studio project files
-* ogg123: backported fix from libfishsound to patch the speex decoder (#1347)
+* ogg123: backported fix from libfishsound to patch the Speex decoder (#1347)
 * oggenc: fixed a core dump while resampling from FLAC (#1316)
+* ogginfo: support for information in Kate streams (#1360)
 
 vorbis-tools 1.2.0 -- 2008-02-21
 

Modified: trunk/vorbis-tools/configure.ac
===================================================================
--- trunk/vorbis-tools/configure.ac	2008-05-10 19:56:15 UTC (rev 14859)
+++ trunk/vorbis-tools/configure.ac	2008-05-11 01:35:59 UTC (rev 14860)
@@ -100,6 +100,7 @@
 AC_ARG_ENABLE(vorbiscomment, [  --disable-vorbiscomment   Skip building vorbiscomment], build_vorbiscomment="$enableval", build_vorbiscomment="yes")
 AC_ARG_WITH(flac,     [  --without-flac     Do not compile FLAC support], build_flac="$withval", build_flac="yes")
 AC_ARG_WITH(speex,    [  --without-speex    Do not compile Speex support], build_speex="$withval", build_speex="yes")
+AC_ARG_WITH(kate,     [  --without-kate     Do not compile Kate support], build_kate="$withval", build_kate="yes")
 
 dnl --------------------------------------------------
 dnl Check for generally needed libraries
@@ -251,6 +252,50 @@
 AM_CONDITIONAL(HAVE_LIBSPEEX, test "x$have_libspeex" = "xyes")
 AC_SUBST(SPEEX_LIBS)
 
+dnl ------------------- Kate -------------------------
+
+KATE_CFLAGS=""
+KATE_LIBS=""
+if test "x$build_kate" = xyes; then
+  AC_CHECK_PROG(HAVE_PKG_CONFIG, pkg-config, yes)
+  if test "x$HAVE_PKG_CONFIG" = "xyes"
+  then
+    PKG_CHECK_MODULES(KATE, oggkate, HAVE_KATE=yes, HAVE_KATE=no)
+  fi
+  if test "x$HAVE_KATE" = "xno"
+  then
+    dnl fall back to the old school test
+    AC_CHECK_LIB(m,log,KATE_LIBS="-lm")
+    AC_CHECK_LIB(kate, [kate_decode_init],
+      [HAVE_KATE=yes; KATE_LIBS="-lkate $KATE_LIBS $OGG_LIBS"],
+      AC_MSG_WARN(libkate missing)
+      HAVE_KATE=no, [$KATE_LIBS $OGG_LIBS]
+    )
+    AC_CHECK_LIB(oggkate, [kate_ogg_decode_headerin],
+      [HAVE_KATE=yes; KATE_LIBS="-loggkate $KATE_LIBS $OGG_LIBS"],
+      AC_MSG_WARN(libkate missing)
+      HAVE_KATE=no, [$KATE_LIBS $OGG_LIBS]
+    )
+    AC_CHECK_HEADER(kate/kate.h,,
+      AC_MSG_WARN(libkate headers missing)
+      HAVE_KATE=no,[ ])
+    AC_CHECK_HEADER(kate/oggkate.h,,
+      AC_MSG_WARN(liboggkate headers missing)
+      HAVE_KATE=no,[ ])
+
+  fi
+  if test "x$HAVE_KATE" = xyes; then
+    AC_DEFINE(HAVE_KATE, 1, [Defined if we have libkate])
+  else
+    build_kate="no"
+    KATE_CFLAGS=""
+    KATE_LIBS=""
+  fi
+fi
+AM_CONDITIONAL(HAVE_KATE, test "x$HAVE_KATE" = "xyes")
+AC_SUBST(KATE_CFLAGS)
+AC_SUBST(KATE_LIBS)
+
 dnl --------------------------------------------------
 dnl Check for headers
 dnl --------------------------------------------------
@@ -358,4 +403,8 @@
         AC_MSG_WARN([curl libraries and/or headers missing, ogg123 
 will NOT be built with http support.])
     fi
+    if test "x$HAVE_KATE" != xyes; then
+        AC_MSG_WARN([Kate libraries and/or headers missing, ogginfo 
+will be built with LIMITED Kate read support.])
+    fi
 fi

Modified: trunk/vorbis-tools/ogginfo/Makefile.am
===================================================================
--- trunk/vorbis-tools/ogginfo/Makefile.am	2008-05-10 19:56:15 UTC (rev 14859)
+++ trunk/vorbis-tools/ogginfo/Makefile.am	2008-05-11 01:35:59 UTC (rev 14860)
@@ -14,9 +14,9 @@
 mandir = @MANDIR@
 man_MANS = $(mans)
 
-INCLUDES = @SHARE_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @I18N_CFLAGS@
+INCLUDES = @SHARE_CFLAGS@ @OGG_CFLAGS@ @VORBIS_CFLAGS@ @KATE_CFLAGS@ @I18N_CFLAGS@
 
-ogginfo_LDADD = @SHARE_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ @LIBICONV@ @I18N_LIBS@
+ogginfo_LDADD = @SHARE_LIBS@ @VORBIS_LIBS@ @KATE_LIBS@ @OGG_LIBS@ @LIBICONV@ @I18N_LIBS@
 ogginfo_DEPENDENCIES = @SHARE_LIBS@
 
 ogginfo_SOURCES = $(ogginfosources)

Modified: trunk/vorbis-tools/ogginfo/ogginfo2.c
===================================================================
--- trunk/vorbis-tools/ogginfo/ogginfo2.c	2008-05-10 19:56:15 UTC (rev 14859)
+++ trunk/vorbis-tools/ogginfo/ogginfo2.c	2008-05-11 01:35:59 UTC (rev 14860)
@@ -21,6 +21,10 @@
 #include <ogg/ogg.h>
 #include <vorbis/codec.h>
 
+#ifdef HAVE_KATE
+#include <kate/oggkate.h>
+#endif
+
 #include <locale.h>
 #include "utf8.h"
 #include "i18n.h"
@@ -116,6 +120,27 @@
     ogg_int64_t framenum_expected;
 } misc_theora_info;
 
+typedef struct {
+#ifdef HAVE_KATE
+    kate_info ki;
+    kate_comment kc;
+#else
+    int num_headers;
+#endif
+
+    int major;
+    int minor;
+    char language[16];
+    char category[16];
+
+    ogg_int64_t bytes;
+    ogg_int64_t lastgranulepos;
+    ogg_int64_t firstgranulepos;
+
+    int doneheaders;
+} misc_kate_info;
+
+static int printlots = 0;
 static int printinfo = 1;
 static int printwarn = 1;
 static int verbose = 1;
@@ -634,6 +659,214 @@
     free(stream->data);
 }
 
+static void kate_process(stream_processor *stream, ogg_page *page )
+{
+    ogg_packet packet;
+    misc_kate_info *inf = stream->data;
+    int header=0, packets=0;
+    int res;
+#ifdef HAVE_KATE
+    int i;
+    const char *encoding = NULL, *directionality = NULL;
+#endif
+
+    ogg_stream_pagein(&stream->os, page);
+    if(!inf->doneheaders)
+        header = 1;
+
+    while(1) {
+        res = ogg_stream_packetout(&stream->os, &packet);
+        if(res < 0) {
+           warn(_("Warning: discontinuity in stream (%d)\n"), stream->num);
+           continue;
+        }
+        else if (res == 0)
+            break;
+
+        packets++;
+        if(!inf->doneheaders) {
+#ifdef HAVE_KATE
+            int ret = kate_ogg_decode_headerin(&inf->ki, &inf->kc, &packet);
+            if(ret < 0) {
+                warn(_("Warning: Could not decode kate header "
+                       "packet %d - invalid kate stream (%d)\n"), 
+                        packet.packetno, stream->num);
+                continue;
+            }
+            else if (ret > 0) {
+                inf->doneheaders=1;
+            }
+#else
+            /* if we're not building against libkate, do some limited checks */
+            if (packet.bytes<64 || memcmp(packet.packet+1, "kate\0\0\0\0", 8)) {
+                warn(_("Warning: packet %d does not seem to be a kate header - "
+                       "invalid kate stream (%d)\n"), 
+                        packet.packetno, stream->num);
+                continue;
+            }
+            if (packet.packetno==inf->num_headers) {
+                inf->doneheaders=1;
+            }
+#endif
+
+            if (packet.packetno==0) {
+#ifdef HAVE_KATE
+                inf->major = inf->ki.bitstream_version_major;
+                inf->minor = inf->ki.bitstream_version_minor;
+                memcpy(inf->language, inf->ki.language, 16);
+                inf->language[15] = 0;
+                memcpy(inf->category, inf->ki.category, 16);
+                inf->category[15] = 0;
+#else
+                inf->major = packet.packet[9];
+                inf->minor = packet.packet[10];
+                inf->num_headers = packet.packet[11];
+                memcpy(inf->language, packet.packet+32, 16);
+                inf->language[15] = 0;
+                memcpy(inf->category, packet.packet+48, 16);
+                inf->category[15] = 0;
+#endif
+            }
+
+            if(inf->doneheaders) {
+                if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
+                    warn(_("Warning: Kate stream %d does not have headers "
+                           "correctly framed. Terminal header page contains "
+                           "additional packets or has non-zero granulepos\n"),
+                            stream->num);
+                info(_("Kate headers parsed for stream %d, "
+                       "information follows...\n"), stream->num);
+
+                info(_("Version: %d.%d\n"), inf->major, inf->minor);
+#ifdef HAVE_KATE
+                info(_("Vendor: %s\n"), inf->kc.vendor);
+#endif
+
+                if (*inf->language) {
+                    info(_("Language: %s\n"), inf->language);
+                }
+                else {
+                    info(_("No language set\n"));
+                }
+                if (*inf->category) {
+                    info(_("Category: %s\n"), inf->category);
+                }
+                else {
+                    info(_("No category set\n"));
+                }
+
+#ifdef HAVE_KATE
+                switch (inf->ki.text_encoding) {
+                  case kate_utf8: encoding=_("utf-8"); break;
+                  default: encoding=NULL; break;
+                }
+                if (encoding) {
+                    info(_("Character encoding: %s\n"),encoding);
+                }
+                else {
+                    info(_("Unknown character encoding\n"));
+                }
+
+                if (printlots) {
+                    switch (inf->ki.text_directionality) {
+                      case kate_l2r_t2b: directionality=_("left to right, top to bottom"); break;
+                      case kate_r2l_t2b: directionality=_("right to left, top to bottom"); break;
+                      case kate_t2b_r2l: directionality=_("top to bottom, right to left"); break;
+                      case kate_t2b_l2r: directionality=_("top to bottom, left to right"); break;
+                      default: directionality=NULL; break;
+                    }
+                    if (directionality) {
+                        info(_("Text directionality: %s\n"),directionality);
+                    }
+                    else {
+                        info(_("Unknown text directionality\n"));
+                    }
+
+                    info("%u regions, %u styles, %u curves, %u motions, %u palettes,\n"
+                         "%u bitmaps, %u font ranges, %u font mappings\n",
+                         inf->ki.nregions, inf->ki.nstyles,
+                         inf->ki.ncurves, inf->ki.nmotions,
+                         inf->ki.npalettes, inf->ki.nbitmaps,
+                         inf->ki.nfont_ranges, inf->ki.nfont_mappings);
+                }
+
+		if(inf->ki.gps_numerator == 0 || inf->ki.gps_denominator == 0) 
+		   warn(_("Invalid zero granulepos rate\n"));
+		else
+		   info(_("Granulepos rate %d/%d (%.02f gps)\n"),
+                       inf->ki.gps_numerator, inf->ki.gps_denominator,
+                       (float)inf->ki.gps_numerator/(float)inf->ki.gps_denominator);
+		
+                if(inf->kc.comments > 0)
+                    info(_("User comments section follows...\n"));
+
+                for(i=0; i < inf->kc.comments; i++) {
+                    const char *comment = inf->kc.user_comments[i];
+		    check_xiph_comment(stream, i, comment, 
+		            inf->kc.comment_lengths[i]);
+		}
+#endif
+                info(_("\n"));
+            }
+        }
+    }
+
+    if(!header) {
+        ogg_int64_t gp = ogg_page_granulepos(page);
+        if(gp > 0) {
+            if(gp < inf->lastgranulepos)
+                warn(_("Warning: granulepos in stream %d decreases from %" 
+                        I64FORMAT " to %" I64FORMAT "\n" ),
+                        stream->num, inf->lastgranulepos, gp);
+            inf->lastgranulepos = gp;
+        }
+        else if(packets && gp<0) { /* zero granpos on data is valid for kate */
+            /* Only do this if we saw at least one packet ending on this page.
+             * It's legal (though very unusual) to have no packets in a page at
+             * all - this is occasionally used to have an empty EOS page */
+            warn(_("Negative granulepos (%lld) on kate stream outside of headers. This file was created by a buggy encoder\n"), gp);
+        }
+        if(inf->firstgranulepos < 0) { /* Not set yet */
+        }
+        inf->bytes += page->header_len + page->body_len;
+    }
+}
+
+#ifdef HAVE_KATE
+static void kate_end(stream_processor *stream) 
+{
+    misc_kate_info *inf = stream->data;
+    long minutes, seconds, milliseconds;
+    double bitrate, time;
+
+    /* This should be lastgranulepos - startgranulepos, or something like that*/
+    //time = (double)(inf->lastgranulepos>>inf->ki.granule_shift) * inf->ki.gps_denominator / inf->ki.gps_numerator;
+    ogg_int64_t gbase=inf->lastgranulepos>>inf->ki.granule_shift;
+    ogg_int64_t goffset=inf->lastgranulepos-(gbase<<inf->ki.granule_shift);
+    time = (double)(gbase+goffset) / ((float)inf->ki.gps_numerator/(float)inf->ki.gps_denominator);
+    minutes = (long)time / 60;
+    seconds = (long)time - minutes*60;
+    milliseconds = (long)((time - minutes*60 - seconds)*1000);
+    bitrate = inf->bytes*8 / time / 1000.0;
+
+    info(_("Kate stream %d:\n"
+           "\tTotal data length: %" I64FORMAT " bytes\n"
+           "\tPlayback length: %ldm:%02ld.%03lds\n"
+           "\tAverage bitrate: %f kb/s\n"), 
+            stream->num,inf->bytes, minutes, seconds, milliseconds, bitrate);
+
+    kate_comment_clear(&inf->kc);
+    kate_info_clear(&inf->ki);
+
+    free(stream->data);
+}
+#else
+static void kate_end(stream_processor *stream) 
+{
+}
+#endif
+
+
 static void process_null(stream_processor *stream, ogg_page *page)
 {
     /* This is for invalid streams. */
@@ -727,6 +960,24 @@
 
 }
 
+static void kate_start(stream_processor *stream)
+{
+    misc_kate_info *info;
+
+    stream->type = "kate";
+    stream->process_page = kate_process;
+    stream->process_end = kate_end;
+
+    stream->data = calloc(1, sizeof(misc_kate_info));
+
+    info = stream->data;
+
+#ifdef HAVE_KATE
+    kate_comment_init(&info->kc);
+    kate_info_init(&info->ki);
+#endif
+}
+
 static stream_processor *find_stream_processor(stream_set *set, ogg_page *page)
 {
     ogg_uint32_t serial = ogg_page_serialno(page);
@@ -813,7 +1064,7 @@
         else if(packet.bytes >= 8 && memcmp(packet.packet, "KW-DIRAC", 8)==0)
             other_start(stream, "dirac (old style)");
         else if(packet.bytes >= 9 && memcmp(packet.packet, "\x80kate\0\0\0\0", 9)==0)
-            other_start(stream, "kate");
+            kate_start(stream);
         else
             other_start(stream, NULL);
 
@@ -1017,6 +1268,8 @@
         }
     }
 
+    if(verbose > 1)
+        printlots = 0;
     if(verbose < 1)
         printinfo = 0;
     if(verbose < 0) 



More information about the commits mailing list