aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/old/flv_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/old/flv_extractor.c')
-rw-r--r--src/plugins/old/flv_extractor.c878
1 files changed, 482 insertions, 396 deletions
diff --git a/src/plugins/old/flv_extractor.c b/src/plugins/old/flv_extractor.c
index f7d762d..2104d79 100644
--- a/src/plugins/old/flv_extractor.c
+++ b/src/plugins/old/flv_extractor.c
@@ -55,16 +55,18 @@
55#define ASTYPE_TYPEDOBJECT 0x10 55#define ASTYPE_TYPEDOBJECT 0x10
56#define ASTYPE_AMF3DATA 0x11 56#define ASTYPE_AMF3DATA 0x11
57 57
58typedef struct { 58typedef struct
59 void * userdata; 59{
60 void (*as_begin_callback)(unsigned char type, void * userdata); 60 void *userdata;
61 void (*as_key_callback)(char * key, void * userdata); 61 void (*as_begin_callback)(unsigned char type, void *userdata);
62 void (*as_end_callback)(unsigned char type, void * value, void * userdata); 62 void (*as_key_callback)(char *key, void *userdata);
63 void (*as_end_callback)(unsigned char type, void *value, void *userdata);
63} AMFParserHandler; 64} AMFParserHandler;
64 65
65/* core datatypes */ 66/* core datatypes */
66 67
67static uint32_t readInt32(const unsigned char **data) 68static uint32_t
69readInt32 (const unsigned char **data)
68{ 70{
69 const unsigned char *ptr = *data; 71 const unsigned char *ptr = *data;
70 uint32_t val; 72 uint32_t val;
@@ -75,7 +77,9 @@ static uint32_t readInt32(const unsigned char **data)
75 return val; 77 return val;
76} 78}
77 79
78static uint32_t readInt24(const unsigned char **data) 80
81static uint32_t
82readInt24 (const unsigned char **data)
79{ 83{
80 const unsigned char *ptr = *data; 84 const unsigned char *ptr = *data;
81 uint32_t val; 85 uint32_t val;
@@ -86,7 +90,9 @@ static uint32_t readInt24(const unsigned char **data)
86 return val; 90 return val;
87} 91}
88 92
89static uint16_t readInt16(const unsigned char **data) 93
94static uint16_t
95readInt16 (const unsigned char **data)
90{ 96{
91 const unsigned char *ptr = *data; 97 const unsigned char *ptr = *data;
92 uint16_t val; 98 uint16_t val;
@@ -97,14 +103,17 @@ static uint16_t readInt16(const unsigned char **data)
97 return val; 103 return val;
98} 104}
99 105
100static double readDouble(const unsigned char **data) 106
107static double
108readDouble (const unsigned char **data)
101{ 109{
102 const unsigned char *ptr = *data; 110 const unsigned char *ptr = *data;
103 double val; 111 double val;
104 112
105 EXTRACTOR_common_floatformat_to_double(&EXTRACTOR_floatformat_ieee_double_big, 113 EXTRACTOR_common_floatformat_to_double (
106 (const void *)ptr, 114 &EXTRACTOR_floatformat_ieee_double_big,
107 &val); 115 (const void *) ptr,
116 &val);
108 ptr += 8; 117 ptr += 8;
109 *data = ptr; 118 *data = ptr;
110 return val; 119 return val;
@@ -113,9 +122,10 @@ static double readDouble(const unsigned char **data)
113 122
114/* actionscript types */ 123/* actionscript types */
115 124
116static int readASNumber(const unsigned char **data, 125static int
117 size_t *len, 126readASNumber (const unsigned char **data,
118 double *retval) 127 size_t *len,
128 double *retval)
119{ 129{
120 const unsigned char *ptr = *data; 130 const unsigned char *ptr = *data;
121 double val; 131 double val;
@@ -123,7 +133,7 @@ static int readASNumber(const unsigned char **data,
123 if (*len < 8) 133 if (*len < 8)
124 return -1; 134 return -1;
125 135
126 val = readDouble(&ptr); 136 val = readDouble (&ptr);
127 *len -= 8; 137 *len -= 8;
128 138
129 *retval = val; 139 *retval = val;
@@ -131,9 +141,11 @@ static int readASNumber(const unsigned char **data,
131 return 0; 141 return 0;
132} 142}
133 143
134static int readASBoolean(const unsigned char **data, 144
135 size_t *len, 145static int
136 int *retval) 146readASBoolean (const unsigned char **data,
147 size_t *len,
148 int *retval)
137{ 149{
138 const unsigned char *ptr = *data; 150 const unsigned char *ptr = *data;
139 int val; 151 int val;
@@ -150,29 +162,33 @@ static int readASBoolean(const unsigned char **data,
150 return 0; 162 return 0;
151} 163}
152 164
153static int readASDate(const unsigned char **data, 165
154 size_t *len, 166static int
155 double *millis, 167readASDate (const unsigned char **data,
156 short *zone) 168 size_t *len,
169 double *millis,
170 short *zone)
157{ 171{
158 const unsigned char *ptr = *data; 172 const unsigned char *ptr = *data;
159 173
160 if (*len < 10) 174 if (*len < 10)
161 return -1; 175 return -1;
162 176
163 *millis = readDouble(&ptr); 177 *millis = readDouble (&ptr);
164 *len -= 8; 178 *len -= 8;
165 179
166 *zone = readInt16(&ptr); 180 *zone = readInt16 (&ptr);
167 *len -= 2; 181 *len -= 2;
168 182
169 *data = ptr; 183 *data = ptr;
170 return 0; 184 return 0;
171} 185}
172 186
173static int readASString(const unsigned char **data, 187
174 size_t *len, 188static int
175 char **retval) 189readASString (const unsigned char **data,
190 size_t *len,
191 char **retval)
176{ 192{
177 const unsigned char *ptr = *data; 193 const unsigned char *ptr = *data;
178 char *ret; 194 char *ret;
@@ -181,15 +197,15 @@ static int readASString(const unsigned char **data,
181 if (*len < 2) 197 if (*len < 2)
182 return -1; 198 return -1;
183 199
184 slen = readInt16(&ptr); 200 slen = readInt16 (&ptr);
185 201
186 if (*len < (2 + slen)) 202 if (*len < (2 + slen))
187 return -1; 203 return -1;
188 204
189 ret = malloc(slen+1); 205 ret = malloc (slen + 1);
190 if (ret == NULL) 206 if (ret == NULL)
191 return -1; 207 return -1;
192 memcpy(ret, ptr, slen); 208 memcpy (ret, ptr, slen);
193 ret[slen] = '\0'; 209 ret[slen] = '\0';
194 ptr += slen; 210 ptr += slen;
195 *len -= (2 + slen); 211 *len -= (2 + slen);
@@ -199,9 +215,11 @@ static int readASString(const unsigned char **data,
199 return 0; 215 return 0;
200} 216}
201 217
202static int parse_amf(const unsigned char **data, 218
203 size_t *len, 219static int
204 AMFParserHandler *handler) 220parse_amf (const unsigned char **data,
221 size_t *len,
222 AMFParserHandler *handler)
205{ 223{
206 const unsigned char *ptr = *data; 224 const unsigned char *ptr = *data;
207 unsigned char astype; 225 unsigned char astype;
@@ -210,45 +228,47 @@ static int parse_amf(const unsigned char **data,
210 ret = 0; 228 ret = 0;
211 astype = *ptr++; 229 astype = *ptr++;
212 (*(handler->as_begin_callback))(astype, handler->userdata); 230 (*(handler->as_begin_callback))(astype, handler->userdata);
213 switch (astype) { 231 switch (astype)
214 case ASTYPE_NUMBER: 232 {
233 case ASTYPE_NUMBER:
215 { 234 {
216 double val; 235 double val;
217 ret = readASNumber(&ptr, len, &val); 236 ret = readASNumber (&ptr, len, &val);
218 if (ret == 0) 237 if (ret == 0)
219 (*(handler->as_end_callback))(astype, 238 (*(handler->as_end_callback))(astype,
220 &val, 239 &val,
221 handler->userdata); 240 handler->userdata);
222 break; 241 break;
223 } 242 }
224 case ASTYPE_BOOLEAN: 243 case ASTYPE_BOOLEAN:
225 { 244 {
226 int val; 245 int val;
227 ret = readASBoolean(&ptr, len, &val); 246 ret = readASBoolean (&ptr, len, &val);
228 if (ret == 0) 247 if (ret == 0)
229 (*(handler->as_end_callback))(astype, 248 (*(handler->as_end_callback))(astype,
230 &val, 249 &val,
231 handler->userdata); 250 handler->userdata);
232 break; 251 break;
233 } 252 }
234 case ASTYPE_STRING: 253 case ASTYPE_STRING:
235 { 254 {
236 char *val; 255 char *val;
237 ret = readASString(&ptr, len, &val); 256 ret = readASString (&ptr, len, &val);
238 if (ret == 0) { 257 if (ret == 0)
258 {
239 (*(handler->as_end_callback))(astype, 259 (*(handler->as_end_callback))(astype,
240 val, 260 val,
241 handler->userdata); 261 handler->userdata);
242 free(val); 262 free (val);
243 } 263 }
244 break; 264 break;
245 } 265 }
246 case ASTYPE_DATE: 266 case ASTYPE_DATE:
247 { 267 {
248 void *tmp[2]; 268 void *tmp[2];
249 double millis; 269 double millis;
250 short tz; 270 short tz;
251 ret = readASDate(&ptr, len, &millis, &tz); 271 ret = readASDate (&ptr, len, &millis, &tz);
252 tmp[0] = &millis; 272 tmp[0] = &millis;
253 tmp[1] = &tz; 273 tmp[1] = &tz;
254 if (ret == 0) 274 if (ret == 0)
@@ -257,53 +277,56 @@ static int parse_amf(const unsigned char **data,
257 handler->userdata); 277 handler->userdata);
258 break; 278 break;
259 } 279 }
260 case ASTYPE_NULL: 280 case ASTYPE_NULL:
261 case ASTYPE_UNDEFINED: 281 case ASTYPE_UNDEFINED:
262 case ASTYPE_UNSUPPORTED: 282 case ASTYPE_UNSUPPORTED:
263 case ASTYPE_ENDOFOBJECT: 283 case ASTYPE_ENDOFOBJECT:
264 (*(handler->as_end_callback))(astype, NULL, handler->userdata); 284 (*(handler->as_end_callback))(astype, NULL, handler->userdata);
265 break; 285 break;
266 case ASTYPE_ARRAY: 286 case ASTYPE_ARRAY:
267 { 287 {
268 long i, alen; 288 long i, alen;
269 if (*len < 4) { 289 if (*len < 4)
290 {
270 ret = -1; 291 ret = -1;
271 break; 292 break;
272 } 293 }
273 alen = readInt32(&ptr); 294 alen = readInt32 (&ptr);
274 *len -= 4; 295 *len -= 4;
275 for (i = 0; i < alen; i++) { 296 for (i = 0; i < alen; i++)
276 ret = parse_amf(&ptr, len, handler); 297 {
298 ret = parse_amf (&ptr, len, handler);
277 if (ret == -1) 299 if (ret == -1)
278 break; 300 break;
279 } 301 }
280 (*(handler->as_end_callback))(ASTYPE_ARRAY, 302 (*(handler->as_end_callback))(ASTYPE_ARRAY,
281 NULL, 303 NULL,
282 handler->userdata); 304 handler->userdata);
283 break; 305 break;
284 } 306 }
285 case ASTYPE_OBJECT: 307 case ASTYPE_OBJECT:
286 { 308 {
287 char *key; 309 char *key;
288 unsigned char type; 310 unsigned char type;
289 311
290 ret = readASString(&ptr, len, &key); 312 ret = readASString (&ptr, len, &key);
291 if (ret == -1) 313 if (ret == -1)
292 break; 314 break;
293 (*(handler->as_key_callback))(key, 315 (*(handler->as_key_callback))(key,
294 handler->userdata); 316 handler->userdata);
295 free(key); 317 free (key);
296 type = *ptr; 318 type = *ptr;
297 while (type != ASTYPE_ENDOFOBJECT) { 319 while (type != ASTYPE_ENDOFOBJECT)
298 ret = parse_amf(&ptr, len, handler); 320 {
321 ret = parse_amf (&ptr, len, handler);
299 if (ret == -1) 322 if (ret == -1)
300 break; 323 break;
301 ret = readASString(&ptr, len, &key); 324 ret = readASString (&ptr, len, &key);
302 if (ret == -1) 325 if (ret == -1)
303 break; 326 break;
304 (*(handler->as_key_callback))(key, 327 (*(handler->as_key_callback))(key,
305 handler->userdata); 328 handler->userdata);
306 free(key); 329 free (key);
307 type = *ptr; 330 type = *ptr;
308 } 331 }
309 if (ret == 0) 332 if (ret == 0)
@@ -312,34 +335,36 @@ static int parse_amf(const unsigned char **data,
312 handler->userdata); 335 handler->userdata);
313 break; 336 break;
314 } 337 }
315 case ASTYPE_MIXEDARRAY: 338 case ASTYPE_MIXEDARRAY:
316 { 339 {
317 char *key; 340 char *key;
318 unsigned char type; 341 unsigned char type;
319 342
320 if (*len < 4) { 343 if (*len < 4)
344 {
321 ret = -1; 345 ret = -1;
322 break; 346 break;
323 } 347 }
324 /* max_index */ readInt32(&ptr); 348 /* max_index */ readInt32 (&ptr);
325 *len -= 4; 349 *len -= 4;
326 ret = readASString(&ptr, len, &key); 350 ret = readASString (&ptr, len, &key);
327 if (ret == -1) 351 if (ret == -1)
328 break; 352 break;
329 (*(handler->as_key_callback))(key, 353 (*(handler->as_key_callback))(key,
330 handler->userdata); 354 handler->userdata);
331 free(key); 355 free (key);
332 type = *ptr; 356 type = *ptr;
333 while (type != ASTYPE_ENDOFOBJECT) { 357 while (type != ASTYPE_ENDOFOBJECT)
334 ret = parse_amf(&ptr, len, handler); 358 {
359 ret = parse_amf (&ptr, len, handler);
335 if (ret == -1) 360 if (ret == -1)
336 break; 361 break;
337 ret = readASString(&ptr, len, &key); 362 ret = readASString (&ptr, len, &key);
338 if (ret == -1) 363 if (ret == -1)
339 break; 364 break;
340 (*(handler->as_key_callback))(key, 365 (*(handler->as_key_callback))(key,
341 handler->userdata); 366 handler->userdata);
342 free(key); 367 free (key);
343 type = *ptr; 368 type = *ptr;
344 } 369 }
345 if (ret == 0) 370 if (ret == 0)
@@ -348,21 +373,22 @@ static int parse_amf(const unsigned char **data,
348 handler->userdata); 373 handler->userdata);
349 break; 374 break;
350 } 375 }
351 default: 376 default:
352 ret = -1; 377 ret = -1;
353 (*(handler->as_end_callback))(astype, 378 (*(handler->as_end_callback))(astype,
354 NULL, 379 NULL,
355 handler->userdata); 380 handler->userdata);
356#if DEBUG 381#if DEBUG
357 printf("parse_amf: Unknown type %02x", astype); 382 printf ("parse_amf: Unknown type %02x", astype);
358#endif 383#endif
359 break; 384 break;
360 } 385 }
361 386
362 *data = ptr; 387 *data = ptr;
363 return ret; 388 return ret;
364} 389}
365 390
391
366/* 392/*
367 * FLV parser 393 * FLV parser
368 */ 394 */
@@ -379,8 +405,9 @@ flv_to_iso_date (double timeval, short timezone,
379 * shift epoch to proleptic times 405 * shift epoch to proleptic times
380 * to make subsequent modulo operations safer. 406 * to make subsequent modulo operations safer.
381 */ 407 */
382 long long my_timeval = (timeval/1000) 408 long long my_timeval = (timeval / 1000)
383 + ((long long) ((1970 * 365) + 478) * (long long) 86400); 409 + ((long long) ((1970 * 365) + 478) * (long
410 long) 86400);
384 411
385 unsigned int seconds = (unsigned int) (my_timeval % 60); 412 unsigned int seconds = (unsigned int) (my_timeval % 60);
386 unsigned int minutes = (unsigned int) ((my_timeval / 60) % 60); 413 unsigned int minutes = (unsigned int) ((my_timeval / 60) % 60);
@@ -396,7 +423,7 @@ flv_to_iso_date (double timeval, short timezone,
396 unsigned int days = (unsigned int) (my_timeval / (24 * 3600)); 423 unsigned int days = (unsigned int) (my_timeval / (24 * 3600));
397 424
398 unsigned int days_in_month[] = 425 unsigned int days_in_month[] =
399 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 426 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
400 unsigned int diff = 0; 427 unsigned int diff = 0;
401 428
402 if ((long long) 0 > my_timeval) 429 if ((long long) 0 > my_timeval)
@@ -413,15 +440,15 @@ flv_to_iso_date (double timeval, short timezone,
413 */ 440 */
414 diff = (days / ((365 * 100) + 24)); 441 diff = (days / ((365 * 100) + 24));
415 if (4 <= diff) 442 if (4 <= diff)
416 { 443 {
417 year += 399; 444 year += 399;
418 days = 364; 445 days = 364;
419 } 446 }
420 else 447 else
421 { 448 {
422 year += (100 * diff); 449 year += (100 * diff);
423 days %= ((365 * 100) + 24); 450 days %= ((365 * 100) + 24);
424 } 451 }
425 452
426 /* 453 /*
427 * remaining leap years 454 * remaining leap years
@@ -430,32 +457,32 @@ flv_to_iso_date (double timeval, short timezone,
430 days %= ((365 * 4) + 1); 457 days %= ((365 * 4) + 1);
431 458
432 while (1) 459 while (1)
460 {
461 if ((0 == (year % 400)) || ((0 == (year % 4)) && (0 != (year % 100))))
433 { 462 {
434 if ((0 == (year % 400)) || ((0 == (year % 4)) && (0 != (year % 100)))) 463 if (366 > days)
435 { 464 {
436 if (366 > days) 465 break;
437 { 466 }
438 break;
439 }
440 else
441 {
442 days -= 366;
443 year++;
444 }
445 }
446 else 467 else
447 { 468 {
448 if (365 > days) 469 days -= 366;
449 { 470 year++;
450 break; 471 }
451 } 472 }
452 else 473 else
453 { 474 {
454 days -= 365; 475 if (365 > days)
455 year++; 476 {
456 } 477 break;
457 } 478 }
479 else
480 {
481 days -= 365;
482 year++;
483 }
458 } 484 }
485 }
459 486
460 if ((0 == (year % 400)) || ((0 == (year % 4)) && (0 != (year % 100)))) 487 if ((0 == (year % 400)) || ((0 == (year % 4)) && (0 != (year % 100))))
461 days_in_month[1] = 29; 488 days_in_month[1] = 29;
@@ -465,12 +492,12 @@ flv_to_iso_date (double timeval, short timezone,
465 492
466 zone_sign = 0; 493 zone_sign = 0;
467 if (timezone < 0) 494 if (timezone < 0)
468 { 495 {
469 zone_sign = -1; 496 zone_sign = -1;
470 timezone = -timezone; 497 timezone = -timezone;
471 } 498 }
472 zone_hours = timezone/60; 499 zone_hours = timezone / 60;
473 zone_minutes = timezone - zone_hours*60; 500 zone_minutes = timezone - zone_hours * 60;
474 501
475 retval = snprintf (rtime, rsize, "%04u-%02u-%02uT%02u:%02u:%02u%c%02d:%02u", 502 retval = snprintf (rtime, rsize, "%04u-%02u-%02uT%02u:%02u:%02u%c%02d:%02u",
476 year, month + 1, days + 1, hours, minutes, seconds, 503 year, month + 1, days + 1, hours, minutes, seconds,
@@ -479,6 +506,7 @@ flv_to_iso_date (double timeval, short timezone,
479 return (retval < rsize) ? 0 : EOVERFLOW; 506 return (retval < rsize) ? 0 : EOVERFLOW;
480} 507}
481 508
509
482typedef struct 510typedef struct
483{ 511{
484 char signature[3]; 512 char signature[3];
@@ -503,20 +531,21 @@ typedef struct
503 531
504#define FLV_TAG_HEADER_SIZE 11 532#define FLV_TAG_HEADER_SIZE 11
505 533
506static int readFLVHeader(const unsigned char **data, 534static int
507 const unsigned char *end, 535readFLVHeader (const unsigned char **data,
508 FLVHeader *hdr) 536 const unsigned char *end,
537 FLVHeader *hdr)
509{ 538{
510 const unsigned char *ptr = *data; 539 const unsigned char *ptr = *data;
511 540
512 if ((ptr + FLV_HEADER_SIZE) > end) 541 if ((ptr + FLV_HEADER_SIZE) > end)
513 return -1; 542 return -1;
514 543
515 memcpy(hdr->signature, ptr, 3); 544 memcpy (hdr->signature, ptr, 3);
516 ptr += 3; 545 ptr += 3;
517 hdr->version = *ptr++; 546 hdr->version = *ptr++;
518 hdr->flags = *ptr++; 547 hdr->flags = *ptr++;
519 hdr->offset = readInt32(&ptr); 548 hdr->offset = readInt32 (&ptr);
520 if (hdr->offset != FLV_HEADER_SIZE) 549 if (hdr->offset != FLV_HEADER_SIZE)
521 return -1; 550 return -1;
522 551
@@ -524,24 +553,28 @@ static int readFLVHeader(const unsigned char **data,
524 return 0; 553 return 0;
525} 554}
526 555
527static int readPreviousTagSize(const unsigned char **data, 556
528 const unsigned char *end, 557static int
529 unsigned long *prev_size) 558readPreviousTagSize (const unsigned char **data,
559 const unsigned char *end,
560 unsigned long *prev_size)
530{ 561{
531 const unsigned char *ptr = *data; 562 const unsigned char *ptr = *data;
532 563
533 if ((ptr + 4) > end) 564 if ((ptr + 4) > end)
534 return -1; 565 return -1;
535 566
536 *prev_size = readInt32(&ptr); 567 *prev_size = readInt32 (&ptr);
537 568
538 *data = ptr; 569 *data = ptr;
539 return 0; 570 return 0;
540} 571}
541 572
542static int readFLVTagHeader(const unsigned char **data, 573
543 const unsigned char *end, 574static int
544 FLVTagHeader *hdr) 575readFLVTagHeader (const unsigned char **data,
576 const unsigned char *end,
577 FLVTagHeader *hdr)
545{ 578{
546 const unsigned char *ptr = *data; 579 const unsigned char *ptr = *data;
547 580
@@ -549,15 +582,17 @@ static int readFLVTagHeader(const unsigned char **data,
549 return -1; 582 return -1;
550 583
551 hdr->type = *ptr++; 584 hdr->type = *ptr++;
552 hdr->bodyLength = readInt24(&ptr); 585 hdr->bodyLength = readInt24 (&ptr);
553 hdr->timestamp = readInt32(&ptr); 586 hdr->timestamp = readInt32 (&ptr);
554 hdr->streamId = readInt24(&ptr); 587 hdr->streamId = readInt24 (&ptr);
555 588
556 *data = ptr; 589 *data = ptr;
557 return 0; 590 return 0;
558} 591}
559 592
560typedef struct { 593
594typedef struct
595{
561 int videoCodec; 596 int videoCodec;
562 char *videoCodecStr; 597 char *videoCodecStr;
563 int videoWidth; 598 int videoWidth;
@@ -573,7 +608,8 @@ typedef struct {
573 int audioRate; 608 int audioRate;
574} FLVStreamInfo; 609} FLVStreamInfo;
575 610
576typedef enum { 611typedef enum
612{
577 FLV_NONE = 0, 613 FLV_NONE = 0,
578 FLV_WIDTH, 614 FLV_WIDTH,
579 FLV_HEIGHT, 615 FLV_HEIGHT,
@@ -586,7 +622,8 @@ typedef enum {
586 FLV_ACODECID 622 FLV_ACODECID
587} FLVStreamAttribute; 623} FLVStreamAttribute;
588 624
589typedef struct { 625typedef struct
626{
590 const char *key; 627 const char *key;
591 FLVStreamAttribute attribute; 628 FLVStreamAttribute attribute;
592} MetaKeyToStreamAttribute; 629} MetaKeyToStreamAttribute;
@@ -605,7 +642,8 @@ static MetaKeyToStreamAttribute key_to_attribute_map[] = {
605 { NULL, FLV_NONE } 642 { NULL, FLV_NONE }
606}; 643};
607 644
608typedef struct { 645typedef struct
646{
609 const char *key; 647 const char *key;
610 enum EXTRACTOR_MetaType type; 648 enum EXTRACTOR_MetaType type;
611} MetaKeyToExtractorItem; 649} MetaKeyToExtractorItem;
@@ -619,7 +657,8 @@ static MetaKeyToExtractorItem key_to_extractor_map[] = {
619 { NULL, EXTRACTOR_METATYPE_RESERVED } 657 { NULL, EXTRACTOR_METATYPE_RESERVED }
620}; 658};
621 659
622typedef struct { 660typedef struct
661{
623 int onMetaData; 662 int onMetaData;
624 int parsingDepth; 663 int parsingDepth;
625 int ret; 664 int ret;
@@ -632,22 +671,25 @@ typedef struct {
632 FLVStreamInfo *streamInfo; 671 FLVStreamInfo *streamInfo;
633} FLVMetaParserState; 672} FLVMetaParserState;
634 673
635static void handleASBegin(unsigned char type, void * userdata) 674static void
675handleASBegin (unsigned char type, void *userdata)
636{ 676{
637 FLVMetaParserState *state = (FLVMetaParserState *)userdata; 677 FLVMetaParserState *state = (FLVMetaParserState *) userdata;
638 678
639 if (state->onMetaData && state->parsingDepth == 0 && 679 if (state->onMetaData && (state->parsingDepth == 0) &&
640 type != ASTYPE_MIXEDARRAY) 680 (type != ASTYPE_MIXEDARRAY) )
641 state->onMetaData = 0; 681 state->onMetaData = 0;
642 682
643 if (type == ASTYPE_ARRAY || type == ASTYPE_MIXEDARRAY || 683 if ((type == ASTYPE_ARRAY) || (type == ASTYPE_MIXEDARRAY) ||
644 type == ASTYPE_OBJECT) 684 (type == ASTYPE_OBJECT) )
645 state->parsingDepth++; 685 state->parsingDepth++;
646} 686}
647 687
648static void handleASKey(char * key, void * userdata) 688
689static void
690handleASKey (char *key, void *userdata)
649{ 691{
650 FLVMetaParserState *state = (FLVMetaParserState *)userdata; 692 FLVMetaParserState *state = (FLVMetaParserState *) userdata;
651 int i; 693 int i;
652 694
653 if (key == NULL) 695 if (key == NULL)
@@ -655,26 +697,29 @@ static void handleASKey(char * key, void * userdata)
655 697
656 i = 0; 698 i = 0;
657 while ((key_to_extractor_map[i].key != NULL) && 699 while ((key_to_extractor_map[i].key != NULL) &&
658 (strcasecmp(key, key_to_extractor_map[i].key) != 0)) 700 (strcasecmp (key, key_to_extractor_map[i].key) != 0))
659 i++; 701 i++;
660 state->currentKeyType = key_to_extractor_map[i].type; 702 state->currentKeyType = key_to_extractor_map[i].type;
661 703
662 i = 0; 704 i = 0;
663 while ((key_to_attribute_map[i].key != NULL) && 705 while ((key_to_attribute_map[i].key != NULL) &&
664 (strcasecmp(key, key_to_attribute_map[i].key) != 0)) 706 (strcasecmp (key, key_to_attribute_map[i].key) != 0))
665 i++; 707 i++;
666 state->currentAttribute = key_to_attribute_map[i].attribute; 708 state->currentAttribute = key_to_attribute_map[i].attribute;
667} 709}
668 710
669static void handleASEnd(unsigned char type, void * value, void * userdata) 711
712static void
713handleASEnd (unsigned char type, void *value, void *userdata)
670{ 714{
671 FLVMetaParserState *state = (FLVMetaParserState *)userdata; 715 FLVMetaParserState *state = (FLVMetaParserState *) userdata;
672 const char *s; 716 const char *s;
673 char tmpstr[30]; 717 char tmpstr[30];
674 718
675 if ((state->parsingDepth == 0) && (type == ASTYPE_STRING)) { 719 if ((state->parsingDepth == 0) && (type == ASTYPE_STRING))
676 s = (const char *)value; 720 {
677 if (!strcmp(s, "onMetaData")) 721 s = (const char *) value;
722 if (! strcmp (s, "onMetaData"))
678 state->onMetaData = 1; 723 state->onMetaData = 1;
679 } 724 }
680 725
@@ -686,50 +731,53 @@ static void handleASEnd(unsigned char type, void * value, void * userdata)
686 (state->currentAttribute != FLV_NONE) && 731 (state->currentAttribute != FLV_NONE) &&
687 (type == ASTYPE_NUMBER)) 732 (type == ASTYPE_NUMBER))
688 { 733 {
689 double n = *((double *)value); 734 double n = *((double *) value);
690 switch (state->currentAttribute) { 735 switch (state->currentAttribute)
691 case FLV_NONE: /* make gcc happy */ 736 {
692 break; 737 case FLV_NONE: /* make gcc happy */
693 case FLV_STEREO: 738 break;
694 break; 739 case FLV_STEREO:
695 case FLV_ACHANNELS: 740 break;
696 state->streamInfo->audioChannels = n; 741 case FLV_ACHANNELS:
697 break; 742 state->streamInfo->audioChannels = n;
698 case FLV_WIDTH: 743 break;
699 if (state->streamInfo->videoWidth == -1) 744 case FLV_WIDTH:
700 state->streamInfo->videoWidth = n; 745 if (state->streamInfo->videoWidth == -1)
701 break; 746 state->streamInfo->videoWidth = n;
702 case FLV_HEIGHT: 747 break;
703 if (state->streamInfo->videoHeight == -1) 748 case FLV_HEIGHT:
704 state->streamInfo->videoHeight = n; 749 if (state->streamInfo->videoHeight == -1)
705 break; 750 state->streamInfo->videoHeight = n;
706 case FLV_FRAMERATE: 751 break;
707 state->streamInfo->videoFrameRate = n; 752 case FLV_FRAMERATE:
708 break; 753 state->streamInfo->videoFrameRate = n;
709 case FLV_VDATARATE: 754 break;
710 state->streamInfo->videoDataRate = n; 755 case FLV_VDATARATE:
711 break; 756 state->streamInfo->videoDataRate = n;
712 case FLV_ADATARATE: 757 break;
713 state->streamInfo->audioDataRate = n; 758 case FLV_ADATARATE:
714 break; 759 state->streamInfo->audioDataRate = n;
715 case FLV_VCODECID: 760 break;
716 if (state->streamInfo->videoCodec == -1) 761 case FLV_VCODECID:
717 state->streamInfo->videoCodec = n; 762 if (state->streamInfo->videoCodec == -1)
718 /* prefer codec ids to fourcc codes */ 763 state->streamInfo->videoCodec = n;
719 if (state->streamInfo->videoCodecStr != NULL) { 764 /* prefer codec ids to fourcc codes */
720 free(state->streamInfo->videoCodecStr); 765 if (state->streamInfo->videoCodecStr != NULL)
721 state->streamInfo->videoCodecStr = NULL; 766 {
722 } 767 free (state->streamInfo->videoCodecStr);
723 break; 768 state->streamInfo->videoCodecStr = NULL;
724 case FLV_ACODECID: 769 }
725 if (state->streamInfo->audioCodec == -1) 770 break;
726 state->streamInfo->audioCodec = n; 771 case FLV_ACODECID:
727 /* prefer codec ids to fourcc codes */ 772 if (state->streamInfo->audioCodec == -1)
728 if (state->streamInfo->audioCodecStr != NULL) { 773 state->streamInfo->audioCodec = n;
729 free(state->streamInfo->audioCodecStr); 774 /* prefer codec ids to fourcc codes */
730 state->streamInfo->audioCodecStr = NULL; 775 if (state->streamInfo->audioCodecStr != NULL)
731 } 776 {
732 break; 777 free (state->streamInfo->audioCodecStr);
778 state->streamInfo->audioCodecStr = NULL;
779 }
780 break;
733 } 781 }
734 } 782 }
735 783
@@ -738,20 +786,21 @@ static void handleASEnd(unsigned char type, void * value, void * userdata)
738 (state->currentAttribute != FLV_NONE) && 786 (state->currentAttribute != FLV_NONE) &&
739 (type == ASTYPE_STRING)) 787 (type == ASTYPE_STRING))
740 { 788 {
741 s = (const char *)value; 789 s = (const char *) value;
742 switch (state->currentAttribute) { 790 switch (state->currentAttribute)
743 case FLV_VCODECID: 791 {
744 if (s != NULL && state->streamInfo->videoCodecStr == NULL && 792 case FLV_VCODECID:
745 state->streamInfo->videoCodec == -1) 793 if ((s != NULL) && (state->streamInfo->videoCodecStr == NULL) &&
746 state->streamInfo->videoCodecStr = strdup(s); 794 (state->streamInfo->videoCodec == -1) )
747 break; 795 state->streamInfo->videoCodecStr = strdup (s);
748 case FLV_ACODECID: 796 break;
749 if (s != NULL && state->streamInfo->audioCodecStr == NULL && 797 case FLV_ACODECID:
750 state->streamInfo->audioCodec == -1) 798 if ((s != NULL) && (state->streamInfo->audioCodecStr == NULL) &&
751 state->streamInfo->audioCodecStr = strdup(s); 799 (state->streamInfo->audioCodec == -1) )
752 break; 800 state->streamInfo->audioCodecStr = strdup (s);
753 default: 801 break;
754 break; 802 default:
803 break;
755 } 804 }
756 } 805 }
757 806
@@ -759,7 +808,7 @@ static void handleASEnd(unsigned char type, void * value, void * userdata)
759 (state->currentAttribute == FLV_STEREO) && 808 (state->currentAttribute == FLV_STEREO) &&
760 (type == ASTYPE_BOOLEAN)) 809 (type == ASTYPE_BOOLEAN))
761 { 810 {
762 int n = *((int *)value); 811 int n = *((int *) value);
763 if (state->streamInfo->audioChannels == -1) 812 if (state->streamInfo->audioChannels == -1)
764 state->streamInfo->audioChannels = (n == 0) ? 1 : 2; 813 state->streamInfo->audioChannels = (n == 0) ? 1 : 2;
765 } 814 }
@@ -769,57 +818,59 @@ static void handleASEnd(unsigned char type, void * value, void * userdata)
769 (state->currentKeyType != EXTRACTOR_METATYPE_RESERVED)) 818 (state->currentKeyType != EXTRACTOR_METATYPE_RESERVED))
770 { 819 {
771 s = NULL; 820 s = NULL;
772 switch (type) { 821 switch (type)
773 case ASTYPE_NUMBER: 822 {
823 case ASTYPE_NUMBER:
774 { 824 {
775 double n = *((double *)value); 825 double n = *((double *) value);
776 s = tmpstr; 826 s = tmpstr;
777 if (state->currentKeyType == EXTRACTOR_METATYPE_DURATION) 827 if (state->currentKeyType == EXTRACTOR_METATYPE_DURATION)
778 snprintf(tmpstr, sizeof(tmpstr), "%.2f s", n); 828 snprintf (tmpstr, sizeof(tmpstr), "%.2f s", n);
779 else 829 else
780 snprintf(tmpstr, sizeof(tmpstr), "%f", n); 830 snprintf (tmpstr, sizeof(tmpstr), "%f", n);
781 break; 831 break;
782 } 832 }
783 case ASTYPE_STRING: 833 case ASTYPE_STRING:
784 { 834 {
785 s = (char *)value; 835 s = (char *) value;
786 break; 836 break;
787 } 837 }
788 case ASTYPE_DATE: 838 case ASTYPE_DATE:
789 { 839 {
790 void **tmp = (void **)value; 840 void **tmp = (void **) value;
791 double *millis; 841 double *millis;
792 short *tz; 842 short *tz;
793 millis = (double *)tmp[0]; 843 millis = (double *) tmp[0];
794 tz = (short *)tmp[1]; 844 tz = (short *) tmp[1];
795 if (0 == flv_to_iso_date(*millis, *tz, tmpstr, sizeof(tmpstr))) 845 if (0 == flv_to_iso_date (*millis, *tz, tmpstr, sizeof(tmpstr)))
796 s = tmpstr; 846 s = tmpstr;
797 break; 847 break;
798 } 848 }
799 } 849 }
800 if ( (s != NULL) && 850 if ( (s != NULL) &&
801 (state->ret == 0) ) 851 (state->ret == 0) )
802 state->ret = state->proc (state->proc_cls, 852 state->ret = state->proc (state->proc_cls,
803 "flv", 853 "flv",
804 state->currentKeyType, 854 state->currentKeyType,
805 EXTRACTOR_METAFORMAT_UTF8, 855 EXTRACTOR_METAFORMAT_UTF8,
806 "text/plain", 856 "text/plain",
807 s, 857 s,
808 strlen (s) + 1); 858 strlen (s) + 1);
809 } 859 }
810 state->currentKeyType = EXTRACTOR_METATYPE_RESERVED; 860 state->currentKeyType = EXTRACTOR_METATYPE_RESERVED;
811 state->currentAttribute = FLV_NONE; 861 state->currentAttribute = FLV_NONE;
812 862
813 if (type == ASTYPE_ARRAY || type == ASTYPE_MIXEDARRAY || 863 if ((type == ASTYPE_ARRAY) || (type == ASTYPE_MIXEDARRAY) ||
814 type == ASTYPE_OBJECT) 864 (type == ASTYPE_OBJECT) )
815 state->parsingDepth--; 865 state->parsingDepth--;
816} 866}
817 867
868
818static int 869static int
819handleMetaBody(const unsigned char *data, size_t len, 870handleMetaBody (const unsigned char *data, size_t len,
820 FLVStreamInfo *stinfo, 871 FLVStreamInfo *stinfo,
821 EXTRACTOR_MetaDataProcessor proc, 872 EXTRACTOR_MetaDataProcessor proc,
822 void *proc_cls) 873 void *proc_cls)
823{ 874{
824 AMFParserHandler handler; 875 AMFParserHandler handler;
825 FLVMetaParserState pstate; 876 FLVMetaParserState pstate;
@@ -836,12 +887,14 @@ handleMetaBody(const unsigned char *data, size_t len,
836 handler.as_key_callback = &handleASKey; 887 handler.as_key_callback = &handleASKey;
837 handler.as_end_callback = &handleASEnd; 888 handler.as_end_callback = &handleASEnd;
838 889
839 while (len > 0 && parse_amf(&data, &len, &handler) == 0); 890 while (len > 0 && parse_amf (&data, &len, &handler) == 0)
891 ;
840 if (pstate.ret != 0) 892 if (pstate.ret != 0)
841 return 1; 893 return 1;
842 return 0; 894 return 0;
843} 895}
844 896
897
845static char *FLVAudioCodecs[] = { 898static char *FLVAudioCodecs[] = {
846 "Uncompressed", 899 "Uncompressed",
847 "ADPCM", 900 "ADPCM",
@@ -875,19 +928,21 @@ static char *FLVAudioSampleRates[] = {
875}; 928};
876 929
877static void 930static void
878handleAudioBody(const unsigned char *data, size_t len, 931handleAudioBody (const unsigned char *data, size_t len,
879 FLVStreamInfo *stinfo) 932 FLVStreamInfo *stinfo)
880{ 933{
881 stinfo->audioChannels = (*data & 0x01) + 1; 934 stinfo->audioChannels = (*data & 0x01) + 1;
882 stinfo->audioSampleBits = (*data & 0x02) >> 1; 935 stinfo->audioSampleBits = (*data & 0x02) >> 1;
883 stinfo->audioRate = (*data & 0x0C) >> 2; 936 stinfo->audioRate = (*data & 0x0C) >> 2;
884 stinfo->audioCodec = (*data & 0xF0) >> 4; 937 stinfo->audioCodec = (*data & 0xF0) >> 4;
885 if (stinfo->audioCodecStr != NULL) { 938 if (stinfo->audioCodecStr != NULL)
886 free(stinfo->audioCodecStr); 939 {
940 free (stinfo->audioCodecStr);
887 stinfo->audioCodecStr = NULL; 941 stinfo->audioCodecStr = NULL;
888 } 942 }
889} 943}
890 944
945
891static char *FLVVideoCodecs[] = { 946static char *FLVVideoCodecs[] = {
892 NULL, 947 NULL,
893 NULL, 948 NULL,
@@ -911,8 +966,8 @@ static int sorenson_predefined_res[][2] = {
911}; 966};
912 967
913static void 968static void
914handleVideoBody(const unsigned char *data, size_t len, 969handleVideoBody (const unsigned char *data, size_t len,
915 FLVStreamInfo *stinfo) 970 FLVStreamInfo *stinfo)
916{ 971{
917 int codecId, frameType; 972 int codecId, frameType;
918 973
@@ -921,84 +976,94 @@ handleVideoBody(const unsigned char *data, size_t len,
921 data++; 976 data++;
922 977
923 /* try to get video dimensions */ 978 /* try to get video dimensions */
924 switch (codecId) { 979 switch (codecId)
925 case 0x02: /* Sorenson */ 980 {
926 if (len < 9) 981 case 0x02: /* Sorenson */
927 break; 982 if (len < 9)
928 if (frameType == 1) {
929 int start_code = (data[0] << 9) | (data[1] << 1) | ((data[2] >> 7)&0x1);
930 int version = (data[2] & 0x7C) >> 2;
931 int frame_size = ((data[3] & 0x03) << 1) | (data[4] >> 7);
932 if (start_code != 0x00000001)
933 break;
934 if (!(version == 0 || version == 1))
935 break;
936 if (frame_size == 0) {
937 stinfo->videoWidth = ((data[4] & 0x7F) >> 1) | (data[5] >> 7);
938 stinfo->videoHeight = ((data[5] & 0x7F) >> 1) | (data[6] >> 7);
939 }
940 else if (frame_size == 1) {
941 stinfo->videoWidth = ((data[4] & 0x7F) << 9) | (data[5] << 1) |
942 (data[6] >> 7);
943 stinfo->videoHeight = ((data[6] & 0x7F) << 9) | (data[7] << 1) |
944 (data[8] >> 7);
945 }
946 else {
947 stinfo->videoWidth = sorenson_predefined_res[frame_size][0];
948 stinfo->videoHeight = sorenson_predefined_res[frame_size][1];
949 }
950 }
951 break; 983 break;
952 case 0x03: /* ScreenVideo */ 984 if (frameType == 1)
953 if (len < 5) 985 {
986 int start_code = (data[0] << 9) | (data[1] << 1) | ((data[2] >> 7) & 0x1);
987 int version = (data[2] & 0x7C) >> 2;
988 int frame_size = ((data[3] & 0x03) << 1) | (data[4] >> 7);
989 if (start_code != 0x00000001)
954 break; 990 break;
955 stinfo->videoWidth = readInt16(&data) & 0x0FFF; 991 if (! ((version == 0) || (version == 1) ))
956 stinfo->videoHeight = readInt16(&data) & 0x0FFF; 992 break;
993 if (frame_size == 0)
994 {
995 stinfo->videoWidth = ((data[4] & 0x7F) >> 1) | (data[5] >> 7);
996 stinfo->videoHeight = ((data[5] & 0x7F) >> 1) | (data[6] >> 7);
997 }
998 else if (frame_size == 1)
999 {
1000 stinfo->videoWidth = ((data[4] & 0x7F) << 9) | (data[5] << 1)
1001 | (data[6] >> 7);
1002 stinfo->videoHeight = ((data[6] & 0x7F) << 9) | (data[7] << 1)
1003 | (data[8] >> 7);
1004 }
1005 else
1006 {
1007 stinfo->videoWidth = sorenson_predefined_res[frame_size][0];
1008 stinfo->videoHeight = sorenson_predefined_res[frame_size][1];
1009 }
1010 }
1011 break;
1012 case 0x03: /* ScreenVideo */
1013 if (len < 5)
957 break; 1014 break;
958 case 0x04: /* On2 VP6 */ 1015 stinfo->videoWidth = readInt16 (&data) & 0x0FFF;
959 case 0x05: 1016 stinfo->videoHeight = readInt16 (&data) & 0x0FFF;
1017 break;
1018 case 0x04: /* On2 VP6 */
1019 case 0x05:
960 { 1020 {
961 unsigned char dim_adj; 1021 unsigned char dim_adj;
962 if (len < 10) 1022 if (len < 10)
963 break; 1023 break;
964 dim_adj = *data++; 1024 dim_adj = *data++;
965 if ((frameType == 1) && ((data[0] & 0x80) == 0)) { 1025 if ((frameType == 1) && ((data[0] & 0x80) == 0))
1026 {
966 /* see ffmpeg vp6 decoder */ 1027 /* see ffmpeg vp6 decoder */
967 int separated_coeff = data[0] & 0x01; 1028 int separated_coeff = data[0] & 0x01;
968 int filter_header = data[1] & 0x06; 1029 int filter_header = data[1] & 0x06;
969 /*int interlaced = data[1] & 0x01; TODO: used in flv ever? */ 1030 /*int interlaced = data[1] & 0x01; TODO: used in flv ever? */
970 if (separated_coeff || !filter_header) { 1031 if (separated_coeff || ! filter_header)
1032 {
971 data += 2; 1033 data += 2;
972 } 1034 }
973 /* XXX encoded/displayed dimensions might vary, but which are the 1035 /* XXX encoded/displayed dimensions might vary, but which are the
974 * right ones? */ 1036 * right ones? */
975 stinfo->videoWidth = (data[3]*16) - (dim_adj>>4); 1037 stinfo->videoWidth = (data[3] * 16) - (dim_adj >> 4);
976 stinfo->videoHeight = (data[2]*16) - (dim_adj&0x0F); 1038 stinfo->videoHeight = (data[2] * 16) - (dim_adj & 0x0F);
977 } 1039 }
978 break; 1040 break;
979 } 1041 }
980 default: 1042 default:
981 break; 1043 break;
982 } 1044 }
983 1045
984 stinfo->videoCodec = codecId; 1046 stinfo->videoCodec = codecId;
985 if (stinfo->videoCodecStr != NULL) { 1047 if (stinfo->videoCodecStr != NULL)
986 free(stinfo->videoCodecStr); 1048 {
1049 free (stinfo->videoCodecStr);
987 stinfo->videoCodecStr = NULL; 1050 stinfo->videoCodecStr = NULL;
988 } 1051 }
989} 1052}
990 1053
991static int readFLVTag(const unsigned char **data, 1054
992 const unsigned char *end, 1055static int
993 FLVStreamInfo *stinfo, 1056readFLVTag (const unsigned char **data,
994 EXTRACTOR_MetaDataProcessor proc, 1057 const unsigned char *end,
995 void *proc_cls) 1058 FLVStreamInfo *stinfo,
1059 EXTRACTOR_MetaDataProcessor proc,
1060 void *proc_cls)
996{ 1061{
997 const unsigned char *ptr = *data; 1062 const unsigned char *ptr = *data;
998 FLVTagHeader header; 1063 FLVTagHeader header;
999 int ret = 0; 1064 int ret = 0;
1000 1065
1001 if (readFLVTagHeader(&ptr, end, &header) == -1) 1066 if (readFLVTagHeader (&ptr, end, &header) == -1)
1002 return -1; 1067 return -1;
1003 1068
1004 if ((ptr + header.bodyLength) > end) 1069 if ((ptr + header.bodyLength) > end)
@@ -1006,17 +1071,17 @@ static int readFLVTag(const unsigned char **data,
1006 1071
1007 switch (header.type) 1072 switch (header.type)
1008 { 1073 {
1009 case FLV_TAG_TYPE_AUDIO: 1074 case FLV_TAG_TYPE_AUDIO:
1010 handleAudioBody(ptr, header.bodyLength, stinfo); 1075 handleAudioBody (ptr, header.bodyLength, stinfo);
1011 break; 1076 break;
1012 case FLV_TAG_TYPE_VIDEO: 1077 case FLV_TAG_TYPE_VIDEO:
1013 handleVideoBody(ptr, header.bodyLength, stinfo); 1078 handleVideoBody (ptr, header.bodyLength, stinfo);
1014 break; 1079 break;
1015 case FLV_TAG_TYPE_META: 1080 case FLV_TAG_TYPE_META:
1016 ret = handleMetaBody(ptr, header.bodyLength, stinfo, proc, proc_cls); 1081 ret = handleMetaBody (ptr, header.bodyLength, stinfo, proc, proc_cls);
1017 break; 1082 break;
1018 default: 1083 default:
1019 break; 1084 break;
1020 } 1085 }
1021 1086
1022 ptr += header.bodyLength; 1087 ptr += header.bodyLength;
@@ -1024,129 +1089,149 @@ static int readFLVTag(const unsigned char **data,
1024 return ret; 1089 return ret;
1025} 1090}
1026 1091
1092
1027#define MAX_FLV_FORMAT_LINE 80 1093#define MAX_FLV_FORMAT_LINE 80
1028static char * printVideoFormat(FLVStreamInfo *stinfo) 1094static char *
1095printVideoFormat (FLVStreamInfo *stinfo)
1029{ 1096{
1030 char s[MAX_FLV_FORMAT_LINE+1]; 1097 char s[MAX_FLV_FORMAT_LINE + 1];
1031 int n; 1098 int n;
1032 size_t len = MAX_FLV_FORMAT_LINE; 1099 size_t len = MAX_FLV_FORMAT_LINE;
1033 1100
1034 n = 0; 1101 n = 0;
1035 /* some files seem to specify only the width or the height, print '?' for 1102 /* some files seem to specify only the width or the height, print '?' for
1036 * the unknown dimension */ 1103 * the unknown dimension */
1037 if (stinfo->videoWidth != -1 || stinfo->videoHeight != -1) { 1104 if ((stinfo->videoWidth != -1) || (stinfo->videoHeight != -1))
1038 if (n < len) { 1105 {
1106 if (n < len)
1107 {
1039 if (stinfo->videoWidth != -1) 1108 if (stinfo->videoWidth != -1)
1040 n += snprintf(s+n, len-n, "%d", stinfo->videoWidth); 1109 n += snprintf (s + n, len - n, "%d", stinfo->videoWidth);
1041 else 1110 else
1042 n += snprintf(s+n, len-n, "?"); 1111 n += snprintf (s + n, len - n, "?");
1043 } 1112 }
1044 1113
1045 if (n < len) { 1114 if (n < len)
1115 {
1046 if (stinfo->videoHeight != -1) 1116 if (stinfo->videoHeight != -1)
1047 n += snprintf(s+n, len-n, "x%d", stinfo->videoHeight); 1117 n += snprintf (s + n, len - n, "x%d", stinfo->videoHeight);
1048 else 1118 else
1049 n += snprintf(s+n, len-n, "x?"); 1119 n += snprintf (s + n, len - n, "x?");
1050 } 1120 }
1051 } 1121 }
1052 1122
1053 if (stinfo->videoFrameRate != 0.0 && n < len) { 1123 if ((stinfo->videoFrameRate != 0.0) && (n < len))
1124 {
1054 if (n > 0) 1125 if (n > 0)
1055 n += snprintf(s+n, len-n, ", "); 1126 n += snprintf (s + n, len - n, ", ");
1056 if (n < len) 1127 if (n < len)
1057 n += snprintf(s+n, len-n, "%0.2f fps", stinfo->videoFrameRate); 1128 n += snprintf (s + n, len - n, "%0.2f fps", stinfo->videoFrameRate);
1058 } 1129 }
1059 1130
1060 if (stinfo->videoCodec > -1 && stinfo->videoCodec < 8 && 1131 if ((stinfo->videoCodec > -1) && (stinfo->videoCodec < 8) &&
1061 FLVVideoCodecs[stinfo->videoCodec] != NULL && n < len) { 1132 (FLVVideoCodecs[stinfo->videoCodec] != NULL) && (n < len) )
1133 {
1062 if (n > 0) 1134 if (n > 0)
1063 n += snprintf(s+n, len-n, ", "); 1135 n += snprintf (s + n, len - n, ", ");
1064 if (n < len) 1136 if (n < len)
1065 n += snprintf(s+n, len-n, "%s", FLVVideoCodecs[stinfo->videoCodec]); 1137 n += snprintf (s + n, len - n, "%s", FLVVideoCodecs[stinfo->videoCodec]);
1066 } 1138 }
1067 else if (stinfo->videoCodecStr != NULL && n < len) { 1139 else if ((stinfo->videoCodecStr != NULL) && (n < len))
1140 {
1068 if (n > 0) 1141 if (n > 0)
1069 n += snprintf(s+n, len-n, ", "); 1142 n += snprintf (s + n, len - n, ", ");
1070 if (n < len) 1143 if (n < len)
1071 n += snprintf(s+n, len-n, "%s", stinfo->videoCodecStr); 1144 n += snprintf (s + n, len - n, "%s", stinfo->videoCodecStr);
1072 } 1145 }
1073 1146
1074 if (stinfo->videoDataRate != 0.0 && n < len) { 1147 if ((stinfo->videoDataRate != 0.0) && (n < len))
1148 {
1075 if (n > 0) 1149 if (n > 0)
1076 n += snprintf(s+n, len-n, ", "); 1150 n += snprintf (s + n, len - n, ", ");
1077 if (n < len) 1151 if (n < len)
1078 n += snprintf(s+n, len-n, "%.4f kbps", stinfo->videoDataRate); 1152 n += snprintf (s + n, len - n, "%.4f kbps", stinfo->videoDataRate);
1079 } 1153 }
1080 1154
1081 if (n == 0) 1155 if (n == 0)
1082 return NULL; 1156 return NULL;
1083 return strdup(s); 1157 return strdup (s);
1084} 1158}
1085 1159
1086static char * printAudioFormat(FLVStreamInfo *stinfo) 1160
1161static char *
1162printAudioFormat (FLVStreamInfo *stinfo)
1087{ 1163{
1088 char s[MAX_FLV_FORMAT_LINE+1]; 1164 char s[MAX_FLV_FORMAT_LINE + 1];
1089 int n; 1165 int n;
1090 size_t len = MAX_FLV_FORMAT_LINE; 1166 size_t len = MAX_FLV_FORMAT_LINE;
1091 1167
1092 n = 0; 1168 n = 0;
1093 if ( (stinfo->audioRate != -1) && (n < len)) { 1169 if ( (stinfo->audioRate != -1) && (n < len))
1094 n += snprintf(s+n, len-n, "%s Hz", FLVAudioSampleRates[stinfo->audioRate]); 1170 {
1171 n += snprintf (s + n, len - n, "%s Hz",
1172 FLVAudioSampleRates[stinfo->audioRate]);
1095 } 1173 }
1096 1174
1097 if ((stinfo->audioSampleBits != -1) && (n < len)) { 1175 if ((stinfo->audioSampleBits != -1) && (n < len))
1176 {
1098 if (n > 0) 1177 if (n > 0)
1099 n += snprintf(s+n, len-n, ", "); 1178 n += snprintf (s + n, len - n, ", ");
1100 if (n < len) 1179 if (n < len)
1101 n += snprintf(s+n, len-n, "%s", 1180 n += snprintf (s + n, len - n, "%s",
1102 FLVAudioSampleSizes[stinfo->audioSampleBits]); 1181 FLVAudioSampleSizes[stinfo->audioSampleBits]);
1103 } 1182 }
1104 1183
1105 if ((stinfo->audioChannels != -1) && (n < len)) { 1184 if ((stinfo->audioChannels != -1) && (n < len))
1185 {
1106 if (n > 0) 1186 if (n > 0)
1107 n += snprintf(s+n, len-n, ", "); 1187 n += snprintf (s + n, len - n, ", ");
1108 if (n < len) { 1188 if (n < len)
1109 if (stinfo->audioChannels >= 1 && stinfo->audioChannels <= 2) 1189 {
1110 n += snprintf(s+n, len-n, "%s", 1190 if ((stinfo->audioChannels >= 1) && (stinfo->audioChannels <= 2))
1111 FLVAudioChannels[stinfo->audioChannels-1]); 1191 n += snprintf (s + n, len - n, "%s",
1192 FLVAudioChannels[stinfo->audioChannels - 1]);
1112 else 1193 else
1113 n += snprintf(s+n, len-n, "%d", 1194 n += snprintf (s + n, len - n, "%d",
1114 stinfo->audioChannels); 1195 stinfo->audioChannels);
1115 } 1196 }
1116 } 1197 }
1117 1198
1118 if ((stinfo->audioCodec > -1) && (stinfo->audioCodec < 12) && 1199 if ((stinfo->audioCodec > -1) && (stinfo->audioCodec < 12) &&
1119 (FLVAudioCodecs[stinfo->audioCodec] != NULL) && (n < len)) { 1200 (FLVAudioCodecs[stinfo->audioCodec] != NULL) && (n < len))
1201 {
1120 if (n > 0) 1202 if (n > 0)
1121 n += snprintf(s+n, len-n, ", "); 1203 n += snprintf (s + n, len - n, ", ");
1122 if (n < len) 1204 if (n < len)
1123 n += snprintf(s+n, len-n, "%s", FLVAudioCodecs[stinfo->audioCodec]); 1205 n += snprintf (s + n, len - n, "%s", FLVAudioCodecs[stinfo->audioCodec]);
1124 } 1206 }
1125 else if ((stinfo->audioCodecStr != NULL) && (n < len)) { 1207 else if ((stinfo->audioCodecStr != NULL) && (n < len))
1208 {
1126 if (n > 0) 1209 if (n > 0)
1127 n += snprintf(s+n, len-n, ", "); 1210 n += snprintf (s + n, len - n, ", ");
1128 if (n < len) 1211 if (n < len)
1129 n += snprintf(s+n, len-n, "%s", stinfo->audioCodecStr); 1212 n += snprintf (s + n, len - n, "%s", stinfo->audioCodecStr);
1130 } 1213 }
1131 1214
1132 if ((stinfo->audioDataRate != 0.0) && (n < len)) { 1215 if ((stinfo->audioDataRate != 0.0) && (n < len))
1216 {
1133 if (n > 0) 1217 if (n > 0)
1134 n += snprintf(s+n, len-n, ", "); 1218 n += snprintf (s + n, len - n, ", ");
1135 if (n < len) 1219 if (n < len)
1136 n += snprintf(s+n, len-n, "%.4f kbps", stinfo->audioDataRate); 1220 n += snprintf (s + n, len - n, "%.4f kbps", stinfo->audioDataRate);
1137 } 1221 }
1138 1222
1139 if (n == 0) 1223 if (n == 0)
1140 return NULL; 1224 return NULL;
1141 return strdup(s); 1225 return strdup (s);
1142} 1226}
1143 1227
1144int 1228
1229int
1145EXTRACTOR_flv_extract (const unsigned char *data, 1230EXTRACTOR_flv_extract (const unsigned char *data,
1146 size_t size, 1231 size_t size,
1147 EXTRACTOR_MetaDataProcessor proc, 1232 EXTRACTOR_MetaDataProcessor proc,
1148 void *proc_cls, 1233 void *proc_cls,
1149 const char *options) 1234 const char *options)
1150{ 1235{
1151 const unsigned char *ptr; 1236 const unsigned char *ptr;
1152 const unsigned char *end; 1237 const unsigned char *end;
@@ -1159,19 +1244,19 @@ EXTRACTOR_flv_extract (const unsigned char *data,
1159 ptr = data; 1244 ptr = data;
1160 end = ptr + size; 1245 end = ptr + size;
1161 1246
1162 if (readFLVHeader(&ptr, end, &header) == -1) 1247 if (readFLVHeader (&ptr, end, &header) == -1)
1163 return 0; 1248 return 0;
1164 1249
1165 if (memcmp(header.signature, FLV_SIGNATURE, 3) != 0) 1250 if (memcmp (header.signature, FLV_SIGNATURE, 3) != 0)
1166 return 0; 1251 return 0;
1167 1252
1168 if (0 != proc (proc_cls, 1253 if (0 != proc (proc_cls,
1169 "flv", 1254 "flv",
1170 EXTRACTOR_METATYPE_MIMETYPE, 1255 EXTRACTOR_METATYPE_MIMETYPE,
1171 EXTRACTOR_METAFORMAT_UTF8, 1256 EXTRACTOR_METAFORMAT_UTF8,
1172 "text/plain", 1257 "text/plain",
1173 "video/x-flv", 1258 "video/x-flv",
1174 strlen ("video/x-flv") + 1)) 1259 strlen ("video/x-flv") + 1))
1175 return 0; 1260 return 0;
1176 if (header.version != 1) 1261 if (header.version != 1)
1177 return 0; 1262 return 0;
@@ -1191,7 +1276,8 @@ EXTRACTOR_flv_extract (const unsigned char *data,
1191 stinfo.audioChannels = -1; 1276 stinfo.audioChannels = -1;
1192 stinfo.audioDataRate = 0.0; 1277 stinfo.audioDataRate = 0.0;
1193 ret = 0; 1278 ret = 0;
1194 while (ptr < end) { 1279 while (ptr < end)
1280 {
1195 if (-1 == (ret = readFLVTag (&ptr, end, &stinfo, proc, proc_cls))) 1281 if (-1 == (ret = readFLVTag (&ptr, end, &stinfo, proc, proc_cls)))
1196 break; 1282 break;
1197 if (readPreviousTagSize (&ptr, end, &prev_tag_size) == -1) 1283 if (readPreviousTagSize (&ptr, end, &prev_tag_size) == -1)
@@ -1201,35 +1287,35 @@ EXTRACTOR_flv_extract (const unsigned char *data,
1201 return 1; 1287 return 1;
1202 s = printVideoFormat (&stinfo); 1288 s = printVideoFormat (&stinfo);
1203 if (s != NULL) 1289 if (s != NULL)
1290 {
1291 if (0 != proc (proc_cls,
1292 "flv",
1293 EXTRACTOR_METATYPE_RESOURCE_TYPE,
1294 EXTRACTOR_METAFORMAT_UTF8,
1295 "text/plain",
1296 s,
1297 strlen (s) + 1))
1204 { 1298 {
1205 if (0 != proc (proc_cls,
1206 "flv",
1207 EXTRACTOR_METATYPE_RESOURCE_TYPE,
1208 EXTRACTOR_METAFORMAT_UTF8,
1209 "text/plain",
1210 s,
1211 strlen (s)+1))
1212 {
1213 free (s);
1214 return 1;
1215 }
1216 free (s); 1299 free (s);
1300 return 1;
1217 } 1301 }
1302 free (s);
1303 }
1218 s = printAudioFormat (&stinfo); 1304 s = printAudioFormat (&stinfo);
1219 if (s != NULL) 1305 if (s != NULL)
1306 {
1307 if (0 != proc (proc_cls,
1308 "flv",
1309 EXTRACTOR_METATYPE_RESOURCE_TYPE,
1310 EXTRACTOR_METAFORMAT_UTF8,
1311 "text/plain",
1312 s,
1313 strlen (s) + 1))
1220 { 1314 {
1221 if (0 != proc (proc_cls,
1222 "flv",
1223 EXTRACTOR_METATYPE_RESOURCE_TYPE,
1224 EXTRACTOR_METAFORMAT_UTF8,
1225 "text/plain",
1226 s,
1227 strlen (s)+1))
1228 {
1229 free (s);
1230 return 1;
1231 }
1232 free (s); 1315 free (s);
1316 return 1;
1233 } 1317 }
1318 free (s);
1319 }
1234 return 0; 1320 return 0;
1235} 1321}