diff options
Diffstat (limited to 'apps/plugins/mpegplayer/disk_buf.c')
-rw-r--r-- | apps/plugins/mpegplayer/disk_buf.c | 150 |
1 files changed, 114 insertions, 36 deletions
diff --git a/apps/plugins/mpegplayer/disk_buf.c b/apps/plugins/mpegplayer/disk_buf.c index 0720197f3a..39563b7041 100644 --- a/apps/plugins/mpegplayer/disk_buf.c +++ b/apps/plugins/mpegplayer/disk_buf.c | |||
@@ -49,6 +49,26 @@ static inline void disk_buf_on_clear_data_notify(struct stream_hdr *sh) | |||
49 | list_remove_item(&sh->nf); | 49 | list_remove_item(&sh->nf); |
50 | } | 50 | } |
51 | 51 | ||
52 | |||
53 | inline bool disk_buf_is_data_ready(struct stream_hdr *sh, | ||
54 | ssize_t margin) | ||
55 | { | ||
56 | /* Data window available? */ | ||
57 | off_t right = sh->win_right; | ||
58 | |||
59 | /* Margins past end-of-file can still return true */ | ||
60 | if (right > disk_buf.filesize - margin) | ||
61 | right = disk_buf.filesize - margin; | ||
62 | |||
63 | return sh->win_left >= disk_buf.win_left && | ||
64 | right + margin <= disk_buf.win_right; | ||
65 | } | ||
66 | |||
67 | void dbuf_l2_init(struct dbuf_l2_cache *l2_p) | ||
68 | { | ||
69 | l2_p->addr = OFF_T_MAX; /* Mark as invalid */ | ||
70 | } | ||
71 | |||
52 | static int disk_buf_on_data_notify(struct stream_hdr *sh) | 72 | static int disk_buf_on_data_notify(struct stream_hdr *sh) |
53 | { | 73 | { |
54 | DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X ", STR_FROM_HEADER(sh)->id); | 74 | DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X ", STR_FROM_HEADER(sh)->id); |
@@ -519,17 +539,16 @@ static void disk_buf_thread(void) | |||
519 | } | 539 | } |
520 | 540 | ||
521 | /* Caches some data from the current file */ | 541 | /* Caches some data from the current file */ |
522 | static int disk_buf_probe(off_t start, size_t length, | 542 | static ssize_t disk_buf_probe(off_t start, size_t length, void **p) |
523 | void **p, size_t *outlen) | ||
524 | { | 543 | { |
525 | off_t end; | 544 | off_t end; |
526 | uint32_t tag, tag_end; | 545 | uint32_t tag, tag_end; |
527 | int page; | 546 | int page; |
528 | 547 | ||
529 | /* Can't read past end of file */ | 548 | /* Can't read past end of file */ |
530 | if (length > (size_t)(disk_buf.filesize - disk_buf.offset)) | 549 | if (length > (size_t)(disk_buf.filesize - start)) |
531 | { | 550 | { |
532 | length = disk_buf.filesize - disk_buf.offset; | 551 | length = disk_buf.filesize - start; |
533 | } | 552 | } |
534 | 553 | ||
535 | /* Can't cache more than the whole buffer size */ | 554 | /* Can't cache more than the whole buffer size */ |
@@ -559,11 +578,6 @@ static int disk_buf_probe(off_t start, size_t length, | |||
559 | + (start & DISK_BUF_PAGE_MASK); | 578 | + (start & DISK_BUF_PAGE_MASK); |
560 | } | 579 | } |
561 | 580 | ||
562 | if (outlen != NULL) | ||
563 | { | ||
564 | *outlen = length; | ||
565 | } | ||
566 | |||
567 | /* Obtain initial load point. If all data was cached, no message is sent | 581 | /* Obtain initial load point. If all data was cached, no message is sent |
568 | * otherwise begin on the first page that is not cached. Since we have to | 582 | * otherwise begin on the first page that is not cached. Since we have to |
569 | * send the message anyway, the buffering thread will determine what else | 583 | * send the message anyway, the buffering thread will determine what else |
@@ -573,12 +587,17 @@ static int disk_buf_probe(off_t start, size_t length, | |||
573 | if (disk_buf.cache[page] != tag) | 587 | if (disk_buf.cache[page] != tag) |
574 | { | 588 | { |
575 | static struct dbuf_range rng IBSS_ATTR; | 589 | static struct dbuf_range rng IBSS_ATTR; |
590 | intptr_t result; | ||
591 | |||
576 | DEBUGF("disk_buf: cache miss\n"); | 592 | DEBUGF("disk_buf: cache miss\n"); |
577 | rng.tag_start = tag; | 593 | rng.tag_start = tag; |
578 | rng.tag_end = tag_end; | 594 | rng.tag_end = tag_end; |
579 | rng.pg_start = page; | 595 | rng.pg_start = page; |
580 | return rb->queue_send(disk_buf.q, DISK_BUF_CACHE_RANGE, | 596 | |
581 | (intptr_t)&rng); | 597 | result = rb->queue_send(disk_buf.q, DISK_BUF_CACHE_RANGE, |
598 | (intptr_t)&rng); | ||
599 | |||
600 | return result == DISK_BUF_NOTIFY_OK ? (ssize_t)length : -1; | ||
582 | } | 601 | } |
583 | 602 | ||
584 | if (++page >= disk_buf.pgcount) | 603 | if (++page >= disk_buf.pgcount) |
@@ -586,35 +605,96 @@ static int disk_buf_probe(off_t start, size_t length, | |||
586 | } | 605 | } |
587 | while (++tag <= tag_end); | 606 | while (++tag <= tag_end); |
588 | 607 | ||
589 | return DISK_BUF_NOTIFY_OK; | 608 | return length; |
590 | } | 609 | } |
591 | 610 | ||
592 | /* Attempt to get a pointer to size bytes on the buffer. Returns real amount of | 611 | /* Attempt to get a pointer to size bytes on the buffer. Returns real amount of |
593 | * data available as well as the size of non-wrapped data after *p. */ | 612 | * data available as well as the size of non-wrapped data after *p. */ |
594 | ssize_t _disk_buf_getbuffer(size_t size, void **pp, void **pwrap, size_t *sizewrap) | 613 | ssize_t disk_buf_getbuffer(size_t size, void **pp, void **pwrap, |
614 | size_t *sizewrap) | ||
595 | { | 615 | { |
596 | disk_buf_lock(); | 616 | disk_buf_lock(); |
597 | 617 | ||
598 | if (disk_buf_probe(disk_buf.offset, size, pp, &size) == DISK_BUF_NOTIFY_OK) | 618 | size = disk_buf_probe(disk_buf.offset, size, pp); |
619 | |||
620 | if (size != (size_t)-1 && pwrap && sizewrap) | ||
599 | { | 621 | { |
600 | if (pwrap && sizewrap) | 622 | uint8_t *p = (uint8_t *)*pp; |
601 | { | ||
602 | uint8_t *p = (uint8_t *)*pp; | ||
603 | 623 | ||
604 | if (p + size > disk_buf.end + DISK_GUARDBUF_SIZE) | 624 | if (p + size > disk_buf.end + DISK_GUARDBUF_SIZE) |
605 | { | 625 | { |
606 | /* Return pointer to wraparound and the size of same */ | 626 | /* Return pointer to wraparound and the size of same */ |
607 | size_t nowrap = (disk_buf.end + DISK_GUARDBUF_SIZE) - p; | 627 | size_t nowrap = (disk_buf.end + DISK_GUARDBUF_SIZE) - p; |
608 | *pwrap = disk_buf.start + DISK_GUARDBUF_SIZE; | 628 | *pwrap = disk_buf.start + DISK_GUARDBUF_SIZE; |
609 | *sizewrap = size - nowrap; | 629 | *sizewrap = size - nowrap; |
610 | } | 630 | } |
611 | else | 631 | else |
612 | { | 632 | { |
613 | *pwrap = NULL; | 633 | *pwrap = NULL; |
614 | *sizewrap = 0; | 634 | *sizewrap = 0; |
615 | } | ||
616 | } | 635 | } |
617 | } | 636 | } |
637 | |||
638 | disk_buf_unlock(); | ||
639 | |||
640 | return size; | ||
641 | } | ||
642 | |||
643 | ssize_t disk_buf_getbuffer_l2(struct dbuf_l2_cache *l2, | ||
644 | size_t size, void **pp) | ||
645 | { | ||
646 | off_t offs; | ||
647 | off_t l2_addr; | ||
648 | size_t l2_size; | ||
649 | void *l2_p; | ||
650 | |||
651 | if (l2 == NULL) | ||
652 | { | ||
653 | /* Shouldn't have to check this normally */ | ||
654 | DEBUGF("disk_buf_getbuffer_l2: l2 = NULL!\n"); | ||
655 | } | ||
656 | |||
657 | if (size > DISK_BUF_L2_CACHE_SIZE) | ||
658 | { | ||
659 | /* Asking for too much; just go through L1 */ | ||
660 | return disk_buf_getbuffer(size, pp, NULL, NULL); | ||
661 | } | ||
662 | |||
663 | offs = disk_buf.offset; /* Other calls keep this within bounds */ | ||
664 | l2_addr = l2->addr; | ||
665 | |||
666 | if (offs >= l2_addr && offs < l2_addr + DISK_BUF_L2_CACHE_SIZE) | ||
667 | { | ||
668 | /* Data is in the local buffer */ | ||
669 | offs &= DISK_BUF_L2_CACHE_MASK; | ||
670 | |||
671 | *pp = l2->data + offs; | ||
672 | if (offs + size > l2->size) | ||
673 | size = l2->size - offs; /* Keep size within file limits */ | ||
674 | |||
675 | return size; | ||
676 | } | ||
677 | |||
678 | /* Have to probe main buffer */ | ||
679 | l2_addr = offs & ~DISK_BUF_L2_CACHE_MASK; | ||
680 | l2_size = DISK_BUF_L2_CACHE_SIZE*2; /* 2nd half is a guard buffer */ | ||
681 | |||
682 | disk_buf_lock(); | ||
683 | |||
684 | l2_size = disk_buf_probe(l2_addr, l2_size, &l2_p); | ||
685 | |||
686 | if (l2_size != (size_t)-1) | ||
687 | { | ||
688 | rb->memcpy(l2->data, l2_p, l2_size); | ||
689 | |||
690 | l2->addr = l2_addr; | ||
691 | l2->size = l2_size; | ||
692 | offs -= l2_addr; | ||
693 | |||
694 | *pp = l2->data + offs; | ||
695 | if (offs + size > l2->size) | ||
696 | size = l2->size - offs; /* Keep size within file limits */ | ||
697 | } | ||
618 | else | 698 | else |
619 | { | 699 | { |
620 | size = -1; | 700 | size = -1; |
@@ -625,6 +705,7 @@ ssize_t _disk_buf_getbuffer(size_t size, void **pp, void **pwrap, size_t *sizewr | |||
625 | return size; | 705 | return size; |
626 | } | 706 | } |
627 | 707 | ||
708 | |||
628 | /* Read size bytes of data into a buffer - advances the buffer pointer | 709 | /* Read size bytes of data into a buffer - advances the buffer pointer |
629 | * and returns the real size read. */ | 710 | * and returns the real size read. */ |
630 | ssize_t disk_buf_read(void *buffer, size_t size) | 711 | ssize_t disk_buf_read(void *buffer, size_t size) |
@@ -633,8 +714,9 @@ ssize_t disk_buf_read(void *buffer, size_t size) | |||
633 | 714 | ||
634 | disk_buf_lock(); | 715 | disk_buf_lock(); |
635 | 716 | ||
636 | if (disk_buf_probe(disk_buf.offset, size, PUN_PTR(void **, &p), | 717 | size = disk_buf_probe(disk_buf.offset, size, (void **)&p); |
637 | &size) == DISK_BUF_NOTIFY_OK) | 718 | |
719 | if (size != (size_t)-1) | ||
638 | { | 720 | { |
639 | if (p + size > disk_buf.end + DISK_GUARDBUF_SIZE) | 721 | if (p + size > disk_buf.end + DISK_GUARDBUF_SIZE) |
640 | { | 722 | { |
@@ -652,10 +734,6 @@ ssize_t disk_buf_read(void *buffer, size_t size) | |||
652 | 734 | ||
653 | disk_buf.offset += size; | 735 | disk_buf.offset += size; |
654 | } | 736 | } |
655 | else | ||
656 | { | ||
657 | size = -1; | ||
658 | } | ||
659 | 737 | ||
660 | disk_buf_unlock(); | 738 | disk_buf_unlock(); |
661 | 739 | ||
@@ -713,7 +791,7 @@ ssize_t disk_buf_prepare_streaming(off_t pos, size_t len) | |||
713 | DEBUGF("prepare streaming:\n pos:%ld len:%zu\n", pos, len); | 791 | DEBUGF("prepare streaming:\n pos:%ld len:%zu\n", pos, len); |
714 | 792 | ||
715 | pos = disk_buf_lseek(pos, SEEK_SET); | 793 | pos = disk_buf_lseek(pos, SEEK_SET); |
716 | disk_buf_probe(pos, len, NULL, &len); | 794 | len = disk_buf_probe(pos, len, NULL); |
717 | 795 | ||
718 | DEBUGF(" probe done: pos:%ld len:%zu\n", pos, len); | 796 | DEBUGF(" probe done: pos:%ld len:%zu\n", pos, len); |
719 | 797 | ||