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 @@
#include <string.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 {
const char *bos_str;
int bos_str_len;
const char *content_type;
OTCodecInfoFunc info_func;
} 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[] = {
{"\200theora", 7, "theora"},
{"\001vorbis", 7, "vorbis"},
{"Speex", 5, "speex"},
{"CMML\0\0\0\0", 8, "cmml"},
{"Annodex", 8, "annodex"},
{"fishead", 8, "skeleton"},
{"\200theora", 7, "theora", ot_theora_info},
{"\001vorbis", 7, "vorbis", ot_vorbis_info},
{"Speex", 5, "speex", ot_speex_info},
{"CMML\0\0\0\0", 8, "cmml", NULL},
{"Annodex", 8, "annodex", NULL},
{"fishead", 8, "skeleton", NULL},
{NULL}
};
const char *
ot_page_identify (const ogg_page * og)
ot_page_identify (const ogg_page * og, char ** info)
{
const char * ret = NULL;
int i;
......@@ -71,6 +169,9 @@ ot_page_identify (const ogg_page * og)
if (og->body_len >= ident->bos_str_len &&
memcmp (og->body, ident->bos_str, ident->bos_str_len) == 0) {
ret = ident->content_type;
if (info && ident->info_func) {
*info = ident->info_func (og->body, og->body_len);
}
break;
}
}
......
......@@ -36,6 +36,6 @@
#include "config.h"
const char *
ot_page_identify (const ogg_page * og);
ot_page_identify (const ogg_page * og, char ** info);
#endif /* __OGGZ_TOOLS_H__ */
......@@ -74,6 +74,7 @@ struct _OI_TrackInfo {
OI_Stats pages;
OI_Stats packets;
const char * codec_name;
char * codec_info;
};
static void
......@@ -150,6 +151,10 @@ oit_print (OI_Info * info, OI_TrackInfo * oit, long serialno)
oi_bitrate (oit->pages.length_total, info->duration));
printf ("\n");
if (oit->codec_info != NULL) {
puts (oit->codec_info);
}
/* Page stats */
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
}
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;
......@@ -306,6 +311,12 @@ oi_pass2 (OGGZ * oggz, OI_Info * info)
return 0;
}
static void
oit_delete (OI_Info * info, OI_TrackInfo * oit, long serialno)
{
if (oit->codec_info) free (oit->codec_info);
}
int
main (int argc, char ** argv)
{
......@@ -335,7 +346,7 @@ main (int argc, char ** argv)
oggz_close (oggz);
/* 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-Bitrate-Average: %ld bps\n",
oi_bitrate (info.length_total, info.duration));
......@@ -343,6 +354,7 @@ main (int argc, char ** argv)
oggzinfo_apply (oit_print, &info);
oggzinfo_apply (oit_delete, &info);
oggz_table_delete (info.tracks);
return (0);
......
......@@ -180,7 +180,7 @@ orstream_new (const ORData *ordata, const ogg_page *og, long serialno)
stream->streamid = streamid_count++;
stream->content_type = "unknown";
ident = ot_page_identify (og);
ident = ot_page_identify (og, NULL);
if (ident != NULL) stream->content_type = ident;
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