Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6605540 authored by Luis GarciaCalderon's avatar Luis GarciaCalderon Committed by Ricardo Cerqueira
Browse files

libstagefright: Enable frame by frame mode

- Enable frame by frame for all formats - local playback & http
  streaming.
- Arbitrary mode is enabled only for specific formats by setting
  a new key (kKeyUseArbitraryMode) in extractor, for following
  formats :
  - H264 Interlaced clips
  - VC1 Advance profile clips
  - MPEG4 in AVI container
- If the arbitrary mode key is not set by the extractor, it will
  default to frame by frame mode for all video clips except
  interlaced clips.
- Adds SPS parsing functionality.

Change-Id: If8c47d0499720eead86b4c4fbe74696aba4423fb
CRs-Fixed: 322872
parent a9651428
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -151,7 +151,10 @@ enum {
    // 3D Video Flag
    kKey3D                = '3Dvf',  // bool (int32_t)
    kKeyHFR               = 'hfr ',  // int32_t
    //Extractor sets this
    kKeyUseArbitraryMode  = 'ArbM'  //bool (int32_t)
#endif

};

enum {
@@ -166,11 +169,6 @@ enum {
    kTypeDivXVer_5,
    kTypeDivXVer_6,
};
enum {
    kTypeWMVSimple,
    kTypeWMVAdvance,
};

enum {
    kTypeWMA,
    kTypeWMAPro,
+2 −1
Original line number Diff line number Diff line
@@ -235,6 +235,7 @@ private:
    bool mIsMetaDataStoredInVideoBuffers;
    bool mOnlySubmitOneBufferAtOneTime;
    bool mInterlaceFormatDetected;
    bool mSPSParsed;
#endif

    // Used to record the decoding time for an output picture from
@@ -369,7 +370,7 @@ private:

    status_t parseAVCCodecSpecificData(
            const void *data, size_t size,
            unsigned *profile, unsigned *level);
            unsigned *profile, unsigned *level, const sp<MetaData> &meta);
#ifdef QCOM_HARDWARE
    void parseFlags( uint32_t flags );
#endif
+15 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#define UTILS_H_

#include <stdint.h>
#include <utils/Errors.h>

namespace android {

@@ -36,6 +37,20 @@ uint64_t U64LE_AT(const uint8_t *ptr);
uint64_t ntoh64(uint64_t x);
uint64_t hton64(uint64_t x);

#ifdef QCOM_HARDWARE
typedef struct {
    uint8_t mProfile;
    uint8_t mLevel;
    int32_t mHeightInMBs;
    int32_t mWidthInMBs;
    int32_t mNumRefFrames;
    int32_t mInterlaced;
} SpsInfo;

status_t
parseSps(uint16_t naluSize,const uint8_t *encodedBytes, SpsInfo *info);
#endif

}  // namespace android

#endif  // UTILS_H_
+6 −0
Original line number Diff line number Diff line
@@ -1933,6 +1933,12 @@ MPEG4Source::MPEG4Source(
        mNALLengthSize = 1 + (ptr[4] & 3);
    }

#ifdef QCOM_HARDWARE
    //MPEG4 extractor can give complete frames,
    //set arbitrary mode to false
    format->setInt32(kKeyUseArbitraryMode, 0);
#endif

    if (mStatistics) logExpectedFrames();
}

+53 −35
Original line number Diff line number Diff line
@@ -704,7 +704,7 @@ sp<MediaSource> OMXCodec::Create(

status_t OMXCodec::parseAVCCodecSpecificData(
        const void *data, size_t size,
        unsigned *profile, unsigned *level) {
        unsigned *profile, unsigned *level, const sp<MetaData> &meta) {
    const uint8_t *ptr = (const uint8_t *)data;

    // verify minimum size and configurationVersion == 1.
@@ -726,6 +726,28 @@ status_t OMXCodec::parseAVCCodecSpecificData(
    // CHECK((ptr[5] >> 5) == 7);  // reserved

    size_t numSeqParameterSets = ptr[5] & 31;
#ifdef QCOM_HARDWARE
    uint16_t spsSize = (((uint16_t)ptr[6]) << 8)
        + (uint16_t)(ptr[7]);
    CODEC_LOGV(" numSeqParameterSets = %d , spsSize = %d",numSeqParameterSets,spsSize);
    SpsInfo info;
    if ( parseSps( spsSize, ptr + 9, &info ) == OK ) {
        mSPSParsed = true;
        CODEC_LOGV("SPS parsed");
        if (info.mInterlaced) {
            mInterlaceFormatDetected = true;
            meta->setInt32(kKeyUseArbitraryMode, 1);
            CODEC_LOGI("Interlace format detected");
        } else {
            CODEC_LOGI("Non-Interlaced format detected");
        }
    }
    else {
        CODEC_LOGI("ParseSPS could not find if content is interlaced");
        mSPSParsed = false;
        mInterlaceFormatDetected = false;
    }
#endif

    ptr += 6;
    size -= 6;
@@ -806,7 +828,7 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
            unsigned profile, level;
            status_t err;
            if ((err = parseAVCCodecSpecificData(
                            data, size, &profile, &level)) != OK) {
                            data, size, &profile, &level, meta)) != OK) {
                LOGE("Malformed AVC codec specific data.");
                return err;
            }
@@ -842,7 +864,13 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
        }

    }
