Commit cc4f3cac authored by conrad's avatar conrad

oggzinfo: display codec info, including audio samplerate, audio channels,

video framerate, video width, video height for vorbis, speex and theora
(closes ticket:75)


git-svn-id: http://svn.annodex.net/liboggz/trunk@1078 8158c8cd-e7e1-0310-9fa4-c5954c97daef
parent 1354b657
...@@ -36,24 +36,122 @@ ...@@ -36,24 +36,122 @@
#include <string.h> #include <string.h>
#include <oggz/oggz.h> #include <oggz/oggz.h>
static ogg_uint32_t
_le_32 (ogg_uint32_t i)
{
ogg_uint32_t ret=i;
#ifdef WORDS_BIGENDIAN
ret = (i>>24);
ret += (i>>8) & 0x0000ff00;
ret += (i<<8) & 0x00ff0000;
ret += (i<<24);
#endif
return ret;
}
static unsigned short
_be_16 (unsigned short s)
{
unsigned short ret=s;
#ifndef WORDS_BIGENDIAN
ret = (s>>8) & 0x00ffU;
ret += (s<<8) & 0xff00U;
#endif
return ret;
}
static ogg_uint32_t
_be_32 (ogg_uint32_t i)
{
ogg_uint32_t ret=i;
#ifndef WORDS_BIGENDIAN
ret = (i>>24);
ret += (i>>8) & 0x0000ff00;
ret += (i<<8) & 0x00ff0000;
ret += (i<<24);
#endif
return ret;
}
#define INT32_LE_AT(x) _le_32((*(ogg_int32_t *)(x)))
#define INT16_BE_AT(x) _be_16((*(ogg_int32_t *)(x)))
#define INT32_BE_AT(x) _be_32((*(ogg_int32_t *)(x)))
typedef char * (* OTCodecInfoFunc) (unsigned char * data, long n);
typedef struct { typedef struct {
const char *bos_str; const char *bos_str;
int bos_str_len; int bos_str_len;
const char *content_type; const char *content_type;
OTCodecInfoFunc info_func;
} OTCodecIdent; } OTCodecIdent;
static char *
ot_theora_info (unsigned char * data, long len)
{
char * buf;
int width, height;
if (len < 41) return NULL;
buf = malloc (80);
width = INT16_BE_AT(&data[8]) << 4;
height = INT16_BE_AT(&data[10]) << 4;
snprintf (buf, 80,
"\tVideo-Framerate: %.3f fps\n"
"\tVideo-Width: %d\n\tVideo-Height: %d\n",
(double)INT32_BE_AT(&data[22])/ (double)INT32_BE_AT(&data[26]),
width, height);
return buf;
}
static char *
ot_vorbis_info (unsigned char * data, long len)
{
char * buf;
if (len < 30) return NULL;
buf = malloc (60);
snprintf (buf, 60,
"\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
INT32_LE_AT(&data[12]), (int)(data[11]));
return buf;
}
static char *
ot_speex_info (unsigned char * data, long len)
{
char * buf;
if (len < 68) return NULL;
buf = malloc (60);
snprintf (buf, 60,
"\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
INT32_LE_AT(&data[36]), INT32_LE_AT(&data[48]));
return buf;
}
static const OTCodecIdent codec_ident[] = { static const OTCodecIdent codec_ident[] = {
{"\200theora", 7, "theora"}, {"\200theora", 7, "theora", ot_theora_info},
{"\001vorbis", 7, "vorbis"}, {"\001vorbis", 7, "vorbis", ot_vorbis_info},
{"Speex", 5, "speex"}, {"Speex", 5, "speex", ot_speex_info},
{"CMML\0\0\0\0", 8, "cmml"}, {"CMML\0\0\0\0", 8, "cmml", NULL},
{"Annodex", 8, "annodex"}, {"Annodex", 8, "annodex", NULL},
{"fishead", 8, "skeleton"}, {"fishead", 8, "skeleton", NULL},
{NULL} {NULL}
}; };
const char * const char *
ot_page_identify (const ogg_page * og) ot_page_identify (const ogg_page * og, char ** info)
{ {
const char * ret = NULL; const char * ret = NULL;
int i; int i;
...@@ -71,6 +169,9 @@ ot_page_identify (const ogg_page * og) ...@@ -71,6 +169,9 @@ ot_page_identify (const ogg_page * og)
if (og->body_len >= ident->bos_str_len && if (og->body_len >= ident->bos_str_len &&
memcmp (og->body, ident->bos_str, ident->bos_str_len) == 0) { memcmp (og->body, ident->bos_str, ident->bos_str_len) == 0) {
ret = ident->content_type; ret = ident->content_type;
if (info && ident->info_func) {
*info = ident->info_func (og->body, og->body_len);
}
break; break;
} }
} }
......
...@@ -36,6 +36,6 @@ ...@@ -36,6 +36,6 @@
#include "config.h" #include "config.h"
const char * const char *
ot_page_identify (const ogg_page * og); ot_page_identify (const ogg_page * og, char ** info);
#endif /* __OGGZ_TOOLS_H__ */ #endif /* __OGGZ_TOOLS_H__ */
...@@ -74,6 +74,7 @@ struct _OI_TrackInfo { ...@@ -74,6 +74,7 @@ struct _OI_TrackInfo {
OI_Stats pages; OI_Stats pages;
OI_Stats packets; OI_Stats packets;
const char * codec_name; const char * codec_name;
char * codec_info;
}; };
static void static void
...@@ -150,6 +151,10 @@ oit_print (OI_Info * info, OI_TrackInfo * oit, long serialno) ...@@ -150,6 +151,10 @@ oit_print (OI_Info * info, OI_TrackInfo * oit, long serialno)
oi_bitrate (oit->pages.length_total, info->duration)); oi_bitrate (oit->pages.length_total, info->duration));
printf ("\n"); printf ("\n");
if (oit->codec_info != NULL) {
puts (oit->codec_info);
}
/* Page stats */ /* Page stats */
oi_stats_print (info, &oit->pages, "Page"); oi_stats_print (info, &oit->pages, "Page");
...@@ -201,7 +206,7 @@ read_page_pass1 (OGGZ * oggz, const ogg_page * og, long serialno, void * user_da ...@@ -201,7 +206,7 @@ read_page_pass1 (OGGZ * oggz, const ogg_page * og, long serialno, void * user_da
} }
if (ogg_page_bos ((ogg_page *)og)) { if (ogg_page_bos ((ogg_page *)og)) {
oit->codec_name = ot_page_identify (og); oit->codec_name = ot_page_identify (og, &oit->codec_info);
} }
bytes = og->header_len + og->body_len; bytes = og->header_len + og->body_len;
...@@ -306,6 +311,12 @@ oi_pass2 (OGGZ * oggz, OI_Info * info) ...@@ -306,6 +311,12 @@ oi_pass2 (OGGZ * oggz, OI_Info * info)
return 0; return 0;
} }
static void
oit_delete (OI_Info * info, OI_TrackInfo * oit, long serialno)
{
if (oit->codec_info) free (oit->codec_info);
}
int int
main (int argc, char ** argv) main (int argc, char ** argv)
{ {
...@@ -335,7 +346,7 @@ main (int argc, char ** argv) ...@@ -335,7 +346,7 @@ main (int argc, char ** argv)
oggz_close (oggz); oggz_close (oggz);
/* Print summary information */ /* Print summary information */
printf ("Duration: %lld ms\n", info.duration); printf ("Content-Duration: %lld ms\n", info.duration);
printf ("Content-Length: %ld bytes\n", info.length_total); printf ("Content-Length: %ld bytes\n", info.length_total);
printf ("Content-Bitrate-Average: %ld bps\n", printf ("Content-Bitrate-Average: %ld bps\n",
oi_bitrate (info.length_total, info.duration)); oi_bitrate (info.length_total, info.duration));
...@@ -343,6 +354,7 @@ main (int argc, char ** argv) ...@@ -343,6 +354,7 @@ main (int argc, char ** argv)
oggzinfo_apply (oit_print, &info); oggzinfo_apply (oit_print, &info);
oggzinfo_apply (oit_delete, &info);
oggz_table_delete (info.tracks); oggz_table_delete (info.tracks);
return (0); return (0);
......
...@@ -180,7 +180,7 @@ orstream_new (const ORData *ordata, const ogg_page *og, long serialno) ...@@ -180,7 +180,7 @@ orstream_new (const ORData *ordata, const ogg_page *og, long serialno)
stream->streamid = streamid_count++; stream->streamid = streamid_count++;
stream->content_type = "unknown"; stream->content_type = "unknown";
ident = ot_page_identify (og); ident = ot_page_identify (og, NULL);
if (ident != NULL) stream->content_type = ident; if (ident != NULL) stream->content_type = ident;
if (ordata->verbose) if (ordata->verbose)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment