media_mix_pcm.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file media player interface
  8. */
  9. #define SYS_LOG_DOMAIN "media"
  10. #include <os_common_api.h>
  11. #include <sys/byteorder.h>
  12. #include <mem_manager.h>
  13. #include <msg_manager.h>
  14. #include <srv_manager.h>
  15. #include <sys_wakelock.h>
  16. #include <string.h>
  17. #include "audio_policy.h"
  18. #include "audio_system.h"
  19. #include "media_player.h"
  20. #include "media_service.h"
  21. #include "media_mem.h"
  22. #include <file_stream.h>
  23. #include "acts_ringbuf.h"
  24. #include "stream.h"
  25. #include <audio_track.h>
  26. #include <sdfs.h>
  27. #include <buffer_stream.h>
  28. struct mix_pcm_manager_t {
  29. io_stream_t mix_pcm_stream;
  30. uint8_t mix_pcm_cnt;
  31. uint8_t mix_track_finish;
  32. struct audio_track_t *mix_pcm_track;
  33. io_stream_t mix_track_stream;
  34. os_delayed_work mix_track_work;
  35. char mix_pcm_name[20];
  36. media_player_t *play_handle;
  37. mix_service_param_t param;
  38. };
  39. static struct mix_pcm_manager_t mix_pcm_context = {0};
  40. static void _mix_pcm_track_callback(uint8_t event, void *user_data)
  41. {
  42. }
  43. static void _media_service_mix_callback(io_stream_t mix_stream, int result, void *reply)
  44. {
  45. struct mix_pcm_manager_t *ctx = &mix_pcm_context;
  46. if (mix_stream != ctx->mix_pcm_stream) {
  47. SYS_LOG_ERR("mix_stream %p %p err \n", mix_stream, ctx->mix_pcm_stream);
  48. return;
  49. }
  50. stream_close(ctx->mix_pcm_stream);
  51. stream_destroy(ctx->mix_pcm_stream);
  52. ctx->mix_pcm_stream = NULL;
  53. ctx->mix_pcm_cnt--;
  54. SYS_LOG_INF("%s %d close\n", __FUNCTION__, __LINE__);
  55. }
  56. static void mix_instream_read_notify(void *observer, int readoff, int writeoff,
  57. int total_size, unsigned char *buf, int num, stream_notify_type type)
  58. {
  59. struct mix_pcm_manager_t *ctx = &mix_pcm_context;
  60. if (stream_get_length(ctx->mix_pcm_stream) <= 0) {
  61. //media_mix_pcm_stream_close();
  62. ctx->mix_track_finish = 1;
  63. SYS_LOG_INF("%s %d %d mix_track_finish:%d\n", __FUNCTION__, __LINE__, stream_get_length(ctx->mix_pcm_stream), ctx->mix_track_finish);
  64. }
  65. }
  66. static io_stream_t open_file_stream(const char *url, int mode)
  67. {
  68. io_stream_t stream = file_stream_create((void*)url);
  69. if (!stream)
  70. return NULL;
  71. if (stream_open(stream, mode)) {
  72. stream_destroy(stream);
  73. return NULL;
  74. }
  75. return stream;
  76. }
  77. static char mix_tmp_data[512];
  78. static void _media_mix_pcm_put_data_work(os_work *work)
  79. {
  80. struct mix_pcm_manager_t *ctx = &mix_pcm_context;
  81. char channel = audio_policy_get_out_channel_type(AUDIO_STREAM_TTS) == AUDIO_CHANNEL_I2STX? 2:1;
  82. if (!ctx->mix_track_finish) {
  83. int mix_len = stream_get_space(ctx->mix_track_stream);
  84. if (mix_len > 512 / channel)
  85. mix_len = 512 / channel;
  86. if (mix_len > stream_get_length(ctx->mix_pcm_stream))
  87. mix_len = stream_get_length(ctx->mix_pcm_stream);
  88. if (mix_len > 0) {
  89. if (channel == 1) { //likely
  90. stream_read(ctx->mix_pcm_stream, mix_tmp_data, mix_len);
  91. stream_write(ctx->mix_track_stream, mix_tmp_data, mix_len);
  92. } else {
  93. short *src = (short *)(&mix_tmp_data[mix_len]);
  94. short *dest = (short *)mix_tmp_data;
  95. stream_read(ctx->mix_pcm_stream, src, mix_len);
  96. for (int i = 0; i < mix_len / 2; i++) {
  97. *dest++ = *src;
  98. *dest++ = *src++;
  99. }
  100. stream_write(ctx->mix_track_stream, mix_tmp_data, mix_len * channel);
  101. }
  102. }
  103. //512 byte data case 16K 16ms
  104. os_delayed_work_submit(&ctx->mix_track_work, 4);
  105. } else {
  106. SYS_LOG_INF("%s %d close\n", __FUNCTION__, __LINE__);
  107. media_mix_pcm_stream_close();
  108. }
  109. }
  110. int media_mix_pcm_stream_open(const char *url, int inrate, int outrate)
  111. {
  112. struct mix_pcm_manager_t *ctx = &mix_pcm_context;
  113. int ret = 0;
  114. if (ctx->mix_pcm_cnt) {
  115. SYS_LOG_ERR("mix pcm is running %d\n", ctx->mix_pcm_cnt);
  116. return -1;
  117. }
  118. ctx->mix_pcm_cnt++;
  119. strcpy(ctx->mix_pcm_name, url);
  120. ctx->mix_pcm_stream = open_file_stream(ctx->mix_pcm_name, MODE_IN);
  121. if (!ctx->mix_pcm_stream) {
  122. SYS_LOG_ERR("stream open failed (%s)\n", ctx->mix_pcm_name);
  123. goto err_exit;
  124. }
  125. media_player_t *player = media_player_get_current_dumpable_player();
  126. if (player) {
  127. mix_service_param_t param;
  128. memset(&param, 0, sizeof(mix_service_param_t));
  129. param.in_rate = inrate;
  130. param.out_rate = outrate;
  131. param.master_db = -6;
  132. param.mix_db = -1;
  133. param.channels = 1;
  134. param.format = PCM_TYPE;
  135. param.input_stream = ctx->mix_pcm_stream;
  136. param.callback = _media_service_mix_callback;
  137. ret = media_player_set_mix_stream(player, &param);
  138. if (ret) {
  139. SYS_LOG_ERR("set mix stream err:%d\n", ret);
  140. goto err_exit;
  141. }
  142. ctx->play_handle = player;
  143. } else {
  144. audio_system_mutex_lock();
  145. struct audio_track_t * mix_pcm_track = audio_track_create(AUDIO_STREAM_TTS, inrate,
  146. AUDIO_FORMAT_PCM_16_BIT, AUDIO_MODE_MONO,
  147. NULL,
  148. _mix_pcm_track_callback, ctx);
  149. if (!mix_pcm_track) {
  150. goto err_exit;
  151. }
  152. ctx->mix_pcm_track = mix_pcm_track;
  153. ctx->mix_track_stream = audio_track_get_stream(ctx->mix_pcm_track);
  154. stream_set_observer(ctx->mix_pcm_stream, ctx, mix_instream_read_notify, STREAM_NOTIFY_READ);
  155. //create workq put data to audio track
  156. os_delayed_work_init(&ctx->mix_track_work, _media_mix_pcm_put_data_work);
  157. os_delayed_work_submit(&ctx->mix_track_work, OS_NO_WAIT);
  158. os_sleep(10);
  159. audio_track_start(mix_pcm_track);
  160. audio_system_mutex_unlock();
  161. }
  162. return 0;
  163. err_exit:
  164. if (ctx->mix_pcm_stream) {
  165. stream_close(ctx->mix_pcm_stream);
  166. stream_destroy(ctx->mix_pcm_stream);
  167. ctx->mix_pcm_stream = NULL;
  168. }
  169. ctx->mix_pcm_cnt--;
  170. return 0;
  171. }
  172. int media_mix_pcm_stream_close(void)
  173. {
  174. struct mix_pcm_manager_t *ctx = &mix_pcm_context;
  175. if (!ctx->mix_pcm_cnt) {
  176. SYS_LOG_ERR("mix pcm no running %d\n", ctx->mix_pcm_cnt);
  177. return -1;
  178. }
  179. if (ctx->mix_pcm_track) {
  180. ctx->mix_track_finish = 0;
  181. os_delayed_work_cancel(&ctx->mix_track_work);
  182. audio_system_mutex_lock();
  183. audio_track_flush(ctx->mix_pcm_track);
  184. audio_track_stop(ctx->mix_pcm_track);
  185. audio_track_destory(ctx->mix_pcm_track);
  186. ctx->mix_pcm_track = NULL;
  187. ctx->mix_pcm_track = NULL;
  188. ctx->mix_pcm_cnt--;
  189. stream_close(ctx->mix_pcm_stream);
  190. stream_destroy(ctx->mix_pcm_stream);
  191. audio_system_mutex_unlock();
  192. } else {
  193. media_player_t *player = media_player_get_current_dumpable_player();
  194. if (player != ctx->play_handle) {
  195. SYS_LOG_ERR("mix_stream %p %p err \n", player, ctx->play_handle);
  196. return -1;
  197. }
  198. int ret = media_player_set_mix_stream(ctx->play_handle, NULL);
  199. if (ret) {
  200. SYS_LOG_ERR("set mix stream err:%d\n", ret);
  201. return 0;
  202. }
  203. }
  204. return 0;
  205. }