Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01cb926c authored by Mingming Yin's avatar Mingming Yin Committed by Steve Kondik
Browse files

audio: Add support for tunnel mode recording

- Add support for tunnel mode recording

Change-Id: I95cdfff729affd784141487521c9f2f714221d11
parent 6ae15d0d
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -186,7 +186,11 @@ public:
            audio_format_t format() const;
            uint32_t    channelCount() const;
            size_t      frameCount() const;
            size_t      frameSize() const { return mFrameSize; }
#ifdef QCOM_HARDWARE
            size_t      frameSize() const;
#else
            size_t      frameSize() const { return mFrameSize; };
#endif
            audio_source_t inputSource() const;


+14 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -104,8 +105,20 @@ private:

    AudioSource(const AudioSource &);
    AudioSource &operator=(const AudioSource &);
};

#ifdef QCOM_HARDWARE
    //additions for tunnel source
public:
    AudioSource(
        audio_source_t inputSource, const sp<MetaData>& meta );

private:
    audio_format_t mFormat;
    String8 mMime;
    int32_t mMaxBufferSize;
    int64_t bufferDurationUs( ssize_t n );
#endif
};
}  // namespace android

#endif  // AUDIO_SOURCE_H_
+88 −1
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
** Not a Contribution.
**
** Copyright 2008, The Android Open Source Project
** Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -136,6 +137,8 @@ status_t AudioRecord::set(
        bool threadCanCallJava,
        int sessionId)
{
    status_t status;

    // FIXME "int" here is legacy and will be replaced by size_t later
    if (frameCountInt < 0) {
        ALOGE("Invalid frame count %d", frameCountInt);
@@ -184,11 +187,15 @@ status_t AudioRecord::set(
#endif
    mChannelCount = channelCount;

#ifdef QCOM_HARDWARE
    mFrameSize = frameSize();
#else
    if (audio_is_linear_pcm(format)) {
        mFrameSize = channelCount * audio_bytes_per_sample(format);
    } else {
        mFrameSize = sizeof(uint8_t);
    }
#endif

    if (sessionId == 0 ) {
        mSessionId = AudioSystem::newAudioSessionId();
@@ -207,12 +214,60 @@ status_t AudioRecord::set(
        return BAD_VALUE;
    }

#ifdef QCOM_HARDWARE
    size_t inputBuffSizeInBytes = -1;
    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
            != NO_ERROR) {
        ALOGE("AudioSystem could not query the input buffer size.");
        return NO_INIT;
    }
    ALOGV("AudioRecord::set() inputBuffSizeInBytes = %d", inputBuffSizeInBytes );

    if (inputBuffSizeInBytes == 0) {
        ALOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
            sampleRate, channelCount, format);
        return BAD_VALUE;
    }

    // Change for Codec type
    int frameSizeInBytes = 0;
    if(inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION) {
        if (audio_is_linear_pcm(format)) {
             frameSizeInBytes = channelCount * (format == AUDIO_FORMAT_PCM_16_BIT ? sizeof(int16_t)
: sizeof(int8_t));
        } else {
             frameSizeInBytes = channelCount *sizeof(int16_t);
        }
    } else {
        if (format ==AUDIO_FORMAT_AMR_NB) {
             frameSizeInBytes = channelCount * AMR_FRAMESIZE; // Full rate framesize
        } else if (format ==AUDIO_FORMAT_EVRC) {
             frameSizeInBytes = channelCount * EVRC_FRAMESIZE; // Full rate framesize
        } else if (format ==AUDIO_FORMAT_QCELP) {
             frameSizeInBytes = channelCount * QCELP_FRAMESIZE; // Full rate framesize
        } else if (format ==AUDIO_FORMAT_AAC) {
             frameSizeInBytes = AAC_FRAMESIZE;
        } else if ((format ==AUDIO_FORMAT_PCM_16_BIT) || (format ==AUDIO_FORMAT_PCM_8_BIT)) {
             if (audio_is_linear_pcm(format)) {
                  frameSizeInBytes = channelCount * (format == AUDIO_FORMAT_PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t));
             } else {
                  frameSizeInBytes = sizeof(int8_t);
             }
        } else if(format == AUDIO_FORMAT_AMR_WB) {
            frameSizeInBytes = channelCount * AMR_WB_FRAMESIZE;

        }
    }
    // We use 2* size of input buffer for ping pong use of record buffer.
    int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
#else
    // validate framecount
    size_t minFrameCount = 0;
    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask);
    status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask);
    if (status != NO_ERROR) {
        return status;
    }
