From a0173f1a014c0815d24af7e9948f5ccc829c8382 Mon Sep 17 00:00:00 2001 From: PacketVideo CM Date: Wed, 23 Sep 2009 16:24:29 -0700 Subject: [PATCH] RIO-7248: Update the author driver to support new audio encoding types. --- android/author/android_audio_input.cpp | 93 ++++- android/author/android_audio_input.h | 25 +- android/author/android_camera_input.cpp | 1 + android/author/authordriver.cpp | 649 +++++++++++++++++++++++++++----- android/author/authordriver.h | 65 ++++ engines/2way/src/pv_2way_sdkinfo.h | 2 +- engines/author/src/pv_author_sdkinfo.h | 2 +- engines/player/src/pv_player_sdkinfo.h | 2 +- 8 files changed, 723 insertions(+), 116 deletions(-) diff --git a/android/author/android_audio_input.cpp b/android/author/android_audio_input.cpp index 73b99349..b52dbe41 100644 --- a/android/author/android_audio_input.cpp +++ b/android/author/android_audio_input.cpp @@ -44,12 +44,14 @@ static const int32 AUTO_RAMP_START_MS = 300; static const int32 AUTO_RAMP_DURATION_MS = 300; //////////////////////////////////////////////////////////////////////////// -AndroidAudioInput::AndroidAudioInput() +AndroidAudioInput::AndroidAudioInput(uint32 audioSource) : OsclTimerObject(OsclActiveObject::EPriorityNominal, "AndroidAudioInput"), iCmdIdCounter(0), iPeer(NULL), iThreadLoggedOn(false), - iAudioSamplingRate(8000), + iAudioNumChannels(DEFAULT_AUDIO_NUMBER_OF_CHANNELS), + iAudioSamplingRate(DEFAULT_AUDIO_SAMPLING_RATE), + iAudioSource(audioSource), iDataEventCounter(0), iWriteCompleteAO(NULL), iTimeStamp(0), @@ -76,8 +78,6 @@ AndroidAudioInput::AndroidAudioInput() { iAudioFormat=PVMF_MIME_FORMAT_UNKNOWN; - iAudioNumChannelsValid=false; - iAudioSamplingRateValid=false; iExitAudioThread=false; iCommandCounter=0; @@ -512,29 +512,52 @@ OSCL_EXPORT_REF PVMFStatus AndroidAudioInput::getParametersSync(PvmiMIOSession s pv_mime_strcmp(identifier, OUTPUT_FORMATS_CUR_QUERY) == 0) { num_parameter_elements = 1; - status = AllocateKvp(parameters, OUTPUT_FORMATS_VALTYPE, num_parameter_elements); + status = AllocateKvp(parameters, (PvmiKeyType)OUTPUT_FORMATS_VALTYPE, num_parameter_elements); if(status != PVMFSuccess) { - LOGV("AllocateKvp failed"); - } - else - { - parameters[0].value.pChar_value = (char*)PVMF_MIME_PCM16; + LOGE("AndroidAudioInput::getParametersSync() OUTPUT_FORMATS_VALTYPE AllocateKvp failed"); + return status; } + + parameters[0].value.pChar_value = (char*)PVMF_MIME_PCM16; } else if(pv_mime_strcmp(identifier, OUTPUT_TIMESCALE_CUR_QUERY) == 0) { num_parameter_elements = 1; - status = AllocateKvp(parameters, OUTPUT_TIMESCALE_CUR_VALUE, num_parameter_elements); + status = AllocateKvp(parameters, (PvmiKeyType)OUTPUT_TIMESCALE_CUR_VALUE, num_parameter_elements); if(status != PVMFSuccess) { - LOGV("AllocateKvp failed"); + LOGE("AndroidAudioInput::getParametersSync() OUTPUT_TIMESCALE_CUR_VALUE AllocateKvp failed"); return status; } // XXX is it okay to hardcode this as the timescale? parameters[0].value.uint32_value = 1000; } + else if (pv_mime_strcmp(identifier, AUDIO_OUTPUT_SAMPLING_RATE_CUR_QUERY) == 0) + { + num_parameter_elements = 1; + status = AllocateKvp(parameters, (PvmiKeyType)AUDIO_OUTPUT_SAMPLING_RATE_CUR_QUERY, num_parameter_elements); + if (status != PVMFSuccess) + { + LOGE("AndroidAudioInput::getParametersSync() AUDIO_OUTPUT_SAMPLING_RATE_CUR_QUERY AllocateKvp failed"); + return status; + } + + parameters[0].value.uint32_value = iAudioSamplingRate; + } + else if (pv_mime_strcmp(identifier, AUDIO_OUTPUT_NUM_CHANNELS_CUR_QUERY) == 0) + { + num_parameter_elements = 1; + status = AllocateKvp(parameters, (PvmiKeyType)AUDIO_OUTPUT_NUM_CHANNELS_CUR_QUERY, num_parameter_elements); + if (status != PVMFSuccess) + { + LOGE("AndroidAudioInput::getParametersSync() AUDIO_OUTPUT_NUM_CHANNELS_CUR_QUERY AllocateKvp failed"); + return status; + } + + parameters[0].value.uint32_value = iAudioNumChannels; + } return status; } @@ -638,6 +661,32 @@ OSCL_EXPORT_REF PVMFStatus AndroidAudioInput::verifyParametersSync(PvmiMIOSessio } //////////////////////////////////////////////////////////////////////////// +bool AndroidAudioInput::setAudioSamplingRate(int32 iSamplingRate) +{ + LOGV("AndroidAudioInput::setAudioSamplingRate( %d )", iSamplingRate); + + if (iSamplingRate == 0) + { + // Setting sampling rate to zero will cause a crash + LOGV("AndroidAudioInput::setAudioSamplingRate() invalid sampling rate. Return false."); + return false; + } + + iAudioSamplingRate = iSamplingRate; + LOGV("AndroidAudioInput::setAudioSamplingRate() iAudioSamplingRate %d set", iAudioSamplingRate); + return true; +} +//////////////////////////////////////////////////////////////////////////// +bool AndroidAudioInput::setAudioNumChannels(int32 iNumChannels) +{ + LOGV("AndroidAudioInput::setAudioNumChannels( %d )", iNumChannels); + + iAudioNumChannels = iNumChannels; + LOGV("AndroidAudioInput::setAudioNumChannels() iAudioNumChannels %d set", iAudioNumChannels); + return true; +} + +//////////////////////////////////////////////////////////////////////////// // Private methods //////////////////////////////////////////////////////////////////////////// @@ -750,8 +799,8 @@ PVMFStatus AndroidAudioInput::DoInit() LOGV("DoInit"); //calculate time for a buffer to fill - iAudioNumChannels = 1; - iMicroSecondsPerDataEvent = (int32)(1000000/iAudioSamplingRate); + iMicroSecondsPerDataEvent = (int32)((1000000/iAudioSamplingRate) / iAudioNumChannels); + LOGV("AndroidAudioInput::DoInit() iMicroSecondsPerDataEvent %d", iMicroSecondsPerDataEvent); iDataEventCounter = 0; @@ -764,8 +813,10 @@ PVMFStatus AndroidAudioInput::DoInit() iMediaBufferMemPool = NULL; } iMediaBufferMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (4)); - if(!iMediaBufferMemPool) + if(!iMediaBufferMemPool) { + LOGV("AndroidAudioInput::DoInit() unable to create memory pool. Return PVMFErrNoMemory."); OSCL_LEAVE(OsclErrNoMemory); + } ); OSCL_FIRST_CATCH_ANY(err, return PVMFErrNoMemory); @@ -809,6 +860,7 @@ PVMFStatus AndroidAudioInput::DoStart() return PVMFSuccess; } +//////////////////////////////////////////////////////////////////////////// int AndroidAudioInput::start_audin_thread_func(TOsclThreadFuncArg arg) { prctl(PR_SET_NAME, (unsigned long) "audio in", 0, 0, 0); @@ -825,6 +877,7 @@ PVMFStatus AndroidAudioInput::DoPause() return PVMFSuccess; } +//////////////////////////////////////////////////////////////////////////// PVMFStatus AndroidAudioInput::DoReset() { LOGV("DoReset"); @@ -997,10 +1050,12 @@ int AndroidAudioInput::audin_thread_func() { iAudioThreadStartLock->lock(); LOGV("create AudioRecord %p", this); - android::AudioRecord - * record = new android::AudioRecord( - android::AudioRecord::DEFAULT_INPUT, iAudioSamplingRate, - android::AudioSystem::PCM_16_BIT, iAudioNumChannels, 4*kBufferSize/iAudioNumChannels/sizeof(int16)); + AudioRecord + * record = new AudioRecord( + iAudioSource, iAudioSamplingRate, + android::AudioSystem::PCM_16_BIT, + iAudioNumChannels, + 4*kBufferSize/iAudioNumChannels/sizeof(int16)); LOGV("AudioRecord created %p, this %p", record, this); status_t res = record->initCheck(); diff --git a/android/author/android_audio_input.h b/android/author/android_audio_input.h index 664c7c21..a31c568a 100644 --- a/android/author/android_audio_input.h +++ b/android/author/android_audio_input.h @@ -38,9 +38,6 @@ #ifndef OSCL_VECTOR_H_INCLUDED #include "oscl_vector.h" #endif -#ifndef PVLOGGER_H_INCLUDED -#include "pvlogger.h" -#endif #ifndef PVMI_MIO_CONTROL_H_INCLUDED #include "pvmi_mio_control.h" #endif @@ -61,6 +58,16 @@ namespace android { +static const int32 DEFAULT_AUDIO_NUMBER_OF_CHANNELS = 1; +static const int32 DEFAULT_AUDIO_SAMPLING_RATE = 8000; + +static const int32 MAX_AUDIO_SAMPLING_RATE = 96000; // In Hz +static const int32 MIN_AUDIO_SAMPLING_RATE = 7350; // In Hz + +static const int32 MAX_AUDIO_NUMBER_OF_CHANNELS = 2; +static const int32 MIN_AUDIO_NUMBER_OF_CHANNELS = 1; + + class AndroidAudioInput; class Mutex; class Condition; @@ -198,7 +205,7 @@ class AndroidAudioInput : public OsclTimerObject, public RefBase { public: - AndroidAudioInput(); + AndroidAudioInput(uint32 audioSource); virtual ~AndroidAudioInput(); // Pure virtuals from PvmiMIOControl @@ -277,7 +284,14 @@ public: */ int maxAmplitude(); + /* Sets the input sampling rate */ + bool setAudioSamplingRate(int32 iSamplingRate); + + /* Set the input number of channels */ + bool setAudioNumChannels(int32 iNumChannels); + private: + AndroidAudioInput(); void Run(); int audin_thread_func(); @@ -366,9 +380,8 @@ private: OSCL_HeapString iAudioFormatString; PVMFFormatType iAudioFormat; int32 iAudioNumChannels; - bool iAudioNumChannelsValid; int32 iAudioSamplingRate; - bool iAudioSamplingRateValid; + uint32 iAudioSource; int32 iFrameSize; int32 iDataEventCounter; diff --git a/android/author/android_camera_input.cpp b/android/author/android_camera_input.cpp index 5d75bff1..89c2a834 100644 --- a/android/author/android_camera_input.cpp +++ b/android/author/android_camera_input.cpp @@ -926,6 +926,7 @@ PVMFStatus AndroidCameraInput::DoInit() } CameraParameters p(s); p.setPreviewSize(mFrameWidth, mFrameHeight); + p.setPreviewFrameRate(mFrameRate); s = p.flatten(); if (mCamera->setParameters(s) != NO_ERROR) { LOGE("Failed to set camera(%p) parameters", mCamera.get()); diff --git a/android/author/authordriver.cpp b/android/author/authordriver.cpp index c7a48791..c51306d5 100644 --- a/android/author/authordriver.cpp +++ b/android/author/authordriver.cpp @@ -22,6 +22,7 @@ #include #include #include +#include // for property_get #include "authordriver.h" #include "pv_omxcore.h" #include @@ -110,8 +111,12 @@ AuthorDriver::AuthorDriver() mVideoFrameRate((int)ANDROID_DEFAULT_FRAME_RATE), mVideoEncoder(VIDEO_ENCODER_DEFAULT), mOutputFormat(OUTPUT_FORMAT_DEFAULT), - mAudioEncoder(AUDIO_ENCODER_DEFAULT) - ,ifpOutput(NULL) + mAudioEncoder(AUDIO_ENCODER_DEFAULT), + mSamplingRate(0), + mNumberOfChannels(0), + mAudio_bitrate_setting(0), + mVideo_bitrate_setting(0), + ifpOutput(NULL) { mSyncSem = new OsclSemaphore(); mSyncSem->Create(); @@ -300,26 +305,14 @@ void AuthorDriver::handleSetAudioSource(set_audio_source_command *ac) { int error = 0; - switch(ac->as) { - case AUDIO_SOURCE_DEFAULT: - case AUDIO_SOURCE_MIC: - mAudioInputMIO = new AndroidAudioInput(); - if(mAudioInputMIO != NULL){ - LOGV("create mio input audio"); - mAudioNode = PvmfMediaInputNodeFactory::Create(static_cast(mAudioInputMIO.get())); - if(mAudioNode){ - break; - } - else{ - // do nothing, let it go in default case - } - } - else{ - // do nothing, let it go in default case + mAudioInputMIO = new AndroidAudioInput(ac->as); + if (mAudioInputMIO != NULL) { + LOGV("create mio input audio"); + mAudioNode = PvmfMediaInputNodeFactory::Create(static_cast(mAudioInputMIO.get())); + if (mAudioNode == NULL) { + commandFailed(ac); + return; } - default: - commandFailed(ac); - return; } OSCL_TRY(error, mAuthor->AddDataSource(*mAudioNode, ac)); @@ -362,23 +355,37 @@ void AuthorDriver::handleSetVideoSource(set_video_source_command *ac) void AuthorDriver::handleSetOutputFormat(set_output_format_command *ac) { int error = 0; - OSCL_HeapString iComposerMimeType; if (ac->of == OUTPUT_FORMAT_DEFAULT) { ac->of = OUTPUT_FORMAT_THREE_GPP; } + OSCL_HeapString mComposerMimeType; + switch(ac->of) { case OUTPUT_FORMAT_THREE_GPP: - iComposerMimeType = "/x-pvmf/ff-mux/3gp"; + mComposerMimeType = "/x-pvmf/ff-mux/3gp"; break; case OUTPUT_FORMAT_MPEG_4: - iComposerMimeType = "/x-pvmf/ff-mux/mp4"; + mComposerMimeType = "/x-pvmf/ff-mux/mp4"; + break; + + //case OUTPUT_FORMAT_RAW_AMR: //"duplicate case value" keep this to be backward compatible + case OUTPUT_FORMAT_AMR_NB: + mComposerMimeType = "/x-pvmf/ff-mux/amr-nb"; + break; + + case OUTPUT_FORMAT_AMR_WB: + mComposerMimeType = "/x-pvmf/ff-mux/amr-wb"; break; - case OUTPUT_FORMAT_RAW_AMR: - iComposerMimeType = "/x-pvmf/ff-mux/amr-nb"; + case OUTPUT_FORMAT_AAC_ADIF: + mComposerMimeType = "/x-pvmf/ff-mux/adif"; + break; + + case OUTPUT_FORMAT_AAC_ADTS: + mComposerMimeType = "/x-pvmf/ff-mux/adts"; break; default: @@ -389,7 +396,7 @@ void AuthorDriver::handleSetOutputFormat(set_output_format_command *ac) mOutputFormat = ac->of; - OSCL_TRY(error, mAuthor->SelectComposer(iComposerMimeType, mComposerConfig, ac)); + OSCL_TRY(error, mAuthor->SelectComposer(mComposerMimeType, mComposerConfig, ac)); OSCL_FIRST_CATCH_ANY(error, commandFailed(ac)); } @@ -402,6 +409,8 @@ void AuthorDriver::media_track_added(status_t status, void *cookie) void AuthorDriver::handleSetAudioEncoder(set_audio_encoder_command *ac) { + LOGV("AuthorDriver::handleSetAudioEncoder(%d)", ac->ae); + int error = 0; OSCL_HeapString iAudioEncoderMimeType; @@ -411,13 +420,118 @@ void AuthorDriver::handleSetAudioEncoder(set_audio_encoder_command *ac) switch(ac->ae) { case AUDIO_ENCODER_AMR_NB: iAudioEncoderMimeType = "/x-pvmf/audio/encode/amr-nb"; + // AMR_NB only supports 8kHz sampling rate + if (mSamplingRate == 0) + { + // Sampling rate not set, use the default + mSamplingRate = 8000; + } + else if (mSamplingRate != 8000) + { + LOGE("Only valid sampling rate for AMR_NB is 8kHz."); + commandFailed(ac); + return; + } + + // AMR_NB only supports mono (IE 1 channel) + if (mNumberOfChannels == 0) + { + // Number of channels not set, use the default + mNumberOfChannels = 1; + } + else if (mNumberOfChannels != 1) + { + LOGE("Only valid number of channels for ANR_NB is 1."); + commandFailed(ac); + return; + } + break; + + case AUDIO_ENCODER_AMR_WB: + iAudioEncoderMimeType = "/x-pvmf/audio/encode/amr-wb"; + // AMR_WB only supports 16kHz sampling rate + if (mSamplingRate == 0) + { + // Sampling rate not set, use the default + mSamplingRate = 16000; + } + else if (mSamplingRate != 16000) + { + LOGE("Only valid sampling rate for AMR_WB is 16kHz."); + commandFailed(ac); + return; + } + + // AMR_WB only supports mono (IE 1 channel) + if (mNumberOfChannels == 0) + { + // Number of channels not set, use the default + mNumberOfChannels = 1; + } + else if (mNumberOfChannels != 1) + { + LOGE("Only valid number of channels for ANR_WB is 1."); + commandFailed(ac); + return; + } break; + case AUDIO_ENCODER_AAC: + case AUDIO_ENCODER_AAC_PLUS: + case AUDIO_ENCODER_EAAC_PLUS: + // Check the sampling rate + if (mSamplingRate == 0) + { + // No sampling rate set, use the default + mSamplingRate = DEFAULT_AUDIO_SAMPLING_RATE; + } + // Check the number of channels + if (mNumberOfChannels == 0) + { + // Number of channels not set, use the default + mNumberOfChannels = DEFAULT_AUDIO_NUMBER_OF_CHANNELS; + } + + // Is file container type AAC-ADIF? + if(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF) + { + // This is an audio only file container, set the correct encoder + iAudioEncoderMimeType = "/x-pvmf/audio/encode/aac/adif"; + } + // AAC-ADTS? + else if (mOutputFormat == OUTPUT_FORMAT_AAC_ADTS) + { + // This is an audio only file container, set the correct encoder + iAudioEncoderMimeType = "/x-pvmf/audio/encode/aac/adts"; + } + // else MPEG4 or 3GPP container ... use AAC-RAW + else + { + // AAC for mixed audio/video containers + iAudioEncoderMimeType = "/x-pvmf/audio/encode/X-MPEG4-AUDIO"; + } + break; default: commandFailed(ac); return; } + LOGV("AuthorDriver::handleSetAudioEncoder() set %d %d \"%s\"", mSamplingRate, mNumberOfChannels, iAudioEncoderMimeType.get_cstr()); + + // Set the sampling rate and number of channels + if (!mAudioInputMIO->setAudioSamplingRate(mSamplingRate)) + { + LOGE("Failed to set the sampling rate %d", mSamplingRate); + commandFailed(ac); + return; + } + if (!mAudioInputMIO->setAudioNumChannels(mNumberOfChannels)) + { + LOGE("Failed to set the number of channels %d", mNumberOfChannels); + commandFailed(ac); + return; + } + mAudioEncoder = ac->ae; OSCL_TRY(error, mAuthor->AddMediaTrack(*mAudioNode, iAudioEncoderMimeType, mSelectedComposer, mAudioEncoderConfig, ac)); @@ -451,6 +565,24 @@ void AuthorDriver::handleSetVideoEncoder(set_video_encoder_command *ac) } mVideoEncoder = ac->ve; + // Set video encoding frame rate and video frame size only when the + // video input MIO is set. + if (mVideoInputMIO) { + if (mVideoFrameRate == 0) { + mVideoFrameRate = DEFAULT_VIDEO_FRAME_RATE; + } + clipVideoFrameRate(); + ((AndroidCameraInput *)mVideoInputMIO)->SetFrameRate(mVideoFrameRate); + + if (mVideoWidth == 0) { + mVideoWidth = DEFAULT_VIDEO_WIDTH; + } + if (mVideoHeight == 0) { + mVideoHeight = DEFAULT_VIDEO_HEIGHT; + } + clipVideoFrameSize(); + ((AndroidCameraInput *)mVideoInputMIO)->SetFrameSize(mVideoWidth, mVideoHeight); + } OSCL_TRY(error, mAuthor->AddMediaTrack(*mVideoNode, iVideoEncoderMimeType, mSelectedComposer, mVideoEncoderConfig, ac)); OSCL_FIRST_CATCH_ANY(error, commandFailed(ac)); @@ -464,22 +596,8 @@ void AuthorDriver::handleSetVideoSize(set_video_size_command *ac) return; } - // FIXME: - // Platform-specific and temporal workaround to prevent video size from being set too large - if (ac->width > ANDROID_MAX_ENCODED_FRAME_WIDTH) { - LOGW("Intended width(%d) exceeds the max allowed width(%d). Max width is used instead.", ac->width, ANDROID_MAX_ENCODED_FRAME_WIDTH); - mVideoWidth = ANDROID_MAX_ENCODED_FRAME_WIDTH; - } else { - mVideoWidth = ac->width; - } - if (ac->height > ANDROID_MAX_ENCODED_FRAME_HEIGHT) { - LOGW("Intended height(%d) exceeds the max allowed height(%d). Max height is used instead.", ac->height, ANDROID_MAX_ENCODED_FRAME_HEIGHT); - mVideoHeight = ANDROID_MAX_ENCODED_FRAME_HEIGHT; - } else { - mVideoHeight = ac->height; - } - - ((AndroidCameraInput *)mVideoInputMIO)->SetFrameSize(mVideoWidth, mVideoHeight); + mVideoWidth = ac->width; + mVideoHeight = ac->height; FinishNonAsyncCommand(ac); } @@ -490,17 +608,8 @@ void AuthorDriver::handleSetVideoFrameRate(set_video_frame_rate_command *ac) commandFailed(ac); return; } - - // FIXME: - // Platform-specific and temporal workaround to accept a reasonable frame rate range - if (ac->rate < ANDROID_MIN_FRAME_RATE_FPS) { - mVideoFrameRate = ANDROID_MIN_FRAME_RATE_FPS; - } else if (ac->rate > ANDROID_MAX_FRAME_RATE_FPS) { - mVideoFrameRate = ANDROID_MAX_FRAME_RATE_FPS; - } else { + mVideoFrameRate = ac->rate; - } - ((AndroidCameraInput *)mVideoInputMIO)->SetFrameRate(mVideoFrameRate); FinishNonAsyncCommand(ac); } @@ -538,20 +647,21 @@ void AuthorDriver::handleSetOutputFile(set_output_file_command *ac) LOGE("Ln %d fopen() error", __LINE__); goto exit; } - - if ( OUTPUT_FORMAT_RAW_AMR == mOutputFormat ) { + + if (( OUTPUT_FORMAT_AMR_NB == mOutputFormat ) || ( OUTPUT_FORMAT_AMR_WB == mOutputFormat ) || + ( OUTPUT_FORMAT_AAC_ADIF == mOutputFormat ) || ( OUTPUT_FORMAT_AAC_ADTS == mOutputFormat )) { PvmfFileOutputNodeConfigInterface *config = OSCL_DYNAMIC_CAST(PvmfFileOutputNodeConfigInterface*, mComposerConfig); if (!config) goto exit; - + ret = config->SetOutputFileDescriptor(&OsclFileHandle(ifpOutput)); - } else if((OUTPUT_FORMAT_THREE_GPP == mOutputFormat) || (OUTPUT_FORMAT_MPEG_4 == mOutputFormat)) { + } else if((OUTPUT_FORMAT_THREE_GPP == mOutputFormat) || (OUTPUT_FORMAT_MPEG_4 == mOutputFormat)){ PVMp4FFCNClipConfigInterface *config = OSCL_DYNAMIC_CAST(PVMp4FFCNClipConfigInterface*, mComposerConfig); if (!config) goto exit; - + config->SetPresentationTimescale(1000); ret = config->SetOutputFileDescriptor(&OsclFileHandle(ifpOutput)); } - + exit: if (ret == PVMFSuccess) { @@ -611,6 +721,51 @@ PVMFStatus AuthorDriver::setMaxDurationOrFileSize( return ret; } +PVMFStatus AuthorDriver::setParamAudioSamplingRate(int64_t aSamplingRate) +{ + // Do a rough check on the incoming sampling rate + if ((aSamplingRate < MIN_AUDIO_SAMPLING_RATE) || (aSamplingRate > MAX_AUDIO_SAMPLING_RATE)) + { + LOGE("setParamAudioSamplingRate() invalid sampling rate."); + return PVMFErrArgument; + } + + mSamplingRate = aSamplingRate; + LOGV("setParamAudioSamplingRate() set sampling rate %d", mSamplingRate); + return PVMFSuccess; +} + + +PVMFStatus AuthorDriver::setParamAudioNumberOfChannels(int64_t aNumberOfChannels) +{ + // Check the number of channels + if ((aNumberOfChannels < MIN_AUDIO_NUMBER_OF_CHANNELS) || (aNumberOfChannels > MAX_AUDIO_NUMBER_OF_CHANNELS)) + { + LOGE("setParamAudioNumberOfChannels() invalid number of channels."); + return PVMFErrArgument; + } + + mNumberOfChannels = aNumberOfChannels; + LOGV("setParamAudioNumberOfChannels() set num channels %d", mNumberOfChannels); + return PVMFSuccess; +} + +PVMFStatus AuthorDriver::setParamAudioEncodingBitrate(int64_t aAudioBitrate) +{ + // Map the incoming audio bitrate settings + if ((aAudioBitrate < MIN_AUDIO_BITRATE_SETTING) || (aAudioBitrate > MAX_AUDIO_BITRATE_SETTING)) + { + LOGE("setParamAudioEncodingBitrate() invalid audio bitrate. Set call ignored."); + return PVMFErrArgument; + } + + // Set the audio bitrate + mAudio_bitrate_setting = aAudioBitrate; + + LOGV("setParamAudioEncodingBitrate() %d", mAudio_bitrate_setting); + return PVMFSuccess; +} + // Attempt to parse an int64 literal optionally surrounded by whitespace, // returns true on success, false otherwise. static bool safe_strtoi64(const char *s, int64 *val) { @@ -664,11 +819,46 @@ PVMFStatus AuthorDriver::setParameter( return setMaxDurationOrFileSize( max_filesize_bytes, false /* limit is filesize */); } + } else if (key == "audio-param-sampling-rate") { + int64_t sampling_rate; + if (safe_strtoi64(value.string(), &sampling_rate)) { + return setParamAudioSamplingRate(sampling_rate); + } + } else if (key == "audio-param-number-of-channels") { + int64_t number_of_channels; + if (safe_strtoi64(value.string(), &number_of_channels)) { + return setParamAudioNumberOfChannels(number_of_channels); + } + } else if (key == "audio-param-encoding-bitrate") { + int64_t audio_bitrate; + if (safe_strtoi64(value.string(), &audio_bitrate)) { + return setParamAudioEncodingBitrate(audio_bitrate); + } + } else if (key == "video-param-encoding-bitrate") { + int64_t video_bitrate; + if (safe_strtoi64(value.string(), &video_bitrate)) { + return setParamVideoEncodingBitrate(video_bitrate); + } } + // Return error if the key wasnt found + LOGE("AuthorDriver::setParameter() unrecognized key \"%s\"", key.string()); return PVMFErrArgument; } +PVMFStatus AuthorDriver::setParamVideoEncodingBitrate(int64_t aVideoBitrate) +{ + if (aVideoBitrate <= 0) + { + LOGE("setParamVideoEncodingBitrate() invalid video bitrate (%lld). Set call ignored.", aVideoBitrate); + return PVMFErrArgument; + } + + mVideo_bitrate_setting = aVideoBitrate; + LOGD("setParamVideoEncodingBitrate() %d", mVideo_bitrate_setting); + return PVMFSuccess; +} + // Applies the requested parameters, completes either successfully or stops // application of parameters upon encountering the first error, finishing the // transaction with the failure result of that initial failure. @@ -721,12 +911,14 @@ void AuthorDriver::handleSetParameters(set_parameters_command *ac) { if (ret == PVMFSuccess) { FinishNonAsyncCommand(ac); } else { - LOGE("Ln %d handleSetParameters(%s) error", __LINE__, params); + LOGE("Ln %d handleSetParameters(\"%s\") error", __LINE__, params); commandFailed(ac); } } + void AuthorDriver::handlePrepare(author_command *ac) { + LOGV("handlePrepare"); int error = 0; OSCL_TRY(error, mAuthor->Init(ac)); OSCL_FIRST_CATCH_ANY(error, commandFailed(ac)); @@ -734,6 +926,7 @@ void AuthorDriver::handlePrepare(author_command *ac) void AuthorDriver::handleStart(author_command *ac) { + LOGV("handleStart"); int error = 0; OSCL_TRY(error, mAuthor->Start(ac)); OSCL_FIRST_CATCH_ANY(error, commandFailed(ac)); @@ -875,11 +1068,17 @@ int AuthorDriver::authorThread() PendForExec(); OsclExecScheduler *sched = OsclExecScheduler::Current(); - sched->StartScheduler(mSyncSem); + error = OsclErrNone; + OSCL_TRY(error, sched->StartScheduler(mSyncSem)); + OSCL_FIRST_CATCH_ANY(error, + // Some AO did a leave, log it + LOGE("Author Engine AO did a leave, error=%d", error) + ); + LOGV("Delete Author"); PVAuthorEngineFactory::DeleteAuthor(mAuthor); mAuthor = NULL; - + // Let the destructor know that we're out mSyncStatus = OK; @@ -909,11 +1108,215 @@ int AuthorDriver::authorThread() ed->mSyncSem->Signal(); } +// Backward compatible hardcoded video bit rate setting +// These bit rate settings are from the original work with +// QCOM's hardware encoders. Originally, anything above +// 420000 bps is not stable, and default low quality bit +// rate it set to 192000 bps. For those devices with +// media capabilities specified as system properties, these +// bit rate settings will not be used. +static int setVideoBitrateHeuristically(int videoWidth) +{ + int bitrate_setting = 192000; + if (videoWidth >= 480) { + bitrate_setting = 420000; + } else if (videoWidth >= 352) { + bitrate_setting = 360000; + } else if (videoWidth >= 320) { + bitrate_setting = 320000; + } + return bitrate_setting; +} + + +// Returns true on success +static bool getMinAndMaxValuesOfProperty(const char*propertyKey, int64& minValue, int64& maxValue) +{ + char value[PROPERTY_VALUE_MAX]; + int rc = property_get(propertyKey, value, 0); + LOGV("property_get(): rc = %d, value=%s", rc, value); + if (rc > 0) { + char* b = strchr(value, ','); + if (b == 0) { // A pair of values separated by ","? + return false; + } else { + String8 key(value, b - value); + if (!safe_strtoi64(key.string(), &minValue) || !safe_strtoi64(b + 1, &maxValue)) { + return false; + } + } + return true; + } + return false; +} + +// Maps the given encoder to a system property key +// Returns true on success +static bool getPropertyKeyForVideoEncoder(video_encoder encoder, char* name, size_t len) +{ + switch(encoder) { + case VIDEO_ENCODER_MPEG_4_SP: + strncpy(name, "ro.media.enc.vid.m4v.", len); + return true; + case VIDEO_ENCODER_H264: + strncpy(name, "ro.media.enc.vid.h264.", len); + return true; + case VIDEO_ENCODER_H263: + strncpy(name, "ro.media.enc.vid.h263.", len); + return true; + default: + LOGE("Failed to get system property key for video encoder(%d)", encoder); + return false; + } +} + +// Retrieves the advertised video property range from system properties for the given encoder. +// If the encoder is not found, or the video property is not listed as a system property, +// default hardcoded min and max values will be used. +static void getSupportedPropertyRange(video_encoder encoder, const char* property, int64& min, int64& max) +{ + char videoEncoderName[PROPERTY_KEY_MAX]; + bool propertyKeyExists = getPropertyKeyForVideoEncoder(encoder, videoEncoderName, PROPERTY_KEY_MAX - 1); + if (propertyKeyExists) { + if ((strlen(videoEncoderName) + strlen(property) + 1) < PROPERTY_KEY_MAX) { // Valid key length + strcat(videoEncoderName, property); + } else { + propertyKeyExists = false; + } + } + if (!propertyKeyExists || !getMinAndMaxValuesOfProperty(videoEncoderName, min, max)) { + if (strcmp(property, "bps") == 0) { + min = MIN_VIDEO_BITRATE_SETTING; + max = MAX_VIDEO_BITRATE_SETTING; + } else if (strcmp(property, "fps") == 0) { + min = ANDROID_MIN_FRAME_RATE_FPS; + max = ANDROID_MAX_FRAME_RATE_FPS; + } else if (strcmp(property, "width") == 0) { + min = ANDROID_MIN_ENCODED_FRAME_WIDTH; + max = ANDROID_MAX_ENCODED_FRAME_WIDTH; + } else if (strcmp(property, "height") == 0) { + min = ANDROID_MIN_ENCODED_FRAME_HEIGHT; + max = ANDROID_MAX_ENCODED_FRAME_HEIGHT; + } else { + LOGE("Unknown video property: %s", property); + min = max = 0; + } + LOGW("Use default video %s range [%lld %lld]", property, min, max); + } +} + +static void getSupportedVideoBitRateRange(video_encoder encoder, int64& minBitRateBps, int64& maxBitRateBps) +{ + getSupportedPropertyRange(encoder, "bps", minBitRateBps, maxBitRateBps); +} + +static void getSupportedVideoFrameRateRange(video_encoder encoder, int64& minFrameRateFps, int64& maxFrameRateFps) +{ + getSupportedPropertyRange(encoder, "fps", minFrameRateFps, maxFrameRateFps); +} + +static void getSupportedVideoFrameWidthRange(video_encoder encoder, int64& minWidth, int64& maxWidth) +{ + getSupportedPropertyRange(encoder, "width", minWidth, maxWidth); +} + +static void getSupportedVideoFrameHeightRange(video_encoder encoder, int64& minHeight, int64& maxHeight) +{ + getSupportedPropertyRange(encoder, "height", minHeight, maxHeight); +} + +// Clips the intented video encoding rate so that it is +// within the advertised support range. Logs a warning if +// the intended bit rate is out of the range. +void AuthorDriver::clipVideoBitrate() +{ + int64 minBitrate, maxBitrate; + getSupportedVideoBitRateRange(mVideoEncoder, minBitrate, maxBitrate); + if (mVideo_bitrate_setting < minBitrate) { + LOGW("Intended video encoding bit rate (%d bps) is too small and will be set to (%lld bps)", mVideo_bitrate_setting, minBitrate); + mVideo_bitrate_setting = minBitrate; + } else if (mVideo_bitrate_setting > maxBitrate) { + LOGW("Intended video encoding bit rate (%d bps) is too large and will be set to (%lld bps)", mVideo_bitrate_setting, maxBitrate); + mVideo_bitrate_setting = maxBitrate; + } +} + +void AuthorDriver::clipVideoFrameRate() +{ + int64 minFrameRate, maxFrameRate; + getSupportedVideoFrameRateRange(mVideoEncoder, minFrameRate, maxFrameRate); + if (mVideoFrameRate < minFrameRate) { + LOGW("Intended video encoding frame rate (%d fps) is too small and will be set to (%lld fps)", mVideoFrameRate, minFrameRate); + mVideoFrameRate = minFrameRate; + } else if (mVideoFrameRate > maxFrameRate) { + LOGW("Intended video encoding frame rate (%d fps) is too large and will be set to (%lld fps)", mVideoFrameRate, maxFrameRate); + mVideoFrameRate = maxFrameRate; + } +} + +void AuthorDriver::clipVideoFrameWidth() +{ + int64 minFrameWidth, maxFrameWidth; + getSupportedVideoFrameWidthRange(mVideoEncoder, minFrameWidth, maxFrameWidth); + if (mVideoWidth < minFrameWidth) { + LOGW("Intended video encoding frame width (%d) is too small and will be set to (%lld)", mVideoWidth, minFrameWidth); + mVideoWidth = minFrameWidth; + } else if (mVideoWidth > maxFrameWidth) { + LOGW("Intended video encoding frame width (%d) is too large and will be set to (%lld)", mVideoWidth, maxFrameWidth); + mVideoWidth = maxFrameWidth; + } +} + +void AuthorDriver::clipVideoFrameHeight() +{ + int64 minFrameHeight, maxFrameHeight; + getSupportedVideoFrameHeightRange(mVideoEncoder, minFrameHeight, maxFrameHeight); + if (mVideoHeight < minFrameHeight) { + LOGW("Intended video encoding frame height (%d) is too small and will be set to (%lld)", mVideoHeight, minFrameHeight); + mVideoHeight = minFrameHeight; + } else if (mVideoHeight > maxFrameHeight) { + LOGW("Intended video encoding frame height (%d) is too large and will be set to (%lld)", mVideoHeight, maxFrameHeight); + mVideoHeight = maxFrameHeight; + } +} + +void AuthorDriver::clipVideoFrameSize() +{ + clipVideoFrameWidth(); + clipVideoFrameHeight(); +} + +void AuthorDriver::clipAACAudioBitrate() +{ + /* ISO-IEC-13818-7 "Information technology. Generic coding of moving + * pictures and associated audio information. Part 7: Advanced Audio + * Coding (AAC)" section 8.2.2.3 defines a formula for the max audio + * bitrate based on the audio sampling rate. + * 6144 (bit/block) / 1024 (samples/block) * sampling_freq * number_of_channels + * + * This method is to calculate the max audio bitrate and clip the desired audio + * bitrate if it exceeds its max. + */ + + int32 calculated_audio_bitrate = 6 * mSamplingRate * mNumberOfChannels; + if ((calculated_audio_bitrate > 0) && + (mAudio_bitrate_setting > calculated_audio_bitrate)) + { + // Clip the bitrate setting + LOGW("Intended audio bitrate (%d) exceeds max bitrate for sampling rate (%d). Setting audio bitrate to its calculated max (%d)", mAudio_bitrate_setting, mSamplingRate, calculated_audio_bitrate); + mAudio_bitrate_setting = calculated_audio_bitrate; + } +} + void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse) { author_command *ac = (author_command *)aResponse.GetContext(); status_t s = aResponse.GetCmdStatus(); - LOGV("Command (%d) completed with status(%d)", ac->which, s); + LOGV("Command (%d) completed with status(%d)", ac? ac->which: -1, s); + if (ac == NULL) { + LOGE("CommandCompleted: Error - null author command!"); + return; + } if (ac->which == AUTHOR_SET_OUTPUT_FORMAT) { mSelectedComposer = aResponse.GetResponseData(); @@ -921,24 +1324,19 @@ void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse) if (ac->which == AUTHOR_SET_VIDEO_ENCODER) { switch(mVideoEncoder) { - case VIDEO_ENCODER_H263: + case VIDEO_ENCODER_H263: case VIDEO_ENCODER_MPEG_4_SP: case VIDEO_ENCODER_H264: { PVMp4H263EncExtensionInterface *config = OSCL_STATIC_CAST(PVMp4H263EncExtensionInterface*, mVideoEncoderConfig); - // TODO: - // fix the hardcoded bit rate settings. if (config) { - int bitrate_setting = 192000; - if (mVideoWidth >= 480) { - bitrate_setting = 420000; // unstable - } else if (mVideoWidth >= 352) { - bitrate_setting = 360000; - } else if (mVideoWidth >= 320) { - bitrate_setting = 320000; + if (mVideo_bitrate_setting == 0) { + mVideo_bitrate_setting = setVideoBitrateHeuristically(mVideoWidth); + LOGW("Video encoding bit rate is set to %d bps", mVideo_bitrate_setting); } + clipVideoBitrate(); config->SetNumLayers(1); - config->SetOutputBitRate(0, bitrate_setting); + config->SetOutputBitRate(0, mVideo_bitrate_setting); config->SetOutputFrameSize(0, mVideoWidth, mVideoHeight); config->SetOutputFrameRate(0, mVideoFrameRate); config->SetIFrameInterval(ANDROID_DEFAULT_I_FRAME_INTERVAL); @@ -951,22 +1349,64 @@ void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse) } if (ac->which == AUTHOR_SET_AUDIO_ENCODER) { - switch(mAudioEncoder) { - case AUDIO_ENCODER_AMR_NB: - { - PVAudioEncExtensionInterface *config = OSCL_STATIC_CAST(PVAudioEncExtensionInterface *, - mAudioEncoderConfig); - if (config) { + // Perform the cast to get the audio config interface + PVAudioEncExtensionInterface *config = OSCL_STATIC_CAST(PVAudioEncExtensionInterface*, + mAudioEncoderConfig); + + if (config) + { + switch(mAudioEncoder) { + case AUDIO_ENCODER_AMR_NB: + case AUDIO_ENCODER_AMR_WB: + { + // Map the audio bitrate to an AMR discreet bitrate + PVMF_GSMAMR_Rate mAMRBitrate; + if(!MapAMRBitrate(mAudio_bitrate_setting, mAMRBitrate)) { + LOGE("Failed to map the audio bitrate to an AMR bitrate! Using the defaults."); + if (mAudioEncoder == AUDIO_ENCODER_AMR_NB) { + mAMRBitrate = DEFAULT_AMR_NARROW_BAND_BITRATE_SETTING; + } + else { // Else use the default wideband setting + mAMRBitrate = DEFAULT_AMR_WIDE_BAND_BITRATE_SETTING; + } + } + config->SetOutputBitRate(mAMRBitrate); config->SetMaxNumOutputFramesPerBuffer(10); - config->SetOutputBitRate(GSM_AMR_5_15); // 5150 bps XXX } - } - break; + break; - default: - break; - } - } + case AUDIO_ENCODER_AAC: + case AUDIO_ENCODER_AAC_PLUS: + case AUDIO_ENCODER_EAAC_PLUS: + { + if (mAudio_bitrate_setting == 0) { + // Audio bitrate wasnt set, use the default + mAudio_bitrate_setting = DEFAULT_AUDIO_BITRATE_SETTING; + } + clipAACAudioBitrate(); + config->SetOutputBitRate(mAudio_bitrate_setting); + + // Set AAC profile level + if (mAudioEncoder == AUDIO_ENCODER_AAC_PLUS) + { + config->SetOutputAacProfile(PV_AAC_ENC_HE); + } + else if (mAudioEncoder == AUDIO_ENCODER_EAAC_PLUS) + { + config->SetOutputAacProfile(PV_AAC_ENC_HE_PS); + } + else + { + // For all others + config->SetOutputAacProfile(PV_AAC_ENC_LC); + } + } + break; + default: + break; + } // End switch(mAudioEncoder) + } // End if (config) + } // End if (ac->which == AUTHOR_SET_AUDIO_ENCODER) // delete video and/or audio nodes to prevent memory leakage // when an authroing session is reused @@ -975,7 +1415,7 @@ void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse) doCleanUp(); } - // Translate the PVMF error codes into Android ones + // Translate the PVMF error codes into Android ones switch(s) { case PVMFSuccess: s = android::OK; break; case PVMFPending: *(char *)0 = 0; break; /* XXX assert */ @@ -988,6 +1428,39 @@ void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse) delete ac; } +bool AuthorDriver::MapAMRBitrate(int32 aAudioBitrate, PVMF_GSMAMR_Rate &anAMRBitrate) +{ + if ((mAudioEncoder != AUDIO_ENCODER_AMR_NB) && + (mAudioEncoder != AUDIO_ENCODER_AMR_WB)) { + LOGE("AuthorDriver::MapAMRBitrate() encoder type is not AMR."); + return false; + } + + // Default to AMR_NB + uint32 AMR_Index = 0; + + // Is this ARM_WB? + if (mAudioEncoder == AUDIO_ENCODER_AMR_WB) + { + // Use the other side of the array + AMR_Index = 1; + } + + uint32 jj; + for (jj = 0; jj < AMR_BITRATE_MAX_NUMBER_OF_ROWS; jj++) + { + if (aAudioBitrate < AMR_BITRATE_MAPPING_ARRAY[jj][AMR_Index].bitrate) + { + // Found a match! + anAMRBitrate = AMR_BITRATE_MAPPING_ARRAY[jj][AMR_Index].actual; + return true; + } + } + + // Failed to map the bitrate. Return false and use the defaults. + return false; +} + void AuthorDriver::HandleErrorEvent(const PVAsyncErrorEvent& aEvent) { LOGE("HandleErrorEvent(%d)", aEvent.GetEventType()); diff --git a/android/author/authordriver.h b/android/author/authordriver.h index b695fc6c..0492703e 100644 --- a/android/author/authordriver.h +++ b/android/author/authordriver.h @@ -64,12 +64,46 @@ // FIXME: // Platform-specic and temporal workaround to prevent video size // from being set too large + #define ANDROID_MAX_ENCODED_FRAME_WIDTH 352 #define ANDROID_MAX_ENCODED_FRAME_HEIGHT 288 +#define ANDROID_MIN_ENCODED_FRAME_WIDTH 176 +#define ANDROID_MIN_ENCODED_FRAME_HEIGHT 144 #define ANDROID_MIN_FRAME_RATE_FPS 5 #define ANDROID_MAX_FRAME_RATE_FPS 20 +static const int32 DEFAULT_VIDEO_FRAME_RATE = 20; +static const int32 DEFAULT_VIDEO_WIDTH = 176; +static const int32 DEFAULT_VIDEO_HEIGHT = 144; + +static const int32 MIN_VIDEO_BITRATE_SETTING = 192000; +static const int32 MAX_VIDEO_BITRATE_SETTING = 420000; +static const int32 MAX_AUDIO_BITRATE_SETTING = 320000; // Max bitrate?? +static const int32 MIN_AUDIO_BITRATE_SETTING = 1; // Min bitrate?? +static const int32 DEFAULT_AUDIO_BITRATE_SETTING = 64000; // Default for all the other audio +static const PVMF_GSMAMR_Rate DEFAULT_AMR_NARROW_BAND_BITRATE_SETTING = GSM_AMR_12_2; +static const PVMF_GSMAMR_Rate DEFAULT_AMR_WIDE_BAND_BITRATE_SETTING = GSM_AMR_23_85; + +typedef struct AMR_BITRATE_MAPPING +{ + int32 bitrate; + PVMF_GSMAMR_Rate actual; +} AMR_BITRATE_MAPPING; + +static const uint32 AMR_BITRATE_MAX_NUMBER_OF_ROWS = 10; +static const AMR_BITRATE_MAPPING AMR_BITRATE_MAPPING_ARRAY[AMR_BITRATE_MAX_NUMBER_OF_ROWS][2] = { + {{1,DEFAULT_AMR_NARROW_BAND_BITRATE_SETTING}, {1, DEFAULT_AMR_WIDE_BAND_BITRATE_SETTING}}, // default values + {{4950, GSM_AMR_4_75}, {7725, GSM_AMR_6_60}}, + {{5525, GSM_AMR_5_15}, {10750, GSM_AMR_8_85}}, + {{6300, GSM_AMR_5_90}, {13450, GSM_AMR_12_65}}, + {{7050, GSM_AMR_6_70}, {15050, GSM_AMR_14_25}}, + {{7625, GSM_AMR_7_40}, {17050, GSM_AMR_15_85}}, + {{9075, GSM_AMR_7_95}, {19050, GSM_AMR_18_25}}, + {{11200, GSM_AMR_10_2}, {21450, GSM_AMR_19_85}}, + {{(MAX_AUDIO_BITRATE_SETTING+1),GSM_AMR_12_2}, {23450, GSM_AMR_23_05}}, + {{(MAX_AUDIO_BITRATE_SETTING+1),GSM_AMR_12_2},{(MAX_AUDIO_BITRATE_SETTING+1), GSM_AMR_23_85}}}; + namespace android { template @@ -276,8 +310,34 @@ private: // milliseconds, otherwise "limit" holds the maximum filesize in bytes. PVMFStatus setMaxDurationOrFileSize(int64_t limit, bool limit_is_duration); + // Used to set the sampling rate of the audio source + PVMFStatus setParamAudioSamplingRate(int64_t aSamplingRate); + + // Used to set the number of channels of the audio source + PVMFStatus setParamAudioNumberOfChannels(int64_t aNumberOfChannels); + + // Used for setting the audio encoding bitrate + PVMFStatus setParamAudioEncodingBitrate(int64_t aAudioBitrate); + PVMFStatus setParameter(const String8 &key, const String8 &value); + // Has no effect if called after video encoder is set + PVMFStatus setParamVideoEncodingBitrate(int64_t aVideoBitrate); + + // Clips the intended video encoding bit rate, frame rate, frame size + // (width and height) so that it is within the supported range. + void clipVideoBitrate(); + void clipVideoFrameRate(); + void clipVideoFrameSize(); + void clipVideoFrameWidth(); + void clipVideoFrameHeight(); + + // Clips the intended AAC audio bitrate so that it is in the supported range + void clipAACAudioBitrate(); + + // Used to map the incoming bitrate to the closest AMR bitrate + bool MapAMRBitrate(int32 aAudioBitrate, PVMF_GSMAMR_Rate &anAMRBitrate); + PVAuthorEngineInterface *mAuthor; PvmiMIOControl *mVideoInputMIO; @@ -312,6 +372,11 @@ private: sp mCamera; sp mListener; + int32 mSamplingRate; + int32 mNumberOfChannels; + int32 mAudio_bitrate_setting; + int32 mVideo_bitrate_setting; + FILE* ifpOutput; }; diff --git a/engines/2way/src/pv_2way_sdkinfo.h b/engines/2way/src/pv_2way_sdkinfo.h index a4746ede..583d0336 100644 --- a/engines/2way/src/pv_2way_sdkinfo.h +++ b/engines/2way/src/pv_2way_sdkinfo.h @@ -21,7 +21,7 @@ // This header file is automatically generated at build-time // *** OFFICIAL RELEASE INFO -- Will not auto update -#define PV2WAY_ENGINE_SDKINFO_LABEL "971436" +#define PV2WAY_ENGINE_SDKINFO_LABEL "971968" #define PV2WAY_ENGINE_SDKINFO_DATE 0x20090918 #endif //PV_2WAY_SDKINFO_H_INCLUDED diff --git a/engines/author/src/pv_author_sdkinfo.h b/engines/author/src/pv_author_sdkinfo.h index 33fafbf8..330a48b4 100644 --- a/engines/author/src/pv_author_sdkinfo.h +++ b/engines/author/src/pv_author_sdkinfo.h @@ -21,7 +21,7 @@ // This header file is automatically generated at build-time // *** OFFICIAL RELEASE INFO -- Will not auto update -#define PVAUTHOR_ENGINE_SDKINFO_LABEL "971436" +#define PVAUTHOR_ENGINE_SDKINFO_LABEL "971968" #define PVAUTHOR_ENGINE_SDKINFO_DATE 0x20090918 #endif //PV_AUTHOR_SDKINFO_H_INCLUDED diff --git a/engines/player/src/pv_player_sdkinfo.h b/engines/player/src/pv_player_sdkinfo.h index 7c066f5c..2fd58ae6 100644 --- a/engines/player/src/pv_player_sdkinfo.h +++ b/engines/player/src/pv_player_sdkinfo.h @@ -21,7 +21,7 @@ // This header file is automatically generated at build-time // *** OFFICIAL RELEASE INFO -- Will not auto update -#define PVPLAYER_ENGINE_SDKINFO_LABEL "971436" +#define PVPLAYER_ENGINE_SDKINFO_LABEL "971968" #define PVPLAYER_ENGINE_SDKINFO_DATE 0x20090918 #endif //PV_PLAYER_SDKINFO_H_INCLUDED -- 2.11.0