Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libva
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
libva
Commits
152b03e8
Commit
152b03e8
authored
Apr 01, 2010
by
Austin Yuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added MIO example based on vaPutSurface
Signed-off-by:
Austin Yuan
<
shengquan.yuan@gmail.com
>
parent
680ebba2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1427 additions
and
0 deletions
+1427
-0
va/android/android_surface_output.cpp
va/android/android_surface_output.cpp
+1091
-0
va/android/android_surface_output.h
va/android/android_surface_output.h
+336
-0
No files found.
va/android/android_surface_output.cpp
0 → 100644
View file @
152b03e8
/* ------------------------------------------------------------------
* Copyright (C) 2008 PacketVideo
*
* 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.
* -------------------------------------------------------------------
*/
//#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>
#include "pvlogger.h"
#include "pv_mime_string_utils.h"
#include "oscl_snprintf.h"
#include "oscl_dll.h"
#ifdef __cplusplus
extern
"C"
{
#endif
#include <va/va.h>
#include <va/va_x11.h>
#ifdef __cplusplus
}
/* extern "C" */
#endif
// Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT
()
//The factory functions.
#include "oscl_mem.h"
using
namespace
android
;
OSCL_EXPORT_REF
AndroidSurfaceOutput
::
AndroidSurfaceOutput
()
:
OsclTimerObject
(
OsclActiveObject
::
EPriorityNominal
,
"androidsurfaceoutput"
)
{
initData
();
iColorConverter
=
NULL
;
mInitialized
=
false
;
mPvPlayer
=
NULL
;
mEmulation
=
false
;
iEosReceived
=
false
;
mNumberOfFramesToHold
=
2
;
}
status_t
AndroidSurfaceOutput
::
set
(
PVPlayer
*
pvPlayer
,
const
sp
<
ISurface
>&
surface
,
bool
emulation
)
{
mPvPlayer
=
pvPlayer
;
mEmulation
=
emulation
;
setVideoSurface
(
surface
);
return
NO_ERROR
;
}
status_t
AndroidSurfaceOutput
::
setVideoSurface
(
const
sp
<
ISurface
>&
surface
)
{
LOGV
(
"setVideoSurface(%p)"
,
surface
.
get
());
// unregister buffers for the old surface
if
(
mSurface
!=
NULL
)
{
LOGV
(
"unregisterBuffers from old surface"
);
mSurface
->
unregisterBuffers
();
}
mSurface
=
surface
;
// register buffers for the new surface
if
((
mSurface
!=
NULL
)
&&
(
mBufferHeap
.
heap
!=
NULL
))
{
LOGV
(
"registerBuffers from old surface"
);
mSurface
->
registerBuffers
(
mBufferHeap
);
}
return
NO_ERROR
;
}
void
AndroidSurfaceOutput
::
initData
()
{
iVideoHeight
=
iVideoWidth
=
iVideoDisplayHeight
=
iVideoDisplayWidth
=
0
;
iVideoFormat
=
PVMF_MIME_FORMAT_UNKNOWN
;
resetVideoParameterFlags
();
iCommandCounter
=
0
;
iLogger
=
NULL
;
iCommandResponseQueue
.
reserve
(
5
);
iWriteResponseQueue
.
reserve
(
5
);
iObserver
=
NULL
;
iLogger
=
NULL
;
iPeer
=
NULL
;
iState
=
STATE_IDLE
;
iIsMIOConfigured
=
false
;
}
void
AndroidSurfaceOutput
::
ResetData
()
//reset all data from this session.
{
Cleanup
();
//reset all the received media parameters.
iVideoFormatString
=
""
;
iVideoFormat
=
PVMF_MIME_FORMAT_UNKNOWN
;
resetVideoParameterFlags
();
iIsMIOConfigured
=
false
;
}
void
AndroidSurfaceOutput
::
resetVideoParameterFlags
()
{
iVideoParameterFlags
=
VIDEO_PARAMETERS_INVALID
;
}
bool
AndroidSurfaceOutput
::
checkVideoParameterFlags
()
{
return
(
iVideoParameterFlags
&
VIDEO_PARAMETERS_MASK
)
==
VIDEO_PARAMETERS_VALID
;
}
/*
* process the write response queue by sending writeComplete to the peer
* (nominally the decoder node).
*
* numFramesToHold is the number of frames to be held in the MIO. During
* playback, we hold the last frame which is used by SurfaceFlinger
* to composite the final output.
*/
void
AndroidSurfaceOutput
::
processWriteResponseQueue
(
int
numFramesToHold
)
{
LOGV
(
"processWriteResponseQueue: queued = %d, numFramesToHold = %d"
,
iWriteResponseQueue
.
size
(),
numFramesToHold
);
while
(
iWriteResponseQueue
.
size
()
>
numFramesToHold
)
{
if
(
iPeer
)
{
iPeer
->
writeComplete
(
iWriteResponseQueue
[
0
].
iStatus
,
iWriteResponseQueue
[
0
].
iCmdId
,
(
OsclAny
*
)
iWriteResponseQueue
[
0
].
iContext
);
}
iWriteResponseQueue
.
erase
(
&
iWriteResponseQueue
[
0
]);
}
}
void
AndroidSurfaceOutput
::
Cleanup
()
//cleanup all allocated memory and release resources.
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Cleanup() In"
));
while
(
!
iCommandResponseQueue
.
empty
())
{
if
(
iObserver
)
iObserver
->
RequestCompleted
(
PVMFCmdResp
(
iCommandResponseQueue
[
0
].
iCmdId
,
iCommandResponseQueue
[
0
].
iContext
,
iCommandResponseQueue
[
0
].
iStatus
));
iCommandResponseQueue
.
erase
(
&
iCommandResponseQueue
[
0
]);
}
processWriteResponseQueue
(
0
);
// We'll close frame buf and delete here for now.
closeFrameBuf
();
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Cleanup() Out"
));
}
OSCL_EXPORT_REF
AndroidSurfaceOutput
::~
AndroidSurfaceOutput
()
{
Cleanup
();
}
PVMFStatus
AndroidSurfaceOutput
::
connect
(
PvmiMIOSession
&
aSession
,
PvmiMIOObserver
*
aObserver
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::connect() called"
));
// Each Session could have its own set of Configuration parameters
//in an array of structures and the session ID could be an index to that array.
//currently supports only one session
if
(
iObserver
)
return
PVMFFailure
;
iObserver
=
aObserver
;
return
PVMFSuccess
;
}
PVMFStatus
AndroidSurfaceOutput
::
disconnect
(
PvmiMIOSession
aSession
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::disconnect() called"
));
//currently supports only one session
iObserver
=
NULL
;
return
PVMFSuccess
;
}
PvmiMediaTransfer
*
AndroidSurfaceOutput
::
createMediaTransfer
(
PvmiMIOSession
&
aSession
,
PvmiKvp
*
read_formats
,
int32
read_flags
,
PvmiKvp
*
write_formats
,
int32
write_flags
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::createMediaTransfer() called"
));
return
(
PvmiMediaTransfer
*
)
this
;
}
void
AndroidSurfaceOutput
::
QueueCommandResponse
(
CommandResponse
&
aResp
)
{
//queue a command response and schedule processing.
iCommandResponseQueue
.
push_back
(
aResp
);
//cancel any timer delay so the command response will happen ASAP.
if
(
IsBusy
())
Cancel
();
RunIfNotReady
();
}
PVMFCommandId
AndroidSurfaceOutput
::
QueryUUID
(
const
PvmfMimeString
&
aMimeType
,
Oscl_Vector
<
PVUuid
,
OsclMemAllocator
>&
aUuids
,
bool
aExactUuidsOnly
,
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::QueryUUID() called"
));
OSCL_UNUSED_ARG
(
aMimeType
);
OSCL_UNUSED_ARG
(
aExactUuidsOnly
);
PVMFCommandId
cmdid
=
iCommandCounter
++
;
PVMFStatus
status
=
PVMFFailure
;
int32
err
;
OSCL_TRY
(
err
,
aUuids
.
push_back
(
PVMI_CAPABILITY_AND_CONFIG_PVUUID
););
if
(
err
==
OsclErrNone
)
status
=
PVMFSuccess
;
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
QueryInterface
(
const
PVUuid
&
aUuid
,
PVInterface
*&
aInterfacePtr
,
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::QueryInterface() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
PVMFStatus
status
=
PVMFFailure
;
if
(
aUuid
==
PVMI_CAPABILITY_AND_CONFIG_PVUUID
)
{
PvmiCapabilityAndConfig
*
myInterface
=
OSCL_STATIC_CAST
(
PvmiCapabilityAndConfig
*
,
this
);
aInterfacePtr
=
OSCL_STATIC_CAST
(
PVInterface
*
,
myInterface
);
status
=
PVMFSuccess
;
}
else
{
status
=
PVMFFailure
;
}
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
void
AndroidSurfaceOutput
::
deleteMediaTransfer
(
PvmiMIOSession
&
aSession
,
PvmiMediaTransfer
*
media_transfer
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::deleteMediaTransfer() called"
));
// This class is implementing the media transfer, so no cleanup is needed
}
PVMFCommandId
AndroidSurfaceOutput
::
Init
(
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Init() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
PVMFStatus
status
=
PVMFFailure
;
switch
(
iState
)
{
case
STATE_LOGGED_ON
:
status
=
PVMFSuccess
;
iState
=
STATE_INITIALIZED
;
break
;
default:
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Invalid State"
));
status
=
PVMFErrInvalidState
;
break
;
}
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
Reset
(
const
OsclAny
*
aContext
)
{
ResetData
();
PVMFCommandId
cmdid
=
iCommandCounter
++
;
CommandResponse
resp
(
PVMFSuccess
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
Start
(
const
OsclAny
*
aContext
)
{
iEosReceived
=
false
;
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Start() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
PVMFStatus
status
=
PVMFFailure
;
switch
(
iState
)
{
case
STATE_INITIALIZED
:
case
STATE_PAUSED
:
iState
=
STATE_STARTED
;
processWriteResponseQueue
(
0
);
status
=
PVMFSuccess
;
break
;
default:
status
=
PVMFErrInvalidState
;
break
;
}
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
// post the last video frame to refresh screen after pause
void
AndroidSurfaceOutput
::
postLastFrame
()
{
// ignore if no surface or heap
if
((
mSurface
==
NULL
)
||
(
mBufferHeap
.
heap
==
NULL
))
return
;
mSurface
->
postBuffer
(
mFrameBuffers
[
mFrameBufferIndex
]);
}
PVMFCommandId
AndroidSurfaceOutput
::
Pause
(
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Pause() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
PVMFStatus
status
=
PVMFFailure
;
switch
(
iState
)
{
case
STATE_STARTED
:
iState
=
STATE_PAUSED
;
status
=
PVMFSuccess
;
// post last buffer to prevent stale data
// if not configured, PVMFMIOConfigurationComplete is not sent
// there should not be any media data.
if
(
iIsMIOConfigured
)
{
postLastFrame
();
}
break
;
default:
status
=
PVMFErrInvalidState
;
break
;
}
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
Flush
(
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Flush() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
PVMFStatus
status
=
PVMFFailure
;
switch
(
iState
)
{
case
STATE_STARTED
:
iState
=
STATE_INITIALIZED
;
status
=
PVMFSuccess
;
break
;
default:
status
=
PVMFErrInvalidState
;
break
;
}
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
DiscardData
(
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::DiscardData() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
//this component doesn't buffer data, so there's nothing
//needed here.
PVMFStatus
status
=
PVMFSuccess
;
processWriteResponseQueue
(
0
);
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
DiscardData
(
PVMFTimestamp
aTimestamp
,
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::DiscardData() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
aTimestamp
=
0
;
//this component doesn't buffer data, so there's nothing
//needed here.
PVMFStatus
status
=
PVMFSuccess
;
processWriteResponseQueue
(
0
);
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
Stop
(
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::Stop() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
PVMFStatus
status
=
PVMFFailure
;
switch
(
iState
)
{
case
STATE_STARTED
:
case
STATE_PAUSED
:
#ifdef PERFORMANCE_MEASUREMENTS_ENABLED
// FIXME: This should be moved to OMAP library
PVOmapVideoProfile
.
MarkEndTime
();
PVOmapVideoProfile
.
PrintStats
();
PVOmapVideoProfile
.
Reset
();
#endif
iState
=
STATE_INITIALIZED
;
status
=
PVMFSuccess
;
break
;
default:
status
=
PVMFErrInvalidState
;
break
;
}
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
CancelAllCommands
(
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::CancelAllCommands() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
//commands are executed immediately upon being received, so
//it isn't really possible to cancel them.
PVMFStatus
status
=
PVMFSuccess
;
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
PVMFCommandId
AndroidSurfaceOutput
::
CancelCommand
(
PVMFCommandId
aCmdId
,
const
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::CancelCommand() called"
));
PVMFCommandId
cmdid
=
iCommandCounter
++
;
//commands are executed immediately upon being received, so
//it isn't really possible to cancel them.
//see if the response is still queued.
PVMFStatus
status
=
PVMFFailure
;
for
(
uint32
i
=
0
;
i
<
iCommandResponseQueue
.
size
();
i
++
)
{
if
(
iCommandResponseQueue
[
i
].
iCmdId
==
aCmdId
)
{
status
=
PVMFSuccess
;
break
;
}
}
CommandResponse
resp
(
status
,
cmdid
,
aContext
);
QueueCommandResponse
(
resp
);
return
cmdid
;
}
void
AndroidSurfaceOutput
::
ThreadLogon
()
{
if
(
iState
==
STATE_IDLE
)
{
iLogger
=
PVLogger
::
GetLoggerObject
(
"PVOmapVideo"
);
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::ThreadLogon() called"
));
AddToScheduler
();
iState
=
STATE_LOGGED_ON
;
}
}
void
AndroidSurfaceOutput
::
ThreadLogoff
()
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::ThreadLogoff() called"
));
if
(
iState
!=
STATE_IDLE
)
{
RemoveFromScheduler
();
iLogger
=
NULL
;
iState
=
STATE_IDLE
;
}
}
void
AndroidSurfaceOutput
::
setPeer
(
PvmiMediaTransfer
*
aPeer
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setPeer() called"
));
// Set the observer
iPeer
=
aPeer
;
}
void
AndroidSurfaceOutput
::
useMemoryAllocators
(
OsclMemAllocator
*
write_alloc
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::useMemoryAllocators() called"
));
//not supported.
}
// This routine will determine whether data can be accepted in a writeAsync
// call and if not, will return true;
bool
AndroidSurfaceOutput
::
CheckWriteBusy
(
uint32
aSeqNum
)
{
// for all other cases, accept data now.
return
false
;
}
PVMFCommandId
AndroidSurfaceOutput
::
writeAsync
(
uint8
aFormatType
,
int32
aFormatIndex
,
uint8
*
aData
,
uint32
aDataLen
,
const
PvmiMediaXferHeader
&
data_header_info
,
OsclAny
*
aContext
)
{
// Do a leave if MIO is not configured except when it is an EOS
if
(
!
iIsMIOConfigured
&&
!
((
PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION
==
aFormatType
)
&&
(
PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM
==
aFormatIndex
)))
{
LOGE
(
"data is pumped in before MIO is configured"
);
OSCL_LEAVE
(
OsclErrInvalidState
);
return
-
1
;
}
uint32
aSeqNum
=
data_header_info
.
seq_num
;
PVMFTimestamp
aTimestamp
=
data_header_info
.
timestamp
;
uint32
flags
=
data_header_info
.
flags
;
if
(
aSeqNum
<
6
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::writeAsync() seqnum %d ts %d context %d"
,
aSeqNum
,
aTimestamp
,
aContext
));
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::writeAsync() Format Type %d Format Index %d length %d"
,
aFormatType
,
aFormatIndex
,
aDataLen
));
}
PVMFStatus
status
=
PVMFFailure
;
switch
(
aFormatType
)
{
case
PVMI_MEDIAXFER_FMT_TYPE_COMMAND
:
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::writeAsync() called with Command info."
));
//ignore
status
=
PVMFSuccess
;
break
;
case
PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION
:
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::writeAsync() called with Notification info."
));
switch
(
aFormatIndex
)
{
case
PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM
:
iEosReceived
=
true
;
break
;
default:
break
;
}
//ignore
status
=
PVMFSuccess
;
break
;
case
PVMI_MEDIAXFER_FMT_TYPE_DATA
:
switch
(
aFormatIndex
)
{
case
PVMI_MEDIAXFER_FMT_INDEX_FMT_SPECIFIC_INFO
:
//format-specific info contains codec headers.
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::writeAsync() called with format-specific info."
));
if
(
iState
<
STATE_INITIALIZED
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_REL
,
iLogger
,
PVLOGMSG_ERR
,
(
0
,
"AndroidSurfaceOutput::writeAsync: Error - Invalid state"
));
status
=
PVMFErrInvalidState
;
}
else
{
status
=
PVMFSuccess
;
}
break
;
case
PVMI_MEDIAXFER_FMT_INDEX_DATA
:
//data contains the media bitstream.
//Verify the state
if
(
iState
!=
STATE_STARTED
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_REL
,
iLogger
,
PVLOGMSG_ERR
,
(
0
,
"AndroidSurfaceOutput::writeAsync: Error - Invalid state"
));
status
=
PVMFErrInvalidState
;
}
else
{
//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
);
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_REL
,
iLogger
,
PVLOGMSG_ERR
,
(
0
,
"AndroidSurfaceOutput::writeAsync: Playback Progress - frame %d"
,
iFrameNumber
++
));
}
break
;
default:
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_REL
,
iLogger
,
PVLOGMSG_ERR
,
(
0
,
"AndroidSurfaceOutput::writeAsync: Error - unrecognized format index"
));
status
=
PVMFFailure
;
break
;
}
break
;
default:
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_REL
,
iLogger
,
PVLOGMSG_ERR
,
(
0
,
"AndroidSurfaceOutput::writeAsync: Error - unrecognized format type"
));
status
=
PVMFFailure
;
break
;
}
//Schedule asynchronous response
PVMFCommandId
cmdid
=
iCommandCounter
++
;
WriteResponse
resp
(
status
,
cmdid
,
aContext
,
aTimestamp
);
iWriteResponseQueue
.
push_back
(
resp
);
RunIfNotReady
();
return
cmdid
;
}
void
AndroidSurfaceOutput
::
writeComplete
(
PVMFStatus
aStatus
,
PVMFCommandId
write_cmd_id
,
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::writeComplete() called"
));
//won't be called since this component is a sink.
}
PVMFCommandId
AndroidSurfaceOutput
::
readAsync
(
uint8
*
data
,
uint32
max_data_len
,
OsclAny
*
aContext
,
int32
*
formats
,
uint16
num_formats
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::readAsync() called"
));
//read not supported.
OsclError
::
Leave
(
OsclErrNotSupported
);
return
-
1
;
}
void
AndroidSurfaceOutput
::
readComplete
(
PVMFStatus
aStatus
,
PVMFCommandId
read_cmd_id
,
int32
format_index
,
const
PvmiMediaXferHeader
&
data_header_info
,
OsclAny
*
aContext
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::readComplete() called"
));
//won't be called since this component is a sink.
}
void
AndroidSurfaceOutput
::
statusUpdate
(
uint32
status_flags
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::statusUpdate() called"
));
//won't be called since this component is a sink.
}
void
AndroidSurfaceOutput
::
cancelCommand
(
PVMFCommandId
command_id
)
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::cancelCommand() called"
));
//the purpose of this API is to cancel a writeAsync command and report
//completion ASAP.
//in this implementation, the write commands are executed immediately
//when received so it isn't really possible to cancel.
//just report completion immediately.
processWriteResponseQueue
(
0
);
}
void
AndroidSurfaceOutput
::
cancelAllCommands
()
{
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::cancelAllCommands() called"
));
//the purpose of this API is to cancel all writeAsync commands and report
//completion ASAP.
//in this implementaiton, the write commands are executed immediately
//when received so it isn't really possible to cancel.
//just report completion immediately.
for
(
uint32
i
=
0
;
i
<
iWriteResponseQueue
.
size
();
i
++
)
{
//report completion
if
(
iPeer
)
iPeer
->
writeComplete
(
iWriteResponseQueue
[
i
].
iStatus
,
iWriteResponseQueue
[
i
].
iCmdId
,(
OsclAny
*
)
iWriteResponseQueue
[
i
].
iContext
);
iWriteResponseQueue
.
erase
(
&
iWriteResponseQueue
[
i
]);
}
}
void
AndroidSurfaceOutput
::
setObserver
(
PvmiConfigAndCapabilityCmdObserver
*
aObserver
)
{
OSCL_UNUSED_ARG
(
aObserver
);
//not needed since this component only supports synchronous capability & config
//APIs.
}
PVMFStatus
AndroidSurfaceOutput
::
getParametersSync
(
PvmiMIOSession
aSession
,
PvmiKeyType
aIdentifier
,
PvmiKvp
*&
aParameters
,
int
&
num_parameter_elements
,
PvmiCapabilityContext
aContext
)
{
OSCL_UNUSED_ARG
(
aSession
);
OSCL_UNUSED_ARG
(
aContext
);
aParameters
=
NULL
;
// This is a query for the list of supported formats.
if
(
pv_mime_strcmp
(
aIdentifier
,
INPUT_FORMATS_CAP_QUERY
)
==
0
)
{
aParameters
=
(
PvmiKvp
*
)
oscl_malloc
(
sizeof
(
PvmiKvp
));
if
(
aParameters
==
NULL
)
return
PVMFErrNoMemory
;
aParameters
[
num_parameter_elements
++
].
value
.
pChar_value
=
(
char
*
)
PVMF_MIME_YUV420
;
return
PVMFSuccess
;
}
//unrecognized key.
return
PVMFFailure
;
}
PVMFStatus
AndroidSurfaceOutput
::
releaseParameters
(
PvmiMIOSession
aSession
,
PvmiKvp
*
aParameters
,
int
num_elements
)
{
//release parameters that were allocated by this component.
if
(
aParameters
)
{
oscl_free
(
aParameters
);
return
PVMFSuccess
;
}
return
PVMFFailure
;
}
void
AndroidSurfaceOutput
::
createContext
(
PvmiMIOSession
aSession
,
PvmiCapabilityContext
&
aContext
)
{
OsclError
::
Leave
(
OsclErrNotSupported
);
}
void
AndroidSurfaceOutput
::
setContextParameters
(
PvmiMIOSession
aSession
,
PvmiCapabilityContext
&
aContext
,
PvmiKvp
*
aParameters
,
int
num_parameter_elements
)
{
OsclError
::
Leave
(
OsclErrNotSupported
);
}
void
AndroidSurfaceOutput
::
DeleteContext
(
PvmiMIOSession
aSession
,
PvmiCapabilityContext
&
aContext
)
{
OsclError
::
Leave
(
OsclErrNotSupported
);
}
void
AndroidSurfaceOutput
::
setParametersSync
(
PvmiMIOSession
aSession
,
PvmiKvp
*
aParameters
,
int
num_elements
,
PvmiKvp
*
&
aRet_kvp
)
{
OSCL_UNUSED_ARG
(
aSession
);
aRet_kvp
=
NULL
;
LOGV
(
"setParametersSync"
);
for
(
int32
i
=
0
;
i
<
num_elements
;
i
++
)
{
//Check against known video parameter keys...
if
(
pv_mime_strcmp
(
aParameters
[
i
].
key
,
MOUT_VIDEO_FORMAT_KEY
)
==
0
)
{
iVideoFormatString
=
aParameters
[
i
].
value
.
pChar_value
;
iVideoFormat
=
iVideoFormatString
.
get_str
();
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setParametersSync() Video Format Key, Value %s"
,
iVideoFormatString
.
get_str
()));
}
else
if
(
pv_mime_strcmp
(
aParameters
[
i
].
key
,
MOUT_VIDEO_WIDTH_KEY
)
==
0
)
{
iVideoWidth
=
(
int32
)
aParameters
[
i
].
value
.
uint32_value
;
iVideoParameterFlags
|=
VIDEO_WIDTH_VALID
;
LOGV
(
"iVideoWidth=%d"
,
iVideoWidth
);
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setParametersSync() Video Width Key, Value %d"
,
iVideoWidth
));
}
else
if
(
pv_mime_strcmp
(
aParameters
[
i
].
key
,
MOUT_VIDEO_HEIGHT_KEY
)
==
0
)
{
iVideoHeight
=
(
int32
)
aParameters
[
i
].
value
.
uint32_value
;
iVideoParameterFlags
|=
VIDEO_HEIGHT_VALID
;
LOGV
(
"iVideoHeight=%d"
,
iVideoHeight
);
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setParametersSync() Video Height Key, Value %d"
,
iVideoHeight
));
}
else
if
(
pv_mime_strcmp
(
aParameters
[
i
].
key
,
MOUT_VIDEO_DISPLAY_HEIGHT_KEY
)
==
0
)
{
iVideoDisplayHeight
=
(
int32
)
aParameters
[
i
].
value
.
uint32_value
;
iVideoParameterFlags
|=
DISPLAY_HEIGHT_VALID
;
LOGV
(
"iVideoDisplayHeight=%d"
,
iVideoDisplayHeight
);
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setParametersSync() Video Display Height Key, Value %d"
,
iVideoDisplayHeight
));
}
else
if
(
pv_mime_strcmp
(
aParameters
[
i
].
key
,
MOUT_VIDEO_DISPLAY_WIDTH_KEY
)
==
0
)
{
iVideoDisplayWidth
=
(
int32
)
aParameters
[
i
].
value
.
uint32_value
;
iVideoParameterFlags
|=
DISPLAY_WIDTH_VALID
;
LOGV
(
"iVideoDisplayWidth=%d"
,
iVideoDisplayWidth
);
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setParametersSync() Video Display Width Key, Value %d"
,
iVideoDisplayWidth
));
}
else
if
(
pv_mime_strcmp
(
aParameters
[
i
].
key
,
MOUT_VIDEO_SUBFORMAT_KEY
)
==
0
)
{
iVideoSubFormat
=
aParameters
[
i
].
value
.
pChar_value
;
iVideoParameterFlags
|=
VIDEO_SUBFORMAT_VALID
;
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setParametersSync() Video SubFormat Key, Value %s"
,
iVideoSubFormat
.
getMIMEStrPtr
()));
LOGV
(
"VIDEO SUBFORMAT SET TO %s
\n
"
,
iVideoSubFormat
.
getMIMEStrPtr
());
}
else
{
//if we get here the key is unrecognized.
PVLOGGER_LOGMSG
(
PVLOGMSG_INST_LLDBG
,
iLogger
,
PVLOGMSG_STACK_TRACE
,
(
0
,
"AndroidSurfaceOutput::setParametersSync() Error, unrecognized key = %s"
,
aParameters
[
i
].
key
));
//set the return value to indicate the unrecognized key
//and return.
aRet_kvp
=
&
aParameters
[
i
];
return
;
}
}
uint32
mycache
=
iVideoParameterFlags
;
// if initialization is complete, update the app display info
if
(
checkVideoParameterFlags
()
)
initCheck
();
iVideoParameterFlags
=
mycache
;
// when all necessary parameters are received, send
// PVMFMIOConfigurationComplete event to observer
if
(
!
iIsMIOConfigured
&&
checkVideoParameterFlags
()
)
{
iIsMIOConfigured
=
true
;
if
(
iObserver
)
{
iObserver
->
ReportInfoEvent
(
PVMFMIOConfigurationComplete
);
}
}
}
PVMFCommandId
AndroidSurfaceOutput
::
setParametersAsync
(
PvmiMIOSession
aSession
,
PvmiKvp
*
aParameters
,
int
num_elements
,
PvmiKvp
*&
aRet_kvp
,
OsclAny
*
context
)
{
OsclError
::
Leave
(
OsclErrNotSupported
);
return
-
1
;
}
uint32
AndroidSurfaceOutput
::
getCapabilityMetric
(
PvmiMIOSession
aSession
)
{
return
0
;
}
PVMFStatus
AndroidSurfaceOutput
::
verifyParametersSync
(
PvmiMIOSession
aSession
,
PvmiKvp
*
aParameters
,
int
num_elements
)
{
OSCL_UNUSED_ARG
(
aSession
);
// Go through each parameter
for
(
int32
i
=
0
;
i
<
num_elements
;
i
++
)
{
char
*
compstr
=
NULL
;
pv_mime_string_extract_type
(
0
,
aParameters
[
i
].
key
,
compstr
);
if
(
pv_mime_strcmp
(
compstr
,
_STRLIT_CHAR
(
"x-pvmf/media/format-type"
))
==
0
)
{
if
(
pv_mime_strcmp
(
aParameters
[
i
].
value
.
pChar_value
,
PVMF_MIME_YUV420
)
==
0
)
{
return
PVMFSuccess
;
}
else
{
return
PVMFErrNotSupported
;
}
}
}
return
PVMFSuccess
;
}
//
// Private section
//
void
AndroidSurfaceOutput
::
Run
()
{
//send async command responses
while
(
!
iCommandResponseQueue
.
empty
())
{
if
(
iObserver
)
iObserver
->
RequestCompleted
(
PVMFCmdResp
(
iCommandResponseQueue
[
0
].
iCmdId
,
iCommandResponseQueue
[
0
].
iContext
,
iCommandResponseQueue
[
0
].
iStatus
));
iCommandResponseQueue
.
erase
(
&
iCommandResponseQueue
[
0
]);
}
//send async write completion
if
(
iEosReceived
)
{
LOGV
(
"Flushing buffers after EOS"
);
processWriteResponseQueue
(
0
);
}
else
{
processWriteResponseQueue
(
1
);
}
}
// create a frame buffer for software codecs
OSCL_EXPORT_REF
bool
AndroidSurfaceOutput
::
initCheck
()
{
// initialize only when we have all the required parameters
if
(
!
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
;
// 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
sp
<
MemoryHeapBase
>
heap
=
new
MemoryHeapBase
(
frameSize
*
kBufferCount
);
if
(
heap
->
heapID
()
<
0
)
{
LOGE
(
"Error creating frame buffer heap"
);
return
false
;
}
mBufferHeap
=
ISurface
::
BufferHeap
(
displayWidth
,
displayHeight
,
frameWidth
,
frameHeight
,
PIXEL_FORMAT_RGB_565
,
heap
);
mSurface
->
registerBuffers
(
mBufferHeap
);
// 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
);
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
)
{
// post to SurfaceFlinger
if
((
mSurface
!=
NULL
)
&&
(
mBufferHeap
.
heap
!=
NULL
))
{
if
(
++
mFrameBufferIndex
==
kBufferCount
)
mFrameBufferIndex
=
0
;
#if 0
{
uint32 *data_pointer = reinterpret_cast<uint32*>(aData);
LOGE("the surfaceid is %x, location %x..\n", *data_pointer, data_pointer);
LOGE("the vadisplay is %x, location %x \n", *(data_pointer + 1), data_pointer + 1);
}
iColorConverter->Convert(aData, static_cast<uint8*>(mBufferHeap.heap->base()) + mFrameBuffers[mFrameBufferIndex]);
mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]);
#endif
uint32
*
data_pointer
=
reinterpret_cast
<
uint32
*>
(
aData
);
// VASurfaceID surface_id =
// reinterpret_cast<VASurfaceID>(*(data_pointer + 1));
VASurfaceID
surface_id
=
*
(
data_pointer
);
VADisplay
va_display
=
reinterpret_cast
<
VADisplay
>
(
*
(
data_pointer
+
1
));
int
data_len
;
LOGE
(
"the surfaceid is %x
\n
"
,
surface_id
);
LOGE
(
"the vadisplay is %x
\n
"
,
va_display
);
#if 0
vaPutSurface(va_display, surface_id, 0,
0, 0, iVideoWidth, iVideoHeight,
0, 0, iVideoDisplayWidth, iVideoDisplayHeight,
NULL, 0, 0);
#else
vaPutSurfaceBuf
(
va_display
,
surface_id
,
0
,
static_cast
<
uint8
*>
(
mBufferHeap
.
heap
->
base
())
+
mFrameBuffers
[
mFrameBufferIndex
],
&
data_len
,
0
,
0
,
iVideoWidth
,
iVideoHeight
,
0
,
0
,
iVideoDisplayWidth
,
iVideoDisplayHeight
,
NULL
,
0
,
0
);
mSurface
->
postBuffer
(
mFrameBuffers
[
mFrameBufferIndex
]);
#endif
}
return
PVMFSuccess
;
}
OSCL_EXPORT_REF
void
AndroidSurfaceOutput
::
closeFrameBuf
()
{
LOGV
(
"closeFrameBuf"
);
if
(
!
mInitialized
)
return
;
mInitialized
=
false
;
if
(
mSurface
.
get
())
{
LOGV
(
"unregisterBuffers"
);
mSurface
->
unregisterBuffers
();
}
// free frame buffers
LOGV
(
"free frame buffers"
);
for
(
int
i
=
0
;
i
<
kBufferCount
;
i
++
)
{
mFrameBuffers
[
i
]
=
0
;
}
// free heaps
LOGV
(
"free frame heap"
);
mBufferHeap
.
heap
.
clear
();
// free color converter
if
(
iColorConverter
!=
0
)
{
LOGV
(
"free color converter"
);
delete
iColorConverter
;
iColorConverter
=
0
;
}
}
OSCL_EXPORT_REF
bool
AndroidSurfaceOutput
::
GetVideoSize
(
int
*
w
,
int
*
h
)
{
*
w
=
iVideoDisplayWidth
;
*
h
=
iVideoDisplayHeight
;
return
iVideoDisplayWidth
!=
0
&&
iVideoDisplayHeight
!=
0
;
}
va/android/android_surface_output.h
0 → 100644
View file @
152b03e8
/* ------------------------------------------------------------------
* Copyright (C) 2008 PacketVideo
*
* 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_H_INCLUDED
#define ANDROID_SURFACE_OUTPUT_H_INCLUDED
#include "pvmi_mio_control.h"
#include "pvmi_media_transfer.h"
#include "oscl_scheduler_ao.h"
#include "pvmi_media_io_observer.h"
#include "oscl_file_io.h"
#include "pvmi_config_and_capability.h"
#include "oscl_string_containers.h"
#include "pvmi_media_io_clock_extension.h"
#ifdef PERFORMANCE_MEASUREMENTS_ENABLED
#include "pvprofile.h"
#endif
// FIXME: Move to OMAP library
// Linux and Kernel Includes for Frame Buffer
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
//#include <linux/fb.h>
//#include <linux/videodev.h>
// SurfaceFlinger
#include <ui/ISurface.h>
// interprocess shared memory support
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
// color converter
#include "cczoomrotation16.h"
// define bits, mask and validity check for video parameters
#define VIDEO_PARAMETERS_INVALID 0
#define VIDEO_SUBFORMAT_VALID (1 << 0)
#define DISPLAY_HEIGHT_VALID (1 << 1)
#define DISPLAY_WIDTH_VALID (1 << 2)
#define VIDEO_HEIGHT_VALID (1 << 3)
#define VIDEO_WIDTH_VALID (1 << 4)
#define VIDEO_PARAMETERS_MASK (VIDEO_SUBFORMAT_VALID | DISPLAY_HEIGHT_VALID | \
DISPLAY_WIDTH_VALID | VIDEO_HEIGHT_VALID | VIDEO_WIDTH_VALID)
#define VIDEO_PARAMETERS_VALID (VIDEO_SUBFORMAT_VALID | DISPLAY_HEIGHT_VALID | \
DISPLAY_WIDTH_VALID | VIDEO_HEIGHT_VALID | VIDEO_WIDTH_VALID)
namespace
android
{
class
PVPlayer
;
}
class
PVLogger
;
class
PVMFMediaClock
;
class
AndroidSurfaceOutput
;
using
namespace
android
;
// 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
{
public:
AndroidSurfaceOutput
();
// parameter initialization
virtual
status_t
set
(
android
::
PVPlayer
*
pvPlayer
,
const
sp
<
ISurface
>&
surface
,
bool
emulation
);
virtual
status_t
setVideoSurface
(
const
sp
<
ISurface
>&
surface
);
// For frame buffer
virtual
bool
initCheck
();
virtual
PVMFStatus
writeFrameBuf
(
uint8
*
aData
,
uint32
aDataLen
,
const
PvmiMediaXferHeader
&
data_header_info
);
virtual
void
postLastFrame
();
virtual
void
closeFrameBuf
();
virtual
~
AndroidSurfaceOutput
();
bool
GetVideoSize
(
int
*
w
,
int
*
h
);
// APIs from PvmiMIOControl
PVMFStatus
connect
(
PvmiMIOSession
&
aSession
,
PvmiMIOObserver
*
aObserver
);
PVMFStatus
disconnect
(
PvmiMIOSession
aSession
);
PVMFCommandId
QueryUUID
(
const
PvmfMimeString
&
aMimeType
,
Oscl_Vector
<
PVUuid
,
OsclMemAllocator
>&
aUuids
,
bool
aExactUuidsOnly
=
false
,
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
QueryInterface
(
const
PVUuid
&
aUuid
,
PVInterface
*&
aInterfacePtr
,
const
OsclAny
*
aContext
=
NULL
);
PvmiMediaTransfer
*
createMediaTransfer
(
PvmiMIOSession
&
aSession
,
PvmiKvp
*
read_formats
=
NULL
,
int32
read_flags
=
0
,
PvmiKvp
*
write_formats
=
NULL
,
int32
write_flags
=
0
);
void
deleteMediaTransfer
(
PvmiMIOSession
&
aSession
,
PvmiMediaTransfer
*
media_transfer
);
void
processWriteResponseQueue
(
int
numFramesToHold
);
PVMFCommandId
Init
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
Reset
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
Start
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
Pause
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
Flush
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
DiscardData
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
DiscardData
(
PVMFTimestamp
aTimestamp
=
0
,
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
Stop
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
CancelAllCommands
(
const
OsclAny
*
aContext
=
NULL
);
PVMFCommandId
CancelCommand
(
PVMFCommandId
aCmdId
,
const
OsclAny
*
aContext
=
NULL
);
void
ThreadLogon
();
void
ThreadLogoff
();
// APIs from PvmiMediaTransfer
void
setPeer
(
PvmiMediaTransfer
*
aPeer
);
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
);
void
writeComplete
(
PVMFStatus
aStatus
,
PVMFCommandId
write_cmd_id
,
OsclAny
*
aContext
);
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
);
void
statusUpdate
(
uint32
status_flags
);
void
cancelCommand
(
PVMFCommandId
command_id
);
void
cancelAllCommands
();
// Pure virtuals from PvmiCapabilityAndConfig
void
setObserver
(
PvmiConfigAndCapabilityCmdObserver
*
aObserver
);
PVMFStatus
getParametersSync
(
PvmiMIOSession
aSession
,
PvmiKeyType
aIdentifier
,
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
);
void
DeleteContext
(
PvmiMIOSession
aSession
,
PvmiCapabilityContext
&
aContext
);
void
setParametersSync
(
PvmiMIOSession
aSession
,
PvmiKvp
*
aParameters
,
int
num_elements
,
PvmiKvp
*
&
aRet_kvp
);
PVMFCommandId
setParametersAsync
(
PvmiMIOSession
aSession
,
PvmiKvp
*
aParameters
,
int
num_elements
,
PvmiKvp
*&
aRet_kvp
,
OsclAny
*
context
=
NULL
);
uint32
getCapabilityMetric
(
PvmiMIOSession
aSession
);
PVMFStatus
verifyParametersSync
(
PvmiMIOSession
aSession
,
PvmiKvp
*
aParameters
,
int
num_elements
);
protected:
void
initData
();
void
resetVideoParameterFlags
();
bool
checkVideoParameterFlags
();
// From OsclTimerObject
void
Run
();
void
Reschedule
();
void
Cleanup
();
void
ResetData
();
PvmiMediaTransfer
*
iPeer
;
// The PvmiMIOControl class observer.
PvmiMIOObserver
*
iObserver
;
//for generating command IDs
uint32
iCommandCounter
;
//State
enum
PVRefFOState
{
STATE_IDLE
,
STATE_LOGGED_ON
,
STATE_INITIALIZED
,
STATE_STARTED
,
STATE_PAUSED
};
PVRefFOState
iState
;
//Control command handling.
class
CommandResponse
{
public:
CommandResponse
(
PVMFStatus
s
,
PVMFCommandId
id
,
const
OsclAny
*
ctx
)
:
iStatus
(
s
),
iCmdId
(
id
),
iContext
(
ctx
)
{}
PVMFStatus
iStatus
;
PVMFCommandId
iCmdId
;
const
OsclAny
*
iContext
;
};
Oscl_Vector
<
CommandResponse
,
OsclMemAllocator
>
iCommandResponseQueue
;
void
QueueCommandResponse
(
CommandResponse
&
);
//Write command handling
class
WriteResponse
{
public:
WriteResponse
(
PVMFStatus
s
,
PVMFCommandId
id
,
const
OsclAny
*
ctx
,
const
PVMFTimestamp
&
ts
)
:
iStatus
(
s
),
iCmdId
(
id
),
iContext
(
ctx
),
iTimestamp
(
ts
)
{}
PVMFStatus
iStatus
;
PVMFCommandId
iCmdId
;
const
OsclAny
*
iContext
;
PVMFTimestamp
iTimestamp
;
};
Oscl_Vector
<
WriteResponse
,
OsclMemAllocator
>
iWriteResponseQueue
;
// Output file parameters
OSCL_wHeapString
<
OsclMemAllocator
>
iOutputFileName
;
Oscl_FileServer
iFs
;
bool
iFsConnected
;
Oscl_File
iOutputFile
;
bool
iFileOpened
;
bool
iEosReceived
;
// Video parameters
uint32
iVideoParameterFlags
;
OSCL_HeapString
<
OsclMemAllocator
>
iVideoFormatString
;
PVMFFormatType
iVideoFormat
;
int32
iVideoHeight
;
int32
iVideoWidth
;
int32
iVideoDisplayHeight
;
int32
iVideoDisplayWidth
;
// hardware specific
PVMFFormatType
iVideoSubFormat
;
bool
iVideoSubFormatValid
;
//For logging
PVLogger
*
iLogger
;
//For implementing the write flow control
bool
CheckWriteBusy
(
uint32
);
unsigned
long
iFrameNumber
;
// software color conversion for software codecs
ColorConvertBase
*
iColorConverter
;
android
::
PVPlayer
*
mPvPlayer
;
bool
mInitialized
;
bool
mEmulation
;
sp
<
ISurface
>
mSurface
;
// frame buffer support
static
const
int
kBufferCount
=
2
;
int
mFrameBufferIndex
;
ISurface
::
BufferHeap
mBufferHeap
;
size_t
mFrameBuffers
[
kBufferCount
];
void
convertFrame
(
void
*
src
,
void
*
dst
,
size_t
len
);
//This bool is set true when all necassary parameters have been received.
bool
iIsMIOConfigured
;
/*
* The value of mNumberOfFramesToHold is hardware/platform specific.
* 1. On non-overlay based platforms, its value it set to 2
* so as to avoid potential tearings oberved during video playback.
* 2. On overlay-based platforms, its value should be overwritten.
* We have observed video decoder starvation when a value other than 1.
*
* We set the default value to 2 in this class. Please change its value
* accordingly in the derived class.
*/
int
mNumberOfFramesToHold
;
#ifdef PERFORMANCE_MEASUREMENTS_ENABLED
PVProfile
PVOmapVideoProfile
;
#endif
};
#endif // ANDROID_SURFACE_OUTPUT_H_INCLUDED
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment