Home | History | Annotate | Download | only in audioflinger
      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 #ifndef ANDROID_AUDIO_BUFLOG_H
     18 #define ANDROID_AUDIO_BUFLOG_H
     19 
     20 /*
     21  * BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data
     22  * and saves them to disk. The files are stored in the path specified in BUFLOG_BASE_PATH and
     23  * are named following this format:
     24  *   YYYYMMDDHHMMSS_id_format_channels_samplingrate.raw
     25  *
     26  * Normally we strip BUFLOG dumps from release builds.
     27  * You can modify this (for example with "#define BUFLOG_NDEBUG 0"
     28  * at the top of your source file) to change that behavior.
     29  *
     30  * usage:
     31  * - Add this to the top of the source file you want to debug:
     32  *   #define BUFLOG_NDEBUG 0
     33  *   #include "BufLog.h"
     34  *
     35  * - dump an audio buffer
     36  *  BUFLOG(buff_id, buff_tag, format, channels, sampling_rate, max_bytes, buff_pointer, buff_size);
     37  *
     38  *  buff_id:   int [0:15]   buffer id. If a buffer doesn't exist, it is created the first time.
     39  *  buff_tag:  char*        string tag used on stream filename and logs
     40  *  format:    int          Audio format (audio_format_t see audio.h)
     41  *  channels:  int          Channel Count
     42  *  sampling_rate:  int     Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc
     43  *  max_bytes: int [0 or positive number]
     44  *                          Maximum size of the file (in bytes) to be output.
     45  *                          If the value is 0, no limit.
     46  *  buff_pointer: void *    Pointer to audio buffer.
     47  *  buff_size:  int         Size (in bytes) of the current audio buffer to be stored.
     48  *
     49  *
     50  *  Example usage:
     51  *    int format       = mConfig.outputCfg.format;
     52  *    int channels     = audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
     53  *    int samplingRate = mConfig.outputCfg.samplingRate;
     54  *    int frameCount   = mConfig.outputCfg.buffer.frameCount;
     55  *    int frameSize    = audio_bytes_per_sample((audio_format_t)format) * channels;
     56  *    int buffSize     = frameCount * frameSize;
     57  *    long maxBytes = 10 * samplingRate * frameSize; //10 seconds max
     58  *  BUFLOG(11, "loudnes_enhancer_out", format, channels, samplingRate, maxBytes,
     59  *                               mConfig.outputCfg.buffer.raw, buffSize);
     60  *
     61  *  Other macros:
     62  *  BUFLOG_EXISTS       returns true if there is an instance of BufLog
     63  *
     64  *  BUFLOG_RESET        If an instance of BufLog exists, it stops the capture and closes all
     65  *                      streams.
     66  *                      If a new call to BUFLOG(..) is done, new streams are created.
     67  */
     68 
     69 #ifndef BUFLOG_NDEBUG
     70 #ifdef NDEBUG
     71 #define BUFLOG_NDEBUG 1
     72 #else
     73 #define BUFLOG_NDEBUG 0
     74 #endif
     75 #endif
     76 
     77 /*
     78  * Simplified macro to send a buffer.
     79  */
     80 #ifndef BUFLOG
     81 #define __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
     82     BufLogSingleton::instance()->write(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, \
     83             BUF, SIZE)
     84 #if BUFLOG_NDEBUG
     85 #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
     86     do { if (0) {  } } while (0)
     87 #else
     88 #define BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE) \
     89     __BUFLOG(STREAMID, TAG, FORMAT, CHANNELS, SAMPLINGRATE, MAXBYTES, BUF, SIZE)
     90 #endif
     91 #endif
     92 
     93 #ifndef BUFLOG_EXISTS
     94 #define BUFLOG_EXISTS BufLogSingleton::instanceExists()
     95 #endif
     96 
     97 #ifndef BUFLOG_RESET
     98 #define BUFLOG_RESET do { if (BufLogSingleton::instanceExists()) { \
     99     BufLogSingleton::instance()->reset(); } } while (0)
    100 #endif
    101 
    102 
    103 #include <stdint.h>
    104 #include <stdio.h>
    105 #include <sys/types.h>
    106 #include <utils/Mutex.h>
    107 
    108 //BufLog configuration
    109 #define BUFLOGSTREAM_MAX_TAGSIZE    32
    110 #define BUFLOG_BASE_PATH            "/data/misc/audioserver"
    111 #define BUFLOG_MAX_PATH_SIZE        300
    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     bool                mPaused;
    139     const unsigned int  mId;
    140     char                mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1];
    141     const unsigned int  mFormat;
    142     const unsigned int  mChannels;
    143     const unsigned int  mSamplingRate;
    144     const size_t        mMaxBytes;
    145     size_t              mByteCount;
    146     FILE                *mFile;
    147     mutable android::Mutex mLock;
    148 
    149     void            closeStream_l();
    150 };
    151 
    152 
    153 class BufLog {
    154 public:
    155     BufLog();
    156     ~BufLog();
    157     BufLog(BufLog const&) {};
    158 
    159     //  streamid:      int [0:BUFLOG_MAXSTREAMS-1]   buffer id.
    160     //                  If a buffer doesn't exist, it is created the first time is referenced
    161     //  tag:           char*  string tag used on stream filename and logs
    162     //  format:        int Audio format (audio_format_t see audio.h)
    163     //  channels:      int          Channel Count
    164     //  samplingRate:  int Sampling rate in Hz. e.g. 8000, 16000, 44100, 48000, etc
    165     //  maxBytes:      int [0 or positive number]
    166     //                  Maximum size of the file (in bytes) to be output.
    167     //                  If the value is 0, no limit.
    168     //  size:          int Size (in bytes) of the current audio buffer to be written.
    169     //  buf:           void *    Pointer to audio buffer.
    170     size_t          write(int streamid,
    171                         const char *tag,
    172                         int format,
    173                         int channels,
    174                         int samplingRate,
    175                         size_t maxBytes,
    176                         const void *buf,
    177                         size_t size);
    178 
    179     // reset will stop and close all active streams, thus finalizing any open file.
    180     //  New streams will be created if write() is called again.
    181     void            reset();
    182 
    183 protected:
    184     static const unsigned int BUFLOG_MAXSTREAMS = 16;
    185     BufLogStream    *mStreams[BUFLOG_MAXSTREAMS];
    186     mutable android::Mutex mLock;
    187 };
    188 
    189 class BufLogSingleton {
    190 public:
    191     static BufLog   *instance();
    192     static bool     instanceExists();
    193 
    194 private:
    195     static void     initOnce();
    196     static BufLog   *mInstance;
    197 };
    198 
    199 #endif //ANDROID_AUDIO_BUFLOG_H
    200