- Timestamp:
- 02/04/08 22:26:37 (4 years ago)
- Location:
- trunk/fm_server/src/fm_input_gst
- Files:
-
- 6 modified
-
fm_input_gst.c (modified) (18 diffs)
-
fm_input_gst.h (modified) (3 diffs)
-
fm_input_gst_common.c (modified) (2 diffs)
-
fm_input_gst_common.h (modified) (3 diffs)
-
gstfmsink.c (modified) (12 diffs)
-
gstfmsink.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/fm_server/src/fm_input_gst/fm_input_gst.c
r198 r221 181 181 { 182 182 g_print ("RESET STATUS!\n"); 183 //input_gst->current_pos_samples = 0;184 input_gst->current_pos_nsec = 0;185 input_gst->seek_at_ns ec= -1;183 input_gst->current_pos_samples = 0; 184 //input_gst->current_pos_nsec = 0; 185 input_gst->seek_at_ns = -1; 186 186 187 187 if (input_gst->common) 188 input_gst->common->gst_seek_to_ns ec= -1;188 input_gst->common->gst_seek_to_ns = -1; 189 189 } 190 190 … … 293 293 gst_element_set_state (input_gst->common->pipeline, GST_STATE_PLAYING); 294 294 295 common->seek_waiting_for_ns ec= 0;295 common->seek_waiting_for_ns = 0; 296 296 } 297 297 … … 352 352 common->input_gst = input_gst; 353 353 common->sem = fm_sem_new (1); 354 common->gst_seek_to_ns ec= -1;354 common->gst_seek_to_ns = -1; 355 355 common->sample_rate = fm_pipeline_get_sample_rate (FM_PIPELINE (element->pipeline)); 356 356 … … 404 404 405 405 406 input_gst->interleaved_buffer = g_new0(gfloat, SAMPLES_TO_BYTES( STD_CHUNK_N_SAMPLES));406 input_gst->interleaved_buffer = g_new0(gfloat, SAMPLES_TO_BYTES(CHUNK_SAMPLES)); 407 407 408 408 if (input_gst->filename) { … … 443 443 return; 444 444 445 g_value_set_int64 (input_gst->val1, input_gst->current_pos_nsec); 446 g_value_set_int64 (input_gst->val2, chk->duration_nsec); 445 guint64 pos_ns = samples_to_ns (input_gst->common, input_gst->current_pos_samples); 446 g_value_set_int64 (input_gst->val1, pos_ns); 447 g_value_set_int64 (input_gst->val2, chk->duration_ns); 447 448 rgc_signal_rt_emit (input_gst, input_gst->rt_signal, input_gst->val1, input_gst->val2, NULL); 448 449 } … … 458 459 FmChunk *c = chunk->data; 459 460 460 g_print ("chunk n. %d - start %llu duration %llu", c->num, (long long unsigned int) c->start_timestamp, (long long unsigned int) c->duration_ns ec);461 g_print ("chunk n. %d - start %llu duration %llu", c->num, (long long unsigned int) c->start_timestamp, (long long unsigned int) c->duration_ns); 461 462 if (c->usable) 462 463 g_print (" USABLE"); … … 467 468 if (((c->usable) && 468 469 (time >= c->start_timestamp) && 469 (time < (c->start_timestamp + c->duration_ns ec))) ||470 (time < (c->start_timestamp + c->duration_ns))) || 470 471 ((time == 0) && (c->start_of_file))) { // see gstfmsink.c:333 471 472 g_print ("Found target %llu at chunk %u\n", (long long unsigned int) time, c->num); … … 514 515 fm_buffer_reset_flags (buffer); 515 516 516 guint64 current_pos_samples = ns_to_samples (common, input_gst->current_pos_nsec);517 //guint64 current_pos_samples = ns_to_samples (common, input_gst->current_pos_nsec); 517 518 518 519 /* Check if we should perform a seek */ 519 if ((input_gst->seek_at_nsec > -1) && chk){ 520 /* We need to convert everything here down to samples and then to bytes */ 521 glong first_avail_sample = current_pos_samples - BYTES_TO_SAMPLES(chk->bytes_behind_us); 522 glong last_avail_sample = current_pos_samples + BYTES_TO_SAMPLES(jack_ringbuffer_read_space(chk->ring)); // we'll need an offset 520 if ((input_gst->seek_at_ns > -1) && chk){ 521 glong first_avail_sample = input_gst->current_pos_samples - chk->samples_behind_us; 522 glong last_avail_sample = input_gst->current_pos_samples + BYTES_TO_SAMPLES(jack_ringbuffer_read_space(chk->ring)); 523 523 524 guint64 seek_at_sample = ns_to_samples (common, input_gst->seek_at_ns ec);524 guint64 seek_at_sample = ns_to_samples (common, input_gst->seek_at_ns); 525 525 526 526 if ((seek_at_sample > first_avail_sample) && (seek_at_sample < last_avail_sample)) { … … 528 528 g_print ("seek at %ld, first %ld last %ld, LOCAL\n", seek_at_sample, first_avail_sample, last_avail_sample); 529 529 530 gint bytes_to_seek = SAMPLES_TO_BYTES(seek_at_sample - current_pos_samples); 531 input_gst->current_pos_nsec = input_gst->seek_at_nsec; 530 gint samples_to_seek = seek_at_sample - input_gst->current_pos_samples; 531 gint bytes_to_seek = SAMPLES_TO_BYTES (samples_to_seek); 532 input_gst->current_pos_samples = seek_at_sample; 532 533 533 534 if (bytes_to_seek > 0) { 534 535 jack_ringbuffer_read_advance(chk->ring, bytes_to_seek); 535 536 } else { 536 chk-> bytes_behind_us += bytes_to_seek; // yes, the "+" is correct537 chk->samples_behind_us += samples_to_seek; // yes, the "+" is correct 537 538 } 538 539 FM_BUFFER_DISCONT (buffer) = TRUE; 539 540 } else { 540 skip_to = _search_chunk (common, input_gst->seek_at_ns ec);541 skip_to = _search_chunk (common, input_gst->seek_at_ns); 541 542 if (skip_to) { 542 543 /* CHUNK seek - the destination is in another ready chunk */ … … 547 548 g_print ("seek at %ld, first %ld last %ld, FAR\n", seek_at_sample, first_avail_sample, last_avail_sample); 548 549 549 common->gst_seek_to_ns ec = input_gst->seek_at_nsec;550 common->gst_seek_to_ns = input_gst->seek_at_ns; 550 551 // g_print (" seek_at_nsec = %lld\n", (long long int) common->gst_seek_to_nsec); 551 common->seek_waiting_for_ns ec = input_gst->seek_at_nsec;552 common->seek_waiting_for_ns = input_gst->seek_at_ns; 552 553 fm_sem_increase (common->sem); 553 554 } 554 555 } 555 input_gst->seek_at_ns ec= -1;556 input_gst->seek_at_ns = -1; 556 557 } 557 558 558 559 559 560 /* Check if a FAR seek has been completed */ 560 if ((!skip_to) && (common->seek_waiting_for_ns ec> -1)) {561 if ((!skip_to) && (common->seek_waiting_for_ns > -1)) { 561 562 // g_print ("Waiting...\n"); 562 skip_to = _search_chunk (common, common->seek_waiting_for_ns ec);563 skip_to = _search_chunk (common, common->seek_waiting_for_ns); 563 564 if (skip_to) 564 common->seek_waiting_for_ns ec= -1;565 common->seek_waiting_for_ns = -1; 565 566 } 566 567 … … 577 578 chk->usable = FALSE; 578 579 579 //input_gst->current_pos_samples = ns_to_samples (common, chk->start_timestamp);580 input_gst->current_pos_nsec= chk->start_timestamp;580 input_gst->current_pos_samples = ns_to_samples (common, chk->start_timestamp); 581 //input_gst->current_pos_ns = chk->start_timestamp; 581 582 g_print("skipping... new position = %llu\n", (long long unsigned int) chk->start_timestamp); 582 583 … … 608 609 609 610 // bytes da scartare 610 guint bytes_from_ring = chk->bytes_behind_us + SAMPLES_TO_BYTES(FM_BUFFER_REQUESTED(buffer)); 611 gint64 eof_samples = ns_to_samples (common, chk->eof_timestamp); 611 guint samples_from_ring = chk->samples_behind_us + FM_BUFFER_REQUESTED(buffer); 612 guint bytes_from_ring = SAMPLES_TO_BYTES(samples_from_ring); 613 /* guint64 eof_samples = ns_to_samples (common, chk->eof_timestamp);*/ 612 614 613 if ((eof_samples > 0) && 614 ((current_pos_samples + FM_BUFFER_REQUESTED (buffer)) > eof_samples)) 615 bytes_from_ring = SAMPLES_TO_BYTES (eof_samples - current_pos_samples); 615 /* if (eof_samples > 0) {*/ 616 if (chk->eof_samples > 0) { 617 // g_print ("Get ready for EOF at chunk pos %lld\n", (long long int) chk->eof_samples); 618 619 if (chk->samples_read + FM_BUFFER_REQUESTED (buffer) > chk->eof_samples) 620 bytes_from_ring = SAMPLES_TO_BYTES (chk->eof_samples - chk->samples_read); 621 622 /* if ((input_gst->current_pos_samples + FM_BUFFER_REQUESTED (buffer)) > eof_samples) 623 bytes_from_ring = SAMPLES_TO_BYTES (eof_samples - input_gst->current_pos_samples);*/ 624 } 616 625 617 626 size_t read_bytes = jack_ringbuffer_peek(chk->ring, (gchar *) input_gst->interleaved_buffer, bytes_from_ring); 618 627 // write (temp_fd, input_gst->interleaved_buffer, SAMPLES_TO_BYTES(FM_BUFFER_REQUESTED(buffer))); 619 628 620 gint useful_read_bytes = read_bytes - chk->bytes_behind_us; 629 guint useful_read_bytes = read_bytes - SAMPLES_TO_BYTES (chk->samples_behind_us); 630 guint useful_read_samples = BYTES_TO_SAMPLES (useful_read_bytes); 631 guint useful_read_ns = samples_to_ns (common, useful_read_samples); 621 632 // g_print("got %d bytes, drop %d, keep %d\n", read_bytes, read_bytes - useful_read_bytes, useful_read_bytes); 622 633 … … 626 637 627 638 /* Timekeeping */ 628 guint64 current_pos_nsec_old = input_gst->current_pos_nsec; 629 guint useful_read_samples = BYTES_TO_SAMPLES (useful_read_bytes); 630 current_pos_samples += useful_read_samples; // se abbiamo un underrun durante bytes_behind_us si sputtana tutto? 631 input_gst->current_pos_nsec += samples_to_ns (common, useful_read_samples); 632 633 buffer->timestamp = current_pos_nsec_old; 639 guint64 current_pos_samples_old = input_gst->current_pos_samples; 640 input_gst->current_pos_samples += useful_read_samples; 641 chk->samples_read += useful_read_samples; 642 643 buffer->timestamp = samples_to_ns (common, current_pos_samples_old); 634 644 buffer->used_samples = buffer->requested_samples; 635 buffer->duration = input_gst->current_pos_nsec - current_pos_nsec_old;645 buffer->duration = samples_to_ns (common, useful_read_samples); 636 646 buffer->silence = FALSE; 637 647 // g_print ("DURATION %lld\n", (long long int) FM_BUFFER_DURATION (buffer)); … … 640 650 641 651 /* Check for EOF */ 642 if ((eof_samples) && (current_pos_samples >= eof_samples)) { 643 g_print ("We're at %lld samples - end of file!\n", (long long int) current_pos_samples); 652 /* if ((eof_samples) && (input_gst->current_pos_samples >= eof_samples)) {*/ 653 if ((chk->eof_samples > 0) && (chk->samples_read >= chk->eof_samples)) { 654 g_print ("We're at %lld samples - end of file!\n", (long long int) input_gst->current_pos_samples); 644 655 chk->eof = TRUE; 645 656 } … … 647 658 648 659 /* int-to-float conversion */ 649 gfloat *start_point = (gfloat *) (((gchar *) input_gst->interleaved_buffer) + chk->bytes_behind_us);660 gfloat *start_point = (gfloat *) (((gchar *) input_gst->interleaved_buffer) + SAMPLES_TO_BYTES (chk->samples_behind_us)); 650 661 fm_buffer_store_interleaved_data(buffer, start_point, FM_BUFFER_REQUESTED(buffer)); 651 662 652 663 653 664 /* Advance ring pointer */ 654 if (chk-> bytes_behind_us >= BYTES_TO_LEAVE_BEHIND) {665 if (chk->samples_behind_us >= CHUNK_LEAVE_BEHIND_SAMPLES) { 655 666 jack_ringbuffer_read_advance(chk->ring, useful_read_bytes); 656 667 fm_sem_increase (common->sem); 657 668 } else { 658 chk-> bytes_behind_us += useful_read_bytes;669 chk->samples_behind_us += useful_read_samples; 659 670 } 660 671 // g_print("behind us %d bytes\n", input_gst->bytes_behind_us); … … 662 673 663 674 /* Send the updated position signal */ 664 input_gst-> sample_count += buffer->requested_samples;665 if (input_gst-> sample_count > TICK_EVERY_N_SAMPLES) {666 input_gst-> sample_count = 0;675 input_gst->tick_ns_count += useful_read_ns; 676 if (input_gst->tick_ns_count > TICK_EVERY_NS) { 677 input_gst->tick_ns_count = 0; 667 678 _send_position (input_gst); 668 679 } … … 771 782 g_return_if_fail (nsec != 0); 772 783 773 gint64 seek_target = input_gst->current_pos_nsec + nsec; 784 /* FIXME: we should do the calculation in the PIPELINE thread to avoid races */ 785 gint64 seek_target = samples_to_ns (input_gst->common, input_gst->current_pos_samples) + nsec; 774 786 775 787 if (seek_target < 0) 776 788 seek_target = 0; 777 789 778 input_gst->seek_at_ns ec= seek_target;790 input_gst->seek_at_ns = seek_target; 779 791 } 780 792 … … 789 801 FmInputGstCommon *common = input_gst->common; 790 802 g_return_if_fail (common->read_chunk); 791 g_return_if_fail (common->read_chunk->duration_ns ec> 0);792 793 input_gst->seek_at_ns ec = common->read_chunk->duration_nsec* pos;803 g_return_if_fail (common->read_chunk->duration_ns > 0); 804 805 input_gst->seek_at_ns = common->read_chunk->duration_ns * pos; 794 806 } 795 807 -
trunk/fm_server/src/fm_input_gst/fm_input_gst.h
r198 r221 21 21 22 22 23 #define TICK_EVERY_N _SAMPLES 400023 #define TICK_EVERY_NS 40000000 24 24 25 25 … … 43 43 gchar *filename; 44 44 45 //gint64 current_pos_samples;46 gint64 current_pos_nsec;45 gint64 current_pos_samples; 46 // gint64 current_pos_nsec; 47 47 48 48 gboolean play_when_ready; … … 50 50 gfloat *interleaved_buffer; 51 51 52 gint64 seek_at_ns ec; // where to seek (it's set by the non-RT threads)52 gint64 seek_at_ns; // where to seek (it's set by the non-RT threads) 53 53 54 guint sample_count; // for "tick"54 guint tick_ns_count; // for "tick" 55 55 56 56 gboolean drop_chunks; // invalidate all the currently unused chunks -
trunk/fm_server/src/fm_input_gst/fm_input_gst_common.c
r198 r221 52 52 guint64 nsec) 53 53 { 54 return (guint64) (nsec / common->ns ec_for_sample);54 return (guint64) (nsec / common->ns_for_sample); 55 55 } 56 56 … … 60 60 guint64 samples) 61 61 { 62 return (guint64) (samples * common->ns ec_for_sample);62 return (guint64) (samples * common->ns_for_sample); 63 63 } -
trunk/fm_server/src/fm_input_gst/fm_input_gst_common.h
r198 r221 22 22 23 23 24 #define STD_CHUNK_N_SAMPLES (16384 * 2)25 #define CHUNK_PRELOAD_ N_SAMPLES (4096 * 2)26 #define BYTES_TO_LEAVE_BEHIND(8192 * 2)24 #define CHUNK_SAMPLES (16384 * 2) 25 #define CHUNK_PRELOAD_SAMPLES (4096 * 2) 26 #define CHUNK_LEAVE_BEHIND_SAMPLES (8192 * 2) 27 27 28 28 … … 43 43 GstClockTime start_timestamp_offset; // where to find the REAL start of the segment requested in the seek 44 44 // (as an offset from the start of the chunk) 45 gint64 duration_ns ec;45 gint64 duration_ns; 46 46 47 47 gint bytes_preloaded; // -1 means ready to read 48 guint bytes_behind_us;48 guint samples_behind_us; 49 49 50 50 /* FIXME: "eof" should be moved to FmInputGst */ 51 51 gboolean eof; // the file ends somewhere in this chunk 52 52 GstClockTime eof_timestamp; // where the file ends (stream timestamp) 53 guint64 eof_samples; // where the file ends (RELATIVE TO CHUNK START!!!!) 53 54 gboolean start_of_file; // 1° buffer of the file 54 55 55 56 gboolean can_destroy; // set after skipping to a new chunk. 56 57 // if TRUE, the buffer will be freed by the GST thread in _do_cleanup() 58 59 guint64 samples_read; 57 60 }; 58 61 … … 83 86 gboolean stop_processing; // discard incoming buffers and delete chunks 84 87 85 gint64 seek_waiting_for_ns ec; // only for a FAR seek, wait for a new chunk returned from GST which starts here86 gint64 gst_seek_to_ns ec;// only for a FAR seek, where GStreamer should seek88 gint64 seek_waiting_for_ns; // only for a FAR seek, wait for a new chunk returned from GST which starts here 89 gint64 gst_seek_to_ns; // only for a FAR seek, where GStreamer should seek 87 90 88 gdouble ns ec_for_sample;91 gdouble ns_for_sample; 89 92 90 93 gboolean loaded; -
trunk/fm_server/src/fm_input_gst/gstfmsink.c
r198 r221 237 237 g_return_val_if_fail (common->write_chunk, TRUE); 238 238 common->write_chunk->eof_timestamp = sink->start_timestamp; 239 common->write_chunk->eof_samples = sink->position_samples; 239 240 g_print("> got EOF at timestamp %lld\n", (long long int) common->write_chunk->eof_timestamp); 240 241 sink->seek_in_progress = FALSE; … … 326 327 } 327 328 328 chk = fm_chunk_new (SAMPLES_TO_BYTES ( STD_CHUNK_N_SAMPLES));329 chk = fm_chunk_new (SAMPLES_TO_BYTES (CHUNK_SAMPLES)); 329 330 chk->num = sink->chunk_count++; 330 331 common->chunks = g_list_append (common->chunks, chk); … … 342 343 chk->start_timestamp = timestamp; 343 344 sink->start_timestamp = timestamp; 345 sink->position_samples = 0; 344 346 345 347 if (sink->seek_target_timestamp != -1) { … … 355 357 356 358 chk->start_timestamp_offset += nsec_to_skip; 357 chk-> bytes_behind_us = SAMPLES_TO_BYTES (ns_to_samples(common, nsec_to_skip));359 chk->samples_behind_us = ns_to_samples(common, nsec_to_skip); 358 360 } else 359 361 g_warning ("too much to skip, seek failed!"); … … 362 364 } 363 365 GstFormat fmt = GST_FORMAT_TIME; 364 gst_element_query_duration (common->sink, &fmt, &chk->duration_ns ec);366 gst_element_query_duration (common->sink, &fmt, &chk->duration_ns); 365 367 // g_print("> gst_element_query_duration %lld\n", chk->duration_samples); 366 368 } … … 385 387 return GST_FLOW_OK; 386 388 387 if (common->gst_seek_to_ns ec> -1) {389 if (common->gst_seek_to_ns > -1) { 388 390 if (sink->seek_in_progress) { 389 391 g_print ("> seek already in progress, we'll try later\n"); … … 391 393 } 392 394 393 g_print("> requested seek to %lld\n", (long long int) common->gst_seek_to_ns ec);394 395 sink->seek_target_timestamp = common->gst_seek_to_ns ec;396 common->gst_seek_to_ns ec= -1;395 g_print("> requested seek to %lld\n", (long long int) common->gst_seek_to_ns); 396 397 sink->seek_target_timestamp = common->gst_seek_to_ns; 398 common->gst_seek_to_ns = -1; 397 399 sink->seek_in_progress = TRUE; 398 400 … … 414 416 415 417 buffer_pos_bytes += written_bytes; 418 sink->position_samples += BYTES_TO_SAMPLES (written_bytes); 416 419 417 420 if (written_bytes < bytes_to_write) { … … 420 423 421 424 if (chk->bytes_preloaded == -1) {} 422 else if (chk->bytes_preloaded > CHUNK_PRELOAD_ N_SAMPLES) {425 else if (chk->bytes_preloaded > CHUNK_PRELOAD_SAMPLES) { 423 426 chk->usable = TRUE; 424 427 // common->chunk_skip_to = chk; … … 428 431 // of the stream now (useful with old MP3 VBR) 429 432 GstFormat fmt = GST_FORMAT_TIME; 430 gst_element_query_duration (common->sink, &fmt, &chk->duration_ns ec);433 gst_element_query_duration (common->sink, &fmt, &chk->duration_ns); 431 434 // g_print("> gst_element_query_duration %lld\n", chk->duration_samples); 432 435 … … 444 447 445 448 sink->start_timestamp = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf); 446 // g_print("> sink-> offset_samples %lld\n", sink->offset_samples);449 // g_print("> sink->position_samples %lld\n", sink->position_samples); 447 450 448 451 return GST_FLOW_OK; … … 459 462 fm_sink->common = (FmInputGstCommon *) ptr; 460 463 461 fm_sink->common->ns ec_for_sample = (gdouble) GST_SECOND / SAMPLES_FOR_SEC;464 fm_sink->common->ns_for_sample = (gdouble) GST_SECOND / SAMPLES_FOR_SEC; 462 465 } 463 466 -
trunk/fm_server/src/fm_input_gst/gstfmsink.h
r198 r221 88 88 GstClockTime seek_target_timestamp; // ns 89 89 90 guint64 position_samples; // from start of chunk 91 90 92 guint bytes_behind_us; 91 93
