• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 /*
20  * BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data
21  * and saves them to disk. The files are stored in the path specified in BUFLOG_BASE_PATH and
22  * are named following this format:
23  *   YYYYMMDDHHMMSS_id_format_channels_samplingrate.raw
24  *
25  * Normally we strip BUFLOG dumps from release builds.
26  * You can modify this (for example with "#define BUFLOG_NDEBUG 0"
27  * at the top of your source file) to change that behavior.
28  *
29  * usage:
30  * - Add this to the top of the source file you want to debug:
31  *   #define BUFLOG_NDEBUG 0
32  *   #include "BufLog.h"
33  *
34  * - dump an audio buffer
35  *  BUFLOG(buff_id, buff_tag, format, channels, sampling_rate, max_bytes, buff_pointer, buff_size);
36  *
37  *  buff_id:   int [0:15]   buffer id. If a buffer doesn't exist, it is created the first time.
38  *  buff_tag:  char*        string tag used on stream filename and logs
39  *  format:    int          Audio format (audio_format_t see audio.h)
40  *  channels:  int          Channel Count
41  *  sampling_rate:  int     Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc
42  *  max_bytes: int [0 or positive number]
43  *                          Maximum size of the file (in bytes) to be output.
44  *                          If the value is 0, no limit.
45  *  buff_pointer: void *    Pointer to audio buffer.
46  *  buff_size:  int         Size (in bytes) of the current audio buffer to be stored.
47  *
48  *
49  *  Example usage:
50  *    int format       = mConfig.outputCfg.format;
51  *    int channels     = audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
52  *    int samplingRate = mConfig.outputCfg.samplingRate;
53  *    int frameCount   = mConfig.outputCfg.buffer.frameCount;
54  *    int frameSize    = audio_bytes_per_sample((audio_format_t)format) * channels;
55  *    int buffSize     = frameCount * frameSize;
56  *    long maxBytes = 10 * samplingRate * frameSize; //10 seconds max
57  *  BUFLOG(11, "loudnes_enhancer_out", format, channels, samplingRate, maxBytes,
58  *                               mConfig.outputCfg.buffer.raw, buffSize);
59  *
60  *  Other macros:
61  *  BUFLOG_EXISTS       returns true if there is an instance of BufLog
62  *
63  *  BUFLOG_RESET        If an instance of BufLog exists, it stops the capture and closes all
64  *                      streams.
65  *                      If a new call to BUFLOG(..) is done, new streams are created.
66  */
67 
68 #ifndef BUFLOG_NDEBUG
69 #ifdef NDEBUG
70 #define BUFLOG_NDEBUG 1
71 #else
72 #define BUFLOG_NDEBUG 0
73 #endif
74 #endif
75 
76 /*
77  * Simplified macro to send a buffer.
78  */
79 #ifndef BUFLOG
80 #define __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
81     BufLogSingleton::instance()->write(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, \
82             BUF, SIZE)
83 #if BUFLOG_NDEBUG
84 #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
85     do { if (0) {  } } while (0)
86 #else
87 #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
88     __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE)
89 #endif
90 #endif
91 
92 #ifndef BUFLOG_EXISTS
93 #define BUFLOG_EXISTS BufLogSingleton::instanceExists()
94 #endif
95 
96 #ifndef BUFLOG_RESET
97 #define BUFLOG_RESET do { if (BufLogSingleton::instanceExists()) { \
98     BufLogSingleton::instance()->reset(); } } while (0)
99 #endif
100 
101 #include <mutex>
102 #include <stdint.h>
103 #include <stdio.h>
104 #include <sys/types.h>
105 
106 //BufLog configuration
107 #define BUFLOGSTREAM_MAX_TAGSIZE    32
108 #define BUFLOG_BASE_PATH            "/data/misc/audioserver"
109 #define BUFLOG_MAX_PATH_SIZE        300
110 
111 namespace android {
112 
113 class BufLogStream {
114 public:
115     BufLogStream(unsigned int id,
116             const char *tag,
117             unsigned int format,
118             unsigned int channels,
119             unsigned int samplingRate,
120             size_t maxBytes);
121     ~BufLogStream();
122 
123     // write buffer to stream
124     //  buf:  pointer to buffer
125     //  size: number of bytes to write
126     size_t          write(const void *buf, size_t size);
127 
128     // pause/resume stream
129     //  pause: true = paused, false = not paused
130     //  return value: previous state of stream (paused or not).
131     bool            setPause(bool pause);
132 
133     // will stop the stream and close any open file
134     // the stream can't be reopen. Instead, a new stream (and file) should be created.
135     void            finalize();
136 
137 private:
138     const unsigned int  mId;
139     const unsigned int  mFormat;
140     const unsigned int  mChannels;
141     const unsigned int  mSamplingRate;
142     const size_t        mMaxBytes;
143     char                mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1]; // const, set in ctor.
144 
145     mutable std::mutex  mLock;
146     bool                mPaused = false;
147     size_t              mByteCount = 0;
148     FILE                *mFile; // set in ctor
149 
150     void            closeStream_l();
151 };
152 
153 class BufLog {
154 public:
155     ~BufLog();
156 
157     //  streamid:      int [0:BUFLOG_MAXSTREAMS-1]   buffer id.
158     //                  If a buffer doesn't exist, it is created the first time is referenced
159     //  tag:           char*  string tag used on stream filename and logs
160     //  format:        int Audio format (audio_format_t see audio.h)
161     //  channels:      int          Channel Count
162     //  samplingRate:  int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc
163     //  maxBytes:      int [0 or positive number]
164     //                  Maximum size of the file (in bytes) to be output.
165     //                  If the value is 0, no limit.
166     //  size:          int Size (in bytes) of the current audio buffer to be written.
167     //  buf:           void *    Pointer to audio buffer.
168     size_t          write(int streamid,
169                         const char *tag,
170                         int format,
171                         int channels,
172                         int samplingRate,
173                         size_t maxBytes,
174                         const void *buf,
175                         size_t size);
176 
177     // reset will stop and close all active streams, thus finalizing any open file.
178     //  New streams will be created if write() is called again.
179     void            reset();
180 
181 protected:
182     static constexpr size_t BUFLOG_MAXSTREAMS = 16;
183     mutable std::mutex mLock;
184     BufLogStream *mStreams[BUFLOG_MAXSTREAMS]{};
185 };
186 
187 class BufLogSingleton {
188 public:
189     static BufLog   *instance();
190     static bool     instanceExists();
191 
192 private:
193     static void     initOnce();
194     static BufLog   *mInstance;
195 };
196 
197 } // namespace android
198