diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-13 13:04:21 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-13 13:04:21 -0700 |
commit | 2c918c82a1735eeaba8cf84d1985b1b1c2ba0018 (patch) | |
tree | a79f7706ca4faa2273d4efcb6cc61a8da83d2044 | |
parent | 9a3f021d759ae484998ddabc3dc94a39496da4a5 (diff) | |
download | opencore-2c918c82a1735eeaba8cf84d1985b1b1c2ba0018.tar.gz |
auto import from //branches/cupcake_rel/...@138607
-rw-r--r-- | android/author/PVMediaRecorder.cpp | 14 | ||||
-rw-r--r-- | android/author/authordriver.cpp | 172 | ||||
-rw-r--r-- | android/author/authordriver.h | 24 | ||||
-rw-r--r-- | android/playerdriver.cpp | 43 | ||||
-rw-r--r-- | engines/player/src/pv_player_engine.cpp | 25 | ||||
-rw-r--r-- | nodes/pvmp4ffparsernode/src/pvmf_mp4ffparser_node.cpp | 44 | ||||
-rw-r--r-- | pvmi/pvmf/include/pvmf_return_codes.h | 4 | ||||
-rw-r--r-- | pvmi/pvmf/src/pvmf_return_codes.cpp | 1 |
8 files changed, 278 insertions, 49 deletions
diff --git a/android/author/PVMediaRecorder.cpp b/android/author/PVMediaRecorder.cpp index bea78ef1b..9464053cc 100644 --- a/android/author/PVMediaRecorder.cpp +++ b/android/author/PVMediaRecorder.cpp @@ -135,6 +135,19 @@ status_t PVMediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) return mAuthorDriverWrapper->enqueueCommand(ac, 0, 0); } +status_t PVMediaRecorder::setParameters(const String8& params) { + LOGV("setParameters(%s)", params.string()); + set_parameters_command *command = new set_parameters_command(params); + if (command == NULL) { + LOGE("failed to construct an author command"); + + return NO_MEMORY; + } + + return mAuthorDriverWrapper->enqueueCommand( + command, NULL /* completion_func */, NULL /* completion_cookie */); +} + status_t PVMediaRecorder::setAudioEncoder(audio_encoder ae) { LOGV("setAudioEncoder(%d)", ae); @@ -278,6 +291,7 @@ status_t PVMediaRecorder::start() LOGE("failed to construct an author command"); return UNKNOWN_ERROR; } + return mAuthorDriverWrapper->enqueueCommand(ac, 0, 0); } diff --git a/android/author/authordriver.cpp b/android/author/authordriver.cpp index 417f6b94a..37d3c7ef1 100644 --- a/android/author/authordriver.cpp +++ b/android/author/authordriver.cpp @@ -24,6 +24,7 @@ #include <ui/ICamera.h> #include "pv_omxmastercore.h" #include "authordriver.h" +#include "pvmf_composer_size_and_duration.h" using namespace android; @@ -249,6 +250,10 @@ void AuthorDriver::Run() handleSetOutputFile((set_output_file_command *)ac); return; + case AUTHOR_SET_PARAMETERS: + handleSetParameters((set_parameters_command *)ac); + return; + case AUTHOR_REMOVE_VIDEO_SOURCE: handleRemoveVideoSource(ac); return; @@ -553,6 +558,149 @@ exit: } } +PVMFStatus AuthorDriver::setMaxDuration(int64_t max_duration_ms) { + PVInterface *interface; + PvmfComposerSizeAndDurationInterface *durationConfig; + + if (max_duration_ms > 0xffffffff) { + // PV API expects this to fit in a uint32. + return PVMFErrArgument; + } + + if (!mComposerConfig) { + return PVMFFailure; + } + + mComposerConfig->queryInterface( + PvmfComposerSizeAndDurationUuid, interface); + + durationConfig = + OSCL_DYNAMIC_CAST(PvmfComposerSizeAndDurationInterface *, interface); + + if (!durationConfig) { + return PVMFFailure; + } + + // SetMaxDuration's first parameter is a boolean "enable", we enable + // enforcement of the maximum duration if it's (strictly) positive, + // otherwise we take it to imply disabling. + PVMFStatus ret = durationConfig->SetMaxDuration( + max_duration_ms > 0, static_cast<uint32>(max_duration_ms)); + + durationConfig->removeRef(); + durationConfig = NULL; + + return ret; +} + +// Attempt to parse an int64 literal optionally surrounded by whitespace, +// returns true on success, false otherwise. +static bool safe_strtoi64(const char *s, int64 *val) { + char *end; + *val = strtoll(s, &end, 10); + + if (end == s || errno == ERANGE) { + return false; + } + + // Skip trailing whitespace + while (isspace(*end)) { + ++end; + } + + // For a successful return, the string must contain nothing but a valid + // int64 literal optionally surrounded by whitespace. + + return *end == '\0'; +} + +// Trim both leading and trailing whitespace from the given string. +static void TrimString(String8 *s) { + size_t num_bytes = s->bytes(); + const char *data = s->string(); + + size_t leading_space = 0; + while (leading_space < num_bytes && isspace(data[leading_space])) { + ++leading_space; + } + + size_t i = num_bytes; + while (i > leading_space && isspace(data[i - 1])) { + --i; + } + + s->setTo(String8(&data[leading_space], i - leading_space)); +} + +PVMFStatus AuthorDriver::setParameter( + const String8& key, const String8& value) { + if (key == "max-duration") { + int64_t max_duration_ms; + if (safe_strtoi64(value.string(), &max_duration_ms)) { + return setMaxDuration(max_duration_ms); + } + } + + return PVMFErrArgument; +} + +// Applies the requested parameters, completes either successfully or stops +// application of parameters upon encountering the first error, finishing the +// transaction with the failure result of that initial failure. +void AuthorDriver::handleSetParameters(set_parameters_command *ac) { + PVMFStatus ret = PVMFSuccess; + + const char *params = ac->params().string(); + const char *key_start = params; + for (;;) { + const char *equal_pos = strchr(key_start, '='); + if (equal_pos == NULL) { + // This key is missing a value. + + ret = PVMFErrArgument; + break; + } + + String8 key(key_start, equal_pos - key_start); + TrimString(&key); + + if (key.length() == 0) { + ret = PVMFErrArgument; + break; + } + + const char *value_start = equal_pos + 1; + const char *semicolon_pos = strchr(value_start, ';'); + String8 value; + if (semicolon_pos == NULL) { + value.setTo(value_start); + } else { + value.setTo(value_start, semicolon_pos - value_start); + } + + ret = setParameter(key, value); + + if (ret != NO_ERROR) { + LOGE("setParameter(%s = %s) failed with result %d", + key.string(), value.string(), ret); + break; + } + + if (semicolon_pos == NULL) { + break; + } + + key_start = semicolon_pos + 1; + } + + if (ret == PVMFSuccess) { + FinishNonAsyncCommand(ac); + } else { + LOGE("Ln %d handleSetParameters(%s) error", __LINE__, params); + commandFailed(ac); + } +} + void AuthorDriver::handlePrepare(author_command *ac) { int error = 0; @@ -836,9 +984,31 @@ void AuthorDriver::HandleErrorEvent(const PVAsyncErrorEvent& aEvent) } } +static int GetMediaRecorderInfoCode(const PVAsyncInformationalEvent& aEvent) { + switch (aEvent.GetEventType()) { + case PVMF_COMPOSER_MAXDURATION_REACHED: + return MEDIA_RECORDER_INFO_MAX_DURATION_REACHED; + + default: + return MEDIA_RECORDER_INFO_UNKNOWN; + } +} + void AuthorDriver::HandleInformationalEvent(const PVAsyncInformationalEvent& aEvent) { - LOGV("HandleInformationalEvent(%d)", aEvent.GetEventType()); + const PVEventType event_type = aEvent.GetEventType(); + assert(!IsPVMFErrCode(event_type)); + if (IsPVMFInfoCode(event_type)) { + LOGV("HandleInformationalEvent(%d:%s)", + event_type, PVMFStatusToString(event_type)); + } else { + LOGV("HandleInformationalEvent(%d)", event_type); + } + + mListener->notify( + MEDIA_RECORDER_EVENT_INFO, + GetMediaRecorderInfoCode(aEvent), + aEvent.GetEventType()); } status_t AuthorDriver::getMaxAmplitude(int *max) diff --git a/android/author/authordriver.h b/android/author/authordriver.h index 0e0d50b08..aeada4111 100644 --- a/android/author/authordriver.h +++ b/android/author/authordriver.h @@ -92,6 +92,7 @@ enum author_command_type { AUTHOR_SET_VIDEO_FRAME_RATE, AUTHOR_SET_PREVIEW_SURFACE, AUTHOR_SET_OUTPUT_FILE, + AUTHOR_SET_PARAMETERS, AUTHOR_PREPARE, AUTHOR_START, AUTHOR_STOP, @@ -108,6 +109,8 @@ struct author_command this->which = which; } + virtual ~author_command() {} + author_command_type which; media_completion_f comp; void *cookie; @@ -176,6 +179,23 @@ struct set_camera_command : author_command sp<ICamera> camera; }; +struct set_parameters_command : author_command +{ + set_parameters_command(const String8& params) + : author_command(AUTHOR_SET_PARAMETERS), + mParams(params) { + } + + const String8& params() const { return mParams; } + +private: + String8 mParams; + + // Disallow copying and assignment. + set_parameters_command(const set_parameters_command&); + set_parameters_command& operator=(const set_parameters_command&); +}; + class AuthorDriver : public OsclActiveObject, public PVCommandStatusObserver, @@ -205,6 +225,7 @@ public: void handleSetVideoFrameRate(set_video_frame_rate_command *ac); void handleSetPreviewSurface(set_preview_surface_command *ac); void handleSetOutputFile(set_output_file_command *ac); + void handleSetParameters(set_parameters_command *ac); void handlePrepare(author_command *ac); void handleStart(author_command *ac); void handleStop(author_command *ac); @@ -248,6 +269,9 @@ private: // Callback for synchronous commands. static void syncCompletion(status_t s, void *cookie); + PVMFStatus setMaxDuration(int64_t max_duration_ms); + PVMFStatus setParameter(const String8 &key, const String8 &value); + PVAuthorEngineInterface *mAuthor; PvmiMIOControl *mVideoInputMIO; diff --git a/android/playerdriver.cpp b/android/playerdriver.cpp index a355510fe..859fab7b5 100644 --- a/android/playerdriver.cpp +++ b/android/playerdriver.cpp @@ -180,6 +180,34 @@ const char *PlayerCommandCodeToString(PlayerCommand::Code code) { } #undef CONSIDER_CODE +// Map a PV status code to a message type (error/info/nop) +// @param status PacketVideo status code as defined in pvmf_return_codes.h +// @return the corresponding android message type. MEDIA_NOP is used as a default. +::android::media_event_type MapStatusToEventType(const PVMFStatus status) { + if (status <= PVMFErrFirst) { + return ::android::MEDIA_ERROR; + } else if (status >= PVMFInfoFirst) { + return ::android::MEDIA_INFO; + } else { + return ::android::MEDIA_NOP; + } +} + +// Map a PV status to an error/info code. +// @param status PacketVideo status code as defined in pvmf_return_codes.h +// @return the corresponding android error/info code. +int MapStatusToEventCode(const PVMFStatus status) { + switch (status) { + case PVMFErrContentInvalidForProgressivePlayback: + return ::android::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK; + default: + // Takes advantage that both error and info codes are mapped to the + // same value. + assert(::android::MEDIA_ERROR_UNKNOWN == ::android::MEDIA_INFO_UNKNOWN); + return ::android::MEDIA_ERROR_UNKNOWN; + } +} + } // anonymous namespace class PlayerDriver : @@ -1146,12 +1174,12 @@ void PlayerDriver::CommandCompleted(const PVCmdResponse& aResponse) status = PVMFSuccess; command->complete(NO_ERROR, true); } else { - // error occurred - LOGE("CommandCompleted with an error or info %s", PVMFStatusToString(status)); - if (status <= PVMFErrFirst) { - mPvPlayer->sendEvent(MEDIA_ERROR, ::android::MEDIA_ERROR_UNKNOWN, status); - } else if (status >= PVMFInfoFirst) { - mPvPlayer->sendEvent(MEDIA_INFO, ::android::MEDIA_INFO_UNKNOWN, status); + // Try to map the PV error code to an Android one. + LOGE("Command %s completed with an error or info %s", command->toString(), PVMFStatusToString(status)); + const media_event_type event_type = MapStatusToEventType(status); + + if (MEDIA_NOP != event_type) { + mPvPlayer->sendEvent(event_type, MapStatusToEventCode(status), status); } else { LOGE("Ignoring: %d", status); } @@ -1169,6 +1197,7 @@ void PlayerDriver::HandleErrorEvent(const PVAsyncErrorEvent& aEvent) if (status > PVMFErrFirst) { LOGE("HandleErrorEvent called with an non-error event [%d]!!", status); } + LOGE("HandleErrorEvent: %s", PVMFStatusToString(status)); // TODO: Map more of the PV error code into the Android Media Player ones. mPvPlayer->sendEvent(MEDIA_ERROR, ::android::MEDIA_ERROR_UNKNOWN, status); @@ -1289,7 +1318,7 @@ void PlayerDriver::HandleInformationalEvent(const PVAsyncInformationalEvent& aEv break; default: - LOGV("HandleInformationalEvent: type=%d UNHANDLED", status); + LOGE("HandleInformationalEvent: type=%d UNHANDLED", status); break; } } diff --git a/engines/player/src/pv_player_engine.cpp b/engines/player/src/pv_player_engine.cpp index 43ac44b3e..f7f82cccd 100644 --- a/engines/player/src/pv_player_engine.cpp +++ b/engines/player/src/pv_player_engine.cpp @@ -3897,6 +3897,7 @@ PVMFStatus PVPlayerEngine::DoSetupSourceNode(PVCommandId aCmdId, OsclAny* aCmdCo return PVMFErrNotSupported; } + int32 leavecode = 0; OSCL_TRY(leavecode, iSourceNode = iPlayerNodeRegistry.CreateNode(foundUuids[0])); OSCL_FIRST_CATCH_ANY(leavecode, @@ -11970,6 +11971,8 @@ void PVPlayerEngine::HandleSourceNodeInit(PVPlayerEngineContext& aNodeContext, c iCommandCompleteInEngineAOPending = false; PVMFStatus cmdstatus; + PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeInit() Status= %s", PVMFStatusToString(aNodeResp.GetCmdStatus()))); + switch (aNodeResp.GetCmdStatus()) { case PVMFSuccess: @@ -12019,7 +12022,25 @@ void PVPlayerEngine::HandleSourceNodeInit(PVPlayerEngineContext& aNodeContext, c } break; - ; + case PVMFErrContentInvalidForProgressivePlayback: + { + SetEngineState(PVP_ENGINE_STATE_ERROR); + AddCommandToQueue(PVP_ENGINE_COMMAND_STOP_DUE_TO_ERROR, NULL, NULL, NULL, false); + + cmdstatus = aNodeResp.GetCmdStatus(); + + PVMFErrorInfoMessageInterface* nextmsg = NULL; + if (aNodeResp.GetEventExtensionInterface()) + { + nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); + } + + PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; + PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg)); + EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg), aNodeResp.GetEventData()); + errmsg->removeRef(); + } + break; default: { @@ -17013,5 +17034,3 @@ void PVPlayerEngine::DepopulateAllRegistries() DepopulateRecognizerRegistry(); } #endif - - diff --git a/nodes/pvmp4ffparsernode/src/pvmf_mp4ffparser_node.cpp b/nodes/pvmp4ffparsernode/src/pvmf_mp4ffparser_node.cpp index c09414df1..57193f3c3 100644 --- a/nodes/pvmp4ffparsernode/src/pvmf_mp4ffparser_node.cpp +++ b/nodes/pvmp4ffparsernode/src/pvmf_mp4ffparser_node.cpp @@ -7211,6 +7211,7 @@ PVMFStatus PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() isProgressiveDownloadable, iMP4HeaderSize); + PVMFStatus retcode = PVMFFailure; if (retCode == EVERYTHING_FINE) { if (isProgressiveDownloadable == true) @@ -7227,11 +7228,11 @@ PVMFStatus PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() *this, iMP4HeaderSize); iDataStreamRequestPending = true; - return PVMFPending; + retcode = PVMFPending; } else { - return PVMFSuccess; + retcode = PVMFSuccess; } } else @@ -7260,7 +7261,7 @@ PVMFStatus PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() download_progress_interface->requestResumeNotification(nptTsinMS, iDownloadComplete); } PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - Auto Pause Triggered, TS = %d", nptTsinMS)); - return PVMFPending; + retcode = PVMFPending; } else { @@ -7272,13 +7273,14 @@ PVMFStatus PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() { // progressive playback and no movie atom found PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - Moov atom not found, needed for progressive playback")); + retcode = PVMFErrContentInvalidForProgressivePlayback; } else { PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - GetMetaDataSize Failed %d", retCode)); } - return PVMFFailure; + return retcode; } return PVMFSuccess; } @@ -8411,37 +8413,3 @@ bool PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand(PVMP4FFNodeTrackPortInfo PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand() BOS sent StreamId=%d ", iStreamID)); return true; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pvmi/pvmf/include/pvmf_return_codes.h b/pvmi/pvmf/include/pvmf_return_codes.h index 5aaaefe0e..46a175bdf 100644 --- a/pvmi/pvmf/include/pvmf_return_codes.h +++ b/pvmi/pvmf/include/pvmf_return_codes.h @@ -161,6 +161,10 @@ const PVMFStatus PVMFLowDiskSpace = (-25); Error due to the requirement of user-id and password input from app for HTTP basic/digest authentication */ const PVMFStatus PVMFErrHTTPAuthenticationRequired = (-26); +/* + Error: the video container is not valid for progressive playback. + */ +const PVMFStatus PVMFErrContentInvalidForProgressivePlayback = (-27); /* Placeholder for last event in range. diff --git a/pvmi/pvmf/src/pvmf_return_codes.cpp b/pvmi/pvmf/src/pvmf_return_codes.cpp index a07a28968..6673706b6 100644 --- a/pvmi/pvmf/src/pvmf_return_codes.cpp +++ b/pvmi/pvmf/src/pvmf_return_codes.cpp @@ -53,6 +53,7 @@ const char *PVMFStatusToString(const PVMFStatus status) { CONSIDER(PVMFErrMaxReached); CONSIDER(PVMFLowDiskSpace); CONSIDER(PVMFErrHTTPAuthenticationRequired); + CONSIDER(PVMFErrContentInvalidForProgressivePlayback); CONSIDER(PVMFInfoPortCreated); CONSIDER(PVMFInfoPortDeleted); CONSIDER(PVMFInfoPortConnected); |