aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-02-10 15:43:59 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-02-10 15:43:59 -0800
commit4170b2688824896bd659e66afe41c4e65f8a9c8b (patch)
tree7190b917de3836bfb1161198e77ec01f163de686
parent1d9c7dff7d4022e4a8f5553a2e79ce586fcb3da5 (diff)
downloadopencore-4170b2688824896bd659e66afe41c4e65f8a9c8b.tar.gz
auto import from //branches/cupcake/...@130745
-rw-r--r--Android.mk35
-rw-r--r--Config.mk51
-rw-r--r--android/android_surface_output.cpp367
-rw-r--r--android/android_surface_output.h128
-rw-r--r--android/author/PVMediaRecorder.cpp17
-rw-r--r--android/author/android_camera_input.cpp115
-rw-r--r--android/author/android_camera_input.h11
-rw-r--r--android/author/authordriver.cpp132
-rw-r--r--android/author/authordriver.h20
-rw-r--r--android/mediascanner.cpp9
-rw-r--r--android/metadatadriver.cpp4
-rw-r--r--android/playerdriver.cpp109
-rw-r--r--android/samples/android_surface_output_fb.cpp318
-rw-r--r--android/samples/android_surface_output_fb.h79
-rw-r--r--engines/author/src/pvaenodeutility.cpp76
-rw-r--r--nodes/pvfileoutputnode/include/pvmf_fileoutput_config.h9
-rw-r--r--nodes/pvfileoutputnode/src/pvmf_fileoutput_node.cpp31
-rw-r--r--nodes/pvfileoutputnode/src/pvmf_fileoutput_node.h1
-rw-r--r--nodes/pvmediainputnode/src/pvmf_media_input_node_outport.cpp1
-rw-r--r--nodes/pvmp4ffcomposernode/include/pvmp4ffcn_clipconfig.h13
-rw-r--r--nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.cpp61
-rw-r--r--nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.h2
-rw-r--r--nodes/pvomxvideodecnode/src/pvmf_omx_videodec_node.cpp22
-rw-r--r--nodes/pvomxvideoencnode/src/pvmf_omx_videoenc_node.cpp27
-rw-r--r--oscl/oscl/osclio/src/oscl_file_native.cpp255
-rw-r--r--oscl/oscl/osclio/src/oscl_file_native.h21
26 files changed, 1119 insertions, 795 deletions
diff --git a/Android.mk b/Android.mk
index b7ba29049..ee47dd1c3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,38 +1,15 @@
ifneq ($(BUILD_WITHOUT_PV),true)
-LOCAL_PATH := $(call my-dir)
-PV_TOP := $(LOCAL_PATH)
-
-include $(CLEAR_VARS)
-PV_CFLAGS := -Wno-non-virtual-dtor -DENABLE_MEMORY_PLAYBACK
+LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-FORMAT := nj
-
-PV_COPY_HEADERS_TO := libpv
-
-PV_INCLUDES := \
- $(PV_TOP)/android \
- $(PV_TOP)/extern_libs_v2/khronos/openmax/include \
- $(PV_TOP)/engines/common/include \
- $(PV_TOP)/engines/player/config/linux_nj \
- $(PV_TOP)/engines/player/include \
- $(PV_TOP)/nodes/pvmediaoutputnode/include \
- $(PV_TOP)/nodes/pvdownloadmanagernode/config/opencore \
- $(PV_TOP)/pvmi/pvmf/include \
- $(PV_TOP)/fileformats/mp4/parser/config/opencore \
- $(PV_TOP)/oscl/oscl/config/linux_nj \
- $(PV_TOP)/oscl/oscl/config/shared \
- $(PV_TOP)/engines/author/include \
- $(PV_TOP)/android/drm/oma1/src \
- $(TARGET_OUT_HEADERS)/$(PV_COPY_HEADERS_TO)
+# Set up the PV variables.
+include $(LOCAL_PATH)/Config.mk
-ALTERNATE_CONFIG := $(if $(wildcard vendor/pv/pvplayer.conf),true)
-ifneq ($(ALTERNATE_CONFIG), true)
+# Install the default configuration file
+# if no value-add configuration is present.
+ifneq ($(VALUE_ADD),1)
$(call add-prebuilt-files, ETC, pvplayer.conf)
-else
-VALUE_ADD := 1
-PV_CFLAGS += -DPV_USE_VALUE_ADD=1
endif
include $(PV_TOP)/pvcommon/Android.mk
diff --git a/Config.mk b/Config.mk
new file mode 100644
index 000000000..c5f74231c
--- /dev/null
+++ b/Config.mk
@@ -0,0 +1,51 @@
+ifndef EXTERNAL_OPENCORE_CONFIG_ONCE
+ # This is the first attempt to include this file.
+ EXTERNAL_OPENCORE_CONFIG_ONCE := true
+
+ PV_TOP := $(my-dir)
+ PV_CFLAGS := -Wno-non-virtual-dtor -DENABLE_SHAREDFD_PLAYBACK
+ FORMAT := nj
+ PV_COPY_HEADERS_TO := libpv
+
+ alternate_config := $(if $(wildcard vendor/pv/pvplayer.conf),true)
+ ifeq ($(alternate_config), true)
+ VALUE_ADD := 1
+ PV_CFLAGS += -DPV_USE_VALUE_ADD=1
+ else
+ VALUE_ADD :=
+ endif
+ alternate_config :=
+
+ PV_INCLUDES := \
+ $(PV_TOP)/android \
+ $(PV_TOP)/extern_libs_v2/khronos/openmax/include \
+ $(PV_TOP)/engines/common/include \
+ $(PV_TOP)/engines/player/config/linux_nj \
+ $(PV_TOP)/engines/player/include \
+ $(PV_TOP)/nodes/pvmediaoutputnode/include \
+ $(PV_TOP)/nodes/pvdownloadmanagernode/config/opencore \
+ $(PV_TOP)/pvmi/pvmf/include \
+ $(PV_TOP)/fileformats/mp4/parser/config/opencore \
+ $(PV_TOP)/oscl/oscl/config/linux_nj \
+ $(PV_TOP)/oscl/oscl/config/shared \
+ $(PV_TOP)/engines/author/include \
+ $(PV_TOP)/android/drm/oma1/src \
+ $(TARGET_OUT_HEADERS)/$(PV_COPY_HEADERS_TO)
+
+ # Stash these values for the next includer of this file.
+ OPENCORE.PV_TOP := $(PV_TOP)
+ OPENCORE.PV_CFLAGS := $(PV_CFLAGS)
+ OPENCORE.FORMAT := $(FORMAT)
+ OPENCORE.PV_COPY_HEADERS_TO := $(PV_COPY_HEADERS_TO)
+ OPENCORE.VALUE_ADD := $(VALUE_ADD)
+ OPENCORE.PV_INCLUDES := $(PV_INCLUDES)
+else
+ # This file has already been included by someone, so we can
+ # use the precomputed values.
+ PV_TOP := $(OPENCORE.PV_TOP)
+ PV_CFLAGS := $(OPENCORE.PV_CFLAGS)
+ FORMAT := $(OPENCORE.FORMAT)
+ PV_COPY_HEADERS_TO := $(OPENCORE.PV_COPY_HEADERS_TO)
+ VALUE_ADD := $(OPENCORE.VALUE_ADD)
+ PV_INCLUDES := $(OPENCORE.PV_INCLUDES)
+endif
diff --git a/android/android_surface_output.cpp b/android/android_surface_output.cpp
index f42701f34..5fa87609b 100644
--- a/android/android_surface_output.cpp
+++ b/android/android_surface_output.cpp
@@ -19,6 +19,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "VideoMIO"
#include <utils/Log.h>
+#include <ui/ISurface.h>
#include "android_surface_output.h"
#include <media/PVPlayer.h>
@@ -29,28 +30,14 @@
#include "oscl_dll.h"
-#define PLATFORM_PRIVATE_PMEM 1
-
// Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT()
//The factory functions.
#include "oscl_mem.h"
-#include <cutils/properties.h>
-
-#if HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
-
using namespace android;
-static const char* pmem_adsp = "/dev/pmem_adsp";
-static const char* pmem = "/dev/pmem";
-
-// This class implements the reference media IO for file output
-// This class constitutes the Media IO component
-
OSCL_EXPORT_REF AndroidSurfaceOutput::AndroidSurfaceOutput() :
OsclTimerObject(OsclActiveObject::EPriorityNominal, "androidsurfaceoutput")
{
@@ -59,21 +46,15 @@ OSCL_EXPORT_REF AndroidSurfaceOutput::AndroidSurfaceOutput() :
iColorConverter = NULL;
mInitialized = false;
mEmulation = false;
- mHardwareCodec = false;
mPvPlayer = NULL;
-
- // running in emulation?
- char value[PROPERTY_VALUE_MAX];
- if (property_get("ro.kernel.qemu", value, 0)) {
- LOGV("Emulation mode - using software codecs");
- mEmulation = true;
- }
+ mEmulation = false;
}
-status_t AndroidSurfaceOutput::set(PVPlayer* pvPlayer, const sp<ISurface>& surface)
+status_t AndroidSurfaceOutput::set(PVPlayer* pvPlayer, const sp<ISurface>& surface, bool emulation)
{
mPvPlayer = pvPlayer;
mSurface = surface;
+ mEmulation = emulation;
return NO_ERROR;
}
@@ -83,9 +64,6 @@ void AndroidSurfaceOutput::initData()
iVideoFormat=PVMF_FORMAT_UNKNOWN;
resetVideoParameterFlags();
- // hardware specific information
- iVideoSubFormat = PVMF_FORMAT_UNKNOWN;
-
iCommandCounter=0;
iLogger=NULL;
iCommandResponseQueue.reserve(5);
@@ -103,18 +81,13 @@ void AndroidSurfaceOutput::ResetData()
//reset all the received media parameters.
iVideoFormatString="";
- iVideoFormat=PVMF_FORMAT_UNKNOWN;
+ iVideoFormat = PVMF_FORMAT_UNKNOWN;
resetVideoParameterFlags();
}
void AndroidSurfaceOutput::resetVideoParameterFlags()
{
iVideoParameterFlags = VIDEO_PARAMETERS_INVALID;
-
- // FIXME: Hack required because subformat is not passed when
- // hardware accelerator is not present.
- // emulator never uses subformat
- if (mEmulation) iVideoParameterFlags |= VIDEO_SUBFORMAT_VALID;
}
bool AndroidSurfaceOutput::checkVideoParameterFlags()
@@ -139,7 +112,7 @@ void AndroidSurfaceOutput::Cleanup()
}
// We'll close frame buf and delete here for now.
- CloseFrameBuf();
+ closeFrameBuf();
}
OSCL_EXPORT_REF AndroidSurfaceOutput::~AndroidSurfaceOutput()
@@ -313,6 +286,11 @@ PVMFCommandId AndroidSurfaceOutput::Start(const OsclAny* aContext)
return cmdid;
}
+// post the last video frame to refresh screen after pause
+void AndroidSurfaceOutput::postLastFrame()
+{
+ mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
+}
PVMFCommandId AndroidSurfaceOutput::Pause(const OsclAny* aContext)
{
@@ -328,13 +306,7 @@ PVMFCommandId AndroidSurfaceOutput::Pause(const OsclAny* aContext)
iState=STATE_PAUSED;
status=PVMFSuccess;
-
- // post last buffer to prevent stale data
- if (mHardwareCodec) {
- mSurface->postBuffer(mOffset);
- } else {
- mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
- }
+ postLastFrame();
break;
default:
@@ -424,9 +396,10 @@ PVMFCommandId AndroidSurfaceOutput::Stop(const OsclAny* aContext)
case STATE_PAUSED:
#ifdef PERFORMANCE_MEASUREMENTS_ENABLED
- PVOmapVideoProfile.MarkEndTime();
- PVOmapVideoProfile.PrintStats();
- PVOmapVideoProfile.Reset();
+ // FIXME: This should be moved to OMAP library
+ PVOmapVideoProfile.MarkEndTime();
+ PVOmapVideoProfile.PrintStats();
+ PVOmapVideoProfile.Reset();
#endif
iState=STATE_INITIALIZED;
@@ -488,7 +461,7 @@ void AndroidSurfaceOutput::ThreadLogon()
{
if(iState==STATE_IDLE)
{
- iLogger = PVLogger::GetLoggerObject("PVOmapVideo");
+ iLogger = PVLogger::GetLoggerObject("VideoMIO");
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::ThreadLogon() called"));
AddToScheduler();
iState=STATE_LOGGED_ON;
@@ -611,7 +584,7 @@ PVMFCommandId AndroidSurfaceOutput::writeAsync(uint8 aFormatType, int32 aFormatI
//printf("V WriteAsync { seq=%d, ts=%d }\n", data_header_info.seq_num, data_header_info.timestamp);
// Call playback to send data to IVA for Color Convert
- status = WriteFrameBuf(aData, aDataLen, data_header_info);
+ status = writeFrameBuf(aData, aDataLen, data_header_info);
PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
(0,"AndroidSurfaceOutput::writeAsync: Playback Progress - frame %d",iFrameNumber++));
@@ -845,6 +818,8 @@ LOGV("VIDEO SUBFORMAT SET TO %d\n",iVideoSubFormat);
return;
}
}
+
+ // if initialization is complete, update the app display info
initCheck();
}
@@ -866,57 +841,6 @@ PVMFStatus AndroidSurfaceOutput::verifyParametersSync (PvmiMIOSession aSession,
}
//
-// For active timing support
-//
-OSCL_EXPORT_REF PVMFStatus AndroidSurfaceOutput_ActiveTimingSupport::SetClock(OsclClock *clockVal)
-{
- iClock=clockVal;
- return PVMFSuccess;
-}
-
-OSCL_EXPORT_REF void AndroidSurfaceOutput_ActiveTimingSupport::addRef()
-{
-}
-
-OSCL_EXPORT_REF void AndroidSurfaceOutput_ActiveTimingSupport::removeRef()
-{
-}
-
-OSCL_EXPORT_REF bool AndroidSurfaceOutput_ActiveTimingSupport::queryInterface(const PVUuid& aUuid, PVInterface*& aInterface)
-{
- aInterface=NULL;
- PVUuid uuid;
- queryUuid(uuid);
- if (uuid==aUuid)
- {
- PvmiClockExtensionInterface* myInterface = OSCL_STATIC_CAST(PvmiClockExtensionInterface*,this);
- aInterface = OSCL_STATIC_CAST(PVInterface*, myInterface);
- return true;
- }
- return false;
-}
-
-void AndroidSurfaceOutput_ActiveTimingSupport::queryUuid(PVUuid& uuid)
-{
- uuid=PvmiClockExtensionInterfaceUuid;
-}
-
-uint32 AndroidSurfaceOutput_ActiveTimingSupport::GetDelayMsec(PVMFTimestamp& aTs)
-{
- if (iClock)
- {
- uint32 currentTime=0;
- bool overflow=false;
- iClock->GetCurrentTime32(currentTime, overflow, OSCLCLOCK_MSEC);
- if(aTs>currentTime)
- {
- return aTs-currentTime;
- }
- }
- return 0;
-}
-
-//
// Private section
//
@@ -949,7 +873,7 @@ OSCL_EXPORT_REF bool AndroidSurfaceOutput::initCheck()
return mInitialized;
// release resources if previously initialized
- CloseFrameBuf();
+ closeFrameBuf();
// reset flags in case display format changes in the middle of a stream
resetVideoParameterFlags();
@@ -961,150 +885,60 @@ OSCL_EXPORT_REF bool AndroidSurfaceOutput::initCheck()
int frameHeight = iVideoHeight;
int frameSize;
- // FIXME: Need to move hardware specific code to partners directory
-
-#if HAVE_ANDROID_OS
- // Dream hardware codec uses semi-planar format
- if (!mEmulation && iVideoSubFormat == PVMF_YUV420_SEMIPLANAR_YVU) {
- LOGV("using hardware codec");
- mHardwareCodec = true;
- } else
-#endif
-
- // software codec
- {
- LOGV("using software codec");
-
-#if HAVE_ANDROID_OS
- // emulation
- if (mEmulation)
-#endif
- {
- // RGB-565 frames are 2 bytes/pixel
- displayWidth = (displayWidth + 1) & -2;
- displayHeight = (displayHeight + 1) & -2;
- frameWidth = (frameWidth + 1) & -2;
- frameHeight = (frameHeight + 1) & -2;
- frameSize = frameWidth * frameHeight * 2;
-
- // create frame buffer heap and register with surfaceflinger
- mFrameHeap = new MemoryHeapBase(frameSize * kBufferCount);
- if (mFrameHeap->heapID() < 0) {
- LOGE("Error creating frame buffer heap");
- return false;
- }
- mSurface->registerBuffers(displayWidth, displayHeight, frameWidth, frameHeight, PIXEL_FORMAT_RGB_565, mFrameHeap);
-
- // create frame buffers
- for (int i = 0; i < kBufferCount; i++) {
- mFrameBuffers[i] = i * frameSize;
- }
-
- // initialize software color converter
- iColorConverter = ColorConvert16::NewL();
- iColorConverter->Init(displayWidth, displayHeight, frameWidth, displayWidth, displayHeight, displayWidth, CCROTATE_NONE);
- iColorConverter->SetMemHeight(frameHeight);
- iColorConverter->SetMode(1);
- }
-
-#if HAVE_ANDROID_OS
- // FIXME: hardware specific
- else {
- // YUV420 frames are 1.5 bytes/pixel
- frameSize = (frameWidth * frameHeight * 3) / 2;
-
- // create frame buffer heap
- sp<MemoryHeapBase> master = new MemoryHeapBase(pmem_adsp, frameSize * kBufferCount);
- if (master->heapID() < 0) {
- LOGE("Error creating frame buffer heap");
- return false;
- }
- master->setDevice(pmem);
- mHeapPmem = new MemoryHeapPmem(master, 0);
- mHeapPmem->slap();
- master.clear();
- mSurface->registerBuffers(displayWidth, displayHeight, frameWidth, frameHeight, PIXEL_FORMAT_YCbCr_420_SP, mHeapPmem);
-
- // create frame buffers
- for (int i = 0; i < kBufferCount; i++) {
- mFrameBuffers[i] = i * frameSize;
- }
- }
-#endif
-
- LOGV("video = %d x %d", displayWidth, displayHeight);
- LOGV("frame = %d x %d", frameWidth, frameHeight);
- LOGV("frame #bytes = %d", frameSize);
+ // RGB-565 frames are 2 bytes/pixel
+ displayWidth = (displayWidth + 1) & -2;
+ displayHeight = (displayHeight + 1) & -2;
+ frameWidth = (frameWidth + 1) & -2;
+ frameHeight = (frameHeight + 1) & -2;
+ frameSize = frameWidth * frameHeight * 2;
+
+ // create frame buffer heap and register with surfaceflinger
+ mFrameHeap = new MemoryHeapBase(frameSize * kBufferCount);
+ if (mFrameHeap->heapID() < 0) {
+ LOGE("Error creating frame buffer heap");
+ return false;
+ }
+
+ ISurface::BufferHeap buffers(displayWidth, displayHeight,
+ frameWidth, frameHeight, PIXEL_FORMAT_RGB_565, mFrameHeap);
+ mSurface->registerBuffers(buffers);
- // register frame buffers with SurfaceFlinger
- mFrameBufferIndex = 0;
- mInitialized = true;
+ // create frame buffers
+ for (int i = 0; i < kBufferCount; i++) {
+ mFrameBuffers[i] = i * frameSize;
}
- // update app
- mPvPlayer->sendEvent(MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
+ // initialize software color converter
+ iColorConverter = ColorConvert16::NewL();
+ iColorConverter->Init(displayWidth, displayHeight, frameWidth, displayWidth, displayHeight, displayWidth, CCROTATE_NONE);
+ iColorConverter->SetMemHeight(frameHeight);
+ iColorConverter->SetMode(1);
+
+ LOGV("video = %d x %d", displayWidth, displayHeight);
+ LOGV("frame = %d x %d", frameWidth, frameHeight);
+ LOGV("frame #bytes = %d", frameSize);
+ // register frame buffers with SurfaceFlinger
+ mFrameBufferIndex = 0;
+ mInitialized = true;
+ mPvPlayer->sendEvent(MEDIA_SET_VIDEO_SIZE, iVideoDisplayWidth, iVideoDisplayHeight);
return mInitialized;
}
-OSCL_EXPORT_REF PVMFStatus AndroidSurfaceOutput::WriteFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info)
+OSCL_EXPORT_REF PVMFStatus AndroidSurfaceOutput::writeFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info)
{
- if (mSurface != 0) {
-
- // initalized?
- if (!mInitialized) {
- LOGV("initializing for hardware");
- // FIXME: Check for hardware codec - move to partners directory
- if (iVideoSubFormat != PVMF_YUV420_SEMIPLANAR_YVU) return PVMFFailure;
- LOGV("got expected format");
- LOGV("private data pointer is 0%p\n", data_header_info.private_data_ptr);
-
- uint32 fd;
- if (!getPmemFd(data_header_info.private_data_ptr, &fd)) {
- LOGE("Error getting pmem heap from private_data_ptr");
- return PVMFFailure;
- }
- sp<MemoryHeapBase> master = (MemoryHeapBase *) fd;
- master->setDevice(pmem);
- mHeapPmem = new MemoryHeapPmem(master, 0);
- mHeapPmem->slap();
- master.clear();
-
- // register frame buffers with SurfaceFlinger
- mSurface->registerBuffers(iVideoDisplayWidth, iVideoDisplayHeight, iVideoWidth, iVideoHeight, PIXEL_FORMAT_YCbCr_420_SP, mHeapPmem);
-
- mInitialized = true;
- }
-
- // hardware codec
- if (mHardwareCodec) {
- // get pmem offset
- if (!getOffset(data_header_info.private_data_ptr, &mOffset)) {
- LOGE("Error getting pmem offset from private_data_ptr");
- return PVMFFailure;
- }
- // post to SurfaceFlinger
- mSurface->postBuffer(mOffset);
- }
+ if (mSurface == 0) return PVMFFailure;
- // software codec
- else {
- if (mEmulation) {
- iColorConverter->Convert(aData, static_cast<uint8*>(mFrameHeap->base()) + mFrameBuffers[mFrameBufferIndex]);
- } else {
- convertFrame(aData, static_cast<uint8*>(mHeapPmem->base()) + mFrameBuffers[mFrameBufferIndex], aDataLen);
- }
- // post to SurfaceFlinger
- if (++mFrameBufferIndex == kBufferCount) mFrameBufferIndex = 0;
- mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
- }
- }
+ iColorConverter->Convert(aData, static_cast<uint8*>(mFrameHeap->base()) + mFrameBuffers[mFrameBufferIndex]);
+ // post to SurfaceFlinger
+ if (++mFrameBufferIndex == kBufferCount) mFrameBufferIndex = 0;
+ mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
return PVMFSuccess;
}
-OSCL_EXPORT_REF void AndroidSurfaceOutput::CloseFrameBuf()
+OSCL_EXPORT_REF void AndroidSurfaceOutput::closeFrameBuf()
{
- LOGV("CloseFrameBuf");
+ LOGV("closeFrameBuf");
if (!mInitialized) return;
mInitialized = false;
@@ -1123,8 +957,6 @@ OSCL_EXPORT_REF void AndroidSurfaceOutput::CloseFrameBuf()
// free heaps
LOGV("free mFrameHeap");
mFrameHeap.clear();
- LOGV("free mHeapPmem");
- mHeapPmem.clear();
// free color converter
if (iColorConverter != 0)
@@ -1141,78 +973,3 @@ OSCL_EXPORT_REF bool AndroidSurfaceOutput::GetVideoSize(int *w, int *h) {
*h = iVideoDisplayHeight;
return iVideoDisplayWidth != 0 && iVideoDisplayHeight != 0;
}
-
-bool AndroidSurfaceOutput::getPmemFd(OsclAny *private_data_ptr, uint32 *pmemFD)
-{
- PLATFORM_PRIVATE_LIST *listPtr = NULL;
- PLATFORM_PRIVATE_PMEM_INFO *pmemInfoPtr = NULL;
- bool returnType = false;
- LOGV("in getPmemfd - privatedataptr=%p\n",private_data_ptr);
- listPtr = (PLATFORM_PRIVATE_LIST*) private_data_ptr;
-
- for (uint32 i=0;i<listPtr->nEntries;i++)
- {
- if(listPtr->entryList->type == PLATFORM_PRIVATE_PMEM)
- {
- LOGV("in getPmemfd - entry type = %d\n",listPtr->entryList->type);
- pmemInfoPtr = (PLATFORM_PRIVATE_PMEM_INFO*) (listPtr->entryList->entry);
- returnType = true;
- if(pmemInfoPtr){
- *pmemFD = pmemInfoPtr->pmem_fd;
- LOGV("in getPmemfd - pmemFD = %d\n",*pmemFD);
- }
- break;
- }
- }
- return returnType;
-}
-
-bool AndroidSurfaceOutput::getOffset(OsclAny *private_data_ptr, uint32 *offset)
-{
- PLATFORM_PRIVATE_LIST *listPtr = NULL;
- PLATFORM_PRIVATE_PMEM_INFO *pmemInfoPtr = NULL;
- bool returnType = false;
-
- listPtr = (PLATFORM_PRIVATE_LIST*) private_data_ptr;
- LOGV("in getOffset: listPtr = %p\n",listPtr);
- for (uint32 i=0;i<listPtr->nEntries;i++)
- {
- if(listPtr->entryList->type == PLATFORM_PRIVATE_PMEM)
- {
- LOGV(" in getOffset: entrytype = %d\n",listPtr->entryList->type);
-
- pmemInfoPtr = (PLATFORM_PRIVATE_PMEM_INFO*) (listPtr->entryList->entry);
- returnType = true;
- if(pmemInfoPtr){
- *offset = pmemInfoPtr->offset;
- LOGV("in getOffset: offset = %d\n",*offset);
- }
- break;
- }
- }
- return returnType;
-}
-
-static inline void* byteOffset(void* p, size_t offset) { return (void*)((uint8_t*)p + offset); }
-
-void AndroidSurfaceOutput::convertFrame(void* src, void* dst, size_t len)
-{
- // copy the Y plane
- size_t y_plane_size = iVideoWidth * iVideoHeight;
- //LOGV("len=%u, y_plane_size=%u", len, y_plane_size);
- memcpy(dst, src, y_plane_size + iVideoWidth);
-
- // re-arrange U's and V's
- uint16_t* pu = (uint16_t*)byteOffset(src, y_plane_size);
- uint16_t* pv = (uint16_t*)byteOffset(pu, y_plane_size / 4);
- uint32_t* p = (uint32_t*)byteOffset(dst, y_plane_size);
-
- int count = y_plane_size / 8;
- //LOGV("u = %p, v = %p, p = %p, count = %d", pu, pv, p, count);
- do {
- uint32_t u = *pu++;
- uint32_t v = *pv++;
- *p++ = ((u & 0xff) << 8) | ((u & 0xff00) << 16) | (v & 0xff) | ((v & 0xff00) << 8);
- } while (--count);
-}
-
diff --git a/android/android_surface_output.h b/android/android_surface_output.h
index 2c2008b3b..74e459ee8 100644
--- a/android/android_surface_output.h
+++ b/android/android_surface_output.h
@@ -32,6 +32,7 @@
#include "pvprofile.h"
#endif
+// FIXME: Move to OMAP library
// Linux and Kernel Includes for Frame Buffer
#include <fcntl.h>
#include <stdint.h>
@@ -49,42 +50,13 @@
// SurfaceFlinger
#include <ui/ISurface.h>
-// pmem interprocess shared memory support
+// interprocess shared memory support
#include <utils/MemoryBase.h>
#include <utils/MemoryHeapBase.h>
-#include <utils/MemoryHeapPmem.h>
// color converter
#include "cczoomrotation16.h"
-// FIXME: Dream specific
-typedef struct PLATFORM_PRIVATE_PMEM_INFO
-{
- /* pmem file descriptor */
- uint32 pmem_fd;
-
- uint32 offset;
-} PLATFORM_PRIVATE_PMEM_INFO;
-
-typedef struct PLATFORM_PRIVATE_ENTRY
-{
- /* Entry type */
- uint32 type;
-
- /* Pointer to platform specific entry */
- OsclAny* entry;
-} PLATFORM_PRIVATE_ENTRY;
-
-typedef struct PLATFORM_PRIVATE_LIST
-{
- /* Number of entries */
- uint32 nEntries;
-
- /* Pointer to array of platform specific entries *
- * Contiguous block of PLATFORM_PRIVATE_ENTRY elements */
- PLATFORM_PRIVATE_ENTRY* entryList;
-} PLATFORM_PRIVATE_LIST;
-
// define bits, mask and validity check for video parameters
#define VIDEO_PARAMETERS_INVALID 0
#define VIDEO_SUBFORMAT_VALID (1 << 0)
@@ -107,61 +79,30 @@ class AndroidSurfaceOutput;
using namespace android;
-// A test feature for simulating a component with active timing.
-class AndroidSurfaceOutput_ActiveTimingSupport:public PvmiClockExtensionInterface
-{
-public:
-
- AndroidSurfaceOutput_ActiveTimingSupport(uint32 limit)
- :iQueueLimit(limit)
- ,iClock(NULL)
- {}
- ~AndroidSurfaceOutput_ActiveTimingSupport()
- {}
-
- //from PvmiClockExtensionInterface
- OSCL_IMPORT_REF PVMFStatus SetClock(OsclClock *clockVal) ;
-
- //from PVInterface
- OSCL_IMPORT_REF void addRef() ;
- OSCL_IMPORT_REF void removeRef() ;
- OSCL_IMPORT_REF bool queryInterface(const PVUuid& uuid, PVInterface*& iface) ;
-
- void queryUuid(PVUuid& uuid);
-
- uint32 GetDelayMsec(PVMFTimestamp&);
-
- uint32 iQueueLimit;
-
- OsclClock* iClock;
-};
-
-
-typedef void (*frame_decoded_f)(void *cookie, int width, int height, int pitch, int format, uint8* data);
+// FIXME: Not used?
+// typedef void (*frame_decoded_f)(void *cookie, int width, int height, int pitch, int format, uint8* data);
// This class implements the reference media IO for file output.
// This class constitutes the Media IO component
-class AndroidSurfaceOutput : public OsclTimerObject
- ,public PvmiMIOControl
- ,public PvmiMediaTransfer
- ,public PvmiCapabilityAndConfig
-
+class AndroidSurfaceOutput : public OsclTimerObject, public PvmiMIOControl,
+ public PvmiMediaTransfer, public PvmiCapabilityAndConfig
{
public:
- OSCL_IMPORT_REF AndroidSurfaceOutput();
+ AndroidSurfaceOutput();
// parameter initialization
- virtual status_t set(android::PVPlayer* pvPlayer, const sp<ISurface>& surface);
+ virtual status_t set(android::PVPlayer* pvPlayer, const sp<ISurface>& surface, bool emulation);
- // For Frame Buffer
- OSCL_IMPORT_REF bool initCheck();
- OSCL_IMPORT_REF PVMFStatus WriteFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info);
- OSCL_IMPORT_REF void CloseFrameBuf();
+ // For frame buffer
+ virtual bool initCheck();
+ virtual PVMFStatus writeFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info);
+ virtual void postLastFrame();
+ virtual void closeFrameBuf();
- OSCL_IMPORT_REF ~AndroidSurfaceOutput();
+ virtual ~AndroidSurfaceOutput();
- OSCL_IMPORT_REF bool GetVideoSize(int *w, int *h);
+ bool GetVideoSize(int *w, int *h);
// APIs from PvmiMIOControl
@@ -210,20 +151,20 @@ public:
void useMemoryAllocators(OsclMemAllocator* write_alloc=NULL);
PVMFCommandId writeAsync(uint8 format_type, int32 format_index,
- uint8* data, uint32 data_len,
- const PvmiMediaXferHeader& data_header_info,
- OsclAny* aContext=NULL);
+ uint8* data, uint32 data_len,
+ const PvmiMediaXferHeader& data_header_info,
+ OsclAny* aContext=NULL);
void writeComplete(PVMFStatus aStatus,
- PVMFCommandId write_cmd_id,
- OsclAny* aContext);
+ PVMFCommandId write_cmd_id,
+ OsclAny* aContext);
- PVMFCommandId readAsync(uint8* data, uint32 max_data_len,
- OsclAny* aContext=NULL,
- int32* formats=NULL, uint16 num_formats=0);
+ PVMFCommandId readAsync(uint8* data, uint32 max_data_len,
+ OsclAny* aContext=NULL,
+ int32* formats=NULL, uint16 num_formats=0);
void readComplete(PVMFStatus aStatus, PVMFCommandId read_cmd_id, int32 format_index,
- const PvmiMediaXferHeader& data_header_info, OsclAny* aContext);
+ const PvmiMediaXferHeader& data_header_info, OsclAny* aContext);
void statusUpdate(uint32 status_flags);
@@ -236,31 +177,31 @@ public:
void setObserver (PvmiConfigAndCapabilityCmdObserver* aObserver);
PVMFStatus getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier,
- PvmiKvp*& aParameters, int& num_parameter_elements, PvmiCapabilityContext aContext);
+ PvmiKvp*& aParameters, int& num_parameter_elements, PvmiCapabilityContext aContext);
PVMFStatus releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements);
void createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext);
void setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext,
- PvmiKvp* aParameters, int num_parameter_elements);
+ PvmiKvp* aParameters, int num_parameter_elements);
void DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext);
void setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters,
- int num_elements, PvmiKvp * & aRet_kvp);
+ int num_elements, PvmiKvp * & aRet_kvp);
PVMFCommandId setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters,
- int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context=NULL);
+ int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context=NULL);
uint32 getCapabilityMetric (PvmiMIOSession aSession);
PVMFStatus verifyParametersSync (PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements);
+ // FIXME: Not used?
+ // void SetFrameDecodedCallback(frame_decoded_f f, void *cookie);
- void SetFrameDecodedCallback(frame_decoded_f f, void *cookie);
-
-private:
+protected:
void initData();
void resetVideoParameterFlags();
bool checkVideoParameterFlags();
@@ -273,9 +214,6 @@ private:
void Cleanup();
void ResetData();
- bool getPmemFd(OsclAny *private_data_ptr, uint32 *pmemFD);
- bool getOffset(OsclAny *private_data_ptr, uint32 *offset);
-
PvmiMediaTransfer* iPeer;
// The PvmiMIOControl class observer.
@@ -367,10 +305,6 @@ private:
sp<MemoryHeapBase> mFrameHeap;
size_t mFrameBuffers[kBufferCount];
- sp<MemoryHeapPmem> mHeapPmem;
- bool mHardwareCodec;
- uint32 mOffset;
-
void convertFrame(void* src, void* dst, size_t len);
#ifdef PERFORMANCE_MEASUREMENTS_ENABLED
diff --git a/android/author/PVMediaRecorder.cpp b/android/author/PVMediaRecorder.cpp
index 1a5d8e4db..652d67f75 100644
--- a/android/author/PVMediaRecorder.cpp
+++ b/android/author/PVMediaRecorder.cpp
@@ -310,7 +310,22 @@ status_t PVMediaRecorder::reset()
LOGE("failed to construct an author command");
return UNKNOWN_ERROR;
}
- return mAuthorDriverWrapper->enqueueCommand(ac, 0, 0);
+ status_t ret = mAuthorDriverWrapper->enqueueCommand(ac, 0, 0);
+ if (ret != OK) {
+ LOGE("failed to do reset(%d)", ret);
+ return UNKNOWN_ERROR;
+ }
+ ret = mAuthorDriverWrapper->enqueueCommand(new author_command(AUTHOR_REMOVE_VIDEO_SOURCE), 0, 0);
+ if (ret != OK) {
+ LOGE("failed to remove video source(%d)", ret);
+ return UNKNOWN_ERROR;
+ }
+ ret = mAuthorDriverWrapper->enqueueCommand(new author_command(AUTHOR_REMOVE_AUDIO_SOURCE), 0, 0);
+ if (ret != OK) {
+ LOGE("failed to remove audio source(%d)", ret);
+ return UNKNOWN_ERROR;
+ }
+ return ret;
}
status_t PVMediaRecorder::close()
diff --git a/android/author/android_camera_input.cpp b/android/author/android_camera_input.cpp
index d6e3bfca7..66d09f07e 100644
--- a/android/author/android_camera_input.cpp
+++ b/android/author/android_camera_input.cpp
@@ -55,17 +55,40 @@ AndroidCameraInput::AndroidCameraInput()
mFrameRate = DEFAULT_FRAME_RATE;
mCamera = NULL;
mHeap = 0;
+
+ // FIXME:
+ // mFrameRefCount is redundant. iSendMediaData.empty() can be used to
+ // determine if there are any frames pending in the encoder.
mFrameRefCount = 0;
mFlags = 0;
iFrameQueue.reserve(5);
iFrameQueueMutex.Create();
}
+void AndroidCameraInput::ReleaseQueuedFrames()
+{
+ LOGV("ReleaseQueuedFrames");
+ iFrameQueueMutex.Lock();
+ while (!iFrameQueue.empty()) {
+ AndroidCameraInputMediaData data = iFrameQueue[0];
+ iFrameQueue.erase(iFrameQueue.begin());
+#if (LOG_NDEBUG == 0)
+ ssize_t offset = 0;
+ size_t size = 0;
+ sp<IMemoryHeap> heap = data.iFrameBuffer->getMemory(&offset, &size);
+ LOGD("writeComplete: ID = %d, base = %p, offset = %p, size = %d ReleaseQueuedFrames", heap->getHeapID(), heap->base(), offset, size);
+#endif
+ mCamera->releaseRecordingFrame(data.iFrameBuffer);
+ }
+ iFrameQueueMutex.Unlock();
+}
+
AndroidCameraInput::~AndroidCameraInput()
{
LOGV("destructor");
if (mCamera != NULL) {
- mCamera->setFrameCallback(NULL, this, FRAME_CALLBACK_FLAG_NOOP);
+ mCamera->setRecordingCallback(NULL, this);
+ ReleaseQueuedFrames();
if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
LOGV("camera was cold when we started, stopping preview");
mCamera->stopPreview();
@@ -350,7 +373,7 @@ void AndroidCameraInput::setPeer(PvmiMediaTransfer* aPeer)
if (iPeer) {
LOGE("iPeer already exists");
} else {
- LOGE("aPeer is a NULL pointer");
+ LOGE("aPeer is a NULL pointer");
}
OSCL_LEAVE(OsclErrGeneral);
return;
@@ -394,16 +417,23 @@ void AndroidCameraInput::writeComplete(PVMFStatus aStatus,
{
LOGV("writeComplete");
OSCL_UNUSED_ARG(aContext);
- if (aStatus != PVMFSuccess) {
- LOGE("writeAsync failed. aStatus=%d", aStatus);
- return;
- }
+ iFrameQueueMutex.Lock();
if (iSentMediaData.empty()) {
LOGE("Nothing to complete");
+ iFrameQueueMutex.Unlock();
return;
}
+ AndroidCameraInputMediaData data = iSentMediaData[0];
+#if (LOG_NDEBUG == 0)
+ ssize_t offset = 0;
+ size_t size = 0;
+ sp<IMemoryHeap> heap = data.iFrameBuffer->getMemory(&offset, &size);
+ LOGD("writeComplete: ID = %d, base = %p, offset = %p, size = %d", heap->getHeapID(), heap->base(), offset, size);
+#endif
+ mCamera->releaseRecordingFrame(data.iFrameBuffer);
+
if (mFrameRefCount) {
--mFrameRefCount;
}
@@ -419,6 +449,12 @@ void AndroidCameraInput::writeComplete(PVMFStatus aStatus,
}
iSentMediaData.erase(iSentMediaData.begin());
+ iFrameQueueMutex.Unlock();
+
+ // reference count is always updated, even if the write fails
+ if (aStatus != PVMFSuccess) {
+ LOGE("writeAsync failed. aStatus=%d", aStatus);
+ }
}
OSCL_EXPORT_REF
@@ -713,13 +749,13 @@ void AndroidCameraInput::Run()
// dequeue frame buffers and write to peer
iFrameQueueMutex.Lock();
- if (!iFrameQueue.empty()) {
+ while (!iFrameQueue.empty()) {
AndroidCameraInputMediaData data = iFrameQueue[0];
iFrameQueue.erase(iFrameQueue.begin());
uint32 writeAsyncID = 0;
int32 error = 0;
- OSCL_TRY(error,writeAsyncID = iPeer->writeAsync(0, 0, (uint8*)data.iFrameBuffer,
+ OSCL_TRY(error,writeAsyncID = iPeer->writeAsync(0, 0, (uint8*) (data.iFrameBuffer->pointer()),
data.iFrameSize, data.iXferHeader););
if (!error) {
@@ -839,14 +875,17 @@ void AndroidCameraInput::DoRequestCompleted(const AndroidCameraInputCmd& aCmd, P
}
}
-static void preview_callback(const sp<IMemory>& frame, void *cookie)
+static void recording_frame_callback(const sp<IMemory>& frame, void *cookie)
{
- LOGV("preview_callback");
+ LOGV("recording_frame_callback");
AndroidCameraInput* input = (AndroidCameraInput*) cookie;
- if (!input->isRecorderStarting()) { // this is not an error
+
+ // this must not happen, and we can't release the frame if it does happen
+ if (!input) {
+ LOGE("Error - CameraInput has not been initialized");
return;
}
-
+
input->postWriteAsync(frame);
}
@@ -861,12 +900,22 @@ PVMFStatus AndroidCameraInput::DoInit()
// create a camera if the app didn't supply one
if (mCamera == 0) {
mCamera = Camera::connect();
- if (mCamera != NULL && mSurface != NULL) {
- mCamera->setPreviewDisplay(mSurface);
+ }
+
+ // always call setPreviewDisplay() regardless whether mCamera is just created or not
+ // return failure if no display surface is available
+ if (mCamera != NULL && mSurface != NULL) {
+ mCamera->setPreviewDisplay(mSurface);
+ } else {
+ if (mCamera == NULL) {
+ LOGE("Camera is not available");
+ } else if (mSurface == NULL) {
+ LOGE("No surface is available for display");
}
+ return PVMFFailure;
}
- LOGD("Intended mFrameWidth=%d, mFrameHe=%d ",mFrameWidth, mFrameHeight);
+ LOGD("Intended mFrameWidth=%d, mFrameHeight=%d ",mFrameWidth, mFrameHeight);
String8 s = mCamera->getParameters();
CameraParameters p(s);
p.setPreviewSize(mFrameWidth, mFrameHeight);
@@ -878,8 +927,10 @@ PVMFStatus AndroidCameraInput::DoInit()
// for video recording.
CameraParameters newCameraParam(mCamera->getParameters());
newCameraParam.getPreviewSize(&mFrameWidth, &mFrameHeight);
- LOGD("Actual mFrameWidth=%d, mFrameHe=%d ",mFrameWidth, mFrameHeight);
- mCamera->startPreview();
+ LOGD("Actual mFrameWidth=%d, mFrameHeight=%d ",mFrameWidth, mFrameHeight);
+ if (mCamera->startPreview() != NO_ERROR) {
+ return PVMFFailure;
+ }
return PVMFSuccess;
}
@@ -887,10 +938,12 @@ PVMFStatus AndroidCameraInput::DoStart()
{
LOGV("DoStart");
iState = STATE_STARTED;
- mCamera->setFrameCallback(preview_callback, this, FRAME_CALLBACK_FLAG_CAMCORDER);
+ mCamera->setRecordingCallback(recording_frame_callback, this);
+ if (mCamera->startRecording() != NO_ERROR) {
+ return PVMFFailure;
+ }
AddDataEventToQueue(iMilliSecondsPerDataEvent);
return PVMFSuccess;
-
}
PVMFStatus AndroidCameraInput::DoPause()
@@ -923,7 +976,10 @@ PVMFStatus AndroidCameraInput::DoStop(const AndroidCameraInputCmd& aCmd)
{
LOGV("DoStop");
iDataEventCounter = 0;
- mCamera->setFrameCallback(NULL, this);
+ iState = STATE_STOPPING;
+ mCamera->setRecordingCallback(NULL, this);
+ mCamera->stopRecording();
+ ReleaseQueuedFrames();
// if no buffers pending, complete the stop command
if (mFrameRefCount == 0) {
@@ -933,7 +989,6 @@ PVMFStatus AndroidCameraInput::DoStop(const AndroidCameraInputCmd& aCmd)
// need to wait for buffers to come back before we stop preview
iPendingCmd = aCmd;
- iState = STATE_STOPPING;
return PVMFPending;
}
@@ -1040,14 +1095,20 @@ void AndroidCameraInput::SetCamera(const sp<android::ICamera>& camera)
PVMFStatus AndroidCameraInput::postWriteAsync(const sp<IMemory>& frame)
{
LOGV("postWriteAsync");
- if (iState != STATE_STARTED) {
- LOGE("postWriteAsync call in an invalid state(%d)", iState);
- return PVMFFailure;
- }
+
if (frame == NULL) {
LOGE("frame is a NULL pointer");
return PVMFFailure;
}
+
+ // release the received recording frame right way
+ // if recording has not been started yet or recording has already finished
+ if (!isRecorderStarting()) {
+ LOGV("Recording is not started, so recording frame is dropped");
+ mCamera->releaseRecordingFrame(frame);
+ return PVMFSuccess;
+ }
+
if (!iPeer) {
LOGW("iPeer is NULL");
return PVMFSuccess;
@@ -1066,7 +1127,7 @@ PVMFStatus AndroidCameraInput::postWriteAsync(const sp<IMemory>& frame)
ssize_t offset = 0;
size_t size = 0;
sp<IMemoryHeap> heap = frame->getMemory(&offset, &size);
- //LOGV("ID = %d, base = %p, offset = %p, size = %d", heap->getHeapID(), heap->base(), offset, size);
+ LOGV("postWriteAsync: ID = %d, base = %p, offset = %p, size = %d", heap->getHeapID(), heap->base(), offset, size);
//LOGV("@@@@@@@@@@@@@ incrementing reference count (%d) @@@@@@@@@@@@@@@", mFrameRefCount);
if (mHeap == 0) {
@@ -1084,7 +1145,7 @@ PVMFStatus AndroidCameraInput::postWriteAsync(const sp<IMemory>& frame)
data.iXferHeader.flags = 0;
data.iXferHeader.duration = 0;
data.iXferHeader.stream_id = 0;
- data.iFrameBuffer = frame->pointer();
+ data.iFrameBuffer = frame;
data.iFrameSize = size;
// lock mutex and queue frame buffer
diff --git a/android/author/android_camera_input.h b/android/author/android_camera_input.h
index 5efb0b88d..f31ffa340 100644
--- a/android/author/android_camera_input.h
+++ b/android/author/android_camera_input.h
@@ -149,12 +149,15 @@ public:
PVMFCommandId iId;
PvmiMediaXferHeader iXferHeader;
- void* iFrameBuffer;
+ sp<IMemory> iFrameBuffer;
size_t iFrameSize;
private:
void Copy(const AndroidCameraInputMediaData& aData) {
- memcpy(this, &aData, sizeof(AndroidCameraInputMediaData));
+ iId = aData.iId;
+ iXferHeader = aData.iXferHeader;
+ iFrameBuffer = aData.iFrameBuffer; // won't mess up the reference count
+ iFrameSize = aData.iFrameSize;
}
};
@@ -288,6 +291,10 @@ public:
bool isRecorderStarting() { return iState==STATE_STARTED?true:false; }
private:
+ // release all queued recording frames that have not been
+ // given the chance to be sent out.
+ void ReleaseQueuedFrames();
+
void Run();
void FrameSizeChanged();
diff --git a/android/author/authordriver.cpp b/android/author/authordriver.cpp
index e4baaeebb..eed79964a 100644
--- a/android/author/authordriver.cpp
+++ b/android/author/authordriver.cpp
@@ -34,15 +34,20 @@ AuthorDriverWrapper::AuthorDriverWrapper()
void AuthorDriverWrapper::resetAndClose()
{
+ LOGV("resetAndClose");
mAuthorDriver->enqueueCommand(new author_command(AUTHOR_RESET), NULL, NULL);
+ mAuthorDriver->enqueueCommand(new author_command(AUTHOR_REMOVE_VIDEO_SOURCE), NULL, NULL);
+ mAuthorDriver->enqueueCommand(new author_command(AUTHOR_REMOVE_AUDIO_SOURCE), NULL, NULL);
mAuthorDriver->enqueueCommand(new author_command(AUTHOR_CLOSE), NULL, NULL);
}
AuthorDriverWrapper::~AuthorDriverWrapper()
{
+ LOGV("Destructor");
if (mAuthorDriver) {
// set the authoring engine to the IDLE state.
PVAEState state = mAuthorDriver->getAuthorEngineState();
+ LOGV("state(%d)", state);
switch (state) {
case PVAE_STATE_IDLE:
break;
@@ -96,6 +101,7 @@ AuthorDriver::AuthorDriver()
mVideoHeight(DEFAULT_FRAME_HEIGHT),
mVideoFrameRate((int)DEFAULT_FRAME_RATE),
mVideoEncoder(VIDEO_ENCODER_DEFAULT),
+ mOutputFormat(OUTPUT_FORMAT_DEFAULT),
mAudioEncoder(AUDIO_ENCODER_DEFAULT)
{
mSyncSem = new OsclSemaphore();
@@ -240,6 +246,14 @@ void AuthorDriver::Run()
handleSetOutputFile((set_output_file_command *)ac);
return;
+ case AUTHOR_REMOVE_VIDEO_SOURCE:
+ handleRemoveVideoSource(ac);
+ return;
+
+ case AUTHOR_REMOVE_AUDIO_SOURCE:
+ handleRemoveAudioSource(ac);
+ return;
+
case AUTHOR_PREPARE: handlePrepare(ac); break;
case AUTHOR_START: handleStart(ac); break;
case AUTHOR_STOP: handleStop(ac); break;
@@ -357,6 +371,8 @@ void AuthorDriver::handleSetOutputFormat(set_output_format_command *ac)
return;
}
+ mOutputFormat = ac->of;
+
OSCL_TRY(error, mAuthor->SelectComposer(iComposerMimeType, mComposerConfig, ac));
OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
}
@@ -429,10 +445,22 @@ void AuthorDriver::handleSetVideoSize(set_video_size_command *ac)
if (mVideoInputMIO == NULL)
return;
- mVideoWidth = ac->width;
- mVideoHeight = ac->height;
+ // 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(ac->width, ac->height);
+ ((AndroidCameraInput *)mVideoInputMIO)->SetFrameSize(mVideoWidth, mVideoHeight);
FinishNonAsyncCommand(ac);
}
@@ -473,24 +501,49 @@ void AuthorDriver::handleSetOutputFile(set_output_file_command *ac)
{
PVMFStatus ret = PVMFFailure;
PvmfFileOutputNodeConfigInterface *config = NULL;
- OSCL_wHeapString<OsclMemAllocator> wFileName;
- oscl_wchar output[512];
+ FILE *ifpOutput = NULL;
+ int handle = -1;
if (!mComposerConfig) goto exit;
config = OSCL_STATIC_CAST(PvmfFileOutputNodeConfigInterface*, mComposerConfig);
if (!config) goto exit;
- oscl_UTF8ToUnicode(ac->path, strlen(ac->path), output, 512);
- wFileName.set(output, oscl_strlen(output));
- ret = config->SetOutputFileName(wFileName);
+ handle = open(ac->path, O_RDWR | O_CREAT );
+ if(-1 == handle) {
+ LOGE("Ln %d open() error %d", __LINE__, handle);
+ goto exit;
+ }
+
+ ifpOutput = fdopen(handle, "wb");
+ if(NULL == ifpOutput) {
+ LOGE("Ln %d fopen() error", __LINE__);
+ goto exit;
+ }
+
+ if ( OUTPUT_FORMAT_RAW_AMR == mOutputFormat ) {
+ PvmfFileOutputNodeConfigInterface *config = OSCL_DYNAMIC_CAST(PvmfFileOutputNodeConfigInterface*, mComposerConfig);
+ if (!config) goto exit;
+
+ ret = config->SetOutputFile(&OsclFileHandle(ifpOutput));
+ } 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->SetOutputFile(&OsclFileHandle(ifpOutput));
+ }
+
exit:
+ free(ac->path);
+
if (ret == PVMFSuccess) {
mOutputFileName = ac->path;
FinishNonAsyncCommand(ac);
} else {
- free(ac->path);
+ LOGE("Ln %d SetOutputFile() error", __LINE__);
+ fclose(ifpOutput);
commandFailed(ac);
}
}
@@ -511,6 +564,7 @@ void AuthorDriver::handleStart(author_command *ac)
void AuthorDriver::handleStop(author_command *ac)
{
+ LOGV("handleStop");
int error = 0;
OSCL_TRY(error, mAuthor->Stop(ac));
OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
@@ -520,6 +574,7 @@ void AuthorDriver::handleStop(author_command *ac)
void AuthorDriver::handleClose(author_command *ac)
{
+ LOGV("handleClose");
int error = 0;
OSCL_TRY(error, mAuthor->Close(ac));
OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
@@ -527,19 +582,45 @@ void AuthorDriver::handleClose(author_command *ac)
void AuthorDriver::handleReset(author_command *ac)
{
+ LOGV("handleReset");
int error = 0;
OSCL_TRY(error, mAuthor->Reset(ac));
OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
- // remove data sources
- removeDataSources(ac);
+ // remove references to configs
+ removeConfigRefs(ac);
}
-void AuthorDriver::removeDataSources(author_command *ac)
+void AuthorDriver::handleRemoveVideoSource(author_command *ac)
{
+ LOGV("handleRemoveVideoSource");
+ if (mVideoNode) {
+ int error = 0;
+ OSCL_TRY(error, mAuthor->RemoveDataSource(*mVideoNode, ac));
+ OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
+ } else {
+ FinishNonAsyncCommand(ac);
+ }
+}
+
+void AuthorDriver::handleRemoveAudioSource(author_command *ac)
+{
+ LOGV("handleRemoveAudioSource");
+ if (mAudioNode) {
+ int error = 0;
+ OSCL_TRY(error, mAuthor->RemoveDataSource(*mAudioNode, ac));
+ OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
+ } else {
+ FinishNonAsyncCommand(ac);
+ }
+}
+
+void AuthorDriver::removeConfigRefs(author_command *ac)
+{
+ LOGV("removeConfigRefs");
if (mOutputFileName) {
if (!mKeepOutputFile) {
- LOGV("remove output filei(%s)", mOutputFileName);
+ LOGV("remove output file(%s)", mOutputFileName);
unlink(mOutputFileName);
}
free(mOutputFileName);
@@ -558,19 +639,11 @@ void AuthorDriver::removeDataSources(author_command *ac)
mAudioEncoderConfig->removeRef();
mAudioEncoderConfig = NULL;
}
- int error = 0;
- if (mAudioNode) {
- OSCL_TRY(error, mAuthor->RemoveDataSource(*mAudioNode));
- OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
- }
- if (mVideoNode) {
- OSCL_TRY(error, mAuthor->RemoveDataSource(*mVideoNode));
- OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
- }
}
void AuthorDriver::handleQuit(author_command *ac)
{
+ LOGV("handleQuit");
OsclExecScheduler *sched = OsclExecScheduler::Current();
sched->StopScheduler();
}
@@ -667,18 +740,9 @@ int AuthorDriver::authorThread()
void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse)
{
author_command *ac = (author_command *)aResponse.GetContext();
- status_t s = 0;
-
- // XXX do we want to make this illegal? combo commands like
- // SETUP_DEFAULT_SINKS will need some changing
- if (ac == NULL) {
- // NULL command may be expected from the author engine from
- // time to time?
- // LOGE("Unexpected NULL command");
- return;
- }
+ status_t s = aResponse.GetCmdStatus();
+ LOGV("Command (%d) completed with status(%d)", ac->which, s);
- LOGV("Command (%d) completed with status(%d)", ac->which, aResponse.GetCmdStatus());
if (ac->which == AUTHOR_SET_OUTPUT_FORMAT) {
mSelectedComposer = aResponse.GetResponseData();
}
@@ -755,7 +819,7 @@ void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse)
}
// Translate the PVMF error codes into Android ones
- switch(aResponse.GetCmdStatus()) {
+ switch(s) {
case PVMFSuccess: s = android::OK; break;
case PVMFPending: *(char *)0 = 0; break; /* XXX assert */
default: s = android::UNKNOWN_ERROR;
diff --git a/android/author/authordriver.h b/android/author/authordriver.h
index db0826ebf..9de4f432b 100644
--- a/android/author/authordriver.h
+++ b/android/author/authordriver.h
@@ -52,8 +52,17 @@
#include "pvmp4h263encextension.h"
#include "pvmp4ffcn_clipconfig.h"
#include "pvmf_fileoutput_config.h"
+#ifndef PVMF_FILEOUTPUT_CONFIG_H_INCLUDED
+#include "pvmf_fileoutput_config.h"
+#endif
#include "pvmfamrencnode_extension.h"
+// 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
+
namespace android {
template<class DestructClass>
@@ -85,6 +94,8 @@ enum author_command_type {
AUTHOR_STOP,
AUTHOR_RESET,
AUTHOR_CLOSE,
+ AUTHOR_REMOVE_VIDEO_SOURCE,
+ AUTHOR_REMOVE_AUDIO_SOURCE,
AUTHOR_QUIT = 100
};
@@ -210,8 +221,12 @@ private:
// the event loop will keep running.
void FinishNonAsyncCommand(author_command *ec);
- // remove input video and/or audio source(s)
- void removeDataSources(author_command *ac);
+ // 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
@@ -246,6 +261,7 @@ private:
int mVideoFrameRate;
//int mVideoBitRate;
video_encoder mVideoEncoder;
+ output_format mOutputFormat;
//int mAudioBitRate;
audio_encoder mAudioEncoder;
diff --git a/android/mediascanner.cpp b/android/mediascanner.cpp
index 6388c4a29..0509c8c61 100644
--- a/android/mediascanner.cpp
+++ b/android/mediascanner.cpp
@@ -426,7 +426,7 @@ static PVMFStatus parseMidi(const char *filename, MediaScannerClient& client) {
file.fd = 0;
file.offset = 0;
file.length = 0;
- result = EAS_OpenFile(easData, &file, &easHandle, NULL);
+ result = EAS_OpenFile(easData, &file, &easHandle);
}
if (result == EAS_SUCCESS) {
result = EAS_Prepare(easData, easHandle);
@@ -551,7 +551,7 @@ static bool fileMatchesExtension(const char* path, const char* extensions) {
while (extensions[0]) {
char* comma = strchr(extensions, ',');
- int length = (comma ? comma - extensions : strlen(extensions));
+ size_t length = (comma ? comma - extensions : strlen(extensions));
if (length == strlen(extension) && strncasecmp(extension, extensions, length) == 0) return true;
extensions += length;
if (extensions[0] == ',') ++extensions;
@@ -611,7 +611,10 @@ status_t MediaScanner::doProcessDirectory(char *path, int pathRemaining, const c
strcat(fileSpot, "/");
int err = doProcessDirectory(path, pathRemaining - nameLength - 1, extensions, client, exceptionCheck, exceptionEnv);
- if (err) goto failure;
+ if (err) {
+ LOGE("Error processing '%s' - skipping\n", path);
+ continue;
+ }
} else if (fileMatchesExtension(path, extensions)) {
struct stat statbuf;
stat(path, &statbuf);
diff --git a/android/metadatadriver.cpp b/android/metadatadriver.cpp
index e1c54fd48..6ef6b311f 100644
--- a/android/metadatadriver.cpp
+++ b/android/metadatadriver.cpp
@@ -183,7 +183,7 @@ bool MetadataDriver::containsSupportedKey(const OSCL_HeapString<OsclMemAllocator
void MetadataDriver::trimKeys()
{
LOGV("trimKeys");
- dumpkeystolog(mMetadataKeyList);
+ //dumpkeystolog(mMetadataKeyList);
mActualMetadataKeyList.clear();
uint32 n = mMetadataKeyList.size();
mActualMetadataKeyList.reserve(n);
@@ -365,7 +365,7 @@ status_t MetadataDriver::setDataSource(const char* srcUrl)
{
LOGV("setDataSource");
// Don't let somebody trick us in to reading some random block of memory.
- if (strncmp("mem://", srcUrl, 6) == 0) {
+ if (strncmp("sharedfd://", srcUrl, 11) == 0) {
LOGE("setDataSource: Invalid url (%s).", srcUrl);
return UNKNOWN_ERROR;
}
diff --git a/android/playerdriver.cpp b/android/playerdriver.cpp
index 31f1a1e84..5a87d53ad 100644
--- a/android/playerdriver.cpp
+++ b/android/playerdriver.cpp
@@ -24,6 +24,7 @@
#include <media/thread_init.h>
#include <utils/threads.h>
#include <utils/List.h>
+#include <cutils/properties.h>
#include <media/MediaPlayerInterface.h>
@@ -76,7 +77,7 @@ using namespace android;
# endif
// library and function name to retrieve device-specific MIOs
-static const char* MIO_LIBRARY_NAME = "libopencorehal";
+static const char* MIO_LIBRARY_NAME = "libopencorehw.so";
static const char* VIDEO_MIO_FACTORY_NAME = "createVideoMio";
typedef AndroidSurfaceOutput* (*VideoMioFactory)();
@@ -183,6 +184,7 @@ private:
bool mSeekComp;
bool mSeekPending;
+ bool mEmulation;
void* mLibHandle;
};
@@ -196,7 +198,8 @@ PlayerDriver::PlayerDriver(PVPlayer* pvPlayer) :
mEndOfData(false),
mRecentSeek(0),
mSeekComp(true),
- mSeekPending(false)
+ mSeekPending(false),
+ mEmulation(false)
{
LOGV("constructor");
mSyncSem = new OsclSemaphore();
@@ -213,8 +216,21 @@ PlayerDriver::PlayerDriver(PVPlayer* pvPlayer) :
mPlayerCapConfig = NULL;
mDownloadContextData = NULL;
- // attempt to open device-specific library
- mLibHandle = ::dlopen(MIO_LIBRARY_NAME, RTLD_NOW);
+ // running in emulation?
+ mLibHandle = NULL;
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("ro.kernel.qemu", value, 0)) {
+ mEmulation = true;
+ LOGV("Emulation mode - using software codecs");
+ } else {
+ // attempt to open h/w specific library
+ mLibHandle = ::dlopen(MIO_LIBRARY_NAME, RTLD_NOW);
+ if (mLibHandle != NULL) {
+ LOGV("OpenCore hardware module loaded");
+ } else {
+ LOGV("OpenCore hardware module not found");
+ }
+ }
// start player thread
LOGV("start player thread");
@@ -601,7 +617,10 @@ void PlayerDriver::handleSetVideoSurface(PlayerSetVideoSurface* ec)
if (mLibHandle != NULL) {
VideoMioFactory f = (VideoMioFactory) ::dlsym(mLibHandle, VIDEO_MIO_FACTORY_NAME);
if (f != NULL) {
+ LOGV("Creating hardware specific MIO");
mio = f();
+ } else {
+ LOGV("MIO factory function not found");
}
}
@@ -612,7 +631,7 @@ void PlayerDriver::handleSetVideoSurface(PlayerSetVideoSurface* ec)
}
// initialize the MIO parameters
- status_t ret = mio->set(mPvPlayer, ec->surface());
+ status_t ret = mio->set(mPvPlayer, ec->surface(), mEmulation);
if (ret != NO_ERROR) {
LOGE("Video MIO set failed");
commandFailed(ec);
@@ -1141,13 +1160,15 @@ void PlayerDriver::HandleInformationalEvent(const PVAsyncInformationalEvent& aEv
}
}
-extern pthread_key_t osclfilenativesigbuskey;
-
namespace android {
#undef LOG_TAG
#define LOG_TAG "PVPlayer"
+#ifdef MAX_OPENCORE_INSTANCES
+/*static*/ volatile int32_t PVPlayer::sNumInstances = 0;
+#endif
+
// ----------------------------------------------------------------------------
// implement the Packet Video player
// ----------------------------------------------------------------------------
@@ -1155,13 +1176,23 @@ PVPlayer::PVPlayer()
{
LOGV("PVPlayer constructor");
mDataSourcePath = NULL;
+ mSharedFd = -1;
+ mIsDataSourceSet = false;
+ mDuration = -1;
+ mPlayerDriver = NULL;
+
+#ifdef MAX_OPENCORE_INSTANCES
+ if (android_atomic_inc(&sNumInstances) >= MAX_OPENCORE_INSTANCES) {
+ LOGW("Exceeds maximum number of OpenCore instances");
+ mInit = -EBUSY;
+ return;
+ }
+#endif
+
LOGV("construct PlayerDriver");
mPlayerDriver = new PlayerDriver(this);
LOGV("send PLAYER_SETUP");
mInit = mPlayerDriver->enqueueCommand(new PlayerSetup(0,0));
- mMemBase = 0;
- mIsDataSourceSet = false;
- mDuration = -1;
}
status_t PVPlayer::initCheck()
@@ -1172,32 +1203,31 @@ status_t PVPlayer::initCheck()
PVPlayer::~PVPlayer()
{
LOGV("PVPlayer destructor");
- PlayerQuit quit = PlayerQuit(0,0);
- mPlayerDriver->enqueueCommand(&quit); // will wait on mSyncSem, signaled by player thread
+ if (mPlayerDriver != NULL) {
+ PlayerQuit quit = PlayerQuit(0,0);
+ mPlayerDriver->enqueueCommand(&quit); // will wait on mSyncSem, signaled by player thread
+ }
free(mDataSourcePath);
- if (mMemBase) {
- munmap(mMemBase, mMemSize);
+ if (mSharedFd >= 0) {
+ close(mSharedFd);
}
-}
-
-status_t PVPlayer::setSigBusHandlerStructTLSKey(pthread_key_t key)
-{
- osclfilenativesigbuskey = key;
- return OK;
+#ifdef MAX_OPENCORE_INSTANCES
+ android_atomic_dec(&sNumInstances);
+#endif
}
status_t PVPlayer::setDataSource(const char *url)
{
LOGV("setDataSource(%s)", url);
- if (mMemBase) {
- munmap(mMemBase, mMemSize);
- mMemBase = NULL;
+ if (mSharedFd >= 0) {
+ close(mSharedFd);
+ mSharedFd = -1;
}
free(mDataSourcePath);
mDataSourcePath = NULL;
// Don't let somebody trick us in to reading some random block of memory
- if (strncmp("mem://", url, 6) == 0)
+ if (strncmp("sharedfd://", url, 11) == 0)
return android::UNKNOWN_ERROR;
mDataSourcePath = strdup(url);
return OK;
@@ -1209,32 +1239,17 @@ status_t PVPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
// Eventually we'll fix PV to use a file descriptor directly instead
// of using mmap().
LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
- if (mMemBase) {
- munmap(mMemBase, mMemSize);
- mMemBase = NULL;
+ if (mSharedFd >= 0) {
+ close(mSharedFd);
+ mSharedFd = -1;
}
free(mDataSourcePath);
mDataSourcePath = NULL;
- // round offset down to page size
- long pagesize = PAGESIZE;
- long mapoffset = offset & ~(pagesize - 1);
- long mapoffsetdelta = offset - mapoffset;
-
- void * bar = mmap(0, length + mapoffsetdelta, PROT_READ, MAP_PRIVATE, fd, mapoffset);
- if ((int)bar == -1) {
- LOGV("error mapping file: %s\n", strerror(errno));
- return android::UNKNOWN_ERROR;
- }
-
- mMemBase = bar;
- mMemSize = length + mapoffsetdelta;
char buf[80];
- sprintf(buf, "mem://%p:%lld:%lld", mMemBase,
- (int64_t) mapoffsetdelta,
- (int64_t) mMemSize - mapoffsetdelta);
+ mSharedFd = dup(fd);
+ sprintf(buf, "sharedfd://%d:%lld:%lld", mSharedFd, offset, length);
mDataSourcePath = strdup(buf);
- madvise(mMemBase, mMemSize, MADV_RANDOM);
return OK;
}
@@ -1417,9 +1432,9 @@ status_t PVPlayer::reset()
}
mSurface.clear();
LOGV("unmap file");
- if (mMemBase) {
- munmap(mMemBase, mMemSize);
- mMemBase = NULL;
+ if (mSharedFd >= 0) {
+ close(mSharedFd);
+ mSharedFd = -1;
}
mIsDataSourceSet = false;
return ret;
diff --git a/android/samples/android_surface_output_fb.cpp b/android/samples/android_surface_output_fb.cpp
new file mode 100644
index 000000000..f0056226c
--- /dev/null
+++ b/android/samples/android_surface_output_fb.cpp
@@ -0,0 +1,318 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2009 Android Open Source Project
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This is a sample video sink using frame buffer push model. The
+ * video output is NV21 (YUV 420 semi-planar with VUVU ordering).
+ * This requires re-ordering the YUV 420 planar output from the
+ * software codec to match the hardware color converter. The
+ * encoder outputs its frames in NV21, so no re-order is necessary.
+ *
+ * The hardware decoder and hardware video unit share pmem buffers
+ * (tunneling mode). For software codecs, we allocate a pmem buffer
+ * and convert the decoded YUV frames while copying to them to the
+ * pmem frame buffers used by the hardware output.
+ *
+ * This code should be compiled into a libopencorehw.so module.
+ * Here is a sample makefile to build the library:
+ *
+ * LOCAL_PATH := $(call my-dir)
+ * include $(CLEAR_VARS)
+ *
+ * # Set up the OpenCore variables.
+ * include external/opencore/Config.mk
+ * LOCAL_C_INCLUDES := $(PV_INCLUDES)
+ *
+ * LOCAL_SRC_FILES := android_surface_output_fb.cpp
+ *
+ * LOCAL_CFLAGS := $(PV_CFLAGS)
+ *
+ * LOCAL_SHARED_LIBRARIES := \
+ * libutils \
+ * libcutils \
+ * libui \
+ * libhardware\
+ * libandroid_runtime \
+ * libmedia \
+ * libsgl \
+ * libopencorecommon \
+ * libicuuc \
+ * libopencoreplayer
+ *
+ * LOCAL_MODULE := libopencorehw
+ *
+ * LOCAL_LDLIBS +=
+ *
+ * include $(BUILD_SHARED_LIBRARY)
+ *
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "VideoMioFB"
+#include <utils/Log.h>
+
+#include "android_surface_output_fb.h"
+#include <media/PVPlayer.h>
+
+#define PLATFORM_PRIVATE_PMEM 1
+
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+
+using namespace android;
+
+static const char* pmem_adsp = "/dev/pmem_adsp";
+static const char* pmem = "/dev/pmem";
+
+OSCL_EXPORT_REF AndroidSurfaceOutputFB::AndroidSurfaceOutputFB() :
+ AndroidSurfaceOutput()
+{
+ mHardwareCodec = false;
+}
+
+OSCL_EXPORT_REF AndroidSurfaceOutputFB::~AndroidSurfaceOutputFB()
+{
+}
+
+// create a frame buffer for software codecs
+OSCL_EXPORT_REF bool AndroidSurfaceOutputFB::initCheck()
+{
+
+ // initialize only when we have all the required parameters
+ if (((iVideoParameterFlags & VIDEO_SUBFORMAT_VALID) == 0) || !checkVideoParameterFlags())
+ return mInitialized;
+
+ // release resources if previously initialized
+ closeFrameBuf();
+
+ // reset flags in case display format changes in the middle of a stream
+ resetVideoParameterFlags();
+
+ // copy parameters in case we need to adjust them
+ int displayWidth = iVideoDisplayWidth;
+ int displayHeight = iVideoDisplayHeight;
+ int frameWidth = iVideoWidth;
+ int frameHeight = iVideoHeight;
+ int frameSize;
+
+ // MSM72xx hardware codec uses semi-planar format
+ if (iVideoSubFormat == PVMF_YUV420_SEMIPLANAR_YVU) {
+ LOGV("using hardware codec");
+ mHardwareCodec = true;
+ } else {
+ LOGV("using software codec");
+
+ // YUV420 frames are 1.5 bytes/pixel
+ frameSize = (frameWidth * frameHeight * 3) / 2;
+
+ // create frame buffer heap
+ sp<MemoryHeapBase> master = new MemoryHeapBase(pmem_adsp, frameSize * kBufferCount);
+ if (master->heapID() < 0) {
+ LOGE("Error creating frame buffer heap");
+ return false;
+ }
+ master->setDevice(pmem);
+ mHeapPmem = new MemoryHeapPmem(master, 0);
+ mHeapPmem->slap();
+ master.clear();
+ ISurface::BufferHeap buffers(displayWidth, displayHeight,
+ frameWidth, frameHeight, PIXEL_FORMAT_YCbCr_420_SP, mHeapPmem);
+ mSurface->registerBuffers(buffers);
+
+ // create frame buffers
+ for (int i = 0; i < kBufferCount; i++) {
+ mFrameBuffers[i] = i * frameSize;
+ }
+
+ LOGV("video = %d x %d", displayWidth, displayHeight);
+ LOGV("frame = %d x %d", frameWidth, frameHeight);
+ LOGV("frame #bytes = %d", frameSize);
+
+ // register frame buffers with SurfaceFlinger
+ mFrameBufferIndex = 0;
+ }
+
+ mInitialized = true;
+ LOGV("sendEvent(MEDIA_SET_VIDEO_SIZE, %d, %d)", iVideoDisplayWidth, iVideoDisplayHeight);
+ mPvPlayer->sendEvent(MEDIA_SET_VIDEO_SIZE, iVideoDisplayWidth, iVideoDisplayHeight);
+ return mInitialized;
+}
+
+PVMFStatus AndroidSurfaceOutputFB::writeFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info)
+{
+ if (mSurface == 0) return PVMFFailure;
+
+ // hardware codec
+ if (mHardwareCodec) {
+
+ // initialize frame buffer heap
+ if (mHeapPmem == 0) {
+ LOGV("initializing for hardware");
+ LOGV("private data pointer is 0%p\n", data_header_info.private_data_ptr);
+
+ // check for correct video format
+ if (iVideoSubFormat != PVMF_YUV420_SEMIPLANAR_YVU) return PVMFFailure;
+
+ uint32 fd;
+ if (!getPmemFd(data_header_info.private_data_ptr, &fd)) {
+ LOGE("Error getting pmem heap from private_data_ptr");
+ return PVMFFailure;
+ }
+ sp<MemoryHeapBase> master = (MemoryHeapBase *) fd;
+ master->setDevice(pmem);
+ mHeapPmem = new MemoryHeapPmem(master, 0);
+ mHeapPmem->slap();
+ master.clear();
+
+ // register frame buffers with SurfaceFlinger
+ ISurface::BufferHeap buffers(iVideoDisplayWidth, iVideoDisplayHeight,
+ iVideoWidth, iVideoHeight,
+ PIXEL_FORMAT_YCbCr_420_SP, mHeapPmem);
+ mSurface->registerBuffers(buffers);
+ }
+
+ // get pmem offset and post to SurfaceFlinger
+ if (!getOffset(data_header_info.private_data_ptr, &mOffset)) {
+ LOGE("Error getting pmem offset from private_data_ptr");
+ return PVMFFailure;
+ }
+ mSurface->postBuffer(mOffset);
+ } else {
+
+ // software codec
+ convertFrame(aData, static_cast<uint8*>(mHeapPmem->base()) + mFrameBuffers[mFrameBufferIndex], aDataLen);
+ // post to SurfaceFlinger
+ if (++mFrameBufferIndex == kBufferCount) mFrameBufferIndex = 0;
+ mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
+ }
+
+ return PVMFSuccess;
+}
+
+// post the last video frame to refresh screen after pause
+void AndroidSurfaceOutputFB::postLastFrame()
+{
+ mSurface->postBuffer(mOffset);
+}
+
+void AndroidSurfaceOutputFB::closeFrameBuf()
+{
+ LOGV("CloseFrameBuf");
+ if (!mInitialized) return;
+
+ mInitialized = false;
+ if (mSurface.get()) {
+ LOGV("unregisterBuffers");
+ mSurface->unregisterBuffers();
+ mSurface.clear();
+ }
+
+ // free frame buffers
+ LOGV("free frame buffers");
+ for (int i = 0; i < kBufferCount; i++) {
+ mFrameBuffers[i] = 0;
+ }
+
+ // free heaps
+ LOGV("free mFrameHeap");
+ mFrameHeap.clear();
+ LOGV("free mHeapPmem");
+ mHeapPmem.clear();
+}
+
+bool AndroidSurfaceOutputFB::getPmemFd(OsclAny *private_data_ptr, uint32 *pmemFD)
+{
+ PLATFORM_PRIVATE_LIST *listPtr = NULL;
+ PLATFORM_PRIVATE_PMEM_INFO *pmemInfoPtr = NULL;
+ bool returnType = false;
+ LOGV("in getPmemfd - privatedataptr=%p\n",private_data_ptr);
+ listPtr = (PLATFORM_PRIVATE_LIST*) private_data_ptr;
+
+ for (uint32 i=0;i<listPtr->nEntries;i++)
+ {
+ if(listPtr->entryList->type == PLATFORM_PRIVATE_PMEM)
+ {
+ LOGV("in getPmemfd - entry type = %d\n",listPtr->entryList->type);
+ pmemInfoPtr = (PLATFORM_PRIVATE_PMEM_INFO*) (listPtr->entryList->entry);
+ returnType = true;
+ if(pmemInfoPtr){
+ *pmemFD = pmemInfoPtr->pmem_fd;
+ LOGV("in getPmemfd - pmemFD = %d\n",*pmemFD);
+ }
+ break;
+ }
+ }
+ return returnType;
+}
+
+bool AndroidSurfaceOutputFB::getOffset(OsclAny *private_data_ptr, uint32 *offset)
+{
+ PLATFORM_PRIVATE_LIST *listPtr = NULL;
+ PLATFORM_PRIVATE_PMEM_INFO *pmemInfoPtr = NULL;
+ bool returnType = false;
+
+ listPtr = (PLATFORM_PRIVATE_LIST*) private_data_ptr;
+ LOGV("in getOffset: listPtr = %p\n",listPtr);
+ for (uint32 i=0;i<listPtr->nEntries;i++)
+ {
+ if(listPtr->entryList->type == PLATFORM_PRIVATE_PMEM)
+ {
+ LOGV(" in getOffset: entrytype = %d\n",listPtr->entryList->type);
+
+ pmemInfoPtr = (PLATFORM_PRIVATE_PMEM_INFO*) (listPtr->entryList->entry);
+ returnType = true;
+ if(pmemInfoPtr){
+ *offset = pmemInfoPtr->offset;
+ LOGV("in getOffset: offset = %d\n",*offset);
+ }
+ break;
+ }
+ }
+ return returnType;
+}
+
+static inline void* byteOffset(void* p, size_t offset) { return (void*)((uint8_t*)p + offset); }
+
+void AndroidSurfaceOutputFB::convertFrame(void* src, void* dst, size_t len)
+{
+ // copy the Y plane
+ size_t y_plane_size = iVideoWidth * iVideoHeight;
+ //LOGV("len=%u, y_plane_size=%u", len, y_plane_size);
+ memcpy(dst, src, y_plane_size + iVideoWidth);
+
+ // re-arrange U's and V's
+ uint16_t* pu = (uint16_t*)byteOffset(src, y_plane_size);
+ uint16_t* pv = (uint16_t*)byteOffset(pu, y_plane_size / 4);
+ uint32_t* p = (uint32_t*)byteOffset(dst, y_plane_size);
+
+ int count = y_plane_size / 8;
+ //LOGV("u = %p, v = %p, p = %p, count = %d", pu, pv, p, count);
+ do {
+ uint32_t u = *pu++;
+ uint32_t v = *pv++;
+ *p++ = ((u & 0xff) << 8) | ((u & 0xff00) << 16) | (v & 0xff) | ((v & 0xff00) << 8);
+ } while (--count);
+}
+
+// factory function for playerdriver linkage
+extern "C" AndroidSurfaceOutput* createVideoMio()
+{
+ return new AndroidSurfaceOutputFB();
+}
+
diff --git a/android/samples/android_surface_output_fb.h b/android/samples/android_surface_output_fb.h
new file mode 100644
index 000000000..aa751be44
--- /dev/null
+++ b/android/samples/android_surface_output_fb.h
@@ -0,0 +1,79 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2009 Android Open Source Project
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+#ifndef ANDROID_SURFACE_OUTPUT_FB_H_INCLUDED
+#define ANDROID_SURFACE_OUTPUT_FB_H_INCLUDED
+
+#include "android_surface_output.h"
+
+// support for shared contiguous physical memory
+#include <utils/MemoryHeapPmem.h>
+
+// data structures for tunneling buffers
+typedef struct PLATFORM_PRIVATE_PMEM_INFO
+{
+ /* pmem file descriptor */
+ uint32 pmem_fd;
+ uint32 offset;
+} PLATFORM_PRIVATE_PMEM_INFO;
+
+typedef struct PLATFORM_PRIVATE_ENTRY
+{
+ /* Entry type */
+ uint32 type;
+
+ /* Pointer to platform specific entry */
+ OsclAny* entry;
+} PLATFORM_PRIVATE_ENTRY;
+
+typedef struct PLATFORM_PRIVATE_LIST
+{
+ /* Number of entries */
+ uint32 nEntries;
+
+ /* Pointer to array of platform specific entries *
+ * Contiguous block of PLATFORM_PRIVATE_ENTRY elements */
+ PLATFORM_PRIVATE_ENTRY* entryList;
+} PLATFORM_PRIVATE_LIST;
+
+
+class AndroidSurfaceOutputFB : public AndroidSurfaceOutput
+{
+public:
+ AndroidSurfaceOutputFB();
+
+ // frame buffer interface
+ virtual bool initCheck();
+ virtual PVMFStatus writeFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info);
+ virtual void postLastFrame();
+ virtual void closeFrameBuf();
+
+ OSCL_IMPORT_REF ~AndroidSurfaceOutputFB();
+
+private:
+ bool getPmemFd(OsclAny *private_data_ptr, uint32 *pmemFD);
+ bool getOffset(OsclAny *private_data_ptr, uint32 *offset);
+ void convertFrame(void* src, void* dst, size_t len);
+
+ // hardware frame buffer support
+ sp<MemoryHeapPmem> mHeapPmem;
+ bool mHardwareCodec;
+ uint32 mOffset;
+};
+
+#endif // ANDROID_SURFACE_OUTPUT_FB_H_INCLUDED
diff --git a/engines/author/src/pvaenodeutility.cpp b/engines/author/src/pvaenodeutility.cpp
index a6aab0d5d..16107c269 100644
--- a/engines/author/src/pvaenodeutility.cpp
+++ b/engines/author/src/pvaenodeutility.cpp
@@ -281,15 +281,6 @@ void PVAuthorEngineNodeUtility::NodeCommandCompleted(const PVMFCmdResp& aRespons
PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVAuthorEngineNodeUtility::NodeCommandCompleted"));
- if (aResponse.GetCmdStatus() != PVMFSuccess)
- {
- PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
- (0, "PVAuthorEngineNodeUtility::NodeCommandCompleted: Command failed - context=0x%x, status=0x%x",
- aResponse.GetContext(), aResponse.GetCmdStatus()));
- CompleteUtilityCmd(iCmdQueue[0], aResponse.GetCmdStatus());
- return;
- }
-
if (iCmdQueue.empty())
{
LOG_ERR((0, "PVAuthorEngineNodeUtility::NodeCommandCompleted: Error - Empty command queue"));
@@ -298,8 +289,17 @@ void PVAuthorEngineNodeUtility::NodeCommandCompleted(const PVMFCmdResp& aRespons
return;
}
- PVMFStatus status = PVMFSuccess;
PVAENodeUtilCmd cmd = iCmdQueue[0];
+ if (aResponse.GetCmdStatus() != PVMFSuccess)
+ {
+ PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
+ (0, "PVAuthorEngineNodeUtility::NodeCommandCompleted: Command failed - context=0x%x, status=0x%x",
+ aResponse.GetContext(), aResponse.GetCmdStatus()));
+ CompleteUtilityCmd(cmd, aResponse.GetCmdStatus());
+ return;
+ }
+
+ PVMFStatus status = PVMFSuccess;
switch (cmd.iType)
{
case PVAENU_CMD_CONNECT:
@@ -339,7 +339,12 @@ void PVAuthorEngineNodeUtility::NodeCommandCompleted(const PVMFCmdResp& aRespons
}
if (status != PVMFPending)
+ {
CompleteUtilityCmd(cmd, status);
+ }
+ else if (iCmdQueue.size() == 1) { // kick off the execution of the command
+ RunIfNotReady();
+ }
}
////////////////////////////////////////////////////////////////////////////
@@ -440,27 +445,53 @@ void PVAuthorEngineNodeUtility::CompleteUtilityCmd(const PVAENodeUtilCmd& aCmd,
{
LOG_ERR((0, "PVAuthorEngineNodeUtility::CompleteUtilityCmd: Error - Observer not set"));
OSCL_LEAVE(OsclErrGeneral);
- // return; This statement was removed to avoid compiler warning for Unreachable Code
+ // return; This statement was removed to avoid compiler warning for Unreachable Code
}
- if (iCmdQueue.empty() || aCmd.iType != iCmdQueue[0].iType)
+ // make the error logs more specific
+ bool emptyCmdQueueOrMismatchedCmd = false;
+ if (iCmdQueue.empty())
+ {
+ emptyCmdQueueOrMismatchedCmd = true;
+ LOG_ERR((0, "PVAuthorEngineNodeUtility::CompleteUtilityCmd: Error - Empty command queue"));
+ }
+ else if (aCmd.iType != iCmdQueue[0].iType)
+ {
+ emptyCmdQueueOrMismatchedCmd = true;
+ LOG_ERR((0, "PVAuthorEngineNodeUtility::CompleteUtilityCmd: Error - Mismatched command (%d vs %d)", aCmd.iType, iCmdQueue[0].iType));
+ }
+ if (emptyCmdQueueOrMismatchedCmd)
{
- LOG_ERR((0, "PVAuthorEngineNodeUtility::CompleteUtilityCmd: Error - Empty command queue or mismatched command"));
PVMFAsyncEvent event(PVMFErrorEvent, PVMFFailure, NULL, NULL);
iObserver->NodeUtilErrorEvent(event);
return;
}
- // Remove command from queue
- iCmdQueue.erase(iCmdQueue.begin());
-
- // Callback to engine
- PVMFCmdResp resp(0, aCmd.iContext, aStatus);
- iObserver->NodeUtilCommandCompleted(resp);
+ if (aStatus == PVMFFailure)
+ {
+ // if one cmd failed, skip the remaining commands in the queue.
+ // send the same error code via callbacks to author engine
+ // to signal the (failure) completion of these commands.
+ while (!iCmdQueue.empty())
+ {
+ PVAENodeUtilCmd cmd = iCmdQueue[0];
+ iCmdQueue.erase(iCmdQueue.begin());
+ PVMFCmdResp resp(0, cmd.iContext, aStatus);
+ iObserver->NodeUtilCommandCompleted(resp);
+ }
+ }
+ else
+ {
+ iCmdQueue.erase(iCmdQueue.begin());
+ PVMFCmdResp resp(0, aCmd.iContext, aStatus);
+ iObserver->NodeUtilCommandCompleted(resp);
+ }
// Run next command when needed
if (!iCmdQueue.empty())
+ {
RunIfNotReady();
+ }
}
////////////////////////////////////////////////////////////////////////////
@@ -909,25 +940,28 @@ PVMFStatus PVAuthorEngineNodeUtility::DoReset(const PVAENodeUtilCmd& aCmd)
PVMFStatus PVAuthorEngineNodeUtility::CompleteStateTransition(const PVAENodeUtilCmd& aCmd,
TPVMFNodeInterfaceState aState)
{
- LOG_STACK_TRACE((0, "PVAuthorEngineNodeUtility::CompleteStateTransition: aState=%d", aState));
+ LOG_STACK_TRACE((0, "PVAuthorEngineNodeUtility::CompleteStateTransition"));
for (uint32 i = 0; i < aCmd.iNodes.size(); i++)
{
if (aCmd.iNodes[i]->iNode->GetState() != aState)
{
+ LOG_STACK_TRACE((0, "PVAuthorEngineNodeUtility::CompleteStateTransition: node %d (%d) does not have the same state as the node util(%d)", i, aCmd.iNodes[i]->iNode->GetState(), aState));
if ((aCmd.iType == PVAENU_CMD_RESET) && (aCmd.iNodes[i]->iNode->GetState() == EPVMFNodeIdle))
{
+ LOG_STACK_TRACE((0, "PVAuthorEngineNodeUtility::CompleteStateTransition: RESET and EPVMFNodeIdle - do nothing"));
//If the command is RESET and GetState() == EPVMFNodeIdle, be tolerant
//do nothing;
}
else
{
// Some nodes have not completed this command. Continue to wait
+ LOG_STACK_TRACE((0, "PVAuthorEngineNodeUtility::CompleteStateTransition: Continue to wait"));
return PVMFPending;
}
}
}
+ LOG_STACK_TRACE((0, "PVAuthorEngineNodeUtility::CompleteStateTransition: return PVMFSuccess"));
return PVMFSuccess;
}
-
diff --git a/nodes/pvfileoutputnode/include/pvmf_fileoutput_config.h b/nodes/pvfileoutputnode/include/pvmf_fileoutput_config.h
index 0d0117057..aec47e304 100644
--- a/nodes/pvfileoutputnode/include/pvmf_fileoutput_config.h
+++ b/nodes/pvfileoutputnode/include/pvmf_fileoutput_config.h
@@ -70,6 +70,15 @@ class PvmfFileOutputNodeConfigInterface : public PVInterface
virtual bool queryInterface(const PVUuid& uuid, PVInterface*& iface) = 0;
/**
+ * This method sets the output file handle. This method must be called before
+ * Start() is called.
+ *
+ * @param aFileHandle Output file handle
+ * @return Completion status of this method.
+ */
+ virtual PVMFStatus SetOutputFile(OsclFileHandle* aFileHandle) = 0;
+
+ /**
* This method sets the output file name. This method must be called before
* the engine / node is initialized.
*
diff --git a/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.cpp b/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.cpp
index c9fe3d1b2..c40e1ff01 100644
--- a/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.cpp
+++ b/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.cpp
@@ -417,6 +417,34 @@ bool PVMFFileOutputNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
}
////////////////////////////////////////////////////////////////////////////
+PVMFStatus PVMFFileOutputNode::SetOutputFile(OsclFileHandle* aFileHandle)
+{
+ if(iInterfaceState != EPVMFNodeIdle
+ && iInterfaceState != EPVMFNodeInitialized
+ && iInterfaceState != EPVMFNodeCreated
+ && iInterfaceState != EPVMFNodePrepared)
+ return false;
+
+ iOutputFileName = _STRLIT("");//wipe out file name if file handle is in use
+ CloseOutputFile();
+
+ if(0 == iOutputFile.SetFileHandle(aFileHandle) )
+ {
+ uint32 mode = Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY;
+ if(!iOutputFile.Open("", mode, iFs ))
+ {
+ iFileOpened = true;
+ iFirstMediaData=true;
+ return PVMFSuccess;
+ }
+ }
+
+ PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
+ (0, "PVMFFileOutputNode::SetOutputFile() Error Ln %d", __LINE__));
+ return PVMFFailure;
+}
+
+////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFFileOutputNode::SetOutputFileName(const OSCL_wString& aFileName)
{
if (iInterfaceState != EPVMFNodeIdle
@@ -425,6 +453,9 @@ PVMFStatus PVMFFileOutputNode::SetOutputFileName(const OSCL_wString& aFileName)
&& iInterfaceState != EPVMFNodePrepared)
return false;
+ CloseOutputFile();
+ iFirstMediaData = false;
+
iOutputFileName = aFileName;
return PVMFSuccess;
}
diff --git a/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.h b/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.h
index 8e8f50e58..b86f09a57 100644
--- a/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.h
+++ b/nodes/pvfileoutputnode/src/pvmf_fileoutput_node.h
@@ -209,6 +209,7 @@ class PVMFFileOutputNode : public OsclActiveObject, public PVMFNodeInterface,
void HandlePortActivity(const PVMFPortActivity& aActivity);
// Pure virtual from PvmfFileOutputNodeConfigInterface
+ PVMFStatus SetOutputFile(OsclFileHandle* aFileHandle);
PVMFStatus SetOutputFileName(const OSCL_wString& aFileName);
// Pure virtual from PvmfComposerSizeAndDurationInterface
diff --git a/nodes/pvmediainputnode/src/pvmf_media_input_node_outport.cpp b/nodes/pvmediainputnode/src/pvmf_media_input_node_outport.cpp
index 23ce2daae..bd18c07a3 100644
--- a/nodes/pvmediainputnode/src/pvmf_media_input_node_outport.cpp
+++ b/nodes/pvmediainputnode/src/pvmf_media_input_node_outport.cpp
@@ -250,6 +250,7 @@ PVMFCommandId PvmfMediaInputNodeOutPort::writeAsync(uint8 format_type, int32 for
iNode->ReportErrorEvent(PVMFErrPortProcessing);
OsclError::Leave(OsclErrGeneral);
+ return -1;
}
diff --git a/nodes/pvmp4ffcomposernode/include/pvmp4ffcn_clipconfig.h b/nodes/pvmp4ffcomposernode/include/pvmp4ffcn_clipconfig.h
index a32a3f662..ca90af77f 100644
--- a/nodes/pvmp4ffcomposernode/include/pvmp4ffcn_clipconfig.h
+++ b/nodes/pvmp4ffcomposernode/include/pvmp4ffcn_clipconfig.h
@@ -41,6 +41,9 @@
#ifndef PV_MP4FFCOMPOSER_CONFIG_H_INCLUDED
#include "pv_mp4ffcomposer_config.h"
#endif
+#ifndef OSCL_FILE_HANDLE_H_INCLUDED
+#include "oscl_file_handle.h"
+#endif
#define KPVMp4FFCNClipConfigUuid PVUuid(0x2e3b479f,0x2c46,0x465c,0xba,0x41,0xb8,0x91,0x11,0xa9,0xdf,0x3a)
@@ -145,6 +148,16 @@ class PVMp4FFCNClipConfigInterface : public PVInterface
virtual bool queryInterface(const PVUuid& uuid, PVInterface*& iface) = 0;
/**
+ * This method sets the output file handle. This method must be called before
+ * Start() is called.
+ *
+ * @param aFileHandle Output file handle
+ * @return Completion status of this method.
+ */
+ virtual PVMFStatus SetOutputFile(OsclFileHandle* aFileHandle) = 0;
+
+
+ /**
* This method sets the output file name. This method must be called before
* Start() is called.
*
diff --git a/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.cpp b/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.cpp
index ccacf95e1..32d815ecd 100644
--- a/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.cpp
+++ b/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.cpp
@@ -106,6 +106,7 @@ PVMp4FFComposerNode::PVMp4FFComposerNode(int32 aPriority)
, iNodeEndOfDataReached(false)
, iformat_h264(PVMF_FORMAT_UNKNOWN)
, iformat_text(PVMF_FORMAT_UNKNOWN)
+ , iOutputFileHandle(NULL)
{
iInterfaceState = EPVMFNodeCreated;
iNum_PPS_Set = 0;
@@ -168,6 +169,11 @@ PVMp4FFComposerNode::~PVMp4FFComposerNode()
{
PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File);
}
+ if(iOutputFileHandle)
+ {
+ OSCL_DELETE( iOutputFileHandle );
+ iOutputFileHandle = NULL;
+ }
if (pConfig != NULL)
{
@@ -439,12 +445,48 @@ OSCL_EXPORT_REF bool PVMp4FFComposerNode::queryInterface(const PVUuid& uuid, PVI
////////////////////////////////////////////////////////////////////////////
// PVMp4FFCNClipConfigInterface routines
////////////////////////////////////////////////////////////////////////////
+OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFile(OsclFileHandle* aFileHandle)
+{
+ if(iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
+ return PVMFFailure;
+
+ iFileName = _STRLIT("");//wipe out file name if file handle is in use
+
+ if(iOutputFileHandle)
+ OSCL_DELETE( iOutputFileHandle );
+ iOutputFileHandle = OSCL_NEW( Oscl_File, () );
+ if( iOutputFileHandle )
+ {
+ if(0 == iOutputFileHandle->SetFileHandle(aFileHandle) )
+ {
+ uint32 mode = Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY;
+ if(!iOutputFileHandle->Open("", mode, iFs ))
+ return PVMFSuccess;
+ PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
+ (0, "PVMp4FFComposerNode::SetOutputFile: Open() Error Ln %d", __LINE__));
+ }
+ OSCL_DELETE( iOutputFileHandle );
+ iOutputFileHandle = NULL;
+ }
+
+ PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
+ (0, "PVMp4FFComposerNode::SetOutputFile() Error Ln %d", __LINE__));
+ return PVMFFailure;
+}
+
+
OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFileName(const OSCL_wString& aFileName)
{
if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
- return false;
+ return PVMFFailure;
iFileName = aFileName;
+ if(iOutputFileHandle)
+ {
+ OSCL_DELETE( iOutputFileHandle );
+ iOutputFileHandle = NULL;
+ }
+
return PVMFSuccess;
}
@@ -1096,8 +1138,21 @@ void PVMp4FFComposerNode::DoStart(PVMp4FFCNCmd& aCmd)
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMp4FFComposerNode::DoStart: Calling PVA_FF_IMpeg4File::createMP4File(%d,0x%x,%d)",
iFileType, &iFs, iAuthoringMode));
- iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
- (void*) & iFs, iAuthoringMode, iFileName, iCacheSize);
+ if(iOutputFileHandle)
+ {
+ OSCL_ASSERT(NULL != iOutputFileHandle->Handle());
+
+ iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iAuthoringMode, iOutputFileHandle, iCacheSize);
+ if( iMpeg4File )
+ {
+ iOutputFileHandle = NULL; //let ff take care of the file close and dealloc
+ }
+ }
+ else
+ {
+ iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
+ (void*)&iFs, iAuthoringMode, iFileName, iCacheSize);
+ }
if (!iMpeg4File)
{
diff --git a/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.h b/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.h
index 9f15ee518..75e66d8a7 100644
--- a/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.h
+++ b/nodes/pvmp4ffcomposernode/src/pvmp4ffcn_node.h
@@ -152,6 +152,7 @@ class PVMp4FFComposerNode : public PVMFNodeInterface,
OSCL_IMPORT_REF bool queryInterface(const PVUuid& uuid, PVInterface*& iface);
// Pure virtual functions from PVMp4FFCNClipConfigInterface
+ OSCL_IMPORT_REF PVMFStatus SetOutputFile(OsclFileHandle* aFileHandle);
OSCL_IMPORT_REF PVMFStatus SetOutputFileName(const OSCL_wString& aFileName);
OSCL_IMPORT_REF PVMFStatus SetAuthoringMode(PVMp4FFCN_AuthoringMode aAuthoringMode = PVMP4FFCN_3GPP_DOWNLOAD_MODE);
OSCL_IMPORT_REF PVMFStatus SetPresentationTimescale(uint32 aTimescale);
@@ -328,6 +329,7 @@ class PVMp4FFComposerNode : public PVMFNodeInterface,
// File format
PVA_FF_IMpeg4File* iMpeg4File;
+ Oscl_File *iOutputFileHandle;
OSCL_wHeapString<OsclMemAllocator> iFileName;
OSCL_wHeapString<OsclMemAllocator> iPostfix;
OSCL_wHeapString<OsclMemAllocator> iOutputPath;
diff --git a/nodes/pvomxvideodecnode/src/pvmf_omx_videodec_node.cpp b/nodes/pvomxvideodecnode/src/pvmf_omx_videodec_node.cpp
index 362b1799e..0fb598294 100644
--- a/nodes/pvomxvideodecnode/src/pvmf_omx_videodec_node.cpp
+++ b/nodes/pvomxvideodecnode/src/pvmf_omx_videodec_node.cpp
@@ -6128,13 +6128,25 @@ void PVMFOMXVideoDecNode::DoCancelAllCommands(PVMFOMXVideoDecNodeCommand& aCmd)
}
//next cancel all queued commands
+ // Create a temporary queue for pending commands
+ // Copy the pending commands to the new queue
+ PVMFOMXVideoDecNodeCmdQ iTempPendingCmds;
+ for(int i=0; i< iInputCommands.size(); i++)
{
- //start at element 1 since this cancel command is element 0.
- while (iInputCommands.size() > 1)
- {
- CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
- }
+ PVMFOMXVideoDecNodeCommand* cmd = iInputCommands.FindById(i);
+ PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXVideoDecNode::DoCancelAllCommands CancelAllCmd ID %d InputCmd ID %d", aCmd.iId , cmd->iId));
+ if ((aCmd.iId > cmd->iId) && ((aCmd.iId - cmd->iId ) < 0x80000000))
+ iTempPendingCmds.StoreL(*cmd);
+ }
+ for(int i=0; i< iTempPendingCmds.size(); i++)
+ {
+ // Get the queue from the top
+ PVMFOMXVideoDecNodeCommand* cmd = iTempPendingCmds.FindById(i);
+ PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXVideoDecNode::DoCancelAllCommands Cancel Cmd ID %d", cmd->iId));
+ //cancel the queued command
+ CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
}
+ iTempPendingCmds.clear();
if (iResetInProgress && !iResetMsgSent)
{
diff --git a/nodes/pvomxvideoencnode/src/pvmf_omx_videoenc_node.cpp b/nodes/pvomxvideoencnode/src/pvmf_omx_videoenc_node.cpp
index e59441a1e..7d12693cc 100644
--- a/nodes/pvomxvideoencnode/src/pvmf_omx_videoenc_node.cpp
+++ b/nodes/pvomxvideoencnode/src/pvmf_omx_videoenc_node.cpp
@@ -2057,20 +2057,25 @@ void PVMFOMXVideoEncNode::DoStop(PVMFVideoEncNodeCommand& aCmd)
////////////////////////////////////////////////////////////////////////////
void PVMFOMXVideoEncNode::DeleteVideoEncoder()
{
-
- if (iOMXVideoEncoder != NULL)
- {
+ LOGV("DeleteVideoEncoder");
+ if (iOMXVideoEncoder != NULL) {
OMX_ERRORTYPE err;
- /* Free Component handle. */
- err = PV_MasterOMX_FreeHandle(iOMXVideoEncoder);
- if (err != OMX_ErrorNone)
- {
- //Error condition report
- PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
- (0, "PVMFOMXVideoEncNode::DeleteVideoEncoder(): Can't free encoder's handle!"));
+ OMX_STATETYPE state;
+ err = OMX_GetState(iOMXVideoEncoder, &state);
+ if (err != OMX_ErrorNone) {
+ LOGE("Failed to get encoder state with failure code(%d)", err);
+ } else if (state != OMX_StateLoaded && state != OMX_StateInvalid) {
+ LOGE("OMX_FreeHandle is called in a state(%d) other than OMX_StateLoaded or OMX_StateInvalid.", state);
}
- iOMXVideoEncoder = NULL;
+ // No matter what, call OMX_FreeHandle anyway
+ err = PV_MasterOMX_FreeHandle(iOMXVideoEncoder);
+ if (err != OMX_ErrorNone) {
+ LOGE("Failed to free encoder handle with failure code(%d)", err);
+ } else {
+ LOGI("video encoder handle has been successfully released");
+ iOMXVideoEncoder = NULL;
+ }
}
}
diff --git a/oscl/oscl/osclio/src/oscl_file_native.cpp b/oscl/oscl/osclio/src/oscl_file_native.cpp
index 7817c0aca..6367088a1 100644
--- a/oscl/oscl/osclio/src/oscl_file_native.cpp
+++ b/oscl/oscl/osclio/src/oscl_file_native.cpp
@@ -24,7 +24,7 @@
#include "oscl_utf8conv.h"
#include "oscl_int64_utils.h"
-#ifdef ENABLE_MEMORY_PLAYBACK
+#ifdef ENABLE_SHAREDFD_PLAYBACK
#undef LOG_TAG
#define LOG_TAG "OsclNativeFile"
#include <utils/Log.h>
@@ -34,97 +34,14 @@
#include "oscl_file_handle.h"
-#ifdef ENABLE_MEMORY_PLAYBACK
-pthread_key_t osclfilenativesigbuskey;
-
-/*
- * Add a structure describing the desired signal handling behavior
- * to the TLS. These structures form a linked list, which is needed
- * because multiple files might be opened by the same thread, in
- * which case we need to figure out which one was the one that
- * faulted.
- */
-static void addspecific(struct mediasigbushandler *newhandler)
-{
- struct mediasigbushandler *existinghandler =
- (struct mediasigbushandler*) pthread_getspecific(osclfilenativesigbuskey);
-
- if (existinghandler)
-{
- // append the new handler
- newhandler->next = NULL;
- existinghandler->next = newhandler;
- }
- else
- {
- newhandler->next = NULL;
- pthread_setspecific(osclfilenativesigbuskey, newhandler);
- }
-}
-
-/*
- * Remove a previously added structure from the list.
- */
-static void removespecific(struct mediasigbushandler *handler)
-{
- struct mediasigbushandler *existinghandler =
- (struct mediasigbushandler*) pthread_getspecific(osclfilenativesigbuskey);
-
- if (existinghandler == NULL || handler == NULL)
-{
- LOGE("logic error");
- return;
- }
-
- // to remove the first one, just set a new TLS entry
- if (existinghandler == handler)
- {
- pthread_setspecific(osclfilenativesigbuskey, handler->next);
- return;
- }
-
- while (existinghandler->next)
- {
- if (existinghandler->next == handler)
- {
- existinghandler->next = existinghandler->next->next;
- return;
- }
- existinghandler = existinghandler->next;
- }
-}
-
-/*
- * Find the struct for a given fault address
- */
-struct mediasigbushandler *OsclNativeFile::getspecificforfaultaddr(char *faultaddr)
-{
- struct mediasigbushandler *h =
- (struct mediasigbushandler*) pthread_getspecific(osclfilenativesigbuskey);
-
- while (h)
-{
- OsclNativeFile *f = (OsclNativeFile*)h->data;
- char *base = (char*) f->membase;
- if (base <= faultaddr && faultaddr < base + f->memlen)
- {
- return h;
- }
- h = h->next;
- }
- LOGE("couldn't find handler for address %p\n", faultaddr);
- return NULL;
-}
-#endif // ENABLE_MEMORY_PLAYBACK
-
OsclNativeFile::OsclNativeFile()
{
iOpenFileHandle = false;
iMode = 0;
iFile = 0;
-#ifdef ENABLE_MEMORY_PLAYBACK
- membase = NULL;
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ iSharedFd = -1;
#endif
}
@@ -226,23 +143,19 @@ int32 OsclNativeFile::Open(const oscl_wchar *filename, uint32 mode
{
return -1;
}
-#ifdef ENABLE_MEMORY_PLAYBACK
- void* base;
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ int fd;
long long offset;
long long len;
- if (sscanf(convfilename, "mem://%p:%lld:%lld", &base, &offset, &len) == 3)
+ if (sscanf(convfilename, "sharedfd://%d:%lld:%lld", &fd, &offset, &len) == 3)
{
- membase = base;
- memoffset = offset;
- memlen = len;
- mempos = 0;
-
- sigbushandler.handlesigbus = sigbushandlerfunc;
- sigbushandler.sigbusvar = NULL;
- sigbushandler.data = this;
- addspecific(&sigbushandler);
- sigbushandler.base = 0; // we do our own address matching
- sigbushandler.len = 0;
+ iSharedFd = fd;
+ iSharedFilePosition = 0;
+ iSharedFileOffset = offset;
+ long long size = lseek64(iSharedFd, 0, SEEK_END);
+ lseek64(iSharedFd, 0, SEEK_SET);
+ size -= offset;
+ iSharedFileSize = size < len ? size : len;
}
else
#endif
@@ -312,22 +225,19 @@ int32 OsclNativeFile::Open(const char *filename, uint32 mode
}
openmode[index++] = '\0';
-#ifdef ENABLE_MEMORY_PLAYBACK
- void* base;
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ int fd;
long long offset;
long long len;
- if (sscanf(filename, "mem://%p:%lld:%lld", &base, &offset, &len) == 3)
+ if (sscanf(filename, "sharedfd://%d:%lld:%lld", &fd, &offset, &len) == 3)
{
- membase = (void*)base;
- memoffset = offset;
- memlen = len;
- mempos = 0;
- sigbushandler.handlesigbus = sigbushandlerfunc;
- sigbushandler.sigbusvar = NULL;
- sigbushandler.data = this;
- addspecific(&sigbushandler);
- sigbushandler.base = 0; // we do our own address matching
- sigbushandler.len = 0;
+ iSharedFd = fd;
+ iSharedFilePosition = 0;
+ iSharedFileOffset = offset;
+ long long size = lseek64(iSharedFd, 0, SEEK_END);
+ lseek64(iSharedFd, 0, SEEK_SET);
+ size -= offset;
+ iSharedFileSize = size < len ? size : len;
}
else
#endif
@@ -375,12 +285,13 @@ int32 OsclNativeFile::Close()
closeret = fclose(iFile);
iFile = NULL;
}
-#ifdef ENABLE_MEMORY_PLAYBACK
- else if (membase != NULL)
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ else if (iSharedFd >= 0)
{
- membase = NULL;
- removespecific(&sigbushandler);
- return 0;
+ // we don't need to, and in fact MUST NOT, close mSharedFd here,
+ // since it might still be shared by another OsclFileNative, and
+ // will be closed by the playerdriver when we're done with it.
+ closeret = 0;
}
#endif
else
@@ -392,59 +303,30 @@ int32 OsclNativeFile::Close()
return closeret;
}
-#ifdef ENABLE_MEMORY_PLAYBACK
-int OsclNativeFile::sigbushandlerfunc(siginfo_t *info, struct mediasigbushandler *data)
-{
- char *faultaddr = (char*) info->si_addr;
- LOGE("read fault at %p\n", faultaddr);
-
- struct mediasigbushandler *h = getspecificforfaultaddr(faultaddr);
- if (h == NULL)
- {
- LOGE("No handler for fault range.");
- return -1;
- }
- else
- {
- ((OsclNativeFile*)h->data)->memcpyfailed = 1;
- // map in a zeroed out page so the operation can succeed
- long pagesize = sysconf(_SC_PAGE_SIZE);
- long pagemask = ~(pagesize - 1);
- void * pageaddr = (void*)(((long)(faultaddr)) & pagemask);
-
- void * bar = mmap(pageaddr, pagesize, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
- if (bar == MAP_FAILED)
- {
- LOGE("couldn't map zero page at %p: %s", pageaddr, strerror(errno));
- return -1;
- }
- }
- return 0;
-}
-#endif
-
uint32 OsclNativeFile::Read(OsclAny *buffer, uint32 size, uint32 numelements)
{
-#ifdef ENABLE_MEMORY_PLAYBACK
- if (membase)
- {
- int req = size * numelements;
- if (mempos + req > memlen)
- {
- req = memlen - mempos;
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ if (iSharedFd >= 0) {
+ // restore position, no locking is needed because all access to the
+ // shared filedescriptor is done by the same thread.
+ lseek64(iSharedFd, iSharedFilePosition + iSharedFileOffset, SEEK_SET);
+ uint32 count = size * numelements;
+ if (iSharedFilePosition + count > iSharedFileSize) {
+ count = iSharedFileSize - iSharedFilePosition;
}
-
- memcpyfailed = 0;
- memcpy(buffer, ((char*)membase) + memoffset + mempos, req);
- if (memcpyfailed)
- {
- LOGE("got bus error while reading");
- return 0;
+ ssize_t numread = read(iSharedFd, buffer, count);
+ // unlock
+ long long curpos = lseek64(iSharedFd, 0, SEEK_CUR);
+ if (curpos >= 0) {
+ iSharedFilePosition = curpos - iSharedFileOffset;
}
- mempos += req;
- return req / size;
+ if (numread < 0) {
+ return numread;
+ }
+ return numread / size;
}
#endif
+
if (iFile)
{
return fread(buffer, OSCL_STATIC_CAST(int32, size), OSCL_STATIC_CAST(int32, numelements), iFile);
@@ -475,8 +357,8 @@ uint32 OsclNativeFile::GetReadAsyncNumElements()
uint32 OsclNativeFile::Write(const OsclAny *buffer, uint32 size, uint32 numelements)
{
-#ifdef ENABLE_MEMORY_PLAYBACK
- if (membase)
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ if (iSharedFd >= 0)
return 0;
#endif
if (iFile)
@@ -490,18 +372,18 @@ int32 OsclNativeFile::Seek(int32 offset, Oscl_File::seek_type origin)
{
{
-#ifdef ENABLE_MEMORY_PLAYBACK
- if (membase)
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ if (iSharedFd >= 0)
{
- int newpos = mempos;
- if (origin == Oscl_File::SEEKCUR) newpos = mempos + offset;
+ int newpos = iSharedFilePosition;
+ if (origin == Oscl_File::SEEKCUR) newpos = newpos + offset;
else if (origin == Oscl_File::SEEKSET) newpos = offset;
- else if (origin == Oscl_File::SEEKEND) newpos = memlen + offset;
+ else if (origin == Oscl_File::SEEKEND) newpos = iSharedFileSize + offset;
if (newpos < 0)
return EINVAL;
- if (newpos > memlen) // is this valid?
- newpos = memlen;
- mempos = newpos;
+ if (newpos > iSharedFileSize) // is this valid?
+ newpos = iSharedFileSize;
+ iSharedFilePosition = newpos;
return 0;
}
#endif
@@ -509,7 +391,7 @@ int32 OsclNativeFile::Seek(int32 offset, Oscl_File::seek_type origin)
{
int32 seekmode = SEEK_CUR;
- if (origin == Oscl_File::SEEKCUR) seekmode = SEEK_CUR;
+ if (origin == Oscl_File::SEEKCUR) seekmode = SEEK_CUR;
else if (origin == Oscl_File::SEEKSET) seekmode = SEEK_SET;
else if (origin == Oscl_File::SEEKEND) seekmode = SEEK_END;
@@ -528,9 +410,9 @@ int32 OsclNativeFile::SetSize(uint32 size)
int32 OsclNativeFile::Tell()
{
-#ifdef ENABLE_MEMORY_PLAYBACK
- if (membase)
- return mempos;
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ if (iSharedFd >= 0)
+ return iSharedFilePosition;
#endif
if (iFile)
return ftell(iFile);
@@ -541,11 +423,6 @@ int32 OsclNativeFile::Tell()
int32 OsclNativeFile::Flush()
{
-
-#ifdef ENABLE_MEMORY_PLAYBACK
- if (membase)
- return 0;
-#endif
if (iFile)
return fflush(iFile);
return EOF;
@@ -556,9 +433,9 @@ int32 OsclNativeFile::Flush()
int32 OsclNativeFile::EndOfFile()
{
-#ifdef ENABLE_MEMORY_PLAYBACK
- if (membase)
- return mempos >= memlen;
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ if (iSharedFd >= 0)
+ return iSharedFilePosition >= iSharedFileSize;
#endif
if (iFile)
return feof(iFile);
@@ -568,10 +445,6 @@ int32 OsclNativeFile::EndOfFile()
int32 OsclNativeFile::GetError()
{
-#ifdef ENABLE_MEMORY_PLAYBACK
- if (membase)
- return 0;
-#endif
if (iFile)
return ferror(iFile);
return 0;
diff --git a/oscl/oscl/osclio/src/oscl_file_native.h b/oscl/oscl/osclio/src/oscl_file_native.h
index b1ca76391..94d4a290c 100644
--- a/oscl/oscl/osclio/src/oscl_file_native.h
+++ b/oscl/oscl/osclio/src/oscl_file_native.h
@@ -56,10 +56,6 @@
#include "oscl_file_types.h"
#endif
-#ifdef ENABLE_MEMORY_PLAYBACK
-#include <media/MediaPlayerInterface.h>
-#endif
-
/**
* OsclNativeFileIO defines the native file operations that must be implemented
* by every Oscl platform.
@@ -131,18 +127,13 @@ class OsclNativeFile : public HeapBase
//native file object.
FILE* iFile;
-#ifdef ENABLE_MEMORY_PLAYBACK
- static int sigbushandlerfunc(siginfo_t *, struct mediasigbushandler *);
- // memory block
- void* membase;
- long long memoffset;
- long long memlen;
- int mempos;
- struct mediasigbushandler sigbushandler;
- int memcpyfailed;
- static struct mediasigbushandler *getspecificforfaultaddr(char *faultaddr);
-#endif
+#ifdef ENABLE_SHAREDFD_PLAYBACK
+ int iSharedFd;
+ long long iSharedFileOffset;
+ long long iSharedFileSize;
+ long long iSharedFilePosition;
+#endif
};
#endif // OSCL_FILE_NATIVE_H_INCLUDED