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

Commit 914dd217 authored by Dichen Zhang's avatar Dichen Zhang
Browse files

Add support for IsHevcIdr()

Bug: 142396980
Test: Extract frame from HEVC video by MediaMetadataRetriever and
extraction option other than closest. Manually print log to see if flag
is set correctly.

Change-Id: I35751299219d71a31b0418c244a1fbd7b7f97e1c
parent a199662c
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include "include/FrameDecoder.h"
#include "include/FrameCaptureLayer.h"
#include "include/HevcUtils.h"
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <gui/Surface.h>
@@ -455,7 +456,8 @@ VideoFrameDecoder::VideoFrameDecoder(
        const sp<IMediaSource> &source)
    : FrameDecoder(componentName, trackMeta, source),
      mFrame(NULL),
      mIsAvcOrHevc(false),
      mIsAvc(false),
      mIsHevc(false),
      mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC),
      mTargetTimeUs(-1LL),
      mDefaultSampleDurationUs(0) {
@@ -478,8 +480,8 @@ sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions(
        return NULL;
    }

    mIsAvcOrHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
            || !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
    mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);

    if (frameTimeUs < 0) {
        int64_t thumbNailTime = -1ll;
@@ -542,8 +544,10 @@ status_t VideoFrameDecoder::onInputReceived(
        ALOGV("Seeking closest: targetTimeUs=%lld", (long long)mTargetTimeUs);
    }

    if (mIsAvcOrHevc && !isSeekingClosest
            && IsIDR(codecBuffer->data(), codecBuffer->size())) {
    if (!isSeekingClosest
            && ((mIsAvc && IsIDR(codecBuffer->data(), codecBuffer->size()))
            || (mIsHevc && IsIDR(
            codecBuffer->data(), codecBuffer->size())))) {
        // Only need to decode one IDR frame, unless we're seeking with CLOSEST
        // option, in which case we need to actually decode to targetTimeUs.
        *flags |= MediaCodec::BUFFER_FLAG_EOS;
+26 −1
Original line number Diff line number Diff line
@@ -32,7 +32,10 @@

namespace android {

static const uint8_t kHevcNalUnitTypes[5] = {
static const uint8_t kHevcNalUnitTypes[8] = {
    kHevcNalUnitTypeCodedSliceIdr,
    kHevcNalUnitTypeCodedSliceIdrNoLP,
    kHevcNalUnitTypeCodedSliceCra,
    kHevcNalUnitTypeVps,
    kHevcNalUnitTypeSps,
    kHevcNalUnitTypePps,
@@ -488,4 +491,26 @@ status_t HevcParameterSets::makeHvcc(uint8_t *hvcc, size_t *hvccSize,
    return OK;
}

bool HevcParameterSets::IsHevcIDR(const uint8_t *data, size_t size) {
    bool foundIDR = false;
    const uint8_t *nalStart;
    size_t nalSize;
    while (!foundIDR && getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
        if (nalSize == 0) {
            ALOGE("Encountered zero-length HEVC NAL");
            return false;
        }

        uint8_t nalType = (nalStart[0] & 0x7E) >> 1;
        switch(nalType) {
            case kHevcNalUnitTypeCodedSliceIdr:
            case kHevcNalUnitTypeCodedSliceIdrNoLP:
            case kHevcNalUnitTypeCodedSliceCra:
                foundIDR = true;
                break;
        }
    }

    return foundIDR;
}
}  // namespace android
+2 −1
Original line number Diff line number Diff line
@@ -135,7 +135,8 @@ protected:
private:
    sp<FrameCaptureLayer> mCaptureLayer;
    VideoFrame *mFrame;
    bool mIsAvcOrHevc;
    bool mIsAvc;
    bool mIsHevc;
    MediaSource::ReadOptions::SeekMode mSeekMode;
    int64_t mTargetTimeUs;
    List<int64_t> mSampleDurations;
+5 −0
Original line number Diff line number Diff line
@@ -30,6 +30,10 @@
namespace android {

enum {
    kHevcNalUnitTypeCodedSliceIdr = 19,
    kHevcNalUnitTypeCodedSliceIdrNoLP = 20,
    kHevcNalUnitTypeCodedSliceCra = 21,

    kHevcNalUnitTypeVps = 32,
    kHevcNalUnitTypeSps = 33,
    kHevcNalUnitTypePps = 34,
@@ -92,6 +96,7 @@ public:
    status_t makeHvcc(uint8_t *hvcc, size_t *hvccSize, size_t nalSizeLength);

    Info getInfo() const { return mInfo; }
    static bool IsHevcIDR(const uint8_t *data, size_t size);

private:
    status_t parseVps(const uint8_t* data, size_t size);