Commit 85e8bb1c authored by conrad's avatar conrad

apply patch from Tahseen Mohammad (Google SoC): display skeleton info in

oggzinfo. This also adds tahseen's skeleton.[ch] files to the tools directory.


git-svn-id: http://svn.annodex.net/liboggz/trunk@2378 8158c8cd-e7e1-0310-9fa4-c5954c97daef
parent 32dc4d36
......@@ -28,7 +28,7 @@ noinst_HEADERS = oggz_tools.h
bin_PROGRAMS = $(oggz_read_programs) $(oggz_rw_programs)
noinst_PROGRAMS = $(oggz_read_noinst_programs) $(oggz_rw_noinst_programs)
oggzinfo_SOURCES = oggzinfo.c oggz_tools.c
oggzinfo_SOURCES = oggzinfo.c oggz_tools.c skeleton.c
oggzinfo_LDADD = $(OGGZ_LIBS) -lm
oggzdump_SOURCES = oggzdump.c oggz_tools.c
......@@ -47,4 +47,4 @@ oggz_basetime_SOURCES = oggz-basetime.c oggz_tools.c
oggz_basetime_LDADD = $(OGGZ_LIBS)
oggz_scan_SOURCES = oggz-scan.c oggz_tools.c
oggz_scan_LDADD = $(OGGZ_LIBS)
\ No newline at end of file
oggz_scan_LDADD = $(OGGZ_LIBS)
......@@ -32,6 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> /* LONG_MAX */
#include <math.h>
......@@ -41,6 +42,8 @@
#include <oggz/oggz.h>
#include "oggz_tools.h"
#include "skeleton.h"
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#else
......@@ -112,12 +115,17 @@ struct _OI_TrackInfo {
OI_Stats packets;
const char * codec_name;
char * codec_info;
int has_fishead;
int has_fisbone;
fishead_packet fhInfo;
fisbone_packet fbInfo;
};
static int show_length = 0;
static int show_bitrate = 0;
static int show_page_stats = 0;
static int show_packet_stats = 0;
static int show_extra_skeleton_info = 0;
static void
oggzinfo_apply (OI_TrackFunc func, OI_Info * info)
......@@ -160,6 +168,9 @@ oggzinfo_trackinfo_new (void)
oit->codec_name = NULL;
oit->codec_info = NULL;
oit->has_fishead = 0;
oit->has_fisbone = 0;
return oit;
}
......@@ -192,6 +203,42 @@ oi_stats_print (OI_Info * info, OI_Stats * stats, char * label)
#endif
}
static void
ot_fishead_print(OI_TrackInfo *oit) {
if (oit->has_fishead) {
/*
printf("\tPresentation Time: %.2f\n", (double)oit->fhInfo.ptime_n/oit->fhInfo.ptime_d);
printf("\tBase Time: %.2f\n", (double)oit->fhInfo.btime_n/oit->fhInfo.btime_d);
*/
printf("\tSkeleton version: %d.%d\n", oit->fhInfo.version_major, oit->fhInfo.version_minor);
/*printf("\tUTC: %s\n", oit->fhInfo.UTC);*/
}
}
static void
ot_fisbone_print(OI_TrackInfo *oit) {
char *messages, *token;
if (oit->has_fisbone) {
printf("\n\tExtra information from Ogg Skeleton\n");
printf("\tserialno: %010d\n", oit->fbInfo.serial_no);
printf("\tNumber of header packets: %d\n", oit->fbInfo.nr_header_packet);
printf("\tGranule rate: %.2f\n", (double)oit->fbInfo.granule_rate_n/oit->fbInfo.granule_rate_d);
printf("\tStart granule: %" PRId64 "\n", oit->fbInfo.start_granule);
printf("\tPreroll: %d\n", oit->fbInfo.preroll);
messages = token = _ogg_calloc(oit->fbInfo.current_header_size+1, sizeof(char));
strcpy(messages, oit->fbInfo.message_header_fields);
printf("\tMessage Header Fields:\n");
while (1) {
token = strsep(&messages, "\n\r");
printf("\t %s\n", token);
if (messages == NULL)
break;
}
}
}
/* oggzinfo_trackinfo_print() */
static void
oit_print (OI_Info * info, OI_TrackInfo * oit, long serialno)
......@@ -228,7 +275,15 @@ oit_print (OI_Info * info, OI_TrackInfo * oit, long serialno)
if (show_packet_stats) {
oi_stats_print (info, &oit->packets, "Packet");
}
}
if (show_extra_skeleton_info && oit->has_fishead) {
ot_fishead_print(oit);
}
if (show_extra_skeleton_info && oit->has_fisbone) {
ot_fisbone_print(oit);
}
}
static void
oi_stats_average (OI_Stats * stats)
......@@ -327,6 +382,17 @@ read_packet_pass1 (OGGZ * oggz, ogg_packet * op, long serialno,
if (op->bytes > oit->packets.length_max)
oit->packets.length_max = op->bytes;
if (!op->e_o_s && !memcmp(op->packet, FISBONE_IDENTIFIER, 8)) {
fisbone_packet fp = fisbone_from_ogg(op);
oit = oggz_table_lookup (info->tracks, fp.serial_no);
oit->has_fisbone = 1;
oit->fbInfo = fp;
} else if (!op->e_o_s && !memcmp(op->packet, FISHEAD_IDENTIFIER, 8)) {
fishead_packet fp = fishead_from_ogg(op);
oit->has_fishead = 1;
oit->fhInfo = fp;
}
return 0;
}
......@@ -408,7 +474,7 @@ main (int argc, char ** argv)
}
while (1) {
char * optstring = "hvlbgpa";
char * optstring = "hvlbgpka";
#ifdef HAVE_GETOPT_LONG
static struct option long_options[] = {
......@@ -418,6 +484,7 @@ main (int argc, char ** argv)
{"bitrate", no_argument, 0, 'b'},
{"page-stats", no_argument, 0, 'g'},
{"packet-stats", no_argument, 0, 'p'},
{"skeleton", no_argument, 0, 'k'},
{"all", no_argument, 0, 'a'},
{0,0,0,0}
};
......@@ -451,6 +518,9 @@ main (int argc, char ** argv)
case 'p': /* packet stats */
show_packet_stats = 1;
break;
case 'k': /* extra skeleton info */
show_extra_skeleton_info = 1;
break;
case 'a':
show_all = 1;
break;
......@@ -481,6 +551,7 @@ main (int argc, char ** argv)
show_bitrate = 1;
show_page_stats = 1;
show_packet_stats = 1;
show_extra_skeleton_info = 1;
}
if (argc > optind+1) {
......
/*
* skeleton.c
* author: Tahseen Mohammad
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ogg/ogg.h>
#include "skeleton.h"
/* write an ogg_page to a file pointer */
int write_ogg_page_to_file(ogg_page *og, FILE *out) {
int written;
written = fwrite(og->header,1, og->header_len, out);
written += fwrite(og->body,1, og->body_len, out);
return written;
}
int add_message_header_field(fisbone_packet *fp,
char *header_key,
char *header_value) {
/* size of both key and value + ': ' + CRLF */
int this_message_size = strlen(header_key) + strlen(header_value) + 4;
if (fp->message_header_fields == NULL) {
fp->message_header_fields = _ogg_calloc(this_message_size, sizeof(char));
} else {
int new_size = (fp->current_header_size + this_message_size) * sizeof(char);
fp->message_header_fields = _ogg_realloc(fp->message_header_fields, new_size);
}
snprintf(fp->message_header_fields + fp->current_header_size,
this_message_size+1,
"%s: %s\r\n",
header_key,
header_value);
fp->current_header_size += this_message_size;
return 0;
}
/* create a ogg_packet from a fishead_packet structure */
ogg_packet ogg_from_fishead(fishead_packet *fp) {
ogg_packet op;
memset(&op, 0, sizeof(op));
op.packet = _ogg_calloc(FISHEAD_SIZE, sizeof(unsigned char));
memset(op.packet, 0, FISHEAD_SIZE);
memcpy (op.packet, FISHEAD_IDENTIFIER, 8); /* identifier */
*((ogg_uint16_t*)(op.packet+8)) = SKELETON_VERSION_MAJOR; /* version major */
*((ogg_uint16_t*)(op.packet+10)) = SKELETON_VERSION_MINOR; /* version minor */
*((ogg_int64_t*)(op.packet+12)) = (ogg_int64_t)fp->ptime_n; /* presentationtime numerator */
*((ogg_int64_t*)(op.packet+20)) = (ogg_int64_t)fp->ptime_d; /* presentationtime denominator */
*((ogg_int64_t*)(op.packet+28)) = (ogg_int64_t)fp->btime_n; /* basetime numerator */
*((ogg_int64_t*)(op.packet+36)) = (ogg_int64_t)fp->btime_d; /* basetime denominator */
/* TODO: UTC time, set to zero for now */
op.b_o_s = 1; /* its the first packet of the stream */
op.e_o_s = 0; /* its not the last packet of the stream */
op.bytes = FISHEAD_SIZE; /* length of the packet in bytes */
return op;
}
/* create a ogg_packet from a fisbone_packet structure.
* call this method after the fisbone_packet is filled and all message header fields are added
* by calling add_message_header_field method.
*/
ogg_packet ogg_from_fisbone(fisbone_packet *fp) {
ogg_packet op;
int packet_size = FISBONE_SIZE + fp->current_header_size;
memset (&op, 0, sizeof (op));
op.packet = _ogg_calloc (packet_size, sizeof(unsigned char));
memset (op.packet, 0, packet_size);
memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */
*((ogg_uint32_t*)(op.packet+8)) = FISBONE_MESSAGE_HEADER_OFFSET; /* offset of the message header fields */
*((ogg_uint32_t*)(op.packet+12)) = fp->serial_no; /* serialno of the respective stream */
*((ogg_uint32_t*)(op.packet+16)) = fp->nr_header_packet; /* number of header packets */
*((ogg_int64_t*)(op.packet+20)) = fp->granule_rate_n; /* granulrate numerator */
*((ogg_int64_t*)(op.packet+28)) = fp->granule_rate_d; /* granulrate denominator */
*((ogg_int64_t*)(op.packet+36)) = fp->start_granule; /* start granule */
*((ogg_uint32_t*)(op.packet+44)) = fp->preroll; /* preroll, for theora its 0 */
*(op.packet+48) = fp->granule_shift; /* granule shift */
memcpy((op.packet+FISBONE_SIZE), fp->message_header_fields, fp->current_header_size);
op.b_o_s = 0;
op.e_o_s = 0;
op.bytes = packet_size; /* size of the packet in bytes */
return op;
}
/* fills up a fishead_packet from a fishead ogg_packet of a skeleton bistream */
fishead_packet fishead_from_ogg(ogg_packet *op) {
fishead_packet fp;
if (memcmp(op->packet, FISHEAD_IDENTIFIER, 8))
; /* invalid packet what do we do? */
fp.version_major = *((ogg_uint16_t*)(op->packet+8)); /* version major */
fp.version_minor = *((ogg_uint16_t*)(op->packet+10)); /* version minor */
fp.ptime_n = *((ogg_int64_t*)(op->packet+12)); /* presentationtime numerator */
fp.ptime_d = *((ogg_int64_t*)(op->packet+20)); /* presentationtime denominator */
fp.btime_n = *((ogg_int64_t*)(op->packet+28)); /* basetime numerator */
fp.btime_d = *((ogg_int64_t*)(op->packet+36)); /* basetime denominator */
memcpy(fp.UTC, op->packet+44, 20);
return fp;
}
/* fills up a fisbone_packet from a fisbone ogg_packet of a skeleton bitstream */
fisbone_packet fisbone_from_ogg(ogg_packet *op) {
fisbone_packet fp;
if (memcmp(op->packet, FISBONE_IDENTIFIER, 8))
; /* invalid value, what do we do? */
fp.serial_no = *((ogg_uint32_t*)(op->packet+12)); /* serialno of the stream represented by this fisbone packet */
fp.nr_header_packet = *((ogg_uint32_t*)(op->packet+16)); /* number of header packets */
fp.granule_rate_n = *((ogg_int64_t*)(op->packet+20)); /* granulrate numerator */
fp.granule_rate_d = *((ogg_int64_t*)(op->packet+28)); /* granulrate denominator */
fp.start_granule = *((ogg_int64_t*)(op->packet+36)); /* start granule */
fp.preroll = *((ogg_uint32_t*)(op->packet+44)); /* preroll, for theora its 0 */
fp.granule_shift = *(op->packet+48); /* granule shift */
fp.current_header_size = op->bytes - FISBONE_SIZE;
fp.message_header_fields = _ogg_calloc(fp.current_header_size+1, sizeof(char));
memcpy(fp.message_header_fields, op->packet+FISBONE_SIZE, fp.current_header_size);
return fp;
}
int add_fishead_to_stream(ogg_stream_state *os, fishead_packet *fp) {
ogg_packet op;
op = ogg_from_fishead(fp);
ogg_stream_packetin(os, &op);
_ogg_free(op.packet);
return 0;
}
int add_fisbone_to_stream(ogg_stream_state *os, fisbone_packet *fp) {
ogg_packet op;
op = ogg_from_fisbone(fp);
ogg_stream_packetin(os, &op);
_ogg_free(op.packet);
return 0;
}
int add_eos_packet_to_stream(ogg_stream_state *os) {
ogg_packet op;
memset (&op, 0, sizeof(op));
op.e_o_s = 1;
ogg_stream_packetin(os, &op);
return 0;
}
int flush_ogg_stream_to_file(ogg_stream_state *os, FILE *out) {
ogg_page og;
int result;
while((result = ogg_stream_flush(os, &og)))
{
if(!result) break;
result = write_ogg_page_to_file(&og, out);
if(result != og.header_len + og.body_len)
return 1;
}
return 0;
}
/*
* skeleton.h
* author: Tahseen Mohammad
*/
#ifndef _SKELETON_H
#define _SKELETON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ogg/ogg.h>
#define SKELETON_VERSION_MAJOR 3
#define SKELETON_VERSION_MINOR 0
#define FISHEAD_IDENTIFIER "fishead\0"
#define FISBONE_IDENTIFIER "fisbone\0"
#define FISHEAD_SIZE 64
#define FISBONE_SIZE 52
#define FISBONE_MESSAGE_HEADER_OFFSET 44
/* fishead_packet holds a fishead header packet. */
typedef struct {
ogg_uint16_t version_major; /* skeleton version major */
ogg_uint16_t version_minor; /* skeleton version minor */
/* Start time of the presentation
* For a new stream presentationtime & basetime is same. */
ogg_int64_t ptime_n; /* presentation time numerator */
ogg_int64_t ptime_d; /* presentation time denominator */
ogg_int64_t btime_n; /* basetime numerator */
ogg_int64_t btime_d; /* basetime denominator */
/* will holds the time of origin of the stream, a 20 bit field. */
unsigned char UTC[20];
} fishead_packet;
/* fisbone_packet holds a fisbone header packet. */
typedef struct {
ogg_uint32_t serial_no; /* serial no of the corresponding stream */
ogg_uint32_t nr_header_packet; /* number of header packets */
/* granule rate is the temporal resolution of the logical bitstream */
ogg_int64_t granule_rate_n; /* granule rate numerator */
ogg_int64_t granule_rate_d; /* granule rate denominator */
ogg_int64_t start_granule; /* start granule value */
ogg_uint32_t preroll; /* preroll */
unsigned char granule_shift; /* 1 byte value holding the granule shift */
char *message_header_fields; /* holds all the message header fields */
/* current total size of the message header fields, for realloc purpose, initially zero */
ogg_uint32_t current_header_size;
} fisbone_packet;
extern int write_ogg_page_to_file(ogg_page *og, FILE *out);
extern int add_message_header_field(fisbone_packet *fp, char *header_key, char *header_value);
/* remember to deallocate the returned ogg_packet properly */
extern ogg_packet ogg_from_fishead(fishead_packet *fp);
extern ogg_packet ogg_from_fisbone(fisbone_packet *fp);
extern fishead_packet fishead_from_ogg(ogg_packet *op);
extern fisbone_packet fisbone_from_ogg(ogg_packet *op);
extern int add_fishead_to_stream(ogg_stream_state *os, fishead_packet *fp);
extern int add_fisbone_to_stream(ogg_stream_state *os, fisbone_packet *fp);
extern int add_eos_packet_to_stream(ogg_stream_state *os);
extern int flush_ogg_stream_to_file(ogg_stream_state *os, FILE *out);
#ifdef __cplusplus
}
#endif
#endif /* _SKELETON_H */
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