Home | History | Annotate | Download | only in enc
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      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 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "M4vH263Encoder"
     19 #include <utils/Log.h>
     20 
     21 #include "M4vH263Encoder.h"
     22 
     23 #include "mp4enc_api.h"
     24 #include "OMX_Video.h"
     25 
     26 #include <media/stagefright/MediaBufferGroup.h>
     27 #include <media/stagefright/MediaDebug.h>
     28 #include <media/stagefright/MediaDefs.h>
     29 #include <media/stagefright/MediaErrors.h>
     30 #include <media/stagefright/MetaData.h>
     31 #include <media/stagefright/Utils.h>
     32 
     33 namespace android {
     34 
     35 inline static void ConvertYUV420SemiPlanarToYUV420Planar(
     36         uint8_t *inyuv, uint8_t* outyuv,
     37         int32_t width, int32_t height) {
     38 
     39     int32_t outYsize = width * height;
     40     uint32_t *outy = (uint32_t *)  outyuv;
     41     uint16_t *outcb = (uint16_t *) (outyuv + outYsize);
     42     uint16_t *outcr = (uint16_t *) (outyuv + outYsize + (outYsize >> 2));
     43 
     44     /* Y copying */
     45     memcpy(outy, inyuv, outYsize);
     46 
     47     /* U & V copying */
     48     uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
     49     for (int32_t i = height >> 1; i > 0; --i) {
     50         for (int32_t j = width >> 2; j > 0; --j) {
     51             uint32_t temp = *inyuv_4++;
     52             uint32_t tempU = temp & 0xFF;
     53             tempU = tempU | ((temp >> 8) & 0xFF00);
     54 
     55             uint32_t tempV = (temp >> 8) & 0xFF;
     56             tempV = tempV | ((temp >> 16) & 0xFF00);
     57 
     58             // Flip U and V
     59             *outcb++ = tempV;
     60             *outcr++ = tempU;
     61         }
     62     }
     63 }
     64 
     65 M4vH263Encoder::M4vH263Encoder(
     66         const sp<MediaSource>& source,
     67         const sp<MetaData>& meta)
     68     : mSource(source),
     69       mMeta(meta),
     70       mNumInputFrames(-1),
     71       mNextModTimeUs(0),
     72       mPrevTimestampUs(-1),
     73       mStarted(false),
     74       mInputBuffer(NULL),
     75       mInputFrameData(NULL),
     76       mGroup(NULL) {
     77 
     78     LOGV("Construct software M4vH263Encoder");
     79 
     80     mHandle = new tagvideoEncControls;
     81     memset(mHandle, 0, sizeof(tagvideoEncControls));
     82 
     83     mInitCheck = initCheck(meta);
     84 }
     85 
     86 M4vH263Encoder::~M4vH263Encoder() {
     87     LOGV("Destruct software M4vH263Encoder");
     88     if (mStarted) {
     89         stop();
     90     }
     91 
     92     delete mEncParams;
     93     delete mHandle;
     94 }
     95 
     96 status_t M4vH263Encoder::initCheck(const sp<MetaData>& meta) {
     97     LOGV("initCheck");
     98     CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
     99     CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
    100     CHECK(meta->findInt32(kKeySampleRate, &mVideoFrameRate));
    101     CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
    102 
    103     // XXX: Add more color format support
    104     CHECK(meta->findInt32(kKeyColorFormat, &mVideoColorFormat));
    105     if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
    106         if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
    107             LOGE("Color format %d is not supported", mVideoColorFormat);
    108             return BAD_VALUE;
    109         }
    110         // Allocate spare buffer only when color conversion is needed.
    111         // Assume the color format is OMX_COLOR_FormatYUV420SemiPlanar.
    112         mInputFrameData =
    113             (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
    114         CHECK(mInputFrameData);
    115     }
    116 
    117     // XXX: Remove this restriction
    118     if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
    119         LOGE("Video frame size %dx%d must be a multiple of 16",
    120             mVideoWidth, mVideoHeight);
    121         return BAD_VALUE;
    122     }
    123 
    124     mEncParams = new tagvideoEncOptions;
    125     memset(mEncParams, 0, sizeof(tagvideoEncOptions));
    126     if (!PVGetDefaultEncOption(mEncParams, 0)) {
    127         LOGE("Failed to get default encoding parameters");
    128         return BAD_VALUE;
    129     }
    130 
    131     // Need to know which role the encoder is in.
    132     // XXX: Set the mode proper for other types of applications
    133     //      like streaming or video conference
    134     const char *mime;
    135     CHECK(meta->findCString(kKeyMIMEType, &mime));
    136     CHECK(!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
    137           !strcmp(mime, MEDIA_MIMETYPE_VIDEO_H263));
    138     if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
    139         mEncParams->encMode = COMBINE_MODE_WITH_ERR_RES;
    140     } else {
    141         mEncParams->encMode = H263_MODE;
    142     }
    143     mEncParams->encWidth[0] = mVideoWidth;
    144     mEncParams->encHeight[0] = mVideoHeight;
    145     mEncParams->encFrameRate[0] = mVideoFrameRate;
    146     mEncParams->rcType = VBR_1;
    147     mEncParams->vbvDelay = (float)5.0;
    148 
    149     // Set profile and level
    150     // If profile and level setting is not correct, failure
    151     // is reported when the encoder is initialized.
    152     mEncParams->profile_level = CORE_PROFILE_LEVEL2;
    153     int32_t profileLevel;
    154     if (meta->findInt32(kKeyVideoLevel, &profileLevel)) {
    155         mEncParams->profile_level = (ProfileLevelType)profileLevel;
    156     }
    157 
    158     mEncParams->packetSize = 32;
    159     mEncParams->rvlcEnable = PV_OFF;
    160     mEncParams->numLayers = 1;
    161     mEncParams->timeIncRes = 1000;
    162     mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
    163 
    164     mEncParams->bitRate[0] = mVideoBitRate;
    165     mEncParams->iQuant[0] = 15;
    166     mEncParams->pQuant[0] = 12;
    167     mEncParams->quantType[0] = 0;
    168     mEncParams->noFrameSkipped = PV_OFF;
    169 
    170     // Set IDR frame refresh interval
    171     int32_t iFramesIntervalSec;
    172     CHECK(meta->findInt32(kKeyIFramesInterval, &iFramesIntervalSec));
    173     if (iFramesIntervalSec < 0) {
    174         mEncParams->intraPeriod = -1;
    175     } else if (iFramesIntervalSec == 0) {
    176         mEncParams->intraPeriod = 1;  // All I frames
    177     } else {
    178         mEncParams->intraPeriod =
    179             (iFramesIntervalSec * mVideoFrameRate);
    180     }
    181 
    182     mEncParams->numIntraMB = 0;
    183     mEncParams->sceneDetect = PV_ON;
    184     mEncParams->searchRange = 16;
    185     mEncParams->mv8x8Enable = PV_OFF;
    186     mEncParams->gobHeaderInterval = 0;
    187     mEncParams->useACPred = PV_ON;
    188     mEncParams->intraDCVlcTh = 0;
    189 
    190     mFormat = new MetaData;
    191     mFormat->setInt32(kKeyWidth, mVideoWidth);
    192     mFormat->setInt32(kKeyHeight, mVideoHeight);
    193     mFormat->setInt32(kKeyBitRate, mVideoBitRate);
    194     mFormat->setInt32(kKeySampleRate, mVideoFrameRate);
    195     mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
    196 
    197     mFormat->setCString(kKeyMIMEType, mime);
    198     mFormat->setCString(kKeyDecoderComponent, "M4vH263Encoder");
    199     return OK;
    200 }
    201 
    202 status_t M4vH263Encoder::start(MetaData *params) {
    203     LOGV("start");
    204     if (mInitCheck != OK) {
    205         return mInitCheck;
    206     }
    207 
    208     if (mStarted) {
    209         LOGW("Call start() when encoder already started");
    210         return OK;
    211     }
    212 
    213     if (!PVInitVideoEncoder(mHandle, mEncParams)) {
    214         LOGE("Failed to initialize the encoder");
    215         return UNKNOWN_ERROR;
    216     }
    217 
    218     mGroup = new MediaBufferGroup();
    219     int32_t maxSize;
    220     if (!PVGetMaxVideoFrameSize(mHandle, &maxSize)) {
    221         maxSize = 256 * 1024;  // Magic #
    222     }
    223     LOGV("Max output buffer size: %d", maxSize);
    224     mGroup->add_buffer(new MediaBuffer(maxSize));
    225 
    226     mSource->start(params);
    227     mNumInputFrames = -1;  // 1st frame contains codec specific data
    228     mStarted = true;
    229 
    230     return OK;
    231 }
    232 
    233 status_t M4vH263Encoder::stop() {
    234     LOGV("stop");
    235     if (!mStarted) {
    236         LOGW("Call stop() when encoder has not started");
    237         return OK;
    238     }
    239 
    240     if (mInputBuffer) {
    241         mInputBuffer->release();
    242         mInputBuffer = NULL;
    243     }
    244 
    245     if (mGroup) {
    246         delete mGroup;
    247         mGroup = NULL;
    248     }
    249 
    250     if (mInputFrameData) {
    251         delete mInputFrameData;
    252         mInputFrameData = NULL;
    253     }
    254 
    255     CHECK(PVCleanUpVideoEncoder(mHandle));
    256 
    257     mSource->stop();
    258     mStarted = false;
    259 
    260     return OK;
    261 }
    262 
    263 sp<MetaData> M4vH263Encoder::getFormat() {
    264     LOGV("getFormat");
    265     return mFormat;
    266 }
    267 
    268 status_t M4vH263Encoder::read(
    269         MediaBuffer **out, const ReadOptions *options) {
    270 
    271     *out = NULL;
    272 
    273     MediaBuffer *outputBuffer;
    274     CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
    275     uint8_t *outPtr = (uint8_t *) outputBuffer->data();
    276     int32_t dataLength = outputBuffer->size();
    277 
    278     // Output codec specific data
    279     if (mNumInputFrames < 0) {
    280         if (!PVGetVolHeader(mHandle, outPtr, &dataLength, 0)) {
    281             LOGE("Failed to get VOL header");
    282             return UNKNOWN_ERROR;
    283         }
    284         LOGV("Output VOL header: %d bytes", dataLength);
    285         outputBuffer->meta_data()->setInt32(kKeyIsCodecConfig, 1);
    286         outputBuffer->set_range(0, dataLength);
    287         *out = outputBuffer;
    288         ++mNumInputFrames;
    289         return OK;
    290     }
    291 
    292     // Ready for accepting an input video frame
    293     if (OK != mSource->read(&mInputBuffer, options)) {
    294         LOGE("Failed to read from data source");
    295         outputBuffer->release();
    296         return UNKNOWN_ERROR;
    297     }
    298 
    299     if (mInputBuffer->size() - ((mVideoWidth * mVideoHeight * 3) >> 1) != 0) {
    300         outputBuffer->release();
    301         mInputBuffer->release();
    302         mInputBuffer = NULL;
    303         return UNKNOWN_ERROR;
    304     }
    305 
    306     int64_t timeUs;
    307     CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
    308 
    309     // When the timestamp of the current sample is the same as that
    310     // of the previous sample, encoding of the current sample is
    311     // bypassed, and the output length of the sample is set to 0
    312     if (mNumInputFrames >= 1 &&
    313         (mNextModTimeUs > timeUs || mPrevTimestampUs == timeUs)) {
    314         // Frame arrives too late
    315         outputBuffer->set_range(0, 0);
    316         *out = outputBuffer;
    317         mInputBuffer->release();
    318         mInputBuffer = NULL;
    319         return OK;
    320     }
    321 
    322     // Don't accept out-of-order samples
    323     CHECK(mPrevTimestampUs < timeUs);
    324     mPrevTimestampUs = timeUs;
    325 
    326     // Color convert to OMX_COLOR_FormatYUV420Planar if necessary
    327     outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
    328     uint8_t *inPtr = (uint8_t *) mInputBuffer->data();
    329     if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
    330         CHECK(mInputFrameData);
    331         CHECK(mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar);
    332         ConvertYUV420SemiPlanarToYUV420Planar(
    333             inPtr, mInputFrameData, mVideoWidth, mVideoHeight);
    334         inPtr = mInputFrameData;
    335     }
    336     CHECK(inPtr != NULL);
    337 
    338     // Ready for encoding a video frame
    339     VideoEncFrameIO vin, vout;
    340     vin.height = ((mVideoHeight + 15) >> 4) << 4;
    341     vin.pitch  = ((mVideoWidth  + 15) >> 4) << 4;
    342     vin.timestamp = (timeUs + 500) / 1000; // in ms
    343     vin.yChan = inPtr;
    344     vin.uChan = vin.yChan + vin.height * vin.pitch;
    345     vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2);
    346     unsigned long modTimeMs = 0;
    347     int32_t nLayer = 0;
    348     MP4HintTrack hintTrack;
    349     if (!PVEncodeVideoFrame(mHandle, &vin, &vout,
    350             &modTimeMs, outPtr, &dataLength, &nLayer) ||
    351         !PVGetHintTrack(mHandle, &hintTrack)) {
    352         LOGE("Failed to encode frame or get hink track at frame %lld",
    353             mNumInputFrames);
    354         outputBuffer->release();
    355         mInputBuffer->release();
    356         mInputBuffer = NULL;
    357         return UNKNOWN_ERROR;
    358     }
    359     CHECK_EQ(NULL, PVGetOverrunBuffer(mHandle));
    360     if (hintTrack.CodeType == 0) {  // I-frame serves as sync frame
    361         outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
    362     }
    363 
    364     ++mNumInputFrames;
    365     mNextModTimeUs = modTimeMs * 1000LL;
    366     outputBuffer->set_range(0, dataLength);
    367     *out = outputBuffer;
    368     mInputBuffer->release();
    369     mInputBuffer = NULL;
    370     return OK;
    371 }
    372 
    373 void M4vH263Encoder::signalBufferReturned(MediaBuffer *buffer) {
    374 }
    375 
    376 }  // namespace android
    377