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

Commit 0af4db6a authored by Chong Zhang's avatar Chong Zhang
Browse files

Fill in frame duration from sample meta

If sample duration is not available, use the average
frame duration of the sequence; if that's not available
default to 30fps.

bug: 120414514
bug: 139815242
test: test some 25fps heif sequence files, the reported
      duration should be 40ms instead of the default 33ms.

Change-Id: I5ddf0a6cbfb44021dee2955badf3f2772586bb1e
parent f5349568
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ public:
            uint32_t angle, uint32_t bpp, bool hasData, size_t iccSize):
        mWidth(width), mHeight(height),
        mDisplayWidth(displayWidth), mDisplayHeight(displayHeight),
        mTileWidth(tileWidth), mTileHeight(tileHeight),
        mTileWidth(tileWidth), mTileHeight(tileHeight), mDurationUs(0),
        mRotationAngle(angle), mBytesPerPixel(bpp), mRowBytes(bpp * width),
        mSize(hasData ? (bpp * width * height) : 0),
        mIccSize(iccSize), mReserved(0) {
@@ -78,6 +78,7 @@ public:
    uint32_t mDisplayHeight;   // Display height before rotation
    uint32_t mTileWidth;       // Tile width (0 if image doesn't have grid)
    uint32_t mTileHeight;      // Tile height (0 if image doesn't have grid)
    int64_t  mDurationUs;      // Frame duration in microseconds
    int32_t  mRotationAngle;   // Rotation angle, clockwise, should be multiple of 90
    uint32_t mBytesPerPixel;   // Number of bytes per pixel
    uint32_t mRowBytes;        // Number of bytes per row before rotation
+1 −2
Original line number Diff line number Diff line
@@ -44,8 +44,7 @@ void initFrameInfo(HeifFrameInfo *info, const VideoFrame *videoFrame) {
    info->mHeight = videoFrame->mHeight;
    info->mRotationAngle = videoFrame->mRotationAngle;
    info->mBytesPerPixel = videoFrame->mBytesPerPixel;
    // TODO: retrieve per-frame duration from extractor/metadataretriever.
    info->mDurationUs = 33333;
    info->mDurationUs = videoFrame->mDurationUs;
    if (videoFrame->mIccSize > 0) {
        info->mIccData.assign(
                videoFrame->getFlattenedIccData(),
+36 −2
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ namespace android {

static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
static const size_t kRetryCount = 50; // must be >0
static const int64_t kDefaultSampleDurationUs = 33333LL; // 33ms

sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
        int32_t width, int32_t height, int32_t tileWidth, int32_t tileHeight,
@@ -199,7 +200,19 @@ sp<IMemory> FrameDecoder::getMetadataOnly(
            tileWidth = tileHeight = 0;
        }
    }
    return allocMetaFrame(trackMeta, width, height, tileWidth, tileHeight, dstBpp);

    sp<IMemory> metaMem = allocMetaFrame(trackMeta, width, height, tileWidth, tileHeight, dstBpp);

    // try to fill sequence meta's duration based on average frame rate,
    // default to 33ms if frame rate is unavailable.
    int32_t frameRate;
    VideoFrame* meta = static_cast<VideoFrame*>(metaMem->pointer());
    if (trackMeta->findInt32(kKeyFrameRate, &frameRate) && frameRate > 0) {
        meta->mDurationUs = 1000000LL / frameRate;
    } else {
        meta->mDurationUs = kDefaultSampleDurationUs;
    }
    return metaMem;
}

FrameDecoder::FrameDecoder(
@@ -443,7 +456,8 @@ VideoFrameDecoder::VideoFrameDecoder(
      mFrame(NULL),
      mIsAvcOrHevc(false),
      mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC),
      mTargetTimeUs(-1LL) {
      mTargetTimeUs(-1LL),
      mDefaultSampleDurationUs(0) {
}

sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions(
@@ -506,6 +520,13 @@ sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions(
        }
    }

    int32_t frameRate;
    if (trackMeta()->findInt32(kKeyFrameRate, &frameRate) && frameRate > 0) {
        mDefaultSampleDurationUs = 1000000LL / frameRate;
    } else {
        mDefaultSampleDurationUs = kDefaultSampleDurationUs;
    }

    return videoFormat;
}

@@ -526,6 +547,12 @@ status_t VideoFrameDecoder::onInputReceived(
        // option, in which case we need to actually decode to targetTimeUs.
        *flags |= MediaCodec::BUFFER_FLAG_EOS;
    }
    int64_t durationUs;
    if (sampleMeta.findInt64(kKeyDuration, &durationUs)) {
        mSampleDurations.push_back(durationUs);
    } else {
        mSampleDurations.push_back(mDefaultSampleDurationUs);
    }
    return OK;
}

@@ -533,6 +560,11 @@ status_t VideoFrameDecoder::onOutputReceived(
        const sp<MediaCodecBuffer> &videoFrameBuffer,
        const sp<AMessage> &outputFormat,
        int64_t timeUs, bool *done) {
    int64_t durationUs = mDefaultSampleDurationUs;
    if (!mSampleDurations.empty()) {
        durationUs = *mSampleDurations.begin();
        mSampleDurations.erase(mSampleDurations.begin());
    }
    bool shouldOutput = (mTargetTimeUs < 0LL) || (timeUs >= mTargetTimeUs);

    // If this is not the target frame, skip color convert.
@@ -587,6 +619,8 @@ status_t VideoFrameDecoder::onOutputReceived(
        setFrame(frameMem);
    }

    mFrame->mDurationUs = durationUs;

    if (mSurfaceControl != nullptr) {
        return captureSurfaceControl();
    }
+2 −0
Original line number Diff line number Diff line
@@ -139,6 +139,8 @@ private:
    bool mIsAvcOrHevc;
    MediaSource::ReadOptions::SeekMode mSeekMode;
    int64_t mTargetTimeUs;
    List<int64_t> mSampleDurations;
    int64_t mDefaultSampleDurationUs;

    sp<Surface> initSurfaceControl();
    status_t captureSurfaceControl();