blob: 601d824e6e4616257074ecce35b3ad3b5650cada [file] [log] [blame]
/*
* Copyright (C) 2008, The Android Open Source Project
* Copyright (C) 2008 HTC Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* authordriver.h
*
* The glue between the Android MediaRecorder and PVAuthorInterface
*/
#ifndef _AUTHORDRIVER_PRIV_H
#define _AUTHORDRIVER_PRIV_H
#include <utils/Log.h>
#include <utils/threads.h>
#include <utils/List.h>
#include <utils/Errors.h>
#include <camera/ICamera.h>
#include <media/mediarecorder.h>
#include "oscl_scheduler.h"
#include "oscl_scheduler_ao.h"
#include "oscl_exception.h"
#include "pvlogger.h"
#include "pvlogger_file_appender.h"
#include "pvlogger_stderr_appender.h"
#include "pvlogger_time_and_id_layout.h"
#include "pvauthorenginefactory.h"
#include "pvauthorengineinterface.h"
#include "pv_engine_observer.h"
#include "pvmf_errorinfomessage_extension.h"
#include "oscl_mem.h"
#include "oscl_mem_audit.h"
#include "oscl_error.h"
#include "oscl_utf8conv.h"
#include "oscl_string_utils.h"
#include "android_camera_input.h"
#include "android_audio_input.h"
#include "pvmf_media_input_node_factory.h"
#include "pvmf_fileoutput_factory.h"
#include "pvmf_node_interface.h"
#include "pvmp4h263encextension.h"
#include "pvmp4ffcn_clipconfig.h"
#include "pvmf_fileoutput_config.h"
#ifndef PVMF_FILEOUTPUT_CONFIG_H_INCLUDED
#include "pvmf_fileoutput_config.h"
#endif
#ifndef PVMF_AUDIO_ENCNODE_EXTENSION_H_INCLUDED
#include "pvmf_audio_encnode_extension.h"
#endif
// 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<class DestructClass>
class LogAppenderDestructDealloc : public OsclDestructDealloc
{
public:
virtual void destruct_and_dealloc(OsclAny *ptr)
{
delete((DestructClass*)ptr);
}
};
// Commands that MediaAuthor sends to the AuthorDriver.
//
enum author_command_type {
AUTHOR_INIT = 1,
AUTHOR_SET_CAMERA,
AUTHOR_SET_VIDEO_SOURCE,
AUTHOR_SET_AUDIO_SOURCE,
AUTHOR_SET_OUTPUT_FORMAT,
AUTHOR_SET_VIDEO_ENCODER,
AUTHOR_SET_AUDIO_ENCODER,
AUTHOR_SET_VIDEO_SIZE,
AUTHOR_SET_VIDEO_FRAME_RATE,
AUTHOR_SET_PREVIEW_SURFACE,
AUTHOR_SET_OUTPUT_FILE,
AUTHOR_SET_PARAMETERS,
AUTHOR_PREPARE,
AUTHOR_START,
AUTHOR_STOP,
AUTHOR_RESET,
AUTHOR_CLOSE,
AUTHOR_REMOVE_VIDEO_SOURCE,
AUTHOR_REMOVE_AUDIO_SOURCE,
AUTHOR_QUIT = 100
};
struct author_command
{
author_command(author_command_type which) {
this->which = which;
}
virtual ~author_command() {}
author_command_type which;
media_completion_f comp;
void *cookie;
};
struct set_audio_source_command : author_command
{
set_audio_source_command() : author_command(AUTHOR_SET_AUDIO_SOURCE) {};
audio_source as;
};
struct set_video_source_command : author_command
{
set_video_source_command() : author_command(AUTHOR_SET_VIDEO_SOURCE) {};
video_source vs;
};
struct set_output_format_command : author_command
{
set_output_format_command() : author_command(AUTHOR_SET_OUTPUT_FORMAT) {};
output_format of;
};
struct set_audio_encoder_command : author_command
{
set_audio_encoder_command() : author_command(AUTHOR_SET_AUDIO_ENCODER) {};
audio_encoder ae;
};
struct set_video_encoder_command : author_command
{
set_video_encoder_command() : author_command(AUTHOR_SET_VIDEO_ENCODER) {};
video_encoder ve;
};
struct set_output_file_command : author_command
{
set_output_file_command() : author_command(AUTHOR_SET_OUTPUT_FILE) {};
int fd;
int64_t offset;
int64_t length;
};
struct set_video_size_command : author_command
{
set_video_size_command() : author_command(AUTHOR_SET_VIDEO_SIZE) {};
int width;
int height;
};
struct set_video_frame_rate_command : author_command
{
set_video_frame_rate_command() : author_command(AUTHOR_SET_VIDEO_FRAME_RATE) {};
int rate;
};
struct set_preview_surface_command : author_command
{
set_preview_surface_command() : author_command(AUTHOR_SET_PREVIEW_SURFACE) {};
sp<ISurface> surface;
};
struct set_camera_command : author_command
{
set_camera_command() : author_command(AUTHOR_SET_CAMERA) {};
sp<ICamera> camera;
};
struct set_parameters_command : author_command
{
set_parameters_command(const String8& params)
: author_command(AUTHOR_SET_PARAMETERS),
mParams(params) {
}
const String8& params() const { return mParams; }
private:
String8 mParams;
// Disallow copying and assignment.
set_parameters_command(const set_parameters_command&);
set_parameters_command& operator=(const set_parameters_command&);
};
class MediaProfiles;
class AuthorDriver :
public OsclActiveObject,
public PVCommandStatusObserver,
public PVInformationalEventObserver,
public PVErrorEventObserver
{
public:
AuthorDriver();
~AuthorDriver();
author_command *dequeueCommand();
status_t enqueueCommand(author_command *ec, media_completion_f comp, void *cookie);
// Dequeues a command from MediaRecorder and gives it to PVAuthorEngine.
void Run();
// Handlers for the various commands we can accept.
void commandFailed(author_command *ac);
void handleInit(author_command *ac);
void handleSetAudioSource(set_audio_source_command *ac);
void handleSetCamera(set_camera_command *ac);
void handleSetVideoSource(set_video_source_command *ac);
void handleSetOutputFormat(set_output_format_command *ac);
void handleSetAudioEncoder(set_audio_encoder_command *ac);
void handleSetVideoEncoder(set_video_encoder_command *ac);
void handleSetVideoSize(set_video_size_command *ac);
void handleSetVideoFrameRate(set_video_frame_rate_command *ac);
void handleSetPreviewSurface(set_preview_surface_command *ac);
void handleSetOutputFile(set_output_file_command *ac);
void handleSetParameters(set_parameters_command *ac);
void handlePrepare(author_command *ac);
void handleStart(author_command *ac);
void handleStop(author_command *ac);
void handleReset(author_command *ac);
void handleClose(author_command *ac);
void handleQuit(author_command *ac);
void endOfData();
void CommandCompleted(const PVCmdResponse& aResponse);
void HandleErrorEvent(const PVAsyncErrorEvent& aEvent);
void HandleInformationalEvent(const PVAsyncInformationalEvent& aEvent);
status_t getMaxAmplitude(int *max);
PVAEState getAuthorEngineState();
status_t setListener(const sp<IMediaPlayerClient>& listener);
private:
// Finish up a non-async command in such a way that
// the event loop will keep running.
void FinishNonAsyncCommand(author_command *ec);
// remove references to configurations
void removeConfigRefs(author_command *ac);
// remove input video or audio source
void handleRemoveVideoSource(author_command *ac);
void handleRemoveAudioSource(author_command *ac);
// Release resources acquired in a recording session
// Can be called only in the IDLE state of the authoring engine
void doCleanUp();
// Starts the PV scheduler thread.
static int startAuthorThread(void *cookie);
int authorThread();
static void media_track_added(status_t s, void *cookie);
// Callback for synchronous commands.
static void syncCompletion(status_t s, void *cookie);
// Limit either the duration of the recording or the resulting file size
// If "limit_is_duration" is true, "limit" holds the maximum duration in
// 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;
PVMFNodeInterface *mVideoNode;
sp<AndroidAudioInput> mAudioInputMIO;
PVMFNodeInterface *mAudioNode;
void *mSelectedComposer;
PVInterface *mComposerConfig;
PVInterface *mVideoEncoderConfig;
PVInterface *mAudioEncoderConfig;
int mVideoWidth;
int mVideoHeight;
int mVideoFrameRate;
//int mVideoBitRate;
video_encoder mVideoEncoder;
output_format mOutputFormat;
//int mAudioBitRate;
audio_encoder mAudioEncoder;
// Semaphore used for synchronous commands.
OsclSemaphore *mSyncSem;
// Status cached by syncCompletion for synchronous commands.
status_t mSyncStatus;
// Command queue and its lock.
List<author_command *> mCommandQueue;
Mutex mQueueLock;
sp<ICamera> mCamera;
sp<IMediaPlayerClient> mListener;
int32 mSamplingRate;
int32 mNumberOfChannels;
int32 mAudio_bitrate_setting;
int32 mVideo_bitrate_setting;
FILE* ifpOutput;
MediaProfiles *mMediaProfiles;
};
class AuthorDriverWrapper
{
public:
AuthorDriverWrapper();
~AuthorDriverWrapper();
status_t enqueueCommand(author_command *ec, media_completion_f comp, void *cookie);
status_t getMaxAmplitude(int *max);
status_t setListener(const sp<IMediaPlayerClient>& listener);
private:
void resetAndClose();
AuthorDriver *mAuthorDriver;
};
}; // namespace android
#endif // _AUTHORDRIVER_PRIV_H