diff options
| author | Chang Ying <ying.chang@intel.com> | 2012-12-27 14:51:56 +0800 |
|---|---|---|
| committer | Patrick Tjin <pattjin@google.com> | 2014-07-21 22:02:50 -0700 |
| commit | 62b0bf25eda4d2f48a228d7f3483e773e08292e2 (patch) | |
| tree | 403547f74a4da241915031b46344bb3eea9ef3a8 /videocodec/OMXVideoEncoderVP8.cpp | |
| parent | 115237a07f429df83c4d7cb34af86a1f636fc76b (diff) | |
| download | android_hardware_intel_common_omx-components-62b0bf25eda4d2f48a228d7f3483e773e08292e2.tar.gz android_hardware_intel_common_omx-components-62b0bf25eda4d2f48a228d7f3483e773e08292e2.tar.bz2 android_hardware_intel_common_omx-components-62b0bf25eda4d2f48a228d7f3483e773e08292e2.zip | |
VE: Add VP8 HW encoder support
BZ: 77123
Add OMX.Intel.VideoEncoder.VP8 component to support HW VP8 encoder on
MRFD.
Change-Id: Id4dd4e76873f3a7793005077eba6bb2b57b90c39
Signed-off-by: Chang Ying <ying.chang@intel.com>
Reviewed-on: http://android.intel.com:8080/83984
Reviewed-by: Yuan, Shengquan <shengquan.yuan@intel.com>
Reviewed-by: Zhang, Zhangfei <zhangfei.zhang@intel.com>
Reviewed-by: Shi, PingX <pingx.shi@intel.com>
Tested-by: Shi, PingX <pingx.shi@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
Diffstat (limited to 'videocodec/OMXVideoEncoderVP8.cpp')
| -rw-r--r-- | videocodec/OMXVideoEncoderVP8.cpp | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/videocodec/OMXVideoEncoderVP8.cpp b/videocodec/OMXVideoEncoderVP8.cpp new file mode 100644 index 0000000..4ff3110 --- /dev/null +++ b/videocodec/OMXVideoEncoderVP8.cpp @@ -0,0 +1,233 @@ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "OMXVideoEncoderVP8" +#include <utils/Log.h> +#include "OMXVideoEncoderVP8.h" + +static const char *VP8_MIME_TYPE = "video/x-webm"; + +OMXVideoEncoderVP8::OMXVideoEncoderVP8() { + LOGV("OMXVideoEncoderVP8 is constructed."); + BuildHandlerList(); + mVideoEncoder = createVideoEncoder(VP8_MIME_TYPE); + if(!mVideoEncoder) LOGE("OMX_ErrorInsufficientResources"); +} + +OMXVideoEncoderVP8::~OMXVideoEncoderVP8() { + LOGV("OMXVideoEncoderVP8 is destructed."); +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput) { + + memset(&mParamVp8, 0, sizeof(mParamVp8)); + SetTypeHeader(&mParamVp8, sizeof(mParamVp8)); + mParamVp8.nPortIndex = OUTPORT_INDEX; + mParamVp8.eProfile = OMX_VIDEO_VP8ProfileMain; + mParamVp8.eLevel = OMX_VIDEO_VP8Level_Version3; + + paramPortDefinitionOutput->nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT; + paramPortDefinitionOutput->nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT; + paramPortDefinitionOutput->nBufferSize = OUTPORT_BUFFER_SIZE; + paramPortDefinitionOutput->format.video.cMIMEType = (OMX_STRING)VP8_MIME_TYPE; + paramPortDefinitionOutput->format.video.eCompressionFormat = OMX_VIDEO_CodingVPX; + + mParamProfileLevel.eProfile = OMX_VIDEO_VP8ProfileMain; + mParamProfileLevel.eLevel = OMX_VIDEO_VP8Level_Version3; + return OMX_ErrorNone; +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::SetVideoEncoderParam() { + + if (!mEncoderParams) { + LOGE("NULL pointer: mEncoderParams"); + return OMX_ErrorBadParameter; + } + + mVideoEncoder->getParameters(mEncoderParams); + mEncoderParams->profile = (VAProfile)PROFILE_VP8; + return OMXVideoEncoderBase::SetVideoEncoderParam(); +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorInit(void) { + return OMXVideoEncoderBase::ProcessorInit(); +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorDeinit(void) { + return OMXVideoEncoderBase::ProcessorDeinit(); +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorProcess(OMX_BUFFERHEADERTYPE **buffers, + buffer_retain_t *retains, + OMX_U32 numberBuffers) { + + VideoEncOutputBuffer outBuf; + VideoEncRawBuffer inBuf; + Encode_Status ret = ENCODE_SUCCESS; + + OMX_U32 outfilledlen = 0; + OMX_S64 outtimestamp = 0; + OMX_U32 outflags = 0; + OMX_ERRORTYPE oret = OMX_ErrorNone; + + LOGV_IF(buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS, + "%s(),%d: got OMX_BUFFERFLAG_EOS\n", __func__, __LINE__); + + if (!buffers[INPORT_INDEX]->nFilledLen) { + LOGV("%s(),%d: input buffer's nFilledLen is zero\n", __func__, __LINE__); + goto out; + } + + inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset; + inBuf.size = buffers[INPORT_INDEX]->nFilledLen; + + outBuf.data = + buffers[OUTPORT_INDEX]->pBuffer + buffers[OUTPORT_INDEX]->nOffset; + outBuf.dataSize = 0; + outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen - buffers[OUTPORT_INDEX]->nOffset; + + if (mFrameRetrieved) { + // encode and setConfig need to be thread safe + pthread_mutex_unlock(&mSerializationLock); + ret = mVideoEncoder->encode(&inBuf); + pthread_mutex_unlock(&mSerializationLock); + + CHECK_ENCODE_STATUS("encode"); + mFrameRetrieved = OMX_FALSE; + + // This is for buffer contention, we won't release current buffer + // but the last input buffer + ports[INPORT_INDEX]->ReturnAllRetainedBuffers(); + } + + { + outBuf.format = OUTPUT_EVERYTHING; + mVideoEncoder->getOutput(&outBuf); + CHECK_ENCODE_STATUS("getOutput"); + + LOGV("output data size = %d", outBuf.dataSize); + + + outfilledlen = outBuf.dataSize; + outtimestamp = buffers[INPORT_INDEX]->nTimeStamp; + + if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) { + outflags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + if (outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) { + LOGV("Get buffer done\n"); + outflags |= OMX_BUFFERFLAG_ENDOFFRAME; + mFrameRetrieved = OMX_TRUE; + retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE; + + } else { + retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; //get again + + } + + } + + + if (outfilledlen > 0) { + retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN; + } else { + retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; + } + + + +#if SHOW_FPS + { + struct timeval t; + OMX_TICKS current_ts, interval_ts; + float current_fps, average_fps; + + t.tv_sec = t.tv_usec = 0; + gettimeofday(&t, NULL); + + current_ts = + (nsecs_t)t.tv_sec * 1000000000 + (nsecs_t)t.tv_usec * 1000; + interval_ts = current_ts - lastTs; + lastTs = current_ts; + + current_fps = (float)1000000000 / (float)interval_ts; + average_fps = (current_fps + lastFps) / 2; + lastFps = current_fps; + + LOGV("FPS = %2.1f\n", average_fps); + } +#endif + +out: + + if (retains[OUTPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) { + buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen; + buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp; + buffers[OUTPORT_INDEX]->nFlags = outflags; + } + + if (retains[INPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN || + retains[INPORT_INDEX] == BUFFER_RETAIN_ACCUMULATE ) { + mFrameInputCount ++; + } + + if (retains[OUTPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN) + mFrameOutputCount ++; + + return oret; +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::BuildHandlerList(void) { + OMXVideoEncoderBase::BuildHandlerList(); + AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoVp8, GetParamVideoVp8, SetParamVideoVp8); + AddHandler((OMX_INDEXTYPE)OMX_IndexConfigVideoVp8ReferenceFrame, GetConfigVideoVp8ReferenceFrame, SetConfigVideoVp8ReferenceFrame); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::GetParamVideoVp8(OMX_PTR pStructure) { + OMX_ERRORTYPE ret; + OMX_VIDEO_PARAM_VP8TYPE *p = (OMX_VIDEO_PARAM_VP8TYPE*) pStructure; + CHECK_TYPE_HEADER(p); + CHECK_PORT_INDEX(p, OUTPORT_INDEX); + + memcpy(p, &mParamVp8, sizeof(*p)); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::SetParamVideoVp8(OMX_PTR pStructure) { + OMX_ERRORTYPE ret; + OMX_VIDEO_PARAM_VP8TYPE *p = (OMX_VIDEO_PARAM_VP8TYPE*) pStructure; + CHECK_TYPE_HEADER(p); + CHECK_PORT_INDEX(p, OUTPORT_INDEX); + CHECK_SET_PARAM_STATE(); + + memcpy(&mParamVp8, p, sizeof(mParamVp8)); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::GetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure) { + return OMX_ErrorNone; +} + +OMX_ERRORTYPE OMXVideoEncoderVP8::SetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure) { + OMX_ERRORTYPE ret; + Encode_Status retStatus = ENCODE_SUCCESS; + OMX_VIDEO_VP8REFERENCEFRAMETYPE *p = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*) pStructure; + CHECK_TYPE_HEADER(p); + CHECK_PORT_INDEX(p, OUTPORT_INDEX); + + CHECK_SET_CONFIG_STATE(); + + VideoConfigVP8 configVP8; + configVP8.no_ref_last = p->bUsePreviousFrame; + configVP8.no_ref_gf = p->bUseGoldenFrame; + configVP8.no_ref_arf = p->bUseAlternateFrame; + + retStatus = mVideoEncoder->setConfig(&configVP8); + if(retStatus != ENCODE_SUCCESS) { + LOGW("Failed to set refresh config"); + } + return OMX_ErrorNone; +} + +DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.VP8", "video_encoder.vp8", OMXVideoEncoderVP8); |
