Home | History | Annotate | Download | only in videocodec
      1 
      2 #define LOG_TAG "OMXVideoEncoderVP8"
      3 #include "OMXVideoEncoderVP8.h"
      4 
      5 static const char *VP8_MIME_TYPE = "video/x-vnd.on2.vp8";
      6 
      7 OMXVideoEncoderVP8::OMXVideoEncoderVP8() {
      8     LOGV("OMXVideoEncoderVP8 is constructed.");
      9     mLastTimestamp = 0x7FFFFFFFFFFFFFFFLL;
     10     BuildHandlerList();
     11     mVideoEncoder = createVideoEncoder(VP8_MIME_TYPE);
     12     if(!mVideoEncoder) LOGE("OMX_ErrorInsufficientResources");
     13 }
     14 
     15 OMXVideoEncoderVP8::~OMXVideoEncoderVP8() {
     16     LOGV("OMXVideoEncoderVP8 is destructed.");
     17 }
     18 
     19 OMX_ERRORTYPE OMXVideoEncoderVP8::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput) {
     20 
     21     memset(&mParamVp8, 0, sizeof(mParamVp8));
     22     SetTypeHeader(&mParamVp8, sizeof(mParamVp8));
     23     mParamVp8.nPortIndex = OUTPORT_INDEX;
     24     mParamVp8.eProfile = OMX_VIDEO_VP8ProfileMain;
     25     mParamVp8.eLevel = OMX_VIDEO_VP8Level_Version3;
     26 
     27     memset(&mConfigVideoVp8ReferenceFrame, 0, sizeof(mConfigVideoVp8ReferenceFrame));
     28     SetTypeHeader(&mConfigVideoVp8ReferenceFrame, sizeof(mConfigVideoVp8ReferenceFrame));
     29     mConfigVideoVp8ReferenceFrame.nPortIndex = OUTPORT_INDEX;
     30     mConfigVideoVp8ReferenceFrame.bUsePreviousFrame = OMX_TRUE;
     31     mConfigVideoVp8ReferenceFrame.bUseGoldenFrame = OMX_TRUE;
     32     mConfigVideoVp8ReferenceFrame.bUseAlternateFrame = OMX_TRUE;
     33     mConfigVideoVp8ReferenceFrame.bPreviousFrameRefresh = OMX_TRUE;
     34     mConfigVideoVp8ReferenceFrame.bGoldenFrameRefresh = OMX_TRUE;
     35     mConfigVideoVp8ReferenceFrame.bAlternateFrameRefresh = OMX_TRUE;
     36 
     37     paramPortDefinitionOutput->nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
     38     paramPortDefinitionOutput->nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
     39     paramPortDefinitionOutput->nBufferSize = OUTPORT_BUFFER_SIZE;
     40     paramPortDefinitionOutput->format.video.cMIMEType = (OMX_STRING)VP8_MIME_TYPE;
     41     paramPortDefinitionOutput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP8;
     42 
     43     // OMX_VIDEO_PARAM_INTEL_NUMBER_OF_TEMPORAL_LAYER
     44     memset(&mTemporalLayer, 0, sizeof(mTemporalLayer));
     45     SetTypeHeader(&mTemporalLayer, sizeof(mTemporalLayer));
     46     mTemporalLayer.nPortIndex = OUTPORT_INDEX;
     47     mTemporalLayer.nNumberOfTemporalLayer = 1;//default value is 1
     48 
     49     mParamProfileLevel.eProfile = OMX_VIDEO_VP8ProfileMain;
     50     mParamProfileLevel.eLevel = OMX_VIDEO_VP8Level_Version3;
     51     return OMX_ErrorNone;
     52 }
     53 
     54 OMX_ERRORTYPE OMXVideoEncoderVP8::SetVideoEncoderParam() {
     55 
     56     if (!mEncoderParams) {
     57         LOGE("NULL pointer: mEncoderParams");
     58         return OMX_ErrorBadParameter;
     59     }
     60 
     61     mVideoEncoder->getParameters(mEncoderParams);
     62     mEncoderParams->profile = VAProfileVP8Version0_3;
     63     return OMXVideoEncoderBase::SetVideoEncoderParam();
     64 }
     65 
     66 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorInit(void) {
     67     return OMXVideoEncoderBase::ProcessorInit();
     68 }
     69 
     70 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorDeinit(void) {
     71     return OMXVideoEncoderBase::ProcessorDeinit();
     72 }
     73 
     74 OMX_ERRORTYPE OMXVideoEncoderVP8::ProcessorProcess(OMX_BUFFERHEADERTYPE **buffers,
     75         buffer_retain_t *retains,
     76         OMX_U32) {
     77 
     78     VideoEncOutputBuffer outBuf;
     79     VideoEncRawBuffer inBuf;
     80     Encode_Status ret = ENCODE_SUCCESS;
     81 
     82     OMX_U32 outfilledlen = 0;
     83     OMX_S64 outtimestamp = 0;
     84     OMX_U32 outflags = 0;
     85     OMX_ERRORTYPE oret = OMX_ErrorNone;
     86     OMX_U32 frameDuration;
     87     OMX_U32 this_fps;
     88     if(buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) {
     89         LOGV("%s(),%d: got OMX_BUFFERFLAG_EOS\n", __func__, __LINE__);
     90         outflags |= OMX_BUFFERFLAG_EOS;
     91     }
     92 
     93     if (!buffers[INPORT_INDEX]->nFilledLen) {
     94         LOGV("%s(),%d: input buffer's nFilledLen is zero\n",  __func__, __LINE__);
     95         goto out;
     96     }
     97 
     98     inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset;
     99     inBuf.size = buffers[INPORT_INDEX]->nFilledLen;
    100     inBuf.type = FTYPE_UNKNOWN;
    101     inBuf.timeStamp = buffers[INPORT_INDEX]->nTimeStamp;
    102 
    103     if (inBuf.timeStamp > mLastTimestamp) {
    104         frameDuration = (OMX_U32)(inBuf.timeStamp - mLastTimestamp);
    105     } else {
    106         frameDuration = (OMX_U32)(1000000 / mEncoderParams->frameRate.frameRateNum);
    107     }
    108 
    109     this_fps = (OMX_U32)((1000000.000 / frameDuration) * 1000 + 1)/1000;
    110 
    111     if(this_fps != mEncoderParams->frameRate.frameRateNum)
    112     {// a new FrameRate is coming
    113         mConfigFramerate.xEncodeFramerate = this_fps;
    114         mEncoderParams->frameRate.frameRateNum = this_fps;
    115         VideoConfigFrameRate framerate;
    116         mVideoEncoder->getConfig(&framerate);
    117         framerate.frameRate.frameRateDenom = 1;
    118         framerate.frameRate.frameRateNum = mConfigFramerate.xEncodeFramerate;
    119         ret = mVideoEncoder->setConfig(&framerate);
    120         if(ret != ENCODE_SUCCESS) {
    121                LOGW("Failed to set frame rate config");
    122         }
    123     }
    124     outBuf.data =
    125         buffers[OUTPORT_INDEX]->pBuffer + buffers[OUTPORT_INDEX]->nOffset;
    126     outBuf.dataSize = 0;
    127     outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen - buffers[OUTPORT_INDEX]->nOffset;
    128 
    129     if (mFrameRetrieved) {
    130         // encode and setConfig need to be thread safe
    131         pthread_mutex_unlock(&mSerializationLock);
    132         ret = mVideoEncoder->encode(&inBuf);
    133         pthread_mutex_unlock(&mSerializationLock);
    134 
    135         CHECK_ENCODE_STATUS("encode");
    136         mFrameRetrieved = OMX_FALSE;
    137 
    138         // This is for buffer contention, we won't release current buffer
    139         // but the last input buffer
    140         ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
    141     }
    142 
    143     {
    144         outBuf.format = OUTPUT_EVERYTHING;
    145         ret = mVideoEncoder->getOutput(&outBuf);
    146         //CHECK_ENCODE_STATUS("getOutput");
    147         if(ret == ENCODE_NO_REQUEST_DATA) {
    148             mFrameRetrieved = OMX_TRUE;
    149             retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    150             if (mSyncEncoding)
    151                 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
    152             else
    153                 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
    154 
    155             goto out;
    156         }
    157 
    158         LOGV("VP8 encode output data size = %d", outBuf.dataSize);
    159 
    160 
    161         outfilledlen = outBuf.dataSize;
    162         outtimestamp = buffers[INPORT_INDEX]->nTimeStamp;
    163         mLastTimestamp = inBuf.timeStamp;
    164         if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) {
    165             outflags |= OMX_BUFFERFLAG_SYNCFRAME;
    166         }
    167 
    168         if (outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) {
    169             LOGV("Get buffer done\n");
    170             outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
    171             mFrameRetrieved = OMX_TRUE;
    172             if (mSyncEncoding)
    173                 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
    174             else
    175                 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
    176 
    177         } else {
    178             retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;  //get again
    179 
    180         }
    181 
    182     }
    183 
    184 
    185     if (outfilledlen > 0) {
    186         retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
    187     } else {
    188         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
    189     }
    190 
    191 
    192 
    193 #if SHOW_FPS
    194     {
    195         struct timeval t;
    196         OMX_TICKS current_ts, interval_ts;
    197         float current_fps, average_fps;
    198 
    199         t.tv_sec = t.tv_usec = 0;
    200         gettimeofday(&t, NULL);
    201 
    202         current_ts =
    203             (nsecs_t)t.tv_sec * 1000000000 + (nsecs_t)t.tv_usec * 1000;
    204         interval_ts = current_ts - lastTs;
    205         lastTs = current_ts;
    206 
    207         current_fps = (float)1000000000 / (float)interval_ts;
    208         average_fps = (current_fps + lastFps) / 2;
    209         lastFps = current_fps;
    210 
    211         LOGV("FPS = %2.1f\n", average_fps);
    212     }
    213 #endif
    214 
    215 out:
    216 
    217     if (retains[OUTPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) {
    218         buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen;
    219         buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp;
    220         buffers[OUTPORT_INDEX]->nFlags = outflags;
    221     }
    222 
    223     if (retains[INPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN ||
    224             retains[INPORT_INDEX] == BUFFER_RETAIN_ACCUMULATE ) {
    225         mFrameInputCount ++;
    226     }
    227 
    228     if (retains[OUTPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN)
    229         mFrameOutputCount ++;
    230 
    231     return oret;
    232 }
    233 
    234 OMX_ERRORTYPE OMXVideoEncoderVP8::BuildHandlerList(void) {
    235     OMXVideoEncoderBase::BuildHandlerList();
    236     AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoVp8, GetParamVideoVp8, SetParamVideoVp8);
    237     AddHandler((OMX_INDEXTYPE)OMX_IndexConfigVideoVp8ReferenceFrame, GetConfigVideoVp8ReferenceFrame, SetConfigVideoVp8ReferenceFrame);
    238     AddHandler((OMX_INDEXTYPE)OMX_IndexExtVP8MaxFrameSizeRatio, GetConfigVp8MaxFrameSizeRatio, SetConfigVp8MaxFrameSizeRatio);
    239 
    240     return OMX_ErrorNone;
    241 }
    242 
    243 OMX_ERRORTYPE OMXVideoEncoderVP8::GetParamVideoVp8(OMX_PTR pStructure) {
    244     OMX_ERRORTYPE ret;
    245     OMX_VIDEO_PARAM_VP8TYPE *p = (OMX_VIDEO_PARAM_VP8TYPE*) pStructure;
    246     CHECK_TYPE_HEADER(p);
    247     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
    248 
    249     memcpy(p, &mParamVp8, sizeof(*p));
    250     return OMX_ErrorNone;
    251 }
    252 
    253 OMX_ERRORTYPE OMXVideoEncoderVP8::SetParamVideoVp8(OMX_PTR pStructure) {
    254     OMX_ERRORTYPE ret;
    255     OMX_VIDEO_PARAM_VP8TYPE *p = (OMX_VIDEO_PARAM_VP8TYPE*) pStructure;
    256     CHECK_TYPE_HEADER(p);
    257     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
    258     CHECK_SET_PARAM_STATE();
    259 
    260     memcpy(&mParamVp8, p, sizeof(mParamVp8));
    261     return OMX_ErrorNone;
    262 }
    263 
    264 OMX_ERRORTYPE OMXVideoEncoderVP8::GetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure) {
    265     OMX_ERRORTYPE ret;
    266     OMX_VIDEO_VP8REFERENCEFRAMETYPE *p = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*)pStructure;
    267     CHECK_TYPE_HEADER(p);
    268     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
    269 
    270     memcpy(p, &mConfigVideoVp8ReferenceFrame, sizeof(*p));
    271 
    272     return OMX_ErrorNone;
    273 }
    274 
    275 OMX_ERRORTYPE OMXVideoEncoderVP8::SetConfigVideoVp8ReferenceFrame(OMX_PTR pStructure) {
    276     OMX_ERRORTYPE ret;
    277     Encode_Status retStatus = ENCODE_SUCCESS;
    278     OMX_VIDEO_VP8REFERENCEFRAMETYPE *p = (OMX_VIDEO_VP8REFERENCEFRAMETYPE*) pStructure;
    279     CHECK_TYPE_HEADER(p);
    280     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
    281 
    282     CHECK_SET_CONFIG_STATE();
    283 
    284     VideoConfigVP8ReferenceFrame configVP8ReferenceFrame;
    285     configVP8ReferenceFrame.no_ref_last = !p->bUsePreviousFrame;
    286     configVP8ReferenceFrame.no_ref_gf = !p->bUseGoldenFrame;
    287     configVP8ReferenceFrame.no_ref_arf = !p->bUseAlternateFrame;
    288     configVP8ReferenceFrame.refresh_alternate_frame = p->bAlternateFrameRefresh;
    289     configVP8ReferenceFrame.refresh_golden_frame = p->bGoldenFrameRefresh;
    290     configVP8ReferenceFrame.refresh_last = p->bPreviousFrameRefresh;
    291 
    292     retStatus = mVideoEncoder->setConfig(&configVP8ReferenceFrame);
    293     if(retStatus != ENCODE_SUCCESS) {
    294         LOGW("Failed to set reference frame");
    295     }
    296     return OMX_ErrorNone;
    297 }
    298 
    299 OMX_ERRORTYPE OMXVideoEncoderVP8::GetConfigVp8MaxFrameSizeRatio(OMX_PTR) {
    300 
    301     return OMX_ErrorNone;
    302 }
    303 
    304 OMX_ERRORTYPE OMXVideoEncoderVP8::SetConfigVp8MaxFrameSizeRatio(OMX_PTR pStructure) {
    305     OMX_ERRORTYPE ret;
    306     Encode_Status retStatus = ENCODE_SUCCESS;
    307     OMX_VIDEO_CONFIG_INTEL_VP8_MAX_FRAME_SIZE_RATIO *p = (OMX_VIDEO_CONFIG_INTEL_VP8_MAX_FRAME_SIZE_RATIO*)pStructure;
    308     CHECK_TYPE_HEADER(p);
    309     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
    310 
    311     CHECK_SET_CONFIG_STATE();
    312 
    313     VideoConfigVP8MaxFrameSizeRatio configVP8MaxFrameSizeRatio;
    314     configVP8MaxFrameSizeRatio.max_frame_size_ratio = p->nMaxFrameSizeRatio;
    315 
    316     retStatus = mVideoEncoder->setConfig(&configVP8MaxFrameSizeRatio);
    317     if(retStatus != ENCODE_SUCCESS) {
    318         LOGW("Failed to set vp8 max frame size ratio");
    319     }
    320 
    321     return OMX_ErrorNone;
    322 }
    323 
    324 DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.VP8", "video_encoder.vp8", OMXVideoEncoderVP8);
    325