#endif
    ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);

    if (frameCount == 0) {
@@ -286,6 +341,38 @@ size_t AudioRecord::frameCount() const
    return mFrameCount;
}

#ifdef QCOM_HARDWARE
size_t AudioRecord::frameSize() const
{
    if(inputSource() == AUDIO_SOURCE_VOICE_COMMUNICATION) {
        if (audio_is_linear_pcm(mFormat)) {
             return channelCount()*audio_bytes_per_sample(mFormat);
        } else {
            return channelCount()*sizeof(int16_t);
        }
    } else {
        if (format() ==AUDIO_FORMAT_AMR_NB) {
             return channelCount() * AMR_FRAMESIZE; // Full rate framesize
        } else if (format() == AUDIO_FORMAT_EVRC) {
             return channelCount() * EVRC_FRAMESIZE; // Full rate framesize
        } else if (format() == AUDIO_FORMAT_QCELP) {
             return channelCount() * QCELP_FRAMESIZE; // Full rate framesize
        } else if (format() == AUDIO_FORMAT_AAC) {
            // Not actual framsize but for variable frame rate AAC encoding,
           // buffer size is treated as a frame size
             return AAC_FRAMESIZE;
        } else if(format() == AUDIO_FORMAT_AMR_WB) {
            return channelCount() * AMR_WB_FRAMESIZE;
        }
        if (audio_is_linear_pcm(mFormat)) {
            return channelCount()*audio_bytes_per_sample(mFormat);
        } else {
            return sizeof(uint8_t);
        }
    }
}
#endif

audio_source_t AudioRecord::inputSource() const
{
    return mInputSource;
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_STATIC_LIBRARIES :=       \
    libstagefright_nuplayer     \
    libstagefright_rtsp         \
    libmedia_helper             \

LOCAL_C_INCLUDES :=                                                 \
    $(call include-path-for, graphics corecg)                       \
+51 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "StagefrightRecorder"
#include <utils/Log.h>

#include <media/AudioParameter.h>
#include "StagefrightRecorder.h"

#include <binder/IPCThreadState.h>
@@ -47,6 +47,7 @@
#include <camera/ICamera.h>
#include <camera/CameraParameters.h>
#include <gui/Surface.h>
#include <utils/String8.h>

#include <utils/Errors.h>
#include <sys/types.h>
@@ -864,6 +865,55 @@ status_t StagefrightRecorder::start() {
}

sp<MediaSource> StagefrightRecorder::createAudioSource() {
#ifdef QCOM_HARDWARE
    bool tunneledSource = false;
    const char *tunnelMime;
    {
        AudioParameter param;
        String8 key("tunneled-input-formats");
        param.add( key, String8("get") );
        String8 valueStr = AudioSystem::getParameters( 0, param.toString());
        AudioParameter result(valueStr);
        int value;
        if ( mAudioEncoder == AUDIO_ENCODER_AMR_NB &&
            result.getInt(String8("AMR"),value) == NO_ERROR ) {
            tunneledSource = true;
            tunnelMime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
        }
#ifdef ENABLE_QC_AV_ENHANCEMENTS
        else if ( mAudioEncoder == AUDIO_ENCODER_QCELP &&
            result.getInt(String8("QCELP"),value) == NO_ERROR ) {
            tunneledSource = true;
            tunnelMime = MEDIA_MIMETYPE_AUDIO_QCELP;
        }
        else if ( mAudioEncoder == AUDIO_ENCODER_EVRC &&
            result.getInt(String8("EVRC"),value) == NO_ERROR ) {
            tunneledSource = true;
            tunnelMime = MEDIA_MIMETYPE_AUDIO_EVRC;
        }
#endif
        else if ( mAudioEncoder == AUDIO_ENCODER_AMR_WB &&
            result.getInt(String8("AWB"),value) == NO_ERROR ) {
            tunneledSource = true;
            tunnelMime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
        }
    }

    if ( tunneledSource ) {
        ALOGD("tunnel recording");
        sp<AudioSource> audioSource = NULL;
        sp<MetaData> meta = new MetaData;
        meta->setInt32(kKeyChannelCount, mAudioChannels);
        meta->setInt32(kKeySampleRate, mSampleRate);
        meta->setInt32(kKeyBitRate, mAudioBitRate);
        if (mAudioTimeScale > 0) {
            meta->setInt32(kKeyTimeScale, mAudioTimeScale);
        }
        meta->setCString( kKeyMIMEType, tunnelMime );
        audioSource = new AudioSource( mAudioSource, meta);
        return audioSource->initCheck( ) == OK ? audioSource : NULL;
    }
#endif
    sp<AudioSource> audioSource =
        new AudioSource(
                mAudioSource,
Loading