2
/* Identify an ASF file and its parameters */
10
/* ASF GUIDs (Only the 1st 32bits out of 128 (MSB), enough for our needs). */
11
#define ASF_GUID_SIMPLE_INDEX 0x33000890 /* Simple Index */
12
#define ASF_GUID_HEADER_EXT 0x5fbf03b5 /* Header Extention */
13
#define ASF_GUID_HEADER 0x75b22630 /* Header */
14
#define ASF_GUID_CONTENT_DESC 0x75b22633 /* Content Description */
15
#define ASF_GUID_DATA 0x75b22636 /* Data */
16
#define ASF_GUID_STREAM_BR_PROP 0x7bf875ce /* Stream Bitrate Properties */
17
#define ASF_GUID_CODEC_LIST 0x86d15240 /* Codec List */
18
#define ASF_GUID_FILE_PROP 0x8cabdca1 /* File Properties */
19
#define ASF_GUID_RESERVED1 0xabd3d211 /* Reserved */
20
#define ASF_GUID_STREAM_PROP 0xb7dc0791 /* Stream Properties */
21
#define ASF_GUID_VIDEO_MEDIA 0xbc19efc0 /* Video Media */
22
#define ASF_GUID_EXT_CONT_DESC 0xd2d0a440 /* Extended Content Description */
23
#define ASF_GUID_AUDIO_MEDIA 0xf8699e40 /* Audio Media */
25
typedef struct __attribute__ ((packed)) {
26
unsigned char guid[16];
27
unsigned long long size;
30
typedef struct __attribute__ ((packed)) {
31
asf_obj_header_t objh;
32
unsigned int nho; /* number of header objects */
33
unsigned char reserved1; /* Must be 0x01 and ignored */
34
unsigned char reserved2; /* Must be 0x02 or fail */
37
typedef struct __attribute__ ((packed)) {
38
unsigned char reserved1[16];
39
unsigned short reserved2;
40
unsigned int data_size;
43
typedef struct __attribute__ ((packed)) {
44
unsigned char fileid[16]; /* file ID */
45
unsigned long long file_size; /* entire file size in bytes */
46
unsigned long long creat_date; /* creation date and time */
47
unsigned long long packets; /* number of packets in the data object */
48
unsigned long long play_duration; /* time needed to play file */
49
unsigned long long send_duration; /* time needed to send file */
50
unsigned long long preroll; /* time to buffer data before play */
51
unsigned long flags; /* Flags (Broadcast/Seekable/Reserved) */
52
unsigned long min_packetsize; /* Minimum packet Size in bytes */
53
unsigned long max_packetsize; /* Maximum packet Size in bytes */
54
unsigned long max_bitrate; /* Maximum bitrate */
57
typedef struct __attribute__ ((packed)) {
58
unsigned char stream_type[16]; /* stream type (GUID) */
59
unsigned char errcorr_type[16]; /* error correction type (GUID) */
60
unsigned long long time_offset; /* time offset */
61
unsigned long type_data_len; /* type specific data len */
62
unsigned long errcorr_data_len; /* error correction specific data len */
63
unsigned short flags; /* flags (stream num/reserved/encrypt) */
64
unsigned long reserved;
67
typedef struct __attribute__ ((packed)) {
68
unsigned char reserved[16]; /* reserved (GUID) */
69
unsigned long num_codec; /* number of codec entries in the list */
73
ASF_AUDIO_VOXWARE = 0x0075,
74
ASF_AUDIO_WMA = 0x0160,
75
ASF_AUDIO_WMA2 = 0x0161, /* Version 7 & 8 */
76
ASF_AUDIO_GMS_AMR_CBR = 0x7A21, /* Fixed bitrate, no SID */
77
ASF_AUDIO_GMS_AMR_VBR = 0x7A22 /* Variable bitrate, including SID */
80
typedef struct __attribute__ ((packed)) {
82
unsigned short channels;
83
unsigned long srate; /* in Hertz */
84
unsigned long bitrate; /* in bytes per second of audio stream */
85
unsigned short block_size; /* in bytes */
86
unsigned short bit_per_sample;
87
unsigned short size; /* size of codec specific data */
90
typedef struct __attribute__ ((packed)) {
91
unsigned long data_size;
92
unsigned long width; /* in pixels */
93
unsigned long height; /* in pixels */
94
unsigned short planes; /* reserved, always 1 */
95
unsigned short depth; /* bits per pixel */
98
unsigned long hppm; /* horizontal pixels per meter */
99
unsigned long vppm; /* vertical pixels per meter */
100
unsigned long colors;
101
unsigned long imp_colors;
102
} asf_video_format_t;
104
typedef struct __attribute__ ((packed)) {
105
unsigned long width; /* in pixels */
106
unsigned long height; /* in pixels */
107
char flags; /* = 2 */
108
unsigned short data_size;
109
asf_video_format_t data;
112
int MEDIA_expectguid(char *expect, char *read) {
114
if (strncmp(expect, read, 4) != 0) {
115
strncpy(buf, read, 4);
117
printf("*ERR* Read '%s' but '%s' was expected\n", buf, expect);
123
int MEDIA_isguid(ulong expect, ulong read) {
124
//printf("except 0x%08lx, read 0x%08lx\n", expect, read);
125
return (expect == read);
128
int MEDIA_identify_asf(FILE *fd) {
130
asf_obj_header_t objh;
131
asf_file_prop_t asffp;
132
asf_stream_prop_t strp;
133
asf_codec_list_t codecs;
134
asf_header_ext_t exth;
135
int stop, ttime, i, j;
142
/* Read header object */
143
fread(&asfh, sizeof(asfh), 1, fd);
144
if (MEDIA_isguid(ASF_GUID_HEADER, *((ulong *) asfh.objh.guid)) == 0) {
145
fseek(fd, opos, SEEK_SET);
148
printf("Format: ASF\n");
149
//printf("Header Size: 0x%x\n", (int) asfh.objh.size);
152
while (fread(&objh, sizeof(objh), 1, fd) > 0) {
154
//fprintf(stderr, "[0x%08lx] size: %lld bytes\n",
155
// (ulong) pos - sizeof(objh), objh.size);
156
// dump_hex(stderr, (uchar *)&objh, sizeof(objh), opos);
157
guid = *((ulong *) &objh.guid);
159
case ASF_GUID_FILE_PROP:
160
if (fread(&asffp, sizeof(asffp), 1, fd) < 0) {
164
fstat(fileno(fd), &fs);
165
if (fs.st_size == asffp.file_size)
166
printf("Size: %llu bytes (%.1f MB)\n", asffp.file_size,
167
asffp.file_size / 1048576.);
169
double d = (double) asffp.file_size;
170
printf("*WARN* Expected size: %llu bytes (%.1f MB)\n"
171
" Missing: %ld bytes (%.1f MB - %.1f%%)\n",
172
asffp.file_size, d / 1048576.,
173
(ulong) asffp.file_size - (ulong) fs.st_size,
174
((ulong) asffp.file_size - (ulong) fs.st_size) / 1048576.,
175
(double) ((ulong) asffp.file_size - fs.st_size) /
176
(double) asffp.file_size * 100.);
178
ttime = asffp.play_duration / 10000000; /* 100 nano-seconds */
179
printf("Length: %d:%02d:%02d\n", ttime / 3600, (ttime / 60) % 60,
181
/* printf("packets: %d, flags: %d, pack_size: %d, max_bitrate: %d\n",
182
(int) asffp.packets, (int) asffp.flags,
183
(int) asffp.min_packetsize, (int) asffp.max_bitrate); */
184
printf("ASF flags:%s%s\n", asffp.flags & 0x01 ? " BROADCAST" : "",
185
asffp.flags & 0x02 ? " SEEKABLE" : "");
187
case ASF_GUID_HEADER_EXT:
188
if (fread(&exth, sizeof(exth), 1, fd) < 0) {
192
if (exth.data_size > 0) {
193
printf("Extention header data: %d bytes\n", exth.data_size);
194
buf = (uchar *) malloc(exth.data_size);
195
if (fread(buf, 1, exth.data_size, fd) < 0) {
199
dump_hex(stderr, buf, exth.data_size, opos);
202
case ASF_GUID_CONTENT_DESC:
203
printf("GUID content description\n");
205
case ASF_GUID_CODEC_LIST:
206
// printf("GUID codec list\n");
207
if (fread(&codecs, sizeof(codecs), 1, fd) < 0) {
211
buf = (uchar *) malloc(objh.size);
212
if (fread(buf, 1, objh.size, fd) < 0) {
216
// dump_hex(stderr, buf, objh.size, opos);
217
// printf("number of codecs: %ld\n", codecs.num_codec);
219
for (i = 1; i <= codecs.num_codec; i++) {
220
ushort type, lname, ldesc, linfo;
221
char *name, *desc, *info, *q;
222
type = *((ushort *) p);
224
lname = *((ushort *) p);
226
name = (char *) malloc(lname + 1);
227
for (q = name, j = 0; j < lname; j++, p += 2)
228
q += sprintf(q, "%c", *(ushort *) p);
230
ldesc = *((ushort *) p);
232
desc = (char *) malloc(ldesc + 1);
233
for (q = desc, j = 0; j < ldesc; j++, p += 2)
234
q += sprintf(q, "%c", *(ushort *) p);
236
linfo = *((ushort *) p);
238
if (type == 0x0002) {
239
switch(*((ushort *) p)) {
241
info = strdup("WMA");
244
info = strdup("WMA2");
246
case ASF_AUDIO_GMS_AMR_CBR:
247
info = strdup("GSM_AMR_CBR");
249
case ASF_AUDIO_GMS_AMR_VBR:
250
info = strdup("GMS_AMR_VBR");
252
case ASF_AUDIO_VOXWARE:
253
info = strdup("VOXWARE");
256
info = (char *) malloc(7);
257
sprintf(info, "0x%04x", *((ushort *) p));
262
info = (char *) malloc(5 * linfo + 1);
263
q = info; /* + sprintf(info, "0x"); */
264
for (j = 0; j < linfo; j++, p++)
265
if (*p >= 32 && *p < 127)
266
q += sprintf(q, "%c", *p);
268
q += sprintf(q, "%02x", *p);
272
printf("codec #%d: [%s] %s, '%s' '%s'\n",
273
i, type == 0x0001 ? "VIDEO" : type == 0x0002 ? "AUDIO" : "?",
281
case ASF_GUID_STREAM_PROP:
282
// printf("GUID stream properties\n");
283
if (fread(&strp, sizeof(strp), 1, fd) < 0) {
287
if (strp.type_data_len > 0) {
288
asf_audio_type_t *auds;
289
asf_video_type_t *vids;
292
// printf("Type specific data: %lu bytes\n", strp.type_data_len);
293
buf = (uchar *) malloc(strp.type_data_len);
294
if (fread(buf, 1, strp.type_data_len, fd) < 0) {
298
switch (*((ulong *) &strp.stream_type)) {
299
case ASF_GUID_AUDIO_MEDIA:
300
auds = (asf_audio_type_t *) buf;
301
switch(auds->codec) {
303
info = strdup("WMA");
306
info = strdup("WMA2");
308
case ASF_AUDIO_GMS_AMR_CBR:
309
info = strdup("GSM_AMR_CBR");
311
case ASF_AUDIO_GMS_AMR_VBR:
312
info = strdup("GMS_AMR_VBR");
314
case ASF_AUDIO_VOXWARE:
315
info = strdup("VOXWARE");
318
info = (char *) malloc(7);
319
sprintf(info, "0x%04x", *((ushort *) buf));
321
printf("[AUDIO] %s, %lu Hz, %.1f kbps, %s\n",
322
info, auds->srate, (double) auds->bitrate * 8. / 1000.,
323
auds->channels == 2 ? "Stereo" :
324
auds->channels == 1 ? "Mono" : "FIXME");
325
if (0 && auds->size != 0)
326
dump_hex(stderr, buf + sizeof(asf_audio_type_t),
330
case ASF_GUID_VIDEO_MEDIA:
331
vids = (asf_video_type_t *) buf;
332
printf("[VIDEO] %c%c%c%c, %lux%lu, %u bpp, %u plane\n",
333
(char) (vids->data.codec & 0xFF),
334
(char) ((vids->data.codec >> 8) & 0xFF),
335
(char) ((vids->data.codec >> 16) & 0xFF),
336
(char) (vids->data.codec >> 24),
337
vids->data.width, vids->data.height,
338
vids->data.depth, vids->data.planes);
341
printf("Stream #%d unrecognized\n", strp.flags & 0x003F);
342
dump_hex(stderr, buf, strp.type_data_len, opos);
345
if (0 && strp.errcorr_data_len > 0) {
346
printf("Error correction specific data: %lu bytes\n",
347
strp.errcorr_data_len);
348
buf = (uchar *) malloc(strp.errcorr_data_len);
349
if (fread(buf, 1, strp.errcorr_data_len, fd) < 0) {
353
dump_hex(stderr, buf, strp.errcorr_data_len, opos);
356
case ASF_GUID_EXT_CONT_DESC:
357
printf("GUID Extended Content Description\n");
359
case ASF_GUID_STREAM_BR_PROP:
360
printf("GUID stream bitrate properties\n");
362
case ASF_GUID_AUDIO_MEDIA:
363
printf("GUID audio stream\n");
365
case ASF_GUID_SIMPLE_INDEX:
366
//printf("GUID simple index\n");
369
//printf("GUID data\n");
373
printf("GUID 0x%08lx unknown\n", guid);
377
fseek(fd, pos + objh.size - sizeof(objh), SEEK_SET);