Home | History | Annotate | Download | only in videoencoder
      1 /*
      2 * Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #include <string.h>
     18 #include <stdlib.h>
     19 
     20 #include "VideoEncoderLog.h"
     21 #include "VideoEncoderMP4.h"
     22 #include <va/va_tpi.h>
     23 
     24 VideoEncoderMP4::VideoEncoderMP4()
     25     :mProfileLevelIndication(3)
     26     ,mFixedVOPTimeIncrement(0) {
     27     mComParams.profile = (VAProfile)PROFILE_MPEG4SIMPLE;
     28     mAutoReferenceSurfaceNum = 2;
     29 }
     30 
     31 Encode_Status VideoEncoderMP4::getHeaderPos(
     32         uint8_t *inBuffer, uint32_t bufSize, uint32_t *headerSize) {
     33 
     34     uint32_t bytesLeft = bufSize;
     35 
     36     *headerSize = 0;
     37     CHECK_NULL_RETURN_IFFAIL(inBuffer);
     38 
     39     if (bufSize < 4) {
     40         //bufSize shoule not < 4
     41         LOG_E("Buffer size too small\n");
     42         return ENCODE_FAIL;
     43     }
     44 
     45     while (bytesLeft > 4  &&
     46             (memcmp("\x00\x00\x01\xB6", &inBuffer[bufSize - bytesLeft], 4) &&
     47              memcmp("\x00\x00\x01\xB3", &inBuffer[bufSize - bytesLeft], 4))) {
     48         --bytesLeft;
     49     }
     50 
     51     if (bytesLeft <= 4) {
     52         LOG_E("NO header found\n");
     53         *headerSize = 0; //
     54     } else {
     55         *headerSize = bufSize - bytesLeft;
     56     }
     57 
     58     return ENCODE_SUCCESS;
     59 }
     60 
     61 Encode_Status VideoEncoderMP4::outputConfigData(
     62         VideoEncOutputBuffer *outBuffer) {
     63 
     64     Encode_Status ret = ENCODE_SUCCESS;
     65     uint32_t headerSize = 0;
     66 
     67     ret = getHeaderPos((uint8_t *)mCurSegment->buf + mOffsetInSeg,
     68             mCurSegment->size - mOffsetInSeg, &headerSize);
     69     CHECK_ENCODE_STATUS_RETURN("getHeaderPos");
     70     if (headerSize == 0) {
     71         outBuffer->dataSize = 0;
     72         mCurSegment = NULL;
     73         return ENCODE_NO_REQUEST_DATA;
     74     }
     75 
     76     if (headerSize <= outBuffer->bufferSize) {
     77         memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, headerSize);
     78         mTotalSizeCopied += headerSize;
     79         mOffsetInSeg += headerSize;
     80         outBuffer->dataSize = headerSize;
     81         outBuffer->remainingSize = 0;
     82         outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
     83         outBuffer->flag |= ENCODE_BUFFERFLAG_CODECCONFIG;
     84         outBuffer->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
     85     } else {
     86         // we need a big enough buffer, otherwise we won't output anything
     87         outBuffer->dataSize = 0;
     88         outBuffer->remainingSize = headerSize;
     89         outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
     90         LOG_E("Buffer size too small\n");
     91         return ENCODE_BUFFER_TOO_SMALL;
     92     }
     93 
     94     return ret;
     95 }
     96 
     97 Encode_Status VideoEncoderMP4::getExtFormatOutput(VideoEncOutputBuffer *outBuffer) {
     98 
     99     Encode_Status ret = ENCODE_SUCCESS;
    100 
    101     LOG_V("Begin\n");
    102     CHECK_NULL_RETURN_IFFAIL(outBuffer);
    103 
    104     switch (outBuffer->format) {
    105         case OUTPUT_CODEC_DATA: {
    106             // Output the codec config data
    107             ret = outputConfigData(outBuffer);
    108             CHECK_ENCODE_STATUS_CLEANUP("outputCodecData");
    109             break;
    110         }
    111         default:
    112             LOG_E("Invalid buffer mode for MPEG-4:2\n");
    113             ret = ENCODE_FAIL;
    114             break;
    115     }
    116 
    117     LOG_I("out size is = %d\n", outBuffer->dataSize);
    118 
    119 
    120 CLEAN_UP:
    121 
    122     LOG_V("End\n");
    123     return ret;
    124 }
    125 
    126 Encode_Status VideoEncoderMP4::renderSequenceParams(EncodeTask *) {
    127 
    128     VAStatus vaStatus = VA_STATUS_SUCCESS;
    129     VAEncSequenceParameterBufferMPEG4 mp4SequenceParams = VAEncSequenceParameterBufferMPEG4();
    130 
    131     uint32_t frameRateNum = mComParams.frameRate.frameRateNum;
    132     uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom;
    133 
    134     LOG_V( "Begin\n\n");
    135     // set up the sequence params for HW
    136     mp4SequenceParams.profile_and_level_indication = mProfileLevelIndication;
    137     mp4SequenceParams.video_object_layer_width= mComParams.resolution.width;
    138     mp4SequenceParams.video_object_layer_height= mComParams.resolution.height;
    139     mp4SequenceParams.vop_time_increment_resolution =
    140             (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom;
    141     mp4SequenceParams.fixed_vop_time_increment= mFixedVOPTimeIncrement;
    142     mp4SequenceParams.bits_per_second= mComParams.rcParams.bitRate;
    143     mp4SequenceParams.frame_rate =
    144             (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom;
    145     mp4SequenceParams.initial_qp = mComParams.rcParams.initQP;
    146     mp4SequenceParams.min_qp = mComParams.rcParams.minQP;
    147     mp4SequenceParams.intra_period = mComParams.intraPeriod;
    148     //mpeg4_seq_param.fixed_vop_rate = 30;
    149 
    150     LOG_V("===mpeg4 sequence params===\n");
    151     LOG_I("profile_and_level_indication = %d\n", (uint32_t)mp4SequenceParams.profile_and_level_indication);
    152     LOG_I("intra_period = %d\n", mp4SequenceParams.intra_period);
    153     LOG_I("video_object_layer_width = %d\n", mp4SequenceParams.video_object_layer_width);
    154     LOG_I("video_object_layer_height = %d\n", mp4SequenceParams.video_object_layer_height);
    155     LOG_I("vop_time_increment_resolution = %d\n", mp4SequenceParams.vop_time_increment_resolution);
    156     LOG_I("fixed_vop_rate = %d\n", mp4SequenceParams.fixed_vop_rate);
    157     LOG_I("fixed_vop_time_increment = %d\n", mp4SequenceParams.fixed_vop_time_increment);
    158     LOG_I("bitrate = %d\n", mp4SequenceParams.bits_per_second);
    159     LOG_I("frame_rate = %d\n", mp4SequenceParams.frame_rate);
    160     LOG_I("initial_qp = %d\n", mp4SequenceParams.initial_qp);
    161     LOG_I("min_qp = %d\n", mp4SequenceParams.min_qp);
    162     LOG_I("intra_period = %d\n\n", mp4SequenceParams.intra_period);
    163 
    164     vaStatus = vaCreateBuffer(
    165             mVADisplay, mVAContext,
    166             VAEncSequenceParameterBufferType,
    167             sizeof(mp4SequenceParams),
    168             1, &mp4SequenceParams,
    169             &mSeqParamBuf);
    170     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    171 
    172     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1);
    173     CHECK_VA_STATUS_RETURN("vaRenderPicture");
    174 
    175     LOG_V( "end\n");
    176     return ENCODE_SUCCESS;
    177 }
    178 
    179 Encode_Status VideoEncoderMP4::renderPictureParams(EncodeTask *task) {
    180 
    181     VAStatus vaStatus = VA_STATUS_SUCCESS;
    182     VAEncPictureParameterBufferMPEG4 mpeg4_pic_param = VAEncPictureParameterBufferMPEG4();
    183     LOG_V( "Begin\n\n");
    184     // set picture params for HW
    185     if(mAutoReference == false){
    186         mpeg4_pic_param.reference_picture = task->ref_surface;
    187         mpeg4_pic_param.reconstructed_picture = task->rec_surface;
    188     }else {
    189         mpeg4_pic_param.reference_picture = mAutoRefSurfaces[0];
    190         mpeg4_pic_param.reconstructed_picture = mAutoRefSurfaces[1];
    191     }
    192 
    193     mpeg4_pic_param.coded_buf = task->coded_buffer;
    194     mpeg4_pic_param.picture_width = mComParams.resolution.width;
    195     mpeg4_pic_param.picture_height = mComParams.resolution.height;
    196     mpeg4_pic_param.vop_time_increment= mFrameNum;
    197     mpeg4_pic_param.picture_type = (task->type == FTYPE_I) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
    198 
    199     LOG_V("======mpeg4 picture params======\n");
    200     LOG_V("reference_picture = 0x%08x\n", mpeg4_pic_param.reference_picture);
    201     LOG_V("reconstructed_picture = 0x%08x\n", mpeg4_pic_param.reconstructed_picture);
    202     LOG_V("coded_buf = 0x%08x\n", mpeg4_pic_param.coded_buf);
    203 //    LOG_I("coded_buf_index = %d\n", mCodedBufIndex);
    204     LOG_V("picture_width = %d\n", mpeg4_pic_param.picture_width);
    205     LOG_V("picture_height = %d\n", mpeg4_pic_param.picture_height);
    206     LOG_V("vop_time_increment = %d\n", mpeg4_pic_param.vop_time_increment);
    207     LOG_V("picture_type = %d\n\n", mpeg4_pic_param.picture_type);
    208 
    209     vaStatus = vaCreateBuffer(
    210             mVADisplay, mVAContext,
    211             VAEncPictureParameterBufferType,
    212             sizeof(mpeg4_pic_param),
    213             1,&mpeg4_pic_param,
    214             &mPicParamBuf);
    215     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    216 
    217     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf, 1);
    218     CHECK_VA_STATUS_RETURN("vaRenderPicture");
    219 
    220     return ENCODE_SUCCESS;
    221 }
    222 
    223 
    224 Encode_Status VideoEncoderMP4::renderSliceParams(EncodeTask *task) {
    225 
    226     VAStatus vaStatus = VA_STATUS_SUCCESS;
    227     uint32_t sliceHeight;
    228     uint32_t sliceHeightInMB;
    229 
    230     VAEncSliceParameterBuffer sliceParams;
    231 
    232     LOG_V( "Begin\n\n");
    233 
    234     sliceHeight = mComParams.resolution.height;
    235     sliceHeight += 15;
    236     sliceHeight &= (~15);
    237     sliceHeightInMB = sliceHeight / 16;
    238 
    239     sliceParams.start_row_number = 0;
    240     sliceParams.slice_height = sliceHeightInMB;
    241     sliceParams.slice_flags.bits.is_intra = (task->type == FTYPE_I)?1:0;
    242     sliceParams.slice_flags.bits.disable_deblocking_filter_idc = 0;
    243 
    244     LOG_V("======mpeg4 slice params======\n");
    245     LOG_I( "start_row_number = %d\n", (int) sliceParams.start_row_number);
    246     LOG_I( "sliceHeightInMB = %d\n", (int) sliceParams.slice_height);
    247     LOG_I( "is_intra = %d\n", (int) sliceParams.slice_flags.bits.is_intra);
    248 
    249     vaStatus = vaCreateBuffer(
    250             mVADisplay, mVAContext,
    251             VAEncSliceParameterBufferType,
    252             sizeof(VAEncSliceParameterBuffer),
    253             1, &sliceParams,
    254             &mSliceParamBuf);
    255     CHECK_VA_STATUS_RETURN("vaCreateBuffer");
    256 
    257     vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSliceParamBuf, 1);
    258     CHECK_VA_STATUS_RETURN("vaRenderPicture");
    259 
    260     LOG_V( "end\n");
    261     return ENCODE_SUCCESS;
    262 }
    263 
    264 Encode_Status VideoEncoderMP4::sendEncodeCommand(EncodeTask *task) {
    265     Encode_Status ret = ENCODE_SUCCESS;
    266     LOG_V( "Begin\n");
    267 
    268     if (mFrameNum == 0) {
    269         ret = renderSequenceParams(task);
    270         CHECK_ENCODE_STATUS_RETURN("renderSequenceParams");
    271     }
    272 
    273     ret = renderPictureParams(task);
    274     CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
    275 
    276     ret = renderSliceParams(task);
    277     CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
    278 
    279     LOG_V( "End\n");
    280     return ENCODE_SUCCESS;
    281 }
    282