[xiph-cvs] cvs commit: vorbis-tools/ogginfo ogginfo2.c
Michael Smith
msmith at xiph.org
Sat Jun 22 23:28:58 PDT 2002
msmith 02/06/22 23:28:58
Modified: ogginfo ogginfo2.c
Log:
Cleanups, options, and a couple of minor extra tests. and a quick todo list.
Revision Changes Path
1.3 +162 -65 vorbis-tools/ogginfo/ogginfo2.c
Index: ogginfo2.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogginfo/ogginfo2.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ogginfo2.c 2002/06/22 16:23:46 1.2
+++ ogginfo2.c 2002/06/23 06:28:57 1.3
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
+#include <stdarg.h>
+#include <getopt.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>
@@ -21,6 +23,24 @@
#define CHUNK 4500
+/* Different implementations have different format strings for 64 bit ints. */
+#ifdef _WIN32
+#define INT64FORMAT "%I64d"
+#else
+#define INT64FORMAT "%Ld"
+#endif
+
+
+/* TODO:
+ *
+ * - detect decreasing granulepos
+ * - detect violations of muxing constraints
+ * - better EOS detection (when EOS not explicitly set)
+ * - detect granulepos 'gaps' (possibly vorbis-specific).
+ * - check for serial number == (unsigned)-1 (will break some tools?)
+ * - more options (e.g. less or more verbose)
+ */
+
typedef struct _stream_processor {
void (*process_page)(struct _stream_processor *, ogg_page *);
void (*process_end)(struct _stream_processor *);
@@ -57,6 +77,10 @@
int doneheaders;
} misc_vorbis_info;
+static int printinfo = 1;
+static int printwarn = 1;
+static int verbose = 1;
+
static stream_set *create_stream_set(void) {
stream_set *set = calloc(1, sizeof(stream_set));
@@ -67,85 +91,124 @@
return set;
}
+static void info(char *format, ...)
+{
+ va_list ap;
+
+ if(!printinfo)
+ return;
+
+ va_start(ap, format);
+ vfprintf(stdout, format, ap);
+ va_end(ap);
+}
+
+static void warn(char *format, ...)
+{
+ va_list ap;
+
+ if(!printwarn)
+ return;
+
+ va_start(ap, format);
+ vfprintf(stdout, format, ap);
+ va_end(ap);
+}
+
+static void error(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf(stdout, format, ap);
+ va_end(ap);
+}
+
static void vorbis_process(stream_processor *stream, ogg_page *page )
{
ogg_packet packet;
- misc_vorbis_info *info = stream->data;
+ misc_vorbis_info *inf = stream->data;
int i, header=0;
ogg_stream_pagein(&stream->os, page);
while(ogg_stream_packetout(&stream->os, &packet) > 0) {
- if(info->doneheaders < 3) {
- if(vorbis_synthesis_headerin(&info->vi, &info->vc, &packet) < 0) {
- fprintf(stderr, _("Warning: Could not decode vorbis header "
+ if(inf->doneheaders < 3) {
+ if(vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) {
+ warn(_("Warning: Could not decode vorbis header "
"packet - invalid vorbis stream (%d)\n"), stream->num);
continue;
}
header = 1;
- info->doneheaders++;
- if(info->doneheaders == 3) {
- fprintf(stderr,
- _("Vorbis headers parsed for stream %d, "
- "information follows...\n"), stream->num);
-
- fprintf(stderr, _("Version: %d\n"), info->vi.version);
- fprintf(stderr, _("Vendor: %s\n"), info->vc.vendor);
- fprintf(stderr, _("Channels: %d\n"), info->vi.channels);
- fprintf(stderr, _("Rate: %ld\n\n"), info->vi.rate);
-
- if(info->vi.bitrate_nominal >= 0)
- fprintf(stderr, _("Nominal bitrate: %f kb/s\n"),
- (double)info->vi.bitrate_nominal / 1000.0);
+ inf->doneheaders++;
+ if(inf->doneheaders == 3) {
+ info(_("Vorbis headers parsed for stream %d, "
+ "information follows...\n"), stream->num);
+
+ info(_("Version: %d\n"), inf->vi.version);
+ info(_("Vendor: %s\n"), inf->vc.vendor);
+ info(_("Channels: %d\n"), inf->vi.channels);
+ info(_("Rate: %ld\n\n"), inf->vi.rate);
+
+ if(inf->vi.bitrate_nominal >= 0)
+ info(_("Nominal bitrate: %f kb/s\n"),
+ (double)inf->vi.bitrate_nominal / 1000.0);
else
- fprintf(stderr, _("Nominal bitrate not set\n"));
+ info(_("Nominal bitrate not set\n"));
- if(info->vi.bitrate_upper >= 0)
- fprintf(stderr, _("Upper bitrate: %f kb/s\n"),
- (double)info->vi.bitrate_upper / 1000.0);
+ if(inf->vi.bitrate_upper >= 0)
+ info(_("Upper bitrate: %f kb/s\n"),
+ (double)inf->vi.bitrate_upper / 1000.0);
else
- fprintf(stderr, _("Upper bitrate not set\n"));
+ info(_("Upper bitrate not set\n"));
- if(info->vi.bitrate_lower >= 0)
- fprintf(stderr, _("Lower bitrate: %f kb/s\n"),
- (double)info->vi.bitrate_lower / 1000.0);
+ if(inf->vi.bitrate_lower >= 0)
+ info(_("Lower bitrate: %f kb/s\n"),
+ (double)inf->vi.bitrate_lower / 1000.0);
else
- fprintf(stderr, _("Lower bitrate not set\n"));
+ info(_("Lower bitrate not set\n"));
- if(info->vc.comments > 0)
- fprintf(stderr, _("User comments section follows...\n"));
+ if(inf->vc.comments > 0)
+ info(_("User comments section follows...\n"));
- for(i=0; i < info->vc.comments; i++)
- fprintf(stderr, "\t%s\n", info->vc.user_comments[i]);
+ for(i=0; i < inf->vc.comments; i++)
+ info("\t%s\n", inf->vc.user_comments[i]);
}
}
}
if(!header) {
- info->bytes += page->header_len + page->body_len;
- info->lastgranulepos = ogg_page_granulepos(page);
+ ogg_int64_t gp = ogg_page_granulepos(page);
+ if(gp > 0) {
+ if(gp < inf->lastgranulepos)
+ warn(_("Warning: granulepos in stream %d decreases from "
+ INT64FORMAT " to " INT64FORMAT "\n"), stream->num,
+ inf->lastgranulepos, gp);
+ inf->lastgranulepos = gp;
+ }
+ inf->bytes += page->header_len + page->body_len;
}
}
static void vorbis_end(stream_processor *stream)
{
- misc_vorbis_info *info = stream->data;
+ misc_vorbis_info *inf = stream->data;
long minutes, seconds;
double bitrate, time;
- time = (double)info->lastgranulepos / info->vi.rate;
+ time = (double)inf->lastgranulepos / inf->vi.rate;
minutes = (long)time / 60;
seconds = (long)time - minutes*60;
- bitrate = info->bytes*8 / time / 1000.0;
+ bitrate = inf->bytes*8 / time / 1000.0;
- fprintf(stderr, _("Vorbis stream %d:\n"
- "\tTotal data length: %ld bytes\n"
- "\tPlayback length: %ldm:%02lds\n"
- "\tAverage bitrate: %f kbps\n"),
- stream->num,info->bytes, minutes, seconds, bitrate);
+ info(_("Vorbis stream %d:\n"
+ "\tTotal data length: %ld bytes\n"
+ "\tPlayback length: %ldm:%02lds\n"
+ "\tAverage bitrate: %f kbps\n"),
+ stream->num,inf->bytes, minutes, seconds, bitrate);
- vorbis_comment_clear(&info->vc);
- vorbis_info_clear(&info->vi);
+ vorbis_comment_clear(&inf->vc);
+ vorbis_info_clear(&inf->vi);
free(stream->data);
}
@@ -167,8 +230,9 @@
int i;
for(i=0; i < set->used; i++) {
if(!set->streams[i].end) {
- fprintf(stderr, _("Warning: EOS not set on stream %d\n"),
+ warn(_("Warning: EOS not set on stream %d\n"),
set->streams[i].num);
+ set->streams[i].process_end(&set->streams[i]);
}
ogg_stream_clear(&set->streams[i].os);
}
@@ -277,8 +341,7 @@
ogg_stream_pagein(&stream->os, page);
res = ogg_stream_packetout(&stream->os, &packet);
if(res <= 0) {
- fprintf(stderr, _(
- "Warning: Invalid header page, no packet found\n"));
+ warn(_("Warning: Invalid header page, no packet found\n"));
return NULL;
}
@@ -291,7 +354,7 @@
res = ogg_stream_packetout(&stream->os, &packet);
if(res > 0) {
- fprintf(stderr, _("Warning: Invalid header page in stream %d, "
+ warn(_("Warning: Invalid header page in stream %d, "
"contains multiple packets\n"), stream->num);
}
@@ -315,7 +378,7 @@
while((ret = ogg_sync_pageout(sync, page)) <= 0) {
if(ret < 0)
- fprintf(stderr, _("Warning: Hole in data found. Corrupted ogg\n"));
+ warn(_("Warning: Hole in data found. Corrupted ogg\n"));
buffer = ogg_sync_buffer(sync, CHUNK);
bytes = fread(buffer, 1, CHUNK, f);
@@ -334,12 +397,12 @@
stream_set *processors = create_stream_set();
if(!file) {
- fprintf(stderr, _("Error opening input file \"%s\": %s\n"), filename,
+ error(_("Error opening input file \"%s\": %s\n"), filename,
strerror(errno));
return;
}
- fprintf(stderr, _("Processing file \"%s\"...\n\n"), filename);
+ info(_("Processing file \"%s\"...\n\n"), filename);
ogg_sync_init(&sync);
@@ -347,30 +410,26 @@
stream_processor *p = find_stream_processor(processors, &page);
if(!p) {
- fprintf(stderr,
- _("Could not find a processor for stream, bailing\n"));
+ error(_("Could not find a processor for stream, bailing\n"));
return;
}
if(p->isillegal && !p->shownillegal) {
- fprintf(stderr,
- _("Warning: illegally placed page(s) for logical stream %d\n"
- "This indicates a corrupt ogg file.\n"), p->num);
+ warn(_("Warning: illegally placed page(s) for logical stream %d\n"
+ "This indicates a corrupt ogg file.\n"), p->num);
p->shownillegal = 1;
continue;
}
if(p->isnew) {
- fprintf(stderr, _("New logical stream (#%d, serial: %08x): type %s\n"),
+ info(_("New logical stream (#%d, serial: %08x): type %s\n"),
p->num, p->serial, p->type);
if(!p->start)
- fprintf(stderr,
- _("Warning: stream start flag not set on stream %d\n"),
+ warn(_("Warning: stream start flag not set on stream %d\n"),
p->num);
}
else if(p->start)
- fprintf(stderr,
- _("Warning: stream start flag found in mid-stream "
+ warn(_("Warning: stream start flag found in mid-stream "
"on stream %d\n"), p->num);
if(!p->isillegal) {
@@ -379,7 +438,7 @@
if(p->end) {
if(p->process_end)
p->process_end(p);
- fprintf(stderr, _("Logical stream %d ended\n"), p->num);
+ info(_("Logical stream %d ended\n"), p->num);
p->isillegal = 1;
}
}
@@ -392,8 +451,21 @@
fclose(file);
}
+static void usage(void) {
+ printf(_("ogginfo 1.0\n"
+ "(c) 2002 Michael Smith <msmith at labyrinth.net.au>\n"
+ "\n"
+ "Usage: ogginfo [flags] files1.ogg [file2.ogg ... fileN.ogg]\n"
+ "Flags supported:\n"
+ "\t-h Show this help message\n"
+ "\t-q Make less verbose. Once will remove detailed informative\n"
+ "\t messages, two will remove warnings\n"
+ "\t-v Make more verbose. This may enable more detailed checks\n"
+ "\t for some stream types.\n\n"));
+}
+
int main(int argc, char **argv) {
- int f;
+ int f, ret;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
@@ -401,14 +473,39 @@
if(argc < 2) {
fprintf(stderr,
- _("Usage: ogginfo file1.ogg [file2.ogg ... fileN.ogg]\n"
+ _("Usage: ogginfo [flags] file1.ogg [file2.ogg ... fileN.ogg]\n"
"\n"
"Ogginfo is a tool for printing information about ogg files\n"
- "and for diagnosing problems with them.\n"));
+ "and for diagnosing problems with them.\n"
+ "Full help shown with \"ogginfo -h\".\n"));
exit(1);
}
+
+ while((ret = getopt(argc, argv, "hvq")) >= 0) {
+ switch(ret) {
+ case 'h':
+ usage();
+ return 0;
+ case 'v':
+ verbose++;
+ break;
+ case 'q':
+ verbose--;
+ break;
+ }
+ }
+
+ if(verbose < 1)
+ printinfo = 0;
+ if(verbose < 0)
+ printwarn = 0;
+
+ if(optind >= argc) {
+ fprintf(stderr, _("No input files specified. \"ogginfo -h\" for help\n"));
+ return 1;
+ }
- for(f=1; f < argc; f++) {
+ for(f=optind; f < argc; f++) {
process_file(argv[f]);
}
<p><p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list