// This class implements the reference media IO for file output
// This class constitutes the Media IO component
-OSCL_EXPORT_REF AndroidSurfaceOutput::AndroidSurfaceOutput(
- PVPlayer* pvPlayer, const sp<ISurface>& surface) :
+OSCL_EXPORT_REF AndroidSurfaceOutput::AndroidSurfaceOutput() :
OsclTimerObject(OsclActiveObject::EPriorityNominal, "androidsurfaceoutput")
{
- LOGV("AndroidAudioSurfaceOutput surface=%p", surface.get());
initData();
iColorConverter = NULL;
mInitialized = false;
mEmulation = false;
mHardwareCodec = false;
- mSurface = surface;
- mPvPlayer = pvPlayer;
+ mPvPlayer = NULL;
// running in emulation?
char value[PROPERTY_VALUE_MAX];
if (property_get("ro.kernel.qemu", value, 0)) {
- LOGV("Running in emulation - fallback to software codecs");
+ LOGV("Emulation mode - using software codecs");
mEmulation = true;
}
}
+status_t AndroidSurfaceOutput::set(PVPlayer* pvPlayer, const sp<ISurface>& surface)
+{
+ mPvPlayer = pvPlayer;
+ mSurface = surface;
+ return NO_ERROR;
+}
+
void AndroidSurfaceOutput::initData()
{
iVideoHeight = iVideoWidth = iVideoDisplayHeight = iVideoDisplayWidth = 0;
{
public:
- OSCL_IMPORT_REF AndroidSurfaceOutput(android::PVPlayer* pvPlayer, const sp<ISurface>& surface);
+ OSCL_IMPORT_REF AndroidSurfaceOutput();
+
+ // parameter initialization
+ virtual status_t set(android::PVPlayer* pvPlayer, const sp<ISurface>& surface);
// For Frame Buffer
OSCL_IMPORT_REF bool initCheck();
status_t PVMediaRecorder::stop()
{
LOGV("stop");
+ status_t ret = doStop();
+ if (OK == ret) {
+ ret = reset();
+ if (OK == ret) {
+ ret = close();
+ }
+ }
+ return ret;
+}
+
+status_t PVMediaRecorder::doStop()
+{
+ LOGV("doStop");
if (mAuthorDriverWrapper == NULL) {
LOGE("author driver wrapper is not initialized yet");
return UNKNOWN_ERROR;
//#define LOG_NDEBUG 0
#define LOG_TAG "AuthorDriver"
+#include <unistd.h>
#include <media/thread_init.h>
#include <ui/ISurface.h>
#include <ui/ICamera.h>
mAuthorDriver = new AuthorDriver();
}
+void AuthorDriverWrapper::resetAndClose()
+{
+ mAuthorDriver->enqueueCommand(new author_command(AUTHOR_RESET), NULL, NULL);
+ mAuthorDriver->enqueueCommand(new author_command(AUTHOR_CLOSE), NULL, NULL);
+}
+
AuthorDriverWrapper::~AuthorDriverWrapper()
{
- author_command *ac = new author_command(AUTHOR_QUIT);
- enqueueCommand(ac, NULL, NULL); // will wait on mSyncSem, signaled by author thread
- delete ac; // have to delete this manually because CommandCompleted won't be called
+ if (mAuthorDriver) {
+ // set the authoring engine to the IDLE state.
+ PVAEState state = mAuthorDriver->getAuthorEngineState();
+ switch (state) {
+ case PVAE_STATE_IDLE:
+ break;
+
+ case PVAE_STATE_RECORDING:
+ mAuthorDriver->enqueueCommand(new author_command(AUTHOR_STOP), NULL, NULL);
+ resetAndClose();
+ break;
+
+ default:
+ resetAndClose();
+ break;
+ }
+
+ // now it is safe to quit.
+ author_command *ac = new author_command(AUTHOR_QUIT);
+ enqueueCommand(ac, NULL, NULL); // will wait on mSyncSem, signaled by author thread
+ delete ac; // have to delete this manually because CommandCompleted won't be called
+ }
}
status_t AuthorDriverWrapper::getMaxAmplitude(int *max)
{
- return mAuthorDriver->getMaxAmplitude(max);
+ if (mAuthorDriver) {
+ return mAuthorDriver->getMaxAmplitude(max);
+ }
+ return NO_INIT;
}
status_t AuthorDriverWrapper::enqueueCommand(author_command *ac, media_completion_f comp, void *cookie)
{
- return mAuthorDriver->enqueueCommand(ac, comp, cookie);
+ if (mAuthorDriver) {
+ return mAuthorDriver->enqueueCommand(ac, comp, cookie);
+ }
+ return NO_INIT;
}
AuthorDriver::AuthorDriver()
mComposerConfig(NULL),
mVideoEncoderConfig(NULL),
mAudioEncoderConfig(NULL),
+ mOutputFileName(NULL),
+ mKeepOutputFile(false),
mVideoWidth(DEFAULT_FRAME_WIDTH),
mVideoHeight(DEFAULT_FRAME_HEIGHT),
mVideoFrameRate((int)DEFAULT_FRAME_RATE),
ret = config->SetOutputFileName(wFileName);
exit:
- free(ac->path);
if (ret == PVMFSuccess) {
+ mOutputFileName = ac->path;
FinishNonAsyncCommand(ac);
} else {
+ free(ac->path);
commandFailed(ac);
}
}
void AuthorDriver::handleStop(author_command *ac)
{
int error = 0;
- OSCL_TRY(error, mAuthor->Stop());
+ OSCL_TRY(error, mAuthor->Stop(ac));
OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
- handleReset(ac);
- handleClose(ac);
+
+ mKeepOutputFile = true;
}
void AuthorDriver::handleClose(author_command *ac)
void AuthorDriver::removeDataSources(author_command *ac)
{
+ if (mOutputFileName) {
+ if (!mKeepOutputFile) {
+ LOGV("remove output filei(%s)", mOutputFileName);
+ unlink(mOutputFileName);
+ }
+ free(mOutputFileName);
+ mOutputFileName = NULL;
+ }
+
if (mComposerConfig) {
mComposerConfig->removeRef();
mComposerConfig = NULL;
return android::OK;
}
-
+PVAEState AuthorDriver::getAuthorEngineState()
+{
+ if (mAuthor) {
+ return mAuthor->GetPVAuthorState();
+ }
+ return PVAE_STATE_IDLE;
+}
void HandleInformationalEvent(const PVAsyncInformationalEvent& aEvent);
status_t getMaxAmplitude(int *max);
+ PVAEState getAuthorEngineState();
private:
// Finish up a non-async command in such a way that
PVInterface *mVideoEncoderConfig;
PVInterface *mAudioEncoderConfig;
+ char *mOutputFileName;
+ bool mKeepOutputFile;
+
int mVideoWidth;
int mVideoHeight;
int mVideoFrameRate;
status_t getMaxAmplitude(int *max);
private:
+ void resetAndClose();
+
AuthorDriver *mAuthorDriver;
};
#include "oscl_assert.h"
#include "oscl_lock_base.h"
#include "oscl_snprintf.h"
+#include "oscl_string_utf8.h"
#include "pvmf_return_codes.h"
#include "pv_mime_string_utils.h"
#include "pv_id3_parcom_constants.h"
for (uint32 i = 0; i < num_frames;i++)
{
const char* key = framevector[i]->key;
+ bool validUtf8 = true;
// type should follow first semicolon
const char* type = strchr(key, ';') + 1;
if (type == 0) continue;
+
+ const char* value = framevector[i]->value.pChar_value;
- // KVP_VALTYPE_UTF8_CHAR check must be first, since KVP_VALTYPE_ISO88591_CHAR is a substring of KVP_VALTYPE_UTF8_CHAR
- // similarly, KVP_VALTYPE_UTF16BE_WCHAR must be checked before KVP_VALTYPE_UTF16_WCHAR
+ // KVP_VALTYPE_UTF8_CHAR check must be first, since KVP_VALTYPE_ISO88591_CHAR
+ // is a substring of KVP_VALTYPE_UTF8_CHAR.
+ // Similarly, KVP_VALTYPE_UTF16BE_WCHAR must be checked before KVP_VALTYPE_UTF16_WCHAR
if (oscl_strncmp(type, KVP_VALTYPE_UTF8_CHAR, KVP_VALTYPE_UTF8_CHAR_LEN) == 0) {
- // utf8
- // pass through directly
- if (!client.handleStringTag(key, framevector[i]->value.pChar_value)) goto failure;
- } else if (oscl_strncmp(type, KVP_VALTYPE_ISO88591_CHAR, KVP_VALTYPE_ISO88591_CHAR_LEN) == 0) {
+ // utf8 can be passed through directly
+ // but first validate to make sure it is legal utf8
+ uint32 valid_chars;
+ validUtf8 = oscl_str_is_valid_utf8((const uint8 *)value, valid_chars);
+ if (validUtf8 && !client.handleStringTag(key, value)) goto failure;
+ }
+
+ // if the value is not valid utf8, then we will treat it as iso-8859-1
+ // and our native encoding detection will try to figure out what it is
+ if (oscl_strncmp(type, KVP_VALTYPE_ISO88591_CHAR, KVP_VALTYPE_ISO88591_CHAR_LEN) == 0
+ || !validUtf8) {
// iso-8859-1
// convert to utf8
// worse case is 2x inflation
- const unsigned char* src = (const unsigned char *)framevector[i]->value.pChar_value;
- char* temp = (char *)alloca(strlen(framevector[i]->value.pChar_value) * 2 + 1);
+ const unsigned char* src = (const unsigned char *)value;
+ char* temp = (char *)alloca(strlen(value) * 2 + 1);
if (temp) {
char* dest = temp;
unsigned int uch;
# define PAGESIZE 4096
# endif
+// library and function name to retrieve device-specific MIOs
+static const char* MIO_LIBRARY_NAME = "libopencorehal";
+static const char* VIDEO_MIO_FACTORY_NAME = "createVideoMio";
+typedef AndroidSurfaceOutput* (*VideoMioFactory)();
+
class PlayerDriver :
public OsclActiveObject,
public PVCommandStatusObserver,
int mRecentSeek;
bool mSeekComp;
bool mSeekPending;
+
+ void* mLibHandle;
};
PlayerDriver::PlayerDriver(PVPlayer* pvPlayer) :
mPlayerCapConfig = NULL;
mDownloadContextData = NULL;
+ // attempt to open device-specific library
+ mLibHandle = ::dlopen(MIO_LIBRARY_NAME, RTLD_NOW);
+
// start player thread
LOGV("start player thread");
createThreadEtc(PlayerDriver::startPlayerThread, this, "PV player");
PlayerDriver::~PlayerDriver()
{
LOGV("destructor");
+ if (mLibHandle != NULL) {
+ ::dlclose(mLibHandle);
+ }
}
PlayerCommand* PlayerDriver::dequeueCommand()
void PlayerDriver::handleSetVideoSurface(PlayerSetVideoSurface* ec)
{
int error = 0;
+ AndroidSurfaceOutput* mio = NULL;
+
+ // attempt to load device-specific video MIO
+ if (mLibHandle != NULL) {
+ VideoMioFactory f = (VideoMioFactory) ::dlsym(mLibHandle, VIDEO_MIO_FACTORY_NAME);
+ if (f != NULL) {
+ mio = f();
+ }
+ }
+
+ // if no device-specific MIO was created, use the generic one
+ if (mio == NULL) {
+ LOGW("Using generic video MIO");
+ mio = new AndroidSurfaceOutput();
+ }
+
+ // initialize the MIO parameters
+ status_t ret = mio->set(mPvPlayer, ec->surface());
+ if (ret != NO_ERROR) {
+ LOGE("Video MIO set failed");
+ commandFailed(ec);
+ delete mio;
+ return;
+ }
+ mVideoOutputMIO = mio;
- mVideoOutputMIO = new AndroidSurfaceOutput(mPvPlayer, ec->surface());
mVideoNode = PVMediaOutputNodeFactory::CreateMediaOutputNode(mVideoOutputMIO);
mVideoSink = new PVPlayerDataSinkPVMFNode;
LOCAL_LDLIBS := -lpthread
-LOCAL_SHARED_LIBRARIES := libopencoreplayer libutils libcutils libui libhardware libandroid_runtime libdrm1 libmedia libsgl libopencorecommon
+LOCAL_SHARED_LIBRARIES := libopencoreplayer libutils libcutils libui libhardware_legacy libandroid_runtime libdrm1 libmedia libsgl libopencorecommon
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -ldl