Merge change 23714 into eclair
* changes: Some work to make audio encoding work.
This commit is contained in:
@@ -24,6 +24,7 @@ include $(BUILD_EXECUTABLE)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
SineSource.cpp \
|
||||
record.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
|
||||
@@ -102,7 +102,7 @@ sp<MetaData> JPEGSource::getFormat() {
|
||||
meta->setCString(kKeyMIMEType, "image/jpeg");
|
||||
meta->setInt32(kKeyWidth, mWidth);
|
||||
meta->setInt32(kKeyHeight, mHeight);
|
||||
meta->setInt32(kKeyCompressedSize, mSize);
|
||||
meta->setInt32(kKeyMaxInputSize, mSize);
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
100
cmds/stagefright/SineSource.cpp
Normal file
100
cmds/stagefright/SineSource.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "SineSource.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <media/stagefright/MediaBufferGroup.h>
|
||||
#include <media/stagefright/MediaDebug.h>
|
||||
#include <media/stagefright/MetaData.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
SineSource::SineSource(int32_t sampleRate, int32_t numChannels)
|
||||
: mStarted(false),
|
||||
mSampleRate(sampleRate),
|
||||
mNumChannels(numChannels),
|
||||
mPhase(0),
|
||||
mGroup(NULL) {
|
||||
CHECK(numChannels == 1 || numChannels == 2);
|
||||
}
|
||||
|
||||
SineSource::~SineSource() {
|
||||
if (mStarted) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
status_t SineSource::start(MetaData *params) {
|
||||
CHECK(!mStarted);
|
||||
|
||||
mGroup = new MediaBufferGroup;
|
||||
mGroup->add_buffer(new MediaBuffer(kBufferSize));
|
||||
|
||||
mPhase = 0;
|
||||
mStarted = true;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t SineSource::stop() {
|
||||
CHECK(mStarted);
|
||||
|
||||
delete mGroup;
|
||||
mGroup = NULL;
|
||||
|
||||
mStarted = false;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
sp<MetaData> SineSource::getFormat() {
|
||||
sp<MetaData> meta = new MetaData;
|
||||
meta->setCString(kKeyMIMEType, "audio/raw");
|
||||
meta->setInt32(kKeyChannelCount, mNumChannels);
|
||||
meta->setInt32(kKeySampleRate, mSampleRate);
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
status_t SineSource::read(
|
||||
MediaBuffer **out, const ReadOptions *options) {
|
||||
*out = NULL;
|
||||
|
||||
MediaBuffer *buffer;
|
||||
status_t err = mGroup->acquire_buffer(&buffer);
|
||||
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
size_t frameSize = mNumChannels * sizeof(int16_t);
|
||||
size_t numFramesPerBuffer = buffer->size() / frameSize;
|
||||
|
||||
int16_t *ptr = (int16_t *)buffer->data();
|
||||
|
||||
const double k = kFrequency / mSampleRate * (2.0 * M_PI);
|
||||
|
||||
double x = mPhase * k;
|
||||
for (size_t i = 0; i < numFramesPerBuffer; ++i) {
|
||||
int16_t amplitude = (int16_t)(32767.0 * sin(x));
|
||||
|
||||
*ptr++ = amplitude;
|
||||
if (mNumChannels == 2) {
|
||||
*ptr++ = amplitude;
|
||||
}
|
||||
|
||||
x += k;
|
||||
}
|
||||
|
||||
buffer->meta_data()->setInt32(kKeyTimeUnits, mPhase);
|
||||
buffer->meta_data()->setInt32(kKeyTimeScale, mSampleRate);
|
||||
|
||||
mPhase += numFramesPerBuffer;
|
||||
|
||||
buffer->set_range(0, numFramesPerBuffer * frameSize);
|
||||
|
||||
*out = buffer;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
39
cmds/stagefright/SineSource.h
Normal file
39
cmds/stagefright/SineSource.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef SINE_SOURCE_H_
|
||||
|
||||
#define SINE_SOURCE_H_
|
||||
|
||||
#include <media/stagefright/MediaSource.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
struct MediaBufferGroup;
|
||||
|
||||
struct SineSource : public MediaSource {
|
||||
SineSource(int32_t sampleRate, int32_t numChannels);
|
||||
|
||||
virtual status_t start(MetaData *params);
|
||||
virtual status_t stop();
|
||||
|
||||
virtual sp<MetaData> getFormat();
|
||||
|
||||
virtual status_t read(
|
||||
MediaBuffer **out, const ReadOptions *options = NULL);
|
||||
|
||||
protected:
|
||||
virtual ~SineSource();
|
||||
|
||||
private:
|
||||
enum { kBufferSize = 8192 };
|
||||
static const double kFrequency = 500.0;
|
||||
|
||||
bool mStarted;
|
||||
int32_t mSampleRate;
|
||||
int32_t mNumChannels;
|
||||
size_t mPhase;
|
||||
|
||||
MediaBufferGroup *mGroup;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // SINE_SOURCE_H_
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "SineSource.h"
|
||||
|
||||
#include <binder/ProcessState.h>
|
||||
#include <media/stagefright/AudioPlayer.h>
|
||||
#include <media/stagefright/CameraSource.h>
|
||||
#include <media/stagefright/MediaBufferGroup.h>
|
||||
#include <media/stagefright/MediaDebug.h>
|
||||
@@ -24,9 +27,11 @@
|
||||
#include <media/stagefright/MmapSource.h>
|
||||
#include <media/stagefright/OMXClient.h>
|
||||
#include <media/stagefright/OMXCodec.h>
|
||||
#include <media/MediaPlayerInterface.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
#if 0
|
||||
class DummySource : public MediaSource {
|
||||
public:
|
||||
DummySource(int width, int height)
|
||||
@@ -158,7 +163,7 @@ int main(int argc, char **argv) {
|
||||
OMXCodec::Create(
|
||||
client.interface(), enc_meta, true /* createEncoder */, decoder);
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
|
||||
writer->addSource(enc_meta, encoder);
|
||||
writer->start();
|
||||
@@ -204,4 +209,60 @@ int main(int argc, char **argv) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
android::ProcessState::self()->startThreadPool();
|
||||
|
||||
OMXClient client;
|
||||
CHECK_EQ(client.connect(), OK);
|
||||
|
||||
const int32_t kSampleRate = 22050;
|
||||
const int32_t kNumChannels = 2;
|
||||
sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
|
||||
|
||||
#if 0
|
||||
sp<MediaPlayerBase::AudioSink> audioSink;
|
||||
AudioPlayer *player = new AudioPlayer(audioSink);
|
||||
player->setSource(audioSource);
|
||||
player->start();
|
||||
|
||||
sleep(10);
|
||||
|
||||
player->stop();
|
||||
#endif
|
||||
|
||||
sp<MetaData> encMeta = new MetaData;
|
||||
encMeta->setCString(kKeyMIMEType, 1 ? "audio/3gpp" : "audio/mp4a-latm");
|
||||
encMeta->setInt32(kKeySampleRate, kSampleRate);
|
||||
encMeta->setInt32(kKeyChannelCount, kNumChannels);
|
||||
encMeta->setInt32(kKeyMaxInputSize, 8192);
|
||||
|
||||
sp<MediaSource> encoder =
|
||||
OMXCodec::Create(client.interface(), encMeta, true, audioSource);
|
||||
|
||||
encoder->start();
|
||||
|
||||
int32_t n = 0;
|
||||
status_t err;
|
||||
MediaBuffer *buffer;
|
||||
while ((err = encoder->read(&buffer)) == OK) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
buffer->release();
|
||||
buffer = NULL;
|
||||
|
||||
if (++n == 10000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("$\n");
|
||||
|
||||
encoder->stop();
|
||||
|
||||
client.disconnect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ enum {
|
||||
kKeyPlatformPrivate = 'priv',
|
||||
kKeyDecoderComponent = 'decC',
|
||||
kKeyBufferID = 'bfID',
|
||||
kKeyCompressedSize = 'cmpS',
|
||||
kKeyMaxInputSize = 'inpS',
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
@@ -155,6 +155,11 @@ private:
|
||||
void setJPEGInputFormat(
|
||||
OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize);
|
||||
|
||||
void setMinBufferSize(OMX_U32 portIndex, OMX_U32 size);
|
||||
|
||||
void setRawAudioFormat(
|
||||
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
|
||||
|
||||
status_t allocateBuffers();
|
||||
status_t allocateBuffersOnPort(OMX_U32 portIndex);
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ sp<OMXCodec> OMXCodec::Create(
|
||||
if (!strcasecmp("audio/3gpp", mime)) {
|
||||
codec->setAMRFormat();
|
||||
}
|
||||
if (!createEncoder && !strcasecmp("audio/mp4a-latm", mime)) {
|
||||
if (!strcasecmp("audio/mp4a-latm", mime)) {
|
||||
int32_t numChannels, sampleRate;
|
||||
CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
|
||||
CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
|
||||
@@ -334,7 +334,7 @@ sp<OMXCodec> OMXCodec::Create(
|
||||
|
||||
int32_t compressedSize;
|
||||
success = success && meta->findInt32(
|
||||
kKeyCompressedSize, &compressedSize);
|
||||
kKeyMaxInputSize, &compressedSize);
|
||||
|
||||
CHECK(success);
|
||||
CHECK(compressedSize > 0);
|
||||
@@ -343,11 +343,42 @@ sp<OMXCodec> OMXCodec::Create(
|
||||
codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
|
||||
}
|
||||
|
||||
int32_t maxInputSize;
|
||||
if (createEncoder && meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
|
||||
codec->setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
|
||||
}
|
||||
|
||||
if (!strcmp(componentName, "OMX.TI.AMR.encode")
|
||||
|| !strcmp(componentName, "OMX.TI.WBAMR.encode")) {
|
||||
codec->setMinBufferSize(kPortIndexOutput, 8192); // XXX
|
||||
}
|
||||
|
||||
codec->initOutputFormat(meta);
|
||||
|
||||
return codec;
|
||||
}
|
||||
|
||||
void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
|
||||
OMX_PARAM_PORTDEFINITIONTYPE def;
|
||||
def.nSize = sizeof(def);
|
||||
def.nVersion.s.nVersionMajor = 1;
|
||||
def.nVersion.s.nVersionMinor = 1;
|
||||
def.nPortIndex = portIndex;
|
||||
|
||||
status_t err = mOMX->get_parameter(
|
||||
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
||||
CHECK_EQ(err, OK);
|
||||
|
||||
if (def.nBufferSize < size) {
|
||||
def.nBufferSize = size;
|
||||
|
||||
}
|
||||
|
||||
err = mOMX->set_parameter(
|
||||
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
||||
CHECK_EQ(err, OK);
|
||||
}
|
||||
|
||||
status_t OMXCodec::setVideoPortFormatType(
|
||||
OMX_U32 portIndex,
|
||||
OMX_VIDEO_CODINGTYPE compressionFormat,
|
||||
@@ -689,7 +720,6 @@ status_t OMXCodec::init() {
|
||||
if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
|
||||
err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
|
||||
CHECK_EQ(err, OK);
|
||||
|
||||
setState(LOADED_TO_IDLE);
|
||||
}
|
||||
|
||||
@@ -1430,6 +1460,41 @@ void OMXCodec::setState(State newState) {
|
||||
mBufferFilled.signal();
|
||||
}
|
||||
|
||||
void OMXCodec::setRawAudioFormat(
|
||||
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
|
||||
OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
|
||||
pcmParams.nSize = sizeof(pcmParams);
|
||||
pcmParams.nVersion.s.nVersionMajor = 1;
|
||||
pcmParams.nVersion.s.nVersionMinor = 1;
|
||||
pcmParams.nPortIndex = portIndex;
|
||||
|
||||
status_t err = mOMX->get_parameter(
|
||||
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
|
||||
|
||||
CHECK_EQ(err, OK);
|
||||
|
||||
pcmParams.nChannels = numChannels;
|
||||
pcmParams.eNumData = OMX_NumericalDataSigned;
|
||||
pcmParams.bInterleaved = OMX_TRUE;
|
||||
pcmParams.nBitPerSample = 16;
|
||||
pcmParams.nSamplingRate = sampleRate;
|
||||
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
|
||||
|
||||
if (numChannels == 1) {
|
||||
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
|
||||
} else {
|
||||
CHECK_EQ(numChannels, 2);
|
||||
|
||||
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
|
||||
pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
|
||||
}
|
||||
|
||||
err = mOMX->set_parameter(
|
||||
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
|
||||
|
||||
CHECK_EQ(err, OK);
|
||||
}
|
||||
|
||||
void OMXCodec::setAMRFormat() {
|
||||
if (!mIsEncoder) {
|
||||
OMX_AUDIO_PARAM_AMRTYPE def;
|
||||
@@ -1459,57 +1524,32 @@ void OMXCodec::setAMRFormat() {
|
||||
CHECK(format->findInt32(kKeySampleRate, &sampleRate));
|
||||
CHECK(format->findInt32(kKeyChannelCount, &numChannels));
|
||||
|
||||
OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
|
||||
pcmParams.nSize = sizeof(pcmParams);
|
||||
pcmParams.nVersion.s.nVersionMajor = 1;
|
||||
pcmParams.nVersion.s.nVersionMinor = 1;
|
||||
pcmParams.nPortIndex = kPortIndexInput;
|
||||
|
||||
status_t err = mOMX->get_parameter(
|
||||
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
|
||||
|
||||
CHECK_EQ(err, OK);
|
||||
|
||||
pcmParams.nChannels = numChannels;
|
||||
pcmParams.eNumData = OMX_NumericalDataSigned;
|
||||
pcmParams.bInterleaved = OMX_TRUE;
|
||||
pcmParams.nBitPerSample = 16;
|
||||
pcmParams.nSamplingRate = sampleRate;
|
||||
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
|
||||
|
||||
if (numChannels == 1) {
|
||||
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
|
||||
} else {
|
||||
CHECK_EQ(numChannels, 2);
|
||||
|
||||
pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
|
||||
pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
|
||||
}
|
||||
|
||||
err = mOMX->set_parameter(
|
||||
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
|
||||
|
||||
CHECK_EQ(err, OK);
|
||||
setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
|
||||
}
|
||||
}
|
||||
|
||||
void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
|
||||
OMX_AUDIO_PARAM_AACPROFILETYPE profile;
|
||||
profile.nSize = sizeof(profile);
|
||||
profile.nVersion.s.nVersionMajor = 1;
|
||||
profile.nVersion.s.nVersionMinor = 1;
|
||||
profile.nPortIndex = kPortIndexInput;
|
||||
if (mIsEncoder) {
|
||||
setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
|
||||
} else {
|
||||
OMX_AUDIO_PARAM_AACPROFILETYPE profile;
|
||||
profile.nSize = sizeof(profile);
|
||||
profile.nVersion.s.nVersionMajor = 1;
|
||||
profile.nVersion.s.nVersionMinor = 1;
|
||||
profile.nPortIndex = kPortIndexInput;
|
||||
|
||||
status_t err =
|
||||
mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
|
||||
CHECK_EQ(err, OK);
|
||||
status_t err = mOMX->get_parameter(
|
||||
mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
|
||||
CHECK_EQ(err, OK);
|
||||
|
||||
profile.nChannels = numChannels;
|
||||
profile.nSampleRate = sampleRate;
|
||||
profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
|
||||
profile.nChannels = numChannels;
|
||||
profile.nSampleRate = sampleRate;
|
||||
profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
|
||||
|
||||
err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
|
||||
CHECK_EQ(err, OK);
|
||||
err = mOMX->set_parameter(
|
||||
mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
|
||||
CHECK_EQ(err, OK);
|
||||
}
|
||||
}
|
||||
|
||||
void OMXCodec::setImageOutputFormat(
|
||||
@@ -2102,40 +2142,46 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
|
||||
{
|
||||
OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
|
||||
|
||||
CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM);
|
||||
if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
|
||||
OMX_AUDIO_PARAM_PCMMODETYPE params;
|
||||
params.nSize = sizeof(params);
|
||||
params.nVersion.s.nVersionMajor = 1;
|
||||
params.nVersion.s.nVersionMinor = 1;
|
||||
params.nPortIndex = kPortIndexOutput;
|
||||
|
||||
OMX_AUDIO_PARAM_PCMMODETYPE params;
|
||||
params.nSize = sizeof(params);
|
||||
params.nVersion.s.nVersionMajor = 1;
|
||||
params.nVersion.s.nVersionMinor = 1;
|
||||
params.nPortIndex = kPortIndexOutput;
|
||||
err = mOMX->get_parameter(
|
||||
mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
|
||||
CHECK_EQ(err, OK);
|
||||
|
||||
err = mOMX->get_parameter(
|
||||
mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
|
||||
CHECK_EQ(err, OK);
|
||||
CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
|
||||
CHECK_EQ(params.nBitPerSample, 16);
|
||||
CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
|
||||
|
||||
CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
|
||||
CHECK_EQ(params.nBitPerSample, 16);
|
||||
CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
|
||||
int32_t numChannels, sampleRate;
|
||||
inputFormat->findInt32(kKeyChannelCount, &numChannels);
|
||||
inputFormat->findInt32(kKeySampleRate, &sampleRate);
|
||||
|
||||
int32_t numChannels, sampleRate;
|
||||
inputFormat->findInt32(kKeyChannelCount, &numChannels);
|
||||
inputFormat->findInt32(kKeySampleRate, &sampleRate);
|
||||
if ((OMX_U32)numChannels != params.nChannels) {
|
||||
LOGW("Codec outputs a different number of channels than "
|
||||
"the input stream contains.");
|
||||
}
|
||||
|
||||
if ((OMX_U32)numChannels != params.nChannels) {
|
||||
LOGW("Codec outputs a different number of channels than "
|
||||
"the input stream contains.");
|
||||
mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
|
||||
|
||||
// Use the codec-advertised number of channels, as some
|
||||
// codecs appear to output stereo even if the input data is
|
||||
// mono.
|
||||
mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
|
||||
|
||||
// The codec-reported sampleRate is not reliable...
|
||||
mOutputFormat->setInt32(kKeySampleRate, sampleRate);
|
||||
} else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
|
||||
mOutputFormat->setCString(kKeyMIMEType, "audio/3gpp");
|
||||
} else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
|
||||
mOutputFormat->setCString(kKeyMIMEType, "audio/mp4a-latm");
|
||||
} else {
|
||||
CHECK(!"Should not be here. Unknown audio encoding.");
|
||||
}
|
||||
|
||||
mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
|
||||
|
||||
// Use the codec-advertised number of channels, as some
|
||||
// codecs appear to output stereo even if the input data is
|
||||
// mono.
|
||||
mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
|
||||
|
||||
// The codec-reported sampleRate is not reliable...
|
||||
mOutputFormat->setInt32(kKeySampleRate, sampleRate);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user