summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/disk_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpegplayer/disk_buf.c')
-rw-r--r--apps/plugins/mpegplayer/disk_buf.c150
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
53inline 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
67void dbuf_l2_init(struct dbuf_l2_cache *l2_p)
68{
69 l2_p->addr = OFF_T_MAX; /* Mark as invalid */
70}
71
52static int disk_buf_on_data_notify(struct stream_hdr *sh) 72static 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 */
522static int disk_buf_probe(off_t start, size_t length, 542static 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. */
594ssize_t _disk_buf_getbuffer(size_t size, void **pp, void **pwrap, size_t *sizewrap) 613ssize_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
643ssize_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. */
630ssize_t disk_buf_read(void *buffer, size_t size) 711ssize_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