1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  *
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include "uvoice_types.h"
12 #include "uvoice_player.h"
13 
14 #include "uvoice_os.h"
15 #include "uvoice_config.h"
16 #include "uvoice_common.h"
17 #include "uvoice_ringbuffer.h"
18 #include "uvoice_play.h"
19 #include "uvoice_format.h"
20 
21 #include "uvoice_cache.h"
22 
23 
24 #if (PLAYER_CACHE_TYPE != 0) && (PLAYER_CACHE_TYPE != 1) && \
25     (PLAYER_CACHE_TYPE != 2)
26 #error "cache type unsupport ! please choose from 0, 1, 2"
27 #endif
28 
29 #ifdef MUSICBOX_APP
30 #define NET_CACHE_TASK_PRIORITY        UVOICE_TASK_PRI_HIGHEST
31 #else
32 #define NET_CACHE_TASK_PRIORITY        UVOICE_TASK_PRI_HIGHER
33 #endif
34 
35 #ifndef PLAYER_CACHE_MEM_SIZE
36 #define PLAYER_CACHE_MEM_SIZE        40
37 #endif
38 
39 #define NET_CACHE_REBUILD_ENABLE        1
40 
41 #define NET_CACHE_FILE_ENABLE            1
42 
43 
net_cache_file(net_cache_t * nc)44 static int net_cache_file(net_cache_t *nc)
45 {
46 #if NET_CACHE_FILE_ENABLE
47     struct cache_file *cache;
48     int load_size = 0;
49     int rd_ret = 0;
50     int ret;
51 
52     if (!nc) {
53         M_LOGE("nc null !\n");
54         return -1;
55     }
56 
57     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
58     nc->cache_running = 1;
59     cache = nc->cache;
60     if (!cache) {
61         M_LOGE("cache null !\n");
62         os_mutex_unlock(nc->lock);
63         return -1;
64     }
65 
66     if (cache->fp) {
67         os_fclose(cache->fp);
68         cache->fp = NULL;
69         M_LOGD("cache file close\n");
70     }
71 
72     cache->fp = os_fopen(nc->cache_config.file_path, "wb+");
73     if (OS_FILE_OPEN_FAIL(cache->fp)) {
74         M_LOGE("open %s failed !\n", nc->cache_config.file_path);
75         nc->cache_running = 0;
76         os_mutex_unlock(nc->lock);
77         return -1;
78     }
79     M_LOGD("cache file open\n");
80 
81     cache->wr_pos = 0;
82     (void)os_fseek(cache->fp, cache->wr_pos, OS_SEEK_SET);
83 
84     if (nc->head_data_size > 0) {
85         ret = os_fwrite(nc->buffer, 1, nc->head_data_size, cache->fp);
86         if (os_ferror(cache->fp) || ret != nc->head_data_size) {
87             M_LOGE("write head data failed %d!\n",
88                 os_ferror(cache->fp));
89             nc->cache_running = 0;
90             os_mutex_unlock(nc->lock);
91             return -1;
92         }
93         cache->wr_pos += nc->head_data_size;
94         nc->load_length += nc->head_data_size;
95         nc->head_data_size = 0;
96     }
97 
98     load_size = MIN(nc->buffer_size,
99         nc->content_length - cache->wr_pos);
100 
101     M_LOGD("start\n");
102 
103     os_mutex_unlock(nc->lock);
104 
105     while (1) {
106         rd_ret = nc->cache_load(nc->priv, nc->buffer, load_size);
107         if (rd_ret < 0) {
108             M_LOGE("load failed !\n");
109             nc->cache_cplt = 1;
110             break;
111         } else if (rd_ret == 0) {
112             M_LOGD("load end\n");
113             nc->cache_cplt = 1;
114             break;
115         } else if (rd_ret != load_size) {
116             M_LOGW("load %d ret %d\n", load_size, rd_ret);
117         }
118 
119         os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
120 
121         (void)os_fseek(cache->fp, cache->wr_pos, OS_SEEK_SET);
122         ret = os_fwrite(nc->buffer, 1, rd_ret, cache->fp);
123         if (os_ferror(cache->fp) || ret != rd_ret) {
124             M_LOGE("cache wr failed %d!\n", os_ferror(cache->fp));
125             nc->cache_cplt = 1;
126             os_mutex_unlock(nc->lock);
127             break;
128         }
129         cache->wr_pos += rd_ret;
130 
131         if (cache->rd_waiting &&
132             cache->wr_pos - cache->rd_pos >= cache->rd_len) {
133             os_sem_signal(cache->rd_sem);
134             cache->rd_waiting = 0;
135         }
136 
137         nc->load_length += rd_ret;
138         if (nc->cache_stop) {
139             if (cache->rd_waiting) {
140                 os_sem_signal(cache->rd_sem);
141                 cache->rd_waiting = 0;
142             }
143             nc->cache_stop = 0;
144             nc->cache_cplt = 1;
145             os_mutex_unlock(nc->lock);
146             M_LOGD("cache stop\n");
147             break;
148         }
149 
150         load_size = MIN(load_size,
151             nc->content_length - nc->load_length);
152 
153         if (load_size <= 0) {
154             if (!nc->sequence) {
155                 M_LOGD("load end\n");
156                 nc->cache_cplt = 1;
157                 os_mutex_unlock(nc->lock);
158                 break;
159             } else {
160                 M_LOGD("request next segment, wr_pos %u load_length %u\n",
161                     cache->wr_pos, nc->load_length);
162                 os_mutex_unlock(nc->lock);
163                 if (nc->event(nc->priv, CACHE_EV_CACHE_CPLT, NULL)) {
164                     M_LOGD("request next segment failed !\n");
165                     nc->cache_cplt = 1;
166                     break;
167                 }
168                 os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
169 
170                 if (nc->head_data_size > 0) {
171                     ret = os_fwrite(nc->buffer,
172                         1, nc->head_data_size, cache->fp);
173                     if (os_ferror(cache->fp) || ret != nc->head_data_size) {
174                         M_LOGE("write head data failed %d!\n",
175                             os_ferror(cache->fp));
176                         if (nc->cplt_waiting) {
177                             nc->cplt_waiting = 0;
178                             os_sem_signal(nc->cplt_sem);
179                         }
180                         nc->cache_running = 0;
181                         os_mutex_unlock(nc->lock);
182                         return -1;
183                     }
184                     cache->wr_pos += nc->head_data_size;
185                     nc->load_length += nc->head_data_size;
186                     M_LOGD("cache seq head data %u\n",
187                         nc->head_data_size);
188                     M_LOGD("cache next segment, wr_pos %u load_length %u\n",
189                         cache->wr_pos, nc->load_length);
190                     nc->head_data_size = 0;
191                 }
192 
193                 load_size = MIN(nc->buffer_size,
194                     nc->content_length - nc->load_length);
195                 if (load_size <= 0) {
196                     M_LOGD("load end\n");
197                     nc->cache_cplt = 1;
198                     os_mutex_unlock(nc->lock);
199                     break;
200                 }
201             }
202         }
203         os_mutex_unlock(nc->lock);
204     }
205 
206     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
207 
208     M_LOGD("complete %d/%d\n",
209         nc->load_length, nc->content_length);
210     if (!nc->sequence)
211         nc->event(nc->priv, CACHE_EV_CACHE_CPLT, NULL);
212     if (nc->cplt_waiting) {
213         nc->cplt_waiting = 0;
214         os_sem_signal(nc->cplt_sem);
215     }
216 
217     nc->cache_running = 0;
218     os_mutex_unlock(nc->lock);
219     return 0;
220 
221 #else
222     return -1;
223 #endif
224 }
225 
net_cache_file_read(void * priv,unsigned char * buffer,int nbytes)226 static int net_cache_file_read(void *priv, unsigned char *buffer, int nbytes)
227 {
228 #if NET_CACHE_FILE_ENABLE
229     net_cache_t *nc = (net_cache_t *)priv;
230     struct cache_file *cache;
231     int ret = 0;
232 
233     if (!nc) {
234         M_LOGE("nc null !\n");
235         return -1;
236     }
237 
238     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
239 
240     cache = nc->cache;
241     if (!cache) {
242         M_LOGE("cache null !\n");
243         os_mutex_unlock(nc->lock);
244         return -1;
245     }
246 
247     if (!cache->rd_start) {
248         cache->rd_len = MIN(nbytes * 10, nc->content_length);
249         cache->rd_start = 1;
250         M_LOGD("read start\n");
251     } else {
252         cache->rd_len = nbytes;
253     }
254 
255     if (nc->seek_offset != 0) {
256         if (nc->seek_offset > 0) {
257             if (nc->seek_offset <= cache->wr_pos - cache->rd_pos) {
258                 cache->rd_pos += nc->seek_offset;
259                 nc->event(nc->priv, CACHE_EV_SEEK_DONE,
260                     (void *)nc->seek_offset);
261                 M_LOGD("seek %d bytes\n", nc->seek_offset);
262             }
263         } else {
264             if (abs(nc->seek_offset) <= cache->rd_pos) {
265                 cache->rd_pos += nc->seek_offset;
266                 nc->event(nc->priv, CACHE_EV_SEEK_DONE,
267                     (void *)nc->seek_offset);
268                 M_LOGD("seek %d bytes\n", nc->seek_offset);
269             }
270         }
271         nc->seek_offset = 0;
272     }
273 
274     while (cache->wr_pos <= cache->rd_pos ||
275         cache->wr_pos - cache->rd_pos < cache->rd_len ||
276         !cache->fp) {
277         if (nc->cache_cplt) {
278             M_LOGD("cache cplt, stop waiting\n");
279             break;
280         }
281 
282         M_LOGD("wait cache, rd_len %u rd_pos %u wr_pos %u\n",
283             cache->rd_len, cache->rd_pos, cache->wr_pos);
284         cache->rd_waiting = 1;
285         os_mutex_unlock(nc->lock);
286 
287         if (os_sem_wait(cache->rd_sem, 30000)) {
288             os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
289             M_LOGE("wait timeout ! rd_len %u rd_pos %u wr_pos %u\n",
290                 cache->rd_len, cache->rd_pos, cache->wr_pos);
291             cache->rd_waiting = 0;
292             goto __exit;
293         }
294         os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
295         cache->rd_waiting = 0;
296         M_LOGD("wait exit, rd_len %u rd_pos %u wr_pos %u\n",
297             cache->rd_len, cache->rd_pos, cache->wr_pos);
298     }
299 
300     if (!cache->fp) {
301         M_LOGE("cache file not open !\n");
302         os_mutex_unlock(nc->lock);
303         return -1;
304     }
305 
306     if (nc->cache_cplt) {
307         if (os_feof(cache->fp) || cache->rd_pos >= cache->wr_pos) {
308             nbytes = 0;
309             M_LOGD("read end\n");
310             goto __exit;
311         } else if (cache->wr_pos - cache->rd_pos < nbytes) {
312             nbytes = cache->wr_pos - cache->rd_pos;
313             M_LOGD("read tail %d\n", nbytes);
314         }
315     }
316 
317     (void)os_fseek(cache->fp, cache->rd_pos, OS_SEEK_SET);
318     ret = os_fread(buffer, 1, nbytes, cache->fp);
319     if (os_ferror(cache->fp) || ret != nbytes) {
320         M_LOGE("read failed %d!\n", os_ferror(cache->fp));
321         os_mutex_unlock(nc->lock);
322         return -1;
323     }
324 
325     cache->rd_pos += nbytes;
326     ret = nbytes;
327 
328 __exit:
329     os_mutex_unlock(nc->lock);
330     return ret;
331 
332 #else
333     return -1;
334 #endif
335 }
336 
net_cache_file_mediainfo(struct cache_file * cache,media_info_t * info,media_format_t format)337 static int net_cache_file_mediainfo(struct cache_file *cache,
338         media_info_t *info, media_format_t format)
339 {
340 #if NET_CACHE_FILE_ENABLE
341     if (!cache) {
342         M_LOGW("cache not enable\n");
343         return -1;
344     }
345 
346     if (!cache->fp) {
347         M_LOGE("cache file not open !\n");
348         return -1;
349     }
350 
351     if (format == MEDIA_FMT_MP3) {
352         char buffer[128];
353         memset(buffer, 0, sizeof(buffer));
354         (void)os_fseek(cache->fp, -128, OS_SEEK_END);
355         int ret = os_fread(buffer, 1, 128, cache->fp);
356         if (ret != 128) {
357             M_LOGE("read failed %d!\n", ret);
358             return -1;
359         }
360 
361         mp3_id3v1_parse(info, buffer, 128);
362     }
363 
364     return 0;
365 
366 #else
367     return -1;
368 #endif
369 }
370 
371 
net_cache_file_reset(struct cache_file * cache)372 static int net_cache_file_reset(struct cache_file *cache)
373 {
374 #if NET_CACHE_FILE_ENABLE
375     if (!cache) {
376         M_LOGE("cache null !\n");
377         return -1;
378     }
379 
380     if (cache->fp) {
381         os_fclose(cache->fp);
382         cache->fp = NULL;
383         M_LOGD("cache file close\n");
384     }
385 
386     cache->rd_pos = 0;
387     cache->wr_pos = 0;
388     cache->rd_waiting = 0;
389     cache->rd_start = 0;
390     cache->rd_len = 0;
391 
392     M_LOGD("file cache reset\n");
393     return 0;
394 
395 #else
396     return -1;
397 #endif
398 }
399 
net_cache_file_init(net_cache_t * nc)400 static int net_cache_file_init(net_cache_t *nc)
401 {
402 #if NET_CACHE_FILE_ENABLE
403     struct cache_file *cache = snd_zalloc(
404             sizeof(struct cache_file), AFM_EXTN);
405     if (!cache) {
406         M_LOGE("alloc cache file failed !\n");
407         return -1;
408     }
409 
410     cache->rd_sem = os_sem_new(0);
411     nc->cache_read = net_cache_file_read;
412     nc->cache = cache;
413 
414     return 0;
415 
416 #else
417     return -1;
418 #endif
419 }
420 
net_cache_file_deinit(net_cache_t * nc)421 static int net_cache_file_deinit(net_cache_t *nc)
422 {
423 #if NET_CACHE_FILE_ENABLE
424     struct cache_file *cache;
425 
426     if (!nc) {
427         M_LOGE("nc null !\n");
428         return -1;
429     }
430 
431     cache = nc->cache;
432     if (!cache) {
433         M_LOGE("cache null !\n");
434         return -1;
435     }
436 
437     net_cache_file_reset(cache);
438     os_sem_free(cache->rd_sem);
439     snd_free(cache);
440     nc->cache_read = NULL;
441     nc->cache = NULL;
442 
443     return 0;
444 
445 #else
446     return -1;
447 #endif
448 }
449 
net_cache_mem(net_cache_t * nc)450 static int net_cache_mem(net_cache_t *nc)
451 {
452     struct cache_mem *cache;
453     int load_size;
454     int rd_ret = 0;
455     int wr_ret = 0;
456 
457     if (!nc) {
458         M_LOGE("nc null !\n");
459         return -1;
460     }
461 
462     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
463 
464     nc->cache_running = 1;
465 
466     cache = nc->cache;
467     if (!cache) {
468         M_LOGE("cache null !\n");
469         os_mutex_unlock(nc->lock);
470         return -1;
471     }
472 
473     if (nc->head_data_size > 0) {
474         if (uvoice_ringbuff_freesize(&cache->rb) < nc->head_data_size) {
475             if (cache->rd_waiting) {
476                 os_sem_signal(cache->rd_sem);
477                 cache->rd_waiting = 0;
478             }
479 
480             cache->wr_len = nc->head_data_size;
481             cache->wr_waiting = 1;
482             os_mutex_unlock(nc->lock);
483 
484             os_sem_wait(cache->wr_sem, OS_WAIT_FOREVER);
485 
486             os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
487             cache->wr_waiting = 0;
488 
489             if (nc->cache_stop) {
490                 nc->cache_stop = 0;
491                 nc->cache_cplt = 1;
492                 M_LOGD("cache stop\n");
493                 os_mutex_unlock(nc->lock);
494                 goto __exit;
495             }
496         }
497         wr_ret = uvoice_ringbuff_fill(&cache->rb,
498             nc->buffer, nc->head_data_size);
499         if (wr_ret < 0) {
500             M_LOGE("fill head data %u failed !\n",
501                     nc->head_data_size);
502             nc->cache_running = 0;
503             os_mutex_unlock(nc->lock);
504             return -1;
505         } else if (wr_ret != nc->head_data_size) {
506             M_LOGW("cache head data %u ret %d\n",
507                 nc->buffer_size, wr_ret);
508         }
509         nc->load_length += nc->head_data_size;
510         nc->head_data_size = 0;
511     }
512 
513     load_size = MIN(nc->buffer_size,
514             nc->content_length - nc->load_length);
515 
516     if (nc->load_length >= nc->content_length) {
517         nc->cache_cplt = 1;
518         goto __exit;
519     }
520 
521     M_LOGD("start\n");
522 
523     os_mutex_unlock(nc->lock);
524 
525     while (1) {
526         rd_ret = nc->cache_load(nc->priv, nc->buffer + nc->offset,
527             load_size);
528         if (rd_ret < 0) {
529             M_LOGE("load failed !\n");
530             nc->cache_cplt = 1;
531             nc->load_length -= nc->offset;
532             break;
533         } else if (rd_ret == 0) {
534             M_LOGD("load end\n");
535             nc->cache_cplt = 1;
536             nc->load_length -= nc->offset;
537             break;
538         } else if (rd_ret != load_size) {
539             M_LOGW("load %d ret %u\n", load_size, rd_ret);
540         }
541 
542         os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
543 
544         if (nc->cache_stop) {
545             nc->cache_stop = 0;
546             nc->cache_cplt = 1;
547             nc->load_length -= nc->offset;
548             M_LOGD("cache stop\n");
549             os_mutex_unlock(nc->lock);
550             goto __exit;
551         }
552 
553         while (uvoice_ringbuff_freesize(&cache->rb) <
554             rd_ret + nc->offset) {
555             if (cache->rd_waiting) {
556                 os_sem_signal(cache->rd_sem);
557                 cache->rd_waiting = 0;
558             }
559 
560             cache->wr_len = rd_ret + nc->offset;
561             cache->wr_waiting = 1;
562             os_mutex_unlock(nc->lock);
563 
564             os_sem_wait(cache->wr_sem, OS_WAIT_FOREVER);
565 
566             os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
567             cache->wr_waiting = 0;
568 
569             if (nc->cache_stop) {
570                 nc->cache_stop = 0;
571                 nc->cache_cplt = 1;
572                 nc->load_length -= nc->offset;
573                 M_LOGD("cache stop\n");
574                 os_mutex_unlock(nc->lock);
575                 goto __exit;
576             }
577         }
578 
579         wr_ret = uvoice_ringbuff_fill(&cache->rb,
580                 nc->buffer, rd_ret + nc->offset);
581         if (wr_ret < 0) {
582             M_LOGE("fill failed %d!\n", wr_ret);
583             nc->cache_cplt = 1;
584             nc->load_length -= nc->offset;
585             os_mutex_unlock(nc->lock);
586             break;
587         } else if (wr_ret != rd_ret + nc->offset) {
588             M_LOGW("fill %u ret %d\n", rd_ret + nc->offset, wr_ret);
589         }
590 
591         nc->load_length += rd_ret;
592 
593         if (nc->offset > 0)
594             nc->offset = 0;
595 
596         if (cache->rd_waiting &&
597             uvoice_ringbuff_dirtysize(&cache->rb) >= cache->rd_len) {
598             cache->rd_waiting = 0;
599             os_sem_signal(cache->rd_sem);
600         }
601 
602         if (nc->cache_stop) {
603             nc->cache_stop = 0;
604             nc->cache_cplt = 1;
605             M_LOGD("stop\n");
606             os_mutex_unlock(nc->lock);
607             break;
608         }
609 
610         load_size = MIN(nc->buffer_size,
611             nc->content_length - nc->load_length);
612 
613         if (load_size <= 0) {
614             if (!nc->sequence) {
615                 M_LOGD("load end\n");
616                 nc->cache_cplt = 1;
617                 os_mutex_unlock(nc->lock);
618                 break;
619             } else {
620                 M_LOGD("request next segment\n");
621                 os_mutex_unlock(nc->lock);
622                 if (nc->event(nc->priv, CACHE_EV_CACHE_CPLT, NULL)) {
623                     M_LOGD("request next segment failed !\n");
624                     nc->cache_cplt = 1;
625                     break;
626                 }
627                 os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
628 
629                 load_size = MIN(nc->buffer_size,
630                     nc->content_length - nc->load_length);
631                 if (load_size <= 0) {
632                     M_LOGD("load end\n");
633                     nc->cache_cplt = 1;
634                     os_mutex_unlock(nc->lock);
635                     break;
636                 }
637 
638                 if (nc->head_data_size > 0) {
639                     nc->offset = nc->head_data_size;
640                     load_size -= nc->offset;
641                     nc->load_length += nc->offset;
642                     M_LOGD("cache head data %u\n", nc->offset);
643                     nc->head_data_size = 0;
644                 }
645             }
646         }
647 
648         os_mutex_unlock(nc->lock);
649     }
650 
651 __exit:
652     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
653     M_LOGD("complete %d/%d\n",
654         nc->load_length, nc->content_length);
655     if (cache->rd_waiting) {
656         M_LOGD("wake rd wait\n");
657         cache->rd_waiting = 0;
658         os_sem_signal(cache->rd_sem);
659     }
660     if (nc->cplt_waiting) {
661         nc->cplt_waiting = 0;
662         os_sem_signal(nc->cplt_sem);
663     }
664 
665     nc->cache_running = 0;
666     os_mutex_unlock(nc->lock);
667     return 0;
668 }
669 
net_cache_mem_read(void * priv,unsigned char * buffer,int nbytes)670 static int net_cache_mem_read(void *priv, unsigned char *buffer,
671     int nbytes)
672 {
673     net_cache_t *nc = (net_cache_t *)priv;
674     struct cache_mem *cache;
675     int ret = 0;
676 
677     if (!nc) {
678         M_LOGE("nc null !\n");
679         return -1;
680     }
681 
682     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
683 
684     if (nbytes <= 0)
685         goto __exit;
686 
687     cache = nc->cache;
688     if (!cache) {
689         M_LOGE("cache null !\n");
690         ret = -1;
691         goto __exit;
692     }
693 
694     if (!cache->rd_start) {
695         #ifdef UVOICE_IOTNLP_ENABLE
696         cache->rd_len = nbytes;
697         #else
698         if (nc->cache_cplt)
699             cache->rd_len = MIN(cache->pool_size,
700                 MIN(nbytes, nc->content_length));
701         else
702             cache->rd_len = MIN(cache->pool_size,
703                 MIN(nbytes * 4, nc->content_length - nc->load_length));
704         if (nbytes > cache->rd_len) {
705             nbytes = cache->rd_len;
706             M_LOGD("update read bytes %d\n", nbytes);
707         }
708         #endif
709         cache->rd_start = 1;
710     } else {
711         cache->rd_len = nbytes;
712     }
713 
714     if (nc->cache_cplt) {
715         if (uvoice_ringbuff_dirtysize(&cache->rb) <= 0) {
716             M_LOGD("data end\n");
717             goto __exit;
718         } else if (uvoice_ringbuff_dirtysize(&cache->rb) < nbytes) {
719             nbytes = uvoice_ringbuff_dirtysize(&cache->rb);
720             cache->rd_len = nbytes;
721             M_LOGD("cache cplt, read %d\n", nbytes);
722         }
723     }
724 
725     if (nc->seek_offset != 0) {
726         if (nc->seek_offset > 0) {
727             if (nc->seek_offset <= uvoice_ringbuff_dirtysize(&cache->rb)) {
728                 uvoice_ringbuff_drop(&cache->rb, nc->seek_offset);
729                 nc->event(nc->priv, CACHE_EV_SEEK_DONE,
730                     (void *)nc->seek_offset);
731             }
732         } else {
733             if (abs(nc->seek_offset) <= uvoice_ringbuff_freesize(&cache->rb)) {
734                 uvoice_ringbuff_back(&cache->rb, abs(nc->seek_offset));
735                 nc->event(nc->priv, CACHE_EV_SEEK_DONE,
736                     (void *)nc->seek_offset);
737             }
738         }
739         M_LOGD("seek %d bytes\n", nc->seek_offset);
740         nc->seek_offset = 0;
741     }
742 
743     if (uvoice_ringbuff_dirtysize(&cache->rb) < cache->rd_len) {
744         cache->rd_waiting = 1;
745         if (cache->wr_waiting) {
746             os_sem_signal(cache->wr_sem);
747             cache->wr_waiting = 0;
748         }
749 
750         if (cache->rd_len == nbytes && !nc->sequence)
751             cache->rd_len = MIN(cache->pool_size / 2,
752                 nc->content_length - nc->load_length);
753 
754         if (cache->rd_len <= 0) {
755             M_LOGD("content end\n");
756             cache->rd_waiting = 0;
757             goto __exit;
758         }
759         nbytes = MIN(nbytes, cache->rd_len);
760         nc->event(nc->priv, CACHE_EV_READ_BLOCK, (void *)1);
761 
762         M_LOGD("wait cache, rd_len %u dirtysize %d freesize %d\n",
763             cache->rd_len,
764             uvoice_ringbuff_dirtysize(&cache->rb),
765             uvoice_ringbuff_freesize(&cache->rb));
766         os_mutex_unlock(nc->lock);
767 
768         if (os_sem_wait(cache->rd_sem, 60000)) {
769             os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
770             M_LOGE("wait timeout ! rd_len %u dirtysize %d freesize %d\n",
771                 cache->rd_len,
772                 uvoice_ringbuff_dirtysize(&cache->rb),
773                 uvoice_ringbuff_freesize(&cache->rb));
774             cache->rd_waiting = 0;
775             goto __exit;
776         }
777         os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
778         M_LOGD("wait exit, rd_len %u dirtysize %d freesize %d\n",
779             cache->rd_len,
780             uvoice_ringbuff_dirtysize(&cache->rb),
781             uvoice_ringbuff_freesize(&cache->rb));
782         nc->event(nc->priv, CACHE_EV_READ_BLOCK, 0);
783         cache->rd_waiting = 0;
784     }
785 
786     if (nc->cache_cplt) {
787         if (uvoice_ringbuff_dirtysize(&cache->rb) <= 0) {
788             M_LOGD("read end\n");
789             goto __exit;
790         } else if (uvoice_ringbuff_dirtysize(&cache->rb) <
791                 nbytes) {
792             nbytes = uvoice_ringbuff_dirtysize(&cache->rb);
793             cache->rd_len = nbytes;
794             M_LOGD("cache cplt, read %d\n", nbytes);
795         }
796     }
797 
798     ret = uvoice_ringbuff_read(&cache->rb, buffer, nbytes);
799     if (ret < 0) {
800         M_LOGE("read %d failed %d!\n", nbytes, ret);
801         ret = -1;
802         goto __exit;
803     } else if (ret != nbytes) {
804         M_LOGW("read %d ret %d\n", nbytes, ret);
805     }
806 
807     if (cache->wr_waiting &&
808         uvoice_ringbuff_freesize(&cache->rb) >= cache->wr_len) {
809         os_sem_signal(cache->wr_sem);
810         cache->wr_waiting = 0;
811     }
812 
813 __exit:
814     os_mutex_unlock(nc->lock);
815     return ret;
816 }
817 
net_cache_mem_reset(struct cache_mem * cache)818 static int net_cache_mem_reset(struct cache_mem *cache)
819 {
820     if (!cache) {
821         M_LOGE("cache null !\n");
822         return -1;
823     }
824 
825     cache->rd_start = 0;
826     cache->wr_waiting = 0;
827     cache->rd_waiting = 0;
828     cache->rd_len = 0;
829     cache->wr_len = 0;
830     memset(cache->pool, 0, cache->pool_size);
831     uvoice_ringbuff_reset(&cache->rb);
832 
833     M_LOGD("mem cache reset\n");
834     return 0;
835 }
836 
net_cache_mem_init(net_cache_t * nc)837 static int net_cache_mem_init(net_cache_t *nc)
838 {
839     struct cache_mem *cache;
840 
841     if (!nc) {
842         M_LOGE("nc null !\n");
843         return -1;
844     }
845 
846     cache = snd_zalloc(sizeof(struct cache_mem), AFM_EXTN);
847     if (!cache) {
848         M_LOGE("alloc cache mem failed !\n");
849         return -1;
850     }
851 
852     cache->pool_size = nc->cache_config.mem_size * 1024;
853     if (nc->sequence && nc->cache_config.mem_size > 40)
854         cache->pool_size = 40 * 1024;
855 
856     cache->pool = snd_zalloc(cache->pool_size + 4, AFM_EXTN);
857     if (!cache->pool) {
858         M_LOGE("alloc cache pool failed !\n");
859         snd_free(cache);
860         return -1;
861     }
862 
863     M_LOGD("alloc cache pool %u\n", cache->pool_size);
864 
865     if (uvoice_ringbuff_init(&cache->rb,
866             cache->pool, cache->pool_size)) {
867         M_LOGE("init ring buffer failed !\n");
868         snd_free(cache->pool);
869         snd_free(cache);
870         return -1;
871     }
872 
873     cache->wr_sem = os_sem_new(0);
874     cache->rd_sem = os_sem_new(0);
875     nc->cache_read = net_cache_mem_read;
876     nc->cache = cache;
877 
878     return 0;
879 }
880 
net_cache_mem_deinit(net_cache_t * nc)881 static int net_cache_mem_deinit(net_cache_t *nc)
882 {
883     struct cache_mem *cache;
884 
885     if (!nc) {
886         M_LOGE("nc null !\n");
887         return -1;
888     }
889 
890     cache = nc->cache;
891     if (!cache) {
892         M_LOGE("cache null !\n");
893         return -1;
894     }
895 
896     os_sem_free(cache->wr_sem);
897     os_sem_free(cache->rd_sem);
898     snd_free(cache->pool);
899     snd_free(cache);
900     nc->cache_read = NULL;
901     nc->cache = NULL;
902 
903     return 0;
904 }
905 
net_cache_task(void * arg)906 static void net_cache_task(void *arg)
907 {
908     net_cache_t *nc = (net_cache_t *)arg;
909     if (!nc) {
910         M_LOGE("nc null !\n");
911         return;
912     }
913 
914     if (nc->cache_config.place == CACHE_FILE)
915         net_cache_file(nc);
916     else if (nc->cache_config.place == CACHE_MEM)
917         net_cache_mem(nc);
918 }
919 
920 
net_get_cacheinfo(net_cache_t * nc,cache_info_t * info)921 int net_get_cacheinfo(net_cache_t *nc, cache_info_t *info)
922 {
923     if (!nc) {
924         M_LOGE("nc null !\n");
925         return -1;
926     }
927 
928     if (!info) {
929         M_LOGE("info null !\n");
930         return -1;
931     }
932 
933     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
934 
935     if (nc->cache_config.place == CACHE_FILE) {
936         struct cache_file *cache = nc->cache;
937         info->dirty_cache_size = cache->rd_pos;
938         info->avail_cache_size = cache->wr_pos - cache->rd_pos;
939     } else if (nc->cache_config.place == CACHE_MEM) {
940         struct cache_mem *cache = nc->cache;
941         info->dirty_cache_size = 0;
942         info->avail_cache_size =
943             uvoice_ringbuff_dirtysize(&cache->rb);
944     }
945 
946     os_mutex_unlock(nc->lock);
947     return 0;
948 }
949 
net_get_mediainfo(net_cache_t * nc,media_info_t * info,media_format_t format)950 int net_get_mediainfo(net_cache_t *nc,
951         media_info_t *info, media_format_t format)
952 {
953     if (!nc) {
954         M_LOGE("nc null !\n");
955         return -1;
956     }
957 
958     if (!info) {
959         M_LOGE("info null !\n");
960         return -1;
961     }
962 
963     os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
964 
965     switch (nc->cache_config.place) {
966         case CACHE_FILE:
967         if (!nc->cache_cplt)
968             break;
969 
970         if (net_cache_file_mediainfo(nc->cache,
971                 info, format)) {
972             M_LOGE("get file mediainfo failed !\n");
973             os_mutex_unlock(nc->lock);
974             return -1;
975         }
976         break;
977         default:
978         break;
979     }
980 
981     os_mutex_unlock(nc->lock);
982     return 0;
983 }
984 
net_cache_reset(net_cache_t * nc)985 int net_cache_reset(net_cache_t *nc)
986 {
987     if (!nc) {
988         M_LOGE("nc null !\n");
989         return -1;
990     }
991 
992     if (nc->cache_config.place == CACHE_NONE) {
993         M_LOGD("cache disabled\n");
994         goto __exit;
995     }
996 
997     if (!nc->cache_cplt && nc->cache_running) {
998         M_LOGE("cache not cplt !\n");
999         return -1;
1000     }
1001 
1002     nc->cache_running = 0;
1003     nc->load_length = 0;
1004     nc->cache_cplt = 0;
1005     nc->seek_offset = 0;
1006     nc->rebuild = 0;
1007 
1008     switch (nc->cache_config.place) {
1009         case CACHE_FILE:
1010         if (net_cache_file_reset(nc->cache)) {
1011             M_LOGE("reset file cache failed !\n");
1012             return -1;
1013         }
1014         break;
1015         case CACHE_MEM:
1016         if (net_cache_mem_reset(nc->cache)) {
1017             M_LOGE("reset mem cache failed !\n");
1018             return -1;
1019         }
1020         break;
1021         default:
1022         break;
1023     }
1024 
1025 __exit:
1026     return 0;
1027 }
1028 
net_cache_seek(net_cache_t * nc,int offset)1029 int net_cache_seek(net_cache_t *nc, int offset)
1030 {
1031     if (!nc) {
1032         M_LOGE("nc null !\n");
1033         return -1;
1034     }
1035 
1036     if (offset != 0) {
1037         os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
1038         nc->seek_offset = offset;
1039         os_mutex_unlock(nc->lock);
1040     }
1041     return 0;
1042 }
1043 
net_cache_start(net_cache_t * nc)1044 int net_cache_start(net_cache_t *nc)
1045 {
1046     if (!nc) {
1047         M_LOGE("nc null !\n");
1048         return -1;
1049     }
1050 
1051     if (nc->load_length >= nc->content_length) {
1052         M_LOGD("load cplt, ignore\n");
1053         nc->cache_cplt = 1;
1054         goto __exit;
1055     }
1056 
1057     if (nc->cache_config.place != CACHE_NONE) {
1058         nc->cache_cplt = 0;
1059         os_task_create(&nc->cache_task, "uvoice_cache_task",
1060             net_cache_task, nc,
1061             2048, NET_CACHE_TASK_PRIORITY);
1062     }
1063 
1064 __exit:
1065     return 0;
1066 }
1067 
net_cache_pause(net_cache_t * nc)1068 int net_cache_pause(net_cache_t *nc)
1069 {
1070     if (!nc) {
1071         M_LOGE("nc null !\n");
1072         return -1;
1073     }
1074 
1075     if (nc->cache_config.place == CACHE_MEM ||
1076         nc->cache_config.place == CACHE_NONE) {
1077         M_LOGD("rebuild cache\n");
1078         nc->rebuild = NET_CACHE_REBUILD_ENABLE;
1079 
1080         /* sequece stream rebuild forcibly */
1081         if (nc->sequence)
1082             nc->rebuild = 1;
1083     }
1084 
1085     return 0;
1086 }
1087 
net_cache_resume(net_cache_t * nc)1088 int net_cache_resume(net_cache_t *nc)
1089 {
1090     if (!nc) {
1091         M_LOGE("nc null !\n");
1092         return -1;
1093     }
1094 
1095     return 0;
1096 }
1097 
net_cache_stop(net_cache_t * nc)1098 int net_cache_stop(net_cache_t *nc)
1099 {
1100     if (!nc) {
1101         M_LOGE("nc null !\n");
1102         return -1;
1103     }
1104 
1105     if (!nc->cache_running) {
1106         M_LOGD("cache not running, ignore\n");
1107         goto __exit;
1108     }
1109 
1110     if (nc->cache_cplt) {
1111         M_LOGD("cache cplt already, ignore\n");
1112         goto __exit;
1113     }
1114 
1115     if (nc->cache_config.place != CACHE_NONE) {
1116         os_mutex_lock(nc->lock, OS_WAIT_FOREVER);
1117         if (!nc->cache_cplt) {
1118             M_LOGD("wait cache cplt\n");
1119             if (nc->cache_config.place == CACHE_MEM) {
1120                 struct cache_mem *cache = nc->cache;
1121                 nc->cache_stop = 1;
1122                 if (cache->wr_waiting) {
1123                     M_LOGD("wake wr waiting\n");
1124                     os_sem_signal(cache->wr_sem);
1125                     cache->wr_waiting = 0;
1126                 }
1127                 cache->rd_start = 0;
1128             } else if (nc->cache_config.place == CACHE_FILE) {
1129                 struct cache_file *cache = nc->cache;
1130                 nc->cache_stop = 1;
1131                 cache->rd_start = 0;
1132             }
1133             nc->cplt_waiting = 1;
1134             os_mutex_unlock(nc->lock);
1135             if (os_sem_wait(nc->cplt_sem, 15000)) {
1136                 nc->cplt_waiting = 0;
1137                 M_LOGW("wait cache cplt timeout !\n");
1138             }
1139             M_LOGD("cache cplt and stop\n");
1140         } else {
1141             nc->cache_cplt = 0;
1142             os_mutex_unlock(nc->lock);
1143         }
1144     }
1145 
1146 __exit:
1147     return 0;
1148 }
1149 
net_cache_create(int read_size,cache_config_t * config,bool sequence)1150 net_cache_t *net_cache_create(int read_size,
1151     cache_config_t *config, bool sequence)
1152 {
1153     net_cache_t *nc;
1154 
1155     nc = snd_zalloc(sizeof(net_cache_t), AFM_EXTN);
1156     if (!nc) {
1157         M_LOGE("alloc net cache failed !\n");
1158         return NULL;
1159     }
1160 
1161     memcpy(&nc->cache_config, config, sizeof(cache_config_t));
1162     nc->buffer_size = read_size;
1163     nc->buffer = snd_zalloc(nc->buffer_size, AFM_MAIN);
1164     if (!nc->buffer) {
1165         M_LOGE("alloc buffer failed !\n");
1166         snd_free(nc);
1167         return NULL;
1168     }
1169     nc->lock = os_mutex_new();
1170     nc->cplt_sem = os_sem_new(0);
1171     if (sequence)
1172         nc->sequence = 1;
1173 
1174     if (nc->cache_config.place == CACHE_FILE) {
1175         if (net_cache_file_init(nc)) {
1176             M_LOGE("init file cache failed !\n");
1177             snd_free(nc->buffer);
1178             snd_free(nc);
1179             return NULL;
1180         }
1181     } else if (nc->cache_config.place == CACHE_MEM) {
1182         if (net_cache_mem_init(nc)) {
1183             M_LOGE("init mem cache failed !\n");
1184             snd_free(nc->buffer);
1185             snd_free(nc);
1186             return NULL;
1187         }
1188     }
1189 
1190     M_LOGD("net cache create\n");
1191     return nc;
1192 }
1193 
net_cache_release(net_cache_t * nc)1194 int net_cache_release(net_cache_t *nc)
1195 {
1196     int ret = 0;
1197 
1198     if (!nc) {
1199         M_LOGE("nc null !\n");
1200         return -1;
1201     }
1202 
1203     if (nc->cache_config.place == CACHE_FILE)
1204         ret = net_cache_file_deinit(nc);
1205     else if (nc->cache_config.place == CACHE_MEM)
1206         ret = net_cache_mem_deinit(nc);
1207     if (ret) {
1208         M_LOGE("cache deinit failed !\n");
1209         return -1;
1210     }
1211 
1212     os_sem_free(nc->cplt_sem);
1213     os_mutex_free(nc->lock);
1214     snd_free(nc->buffer);
1215     snd_free(nc);
1216 
1217     M_LOGD("net cache release\n");
1218     return 0;
1219 }
1220 
1221