#ifndef QCOM_HARDWARE
    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX, mMIME) || !strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX4, mMIME)) {
#else
    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX, mMIME) ||
        !strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX4, mMIME) ||
        !strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX311, mMIME)) {
#endif
        LOGV("Setting the QOMX_VIDEO_PARAM_DIVXTYPE params ");
        QOMX_VIDEO_PARAM_DIVXTYPE paramDivX;
        InitOMXParams(&paramDivX);
@@ -857,6 +885,8 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
            paramDivX.eFormat = QOMX_VIDEO_DIVXFormat5;
        } else if(DivxVersion == kTypeDivXVer_6) {
            paramDivX.eFormat = QOMX_VIDEO_DIVXFormat6;
        } else if(DivxVersion == kTypeDivXVer_3_11 ) {
            paramDivX.eFormat = QOMX_VIDEO_DIVXFormat311;
        } else {
            paramDivX.eFormat = QOMX_VIDEO_DIVXFormatUnused;
        }
@@ -911,39 +941,6 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
        if(err!=OK){
           return err;
        }
    } else if(!strcasecmp(MEDIA_MIMETYPE_VIDEO_WMV, mMIME)) {
	        OMX_QCOM_PARAM_PORTDEFINITIONTYPE portdef;
	        portdef.nSize = sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
	        portdef.nPortIndex = 0; //Input port.
	        portdef.nMemRegion = OMX_QCOM_MemRegionInvalid;
	        portdef.nCacheAttr = OMX_QCOM_CacheAttrNone;
        int32_t WMVProfile = 0;
        CHECK(meta->findInt32(kKeyWMVProfile,&WMVProfile));

        if(WMVProfile == kTypeWMVAdvance)
        {
            portdef.nFramePackingFormat = OMX_QCOM_FramePacking_Arbitrary;
            LOGV("Setting decoder in Arbitary Mode --- ADVANCE PROFILE");
        }
        else
        {
            portdef.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame;
            LOGV("Setting decoder in Frame-By-Frame Mode --- SIMPLE Profile");
        }

        char value[PROPERTY_VALUE_MAX];
        status_t err = mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_QcomIndexPortDefn, &portdef, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE));
        if (!property_get("ro.product.device", value, "1")
            || !strcmp(value, "msm7627_surf") || !strcmp(value, "msm7627_ffa")
            || !strcmp(value, "msm7627_7x_surf") || !strcmp(value, "msm7627_7x_ffa")
            || !strcmp(value, "msm7625_surf") || !strcmp(value, "msm7625_ffa"))
        {
            LOGE("OMX_QCOM_FramePacking_OnlyOneCompleteFrame not supported by component err: %d", err);
        } else {
            if(err!=OK){
               return err;
            }
        }
#endif
    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
            || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
@@ -991,6 +988,26 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
            if (err != OK) {
                return err;
            }

#ifdef QCOM_HARDWARE
            int32_t useArbitraryMode = 0;
            success = meta->findInt32(kKeyUseArbitraryMode, &useArbitraryMode);
            if (success && useArbitraryMode == 1) {
                CODEC_LOGI("Decoder should be in arbitrary mode");
                // Is it required to set OMX_QCOM_FramePacking_Arbitrary ??
            }
            else{
                CODEC_LOGI("Enable frame by frame mode");
                OMX_QCOM_PARAM_PORTDEFINITIONTYPE portFmt;
                portFmt.nPortIndex = kPortIndexInput;
                portFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame;
                err = mOMX->setParameter(
                        mNode, (OMX_INDEXTYPE)OMX_QcomIndexPortDefn, (void *)&portFmt, sizeof(portFmt));
                if(err != OK) {
                    LOGW("Failed to set frame packing format on component");
                }
            }
#endif
        }
    }

@@ -1889,6 +1906,7 @@ OMXCodec::OMXCodec(
              || !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode"))
                        ? NULL : nativeWindow),
      mInterlaceFormatDetected(false),
      mSPSParsed(false),
      mThumbnailMode(false) {
#else
      mNativeWindow(!strncmp(componentName, "OMX.google.", 11)
Loading