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