Changeset 3751
- Timestamp:
- 2008-10-29 04:06:26 (2 months ago)
- Files:
-
- libannodex/trunk/src/importers/anx_import_ogg.c (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
libannodex/trunk/src/importers/anx_import_ogg.c
r3750 r3751 86 86 typedef enum { 87 87 STATE_HEADERS, 88 STATE_GLUE, 89 #if 0 88 90 STATE_GRANULEINFO, 89 91 STATE_FILTER, 92 #endif 90 93 STATE_DATA 91 94 } state_t; … … 112 115 struct _AnxOggTrack { 113 116 AnxSourceTrack source_track; 117 int nr_headers_remaining; 118 119 /* Queue of packets corresponding to the last GOP of the 120 * glue section for this track. */ 121 AnxList * glue_packets; 122 114 123 int need_keygranule; 115 124 ogg_int64_t keygranule; 116 125 double keygranule_time; 117 126 int filter_got_keygranule; 118 int nr_headers_remaining;119 127 }; 120 128 … … 137 145 int got_skeleton_eos; 138 146 139 longnr_headers_remaining;140 longheaders_unread;147 int nr_headers_remaining; 148 int headers_unread; 141 149 142 150 int use_granule_seek; … … 147 155 148 156 /* Maintain a list of AnxOggTracks */ 149 OggzTable * logicals; 150 157 OggzTable * tracks; 158 159 /* Packet queues */ 160 AnxList * header_queue; 151 161 AnxList * delivery_queue; 162 152 163 long current_offset; /* offset into current packet */ 153 164 … … 288 299 aop->eos = op->e_o_s; 289 300 301 memcpy (aop->data, op->packet, op->bytes); 302 290 303 return aop; 291 304 } … … 312 325 void * user_data) 313 326 { 314 unsigned char * header = op->packet;315 327 AnxOggData * aod = (AnxOggData *)user_data; 316 328 AnxOggTrack * aot = NULL; 329 AnxOggPacket * aop = NULL; 317 330 AnxSource * m = aod->anx_source; 318 331 AnxSourceTrack * track = NULL; … … 321 334 int got_headers = 0; 322 335 323 aot = (AnxOggTrack *) oggz_table_lookup (aod-> logicals, serialno);336 aot = (AnxOggTrack *) oggz_table_lookup (aod->tracks, serialno); 324 337 if (aot != NULL) { 325 338 need_insert = 0; 326 339 } 327 340 341 content = oggz_stream_get_content (oggz, serialno); 342 328 343 if (op->b_o_s) { 329 content = oggz_stream_get_content (oggz, serialno);330 344 331 345 if (content == OGGZ_CONTENT_CMML) { … … 398 412 399 413 if (need_insert) { 400 oggz_table_insert (aod-> logicals, serialno, aot);414 oggz_table_insert (aod->tracks, serialno, aot); 401 415 } 402 416 … … 432 446 } 433 447 448 if (content != OGGZ_CONTENT_CMML) { 449 aot = (AnxOggTrack *) oggz_table_lookup (aod->tracks, serialno); 450 track = &(aot->source_track); 451 } 452 434 453 aod->got_non_bos = 1; 435 454 } … … 445 464 } 446 465 466 /* Add this packet to the headers_queue */ 467 if (track) { 468 aop = anxogg_packet_new (op, track, 0.0); 469 aod->header_queue = anx_list_append (aod->header_queue, aop); 470 } 471 447 472 if (got_headers) { 473 #if 0 448 474 if (m->start_time != 0.0) { 449 475 if (oggz_seek_units (oggz, 0, SEEK_CUR) >= 0) { 450 476 oggz_set_data_start (oggz, oggz_tell (oggz)); 451 if (aod->use_granule_seek) aod->state = STATE_GRANULEINFO; 477 if (aod->use_granule_seek) 478 aod->state = STATE_GRANULEINFO; 452 479 } 453 480 } else { 454 481 aod->state = STATE_DATA; 455 482 } 483 #else 484 aod->state = STATE_GLUE; 485 aod->headers_unread = anx_list_length (aod->header_queue); 486 #endif 456 487 return OGGZ_STOP_OK; 457 488 } … … 460 491 } 461 492 493 /* 494 * OggzReadPacket read_packet_glue 495 * 496 * Parse Ogg packets up to the start point. 497 */ 498 static int 499 read_packet_glue (OGGZ * oggz, ogg_packet * op, long serialno, 500 void * user_data) 501 { 502 AnxOggData * aod = (AnxOggData *)user_data; 503 AnxOggTrack * aot = NULL; 504 AnxSourceTrack * track = NULL; 505 AnxOggPacket * aop; 506 int granuleshift, iframe; 507 double start_time, at_time; 508 509 aot = (AnxOggTrack *) oggz_table_lookup (aod->tracks, serialno); 510 511 /* If this track is not in the table, ignore it. */ 512 if (aot == NULL) return OGGZ_CONTINUE; 513 514 track = &(aot->source_track); 515 516 /* If we are past the start time, then queue this packet for delivery 517 * and set state to STATE_DATA */ 518 start_time = aod->anx_source->start_time; 519 at_time = gp_to_time (aod->oggz, serialno, op->granulepos); 520 if (at_time >= start_time) { 521 aop = anxogg_packet_new (op, track, at_time); 522 aod->delivery_queue = anx_list_append (aod->delivery_queue, aop); 523 aod->state = STATE_DATA; 524 return OGGZ_STOP_OK; 525 } 526 527 granuleshift = oggz_get_granuleshift(oggz, serialno); 528 /* No need to cache packets of tracks without granuleshift */ 529 if (granuleshift == 0) return OGGZ_CONTINUE; 530 531 /* If this is a keyframe, clear the glue_packets queue for this track */ 532 iframe = op->granulepos >> granuleshift; 533 if (op->granulepos != -1 && (iframe << granuleshift) == op->granulepos) { 534 anx_list_free_with (aot->glue_packets, anxogg_packet_free); 535 aot->glue_packets = NULL; 536 } 537 538 /* Append this packet to this track's list of glue_packets */ 539 aop = anxogg_packet_new (op, track, at_time); 540 aot->glue_packets = anx_list_append (aot->glue_packets, aop); 541 542 return OGGZ_CONTINUE; 543 } 544 545 /* 546 * Create a single list containing all the glue packets from all 547 * tracks, in time order. 548 */ 549 static AnxList * 550 merge_glue (AnxOggData * aod) 551 { 552 AnxList * glued = NULL, * candidates = NULL, * c, * min_aot_l, * min_aop_l; 553 AnxOggTrack * aot = NULL, * min_aot; 554 AnxOggPacket * aop = NULL; 555 int i, ntracks, ncandidates=0; 556 long serialno; 557 double at_time, min_time; 558 559 /* Prime candidates */ 560 ntracks = oggz_table_size (aod->tracks); 561 for (i=0; i < ntracks; i++) { 562 aot = oggz_table_nth (aod->tracks, i, &serialno); 563 if (aot != NULL && aot->glue_packets != NULL) { 564 candidates = anx_list_append (candidates, aot); 565 } 566 } 567 568 /* Merge candidates */ 569 while (candidates != NULL) { 570 /* Find minimum time packet in all glue buffers */ 571 min_time = 10e100; 572 min_aot_l = NULL; 573 for (c = candidates; c; c = c->next) { 574 aot = (AnxOggTrack *)c->data; 575 aop = (AnxOggPacket *)aot->glue_packets->data; 576 if (aop->current_time < min_time) { 577 /* This is the min so far ... */ 578 min_time = aop->current_time; 579 min_aot_l = c; 580 } 581 } 582 583 /* Got min_aot */ 584 min_aot = min_aot_l->data; 585 586 /* Stash the AnxList* containing the minimum glue packet */ 587 min_aop_l = min_aot->glue_packets; 588 589 /* Set that track's glue_packets to it's own tail */ 590 min_aot->glue_packets = min_aop_l->next; 591 if (min_aot->glue_packets) { 592 /* If packets are remaining, clear the head's prev pointer */ 593 min_aot->glue_packets->prev = NULL; 594 } else { 595 /* Otherwise, we can remove this track from future candidates */ 596 candidates = anx_list_remove (candidates, min_aot_l); 597 /* Free the min_aot_l container (but not its AnxOggTrack data) */ 598 anx_free (min_aot_l); 599 } 600 601 /* Append the min_aop to the list of glued packets we are building */ 602 glued = anx_list_append (glued, min_aop_l->data); 603 604 /* Free the min_aop_l container (but not it's AnxOggPacket data) */ 605 anx_free (min_aop_l); 606 } 607 608 return glued; 609 } 610 611 static int 612 init_delivery_queue (AnxOggData * aod, AnxList * glued) 613 { 614 AnxList * queue = NULL, * tail; 615 616 queue = aod->header_queue; 617 tail = anx_list_tail (queue); 618 619 /* If there packets glued, join them to the header queue */ 620 if (glued != NULL) { 621 tail->next = glued; 622 glued->prev = tail; 623 624 /* Advance tail to the tail of (glued)queue */ 625 tail = anx_list_tail (glued); 626 } 627 628 /* If there's any packets already queued for delivery during gluing, 629 * join them too. */ 630 if (aod->delivery_queue != NULL) { 631 tail->next = aod->delivery_queue; 632 aod->delivery_queue->prev = tail; 633 } 634 635 /* Now queue points to the original headers++glued++delivery, so 636 * mark that for delivery */ 637 aod->delivery_queue = queue; 638 639 /* And clear the header_queue pointer as it is no longer needed */ 640 aod->header_queue = NULL; 641 642 return 0; 643 } 644 645 #if 0 462 646 static int 463 647 granuleinfo_update_state (AnxOggData * aod) … … 466 650 int i, n; 467 651 468 #ifdef DEBUG469 //fprintf (aod->df, "anxogg::granuleinfo_update_state cmml %010ld %s\n",470 // aod->cmml_serialno,471 // aod->cmml_need_keygranule ? "needs keygranule" : "no keygranule");472 #endif473 474 652 if (aod->cmml_serialno != -1 && aod->cmml_need_keygranule) return 0; 475 653 476 n = oggz_table_size (aod-> logicals);477 478 #ifdef DEBUG 479 fprintf (aod->df, "anxogg::granuleinfo_update_state %d logicals\n", n);654 n = oggz_table_size (aod->tracks); 655 656 #ifdef DEBUG 657 fprintf (aod->df, "anxogg::granuleinfo_update_state %d tracks\n", n); 480 658 #endif 481 659 482 660 for (i = 0; i < n; i++) { 483 aot = (AnxOggTrack *)oggz_table_nth (aod-> logicals, i, NULL);661 aot = (AnxOggTrack *)oggz_table_nth (aod->tracks, i, NULL); 484 662 if (aot->need_keygranule) { 485 663 #ifdef DEBUG … … 560 738 } else { 561 739 562 aot = (AnxOggTrack *) oggz_table_lookup (aod-> logicals, serialno);740 aot = (AnxOggTrack *) oggz_table_lookup (aod->tracks, serialno); 563 741 if (aot == NULL) { 564 742 /* If this track is not in the table, ignore it. */ … … 618 796 return OGGZ_STOP_OK; 619 797 } 798 #endif 620 799 621 800 static int 622 801 anxogg_setup (AnxOggData * aod) 623 802 { 803 AnxList * glued; 624 804 long n; 625 805 double start_time = 0.0, end_time = -1.0; … … 643 823 #endif 644 824 825 /* Slurp glue section */ 826 oggz_set_read_callback (aod->oggz, -1, read_packet_glue, aod); 827 while (aod->state == STATE_GLUE && 828 (n = oggz_read (aod->oggz, 1024)) != 0); 829 830 /* Now merge the glue section, and build the initial delivery queue */ 831 glued = merge_glue (aod); 832 init_delivery_queue (aod, glued); 833 834 #if 0 645 835 /* Find bitrate info */ 646 836 start_time = aod->anx_source->start_time; … … 724 914 oggz_seek (aod->oggz, 0, SEEK_SET); 725 915 aod->nr_headers_remaining = aod->headers_unread; 916 #endif 726 917 727 918 return 0; … … 732 923 */ 733 924 925 #if 0 734 926 static double 735 927 anxogg_seek_update (AnxSource * source) … … 785 977 return offset; 786 978 } 979 #endif 787 980 788 981 static long … … 791 984 AnxOggData * aod = (AnxOggData *)media->custom_data; 792 985 793 do_read:986 //do_read: 794 987 795 988 while ((aod->delivery_queue == NULL) && (oggz_read (aod->oggz, 1024)) != 0); 796 989 990 #if 0 797 991 if (aod->need_seek == NEED_SEEK && aod->nr_headers_remaining == 0) { 798 992 anxogg_seek_update (media); 799 993 goto do_read; 800 994 } 995 #endif 801 996 802 997 return 0; 803 998 } 804 999 1000 #if 0 805 1001 /*********************************************************** 806 1002 * A filter predicate, used between the min seek granule … … 890 1086 #endif 891 1087 } 1088 #endif 892 1089 893 1090 /* … … 915 1112 916 1113 if (!(aod->cmml_serialno != -1 && serialno == aod->cmml_serialno)) { 917 aot = (AnxOggTrack *) oggz_table_lookup (aod-> logicals, serialno);1114 aot = (AnxOggTrack *) oggz_table_lookup (aod->tracks, serialno); 918 1115 if (aot == NULL) { 919 1116 #ifdef DEBUG … … 991 1188 992 1189 #ifdef DEBUG 993 fprintf (aod->df, "anxogg::read_packet: Filter? (%s)\n", 994 aod->state == STATE_FILTER ? "USE_FN" : "NO_FN"); 995 #endif 996 997 if (!aod->ignore_media && !aod->got_end && 998 (aod->state != STATE_FILTER || filter (aod, aot, serialno, op))) { 1190 //fprintf (aod->df, "anxogg::read_packet: Filter? (%s)\n", 1191 // aod->state == STATE_FILTER ? "USE_FN" : "NO_FN"); 1192 #endif 1193 1194 if (!aod->ignore_media && !aod->got_end) { 1195 // && 1196 //(aod->state != STATE_FILTER || filter (aod, aot, serialno, op))) { 999 1197 #ifdef DEBUG 1000 1198 fprintf (aod->df, "anxogg::read_packet_data: no, copy out\n"); … … 1003 1201 aop = anxogg_packet_new (op, track, 1004 1202 ((double)oggz_tell_units(oggz)) / SUBSECONDS); 1005 memcpy (aop->data, op->packet, op->bytes);1006 1007 1203 aod->delivery_queue = anx_list_append (aod->delivery_queue, aop); 1008 1204 1205 #if 0 1009 1206 if (aot->nr_headers_remaining > 0) { 1010 1207 aod->nr_headers_remaining--; … … 1028 1225 } 1029 1226 } 1227 #endif 1030 1228 } 1031 1229 … … 1073 1271 /* If that's finished this media packet, advance to the next one */ 1074 1272 if (aod->current_offset >= aop->length) { 1273 1075 1274 aod->delivery_queue = anx_list_remove (aod->delivery_queue, head); 1076 1275 … … 1154 1353 aod->need_seek = NEED_SEEK_PENDING; 1155 1354 aod->got_end = 0; 1156 aod->logicals = oggz_table_new (); 1355 aod->tracks = oggz_table_new (); 1356 1357 aod->header_queue = NULL; 1157 1358 1158 1359 aod->delivery_queue = NULL; … … 1243 1444 anx_list_free_with (aod->delivery_queue, (AnxFreeFunc)anxogg_packet_free); 1244 1445 1245 n = oggz_table_size (aod-> logicals);1446 n = oggz_table_size (aod->tracks); 1246 1447 for (i = 0; i < n; i++) { 1247 aot = (AnxOggTrack *)oggz_table_nth (aod-> logicals, i, NULL);1448 aot = (AnxOggTrack *)oggz_table_nth (aod->tracks, i, NULL); 1248 1449 if (aot) { 1249 1450 track = &(aot->source_track); … … 1254 1455 } 1255 1456 1256 oggz_table_delete (aod-> logicals);1457 oggz_table_delete (aod->tracks); 1257 1458 1258 1459 #ifdef DEBUG