2
0

output_bt.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #include "squeezelite.h"
  2. #include "perf_trace.h"
  3. extern struct outputstate output;
  4. extern struct buffer *outputbuf;
  5. extern struct buffer *streambuf;
  6. extern u8_t *silencebuf;
  7. #define LOCK mutex_lock(outputbuf->mutex)
  8. #define UNLOCK mutex_unlock(outputbuf->mutex)
  9. #define LOCK_S mutex_lock(streambuf->mutex)
  10. #define UNLOCK_S mutex_unlock(streambuf->mutex)
  11. #define FRAME_BLOCK MAX_SILENCE_FRAMES
  12. #define STATS_REPORT_DELAY_MS 15000
  13. extern void hal_bluetooth_init(const char * options);
  14. static log_level loglevel;
  15. uint8_t * btout;
  16. static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
  17. s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
  18. #define DECLARE_ALL_MIN_MAX \
  19. DECLARE_MIN_MAX(req);\
  20. DECLARE_MIN_MAX(rec);\
  21. DECLARE_MIN_MAX(bt);\
  22. DECLARE_MIN_MAX(under);\
  23. DECLARE_MIN_MAX(stream_buf);\
  24. DECLARE_MIN_MAX_DURATION(lock_out_time)
  25. #define RESET_ALL_MIN_MAX \
  26. RESET_MIN_MAX(bt); \
  27. RESET_MIN_MAX(req); \
  28. RESET_MIN_MAX(rec); \
  29. RESET_MIN_MAX(under); \
  30. RESET_MIN_MAX(stream_buf); \
  31. RESET_MIN_MAX_DURATION(lock_out_time)
  32. DECLARE_ALL_MIN_MAX;
  33. void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle) {
  34. loglevel = level;
  35. hal_bluetooth_init(device);
  36. output.write_cb = &_write_frames;
  37. }
  38. static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
  39. s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr) {
  40. assert(btout != NULL);
  41. if (!silence ) {
  42. if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
  43. _apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
  44. }
  45. if (gainL != FIXED_ONE || gainR!= FIXED_ONE) {
  46. _apply_gain(outputbuf, out_frames, gainL, gainR);
  47. }
  48. #if BYTES_PER_FRAME == 4
  49. memcpy(btout, outputbuf->readp, out_frames * BYTES_PER_FRAME);
  50. #else
  51. {
  52. frames_t count = out_frames;
  53. s32_t *_iptr = (s32_t*) outputbuf->readp;
  54. s16_t *_optr = (s16_t*) bt_optr;
  55. while (count--) {
  56. *_optr++ = *_iptr++ >> 16;
  57. *_optr++ = *_iptr++ >> 16;
  58. }
  59. }
  60. #endif
  61. } else {
  62. u8_t *buf = silencebuf;
  63. memcpy(btout, buf, out_frames * BYTES_PER_FRAME);
  64. }
  65. return (int)out_frames;
  66. }
  67. int32_t output_bt_data(uint8_t *data, int32_t len) {
  68. int32_t avail_data = 0, wanted_len = 0, start_timer = 0;
  69. if (len < 0 || data == NULL ) {
  70. return 0;
  71. }
  72. btout = data;
  73. // This is how the BTC layer calculates the number of bytes to
  74. // for us to send. (BTC_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16) - availPcmBytes
  75. wanted_len=len;
  76. SET_MIN_MAX(len,req);
  77. TIME_MEASUREMENT_START(start_timer);
  78. LOCK;
  79. output.device_frames = 0; // todo: check if this is the right way do to this.
  80. output.updated = gettime_ms();
  81. output.frames_played_dmp = output.frames_played;
  82. SET_MIN_MAX_SIZED(_buf_used(outputbuf),bt,outputbuf->size);
  83. do {
  84. avail_data = _output_frames( wanted_len/BYTES_PER_FRAME )*BYTES_PER_FRAME; // Keep the transfer buffer full
  85. wanted_len-=avail_data;
  86. } while (wanted_len > 0 && avail_data != 0);
  87. if (wanted_len > 0) {
  88. SET_MIN_MAX(wanted_len, under);
  89. }
  90. UNLOCK;
  91. SET_MIN_MAX(TIME_MEASUREMENT_GET(start_timer),lock_out_time);
  92. SET_MIN_MAX((len-wanted_len), rec);
  93. TIME_MEASUREMENT_START(start_timer);
  94. return len-wanted_len;
  95. }
  96. void output_bt_tick(void) {
  97. static time_t lastTime=0;
  98. LOCK_S;
  99. SET_MIN_MAX_SIZED(_buf_used(streambuf), stream_buf, streambuf->size);
  100. UNLOCK_S;
  101. if (lastTime <= gettime_ms() )
  102. {
  103. lastTime = gettime_ms() + STATS_REPORT_DELAY_MS;
  104. LOG_INFO("Statistics over %u secs. " , STATS_REPORT_DELAY_MS/1000);
  105. LOG_INFO(" +==========+==========+================+=====+================+");
  106. LOG_INFO(" | max | min | average | avg | count |");
  107. LOG_INFO(" | (bytes) | (bytes) | (bytes) | pct | |");
  108. LOG_INFO(" +==========+==========+================+=====+================+");
  109. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("stream avl",stream_buf));
  110. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("output avl",bt));
  111. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("requested",req));
  112. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("received",rec));
  113. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("underrun",under));
  114. LOG_INFO( " +==========+==========+================+=====+================+");
  115. LOG_INFO("\n");
  116. LOG_INFO(" ==========+==========+===========+===========+ ");
  117. LOG_INFO(" max (us) | min (us) | avg(us) | count | ");
  118. LOG_INFO(" ==========+==========+===========+===========+ ");
  119. LOG_INFO(LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("Out Buf Lock",lock_out_time));
  120. LOG_INFO(" ==========+==========+===========+===========+");
  121. RESET_ALL_MIN_MAX;
  122. }
  123. }