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

Commit 6ffdc403 authored by Byeongjo Park's avatar Byeongjo Park Committed by Lajos Molnar
Browse files

VT: Dropping P-frames till I-frame provided



[Problem] Video is not shown even a video call connected.
[Cause] Remote side sent I-frame few times at the beginning of the
  stream then just sending P-frames only.
  In above behavior of remote device, DUT can not show video till
  end of the call if I-frames are missed.
  Because remote device will not send next I-frame until RTCP:FIR received.
[Solution] Discards P-frames Then request a new I-frame by sending RTCP:FIR.

Bug: 173163174
Bug: 173474333

Change-Id: If81dd3c154071953a7fd0d1cd354c5432bf4cb43
Signed-off-by: default avatarByeongjo Park <bjo.park@samsung.com>
Signed-off-by: default avatarKim Sungyeon <sy85.kim@samsung.com>
Merged-In: If81dd3c154071953a7fd0d1cd354c5432bf4cb43
parent 25c3a3d2
Loading
Loading
Loading
Loading
+54 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/hexdump.h>

#include <stdint.h>
@@ -39,7 +40,9 @@ AAVCAssembler::AAVCAssembler(const sp<AMessage> &notify)
      mNextExpectedSeqNo(0),
      mAccessUnitDamaged(false),
      mFirstIFrameProvided(false),
      mLastIFrameProvidedAtMs(0) {
      mLastIFrameProvidedAtMs(0),
      mWidth(0),
      mHeight(0) {
}

AAVCAssembler::~AAVCAssembler() {
@@ -115,6 +118,8 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
    sp<ABuffer> buffer = *queue->begin();
    uint32_t rtpTime;
    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
    buffer->meta()->setObject("source", source);

    int64_t startTime = source->mFirstSysTime / 1000;
    int64_t nowTime = ALooper::GetNowUs() / 1000;
    int64_t playedTime = nowTime - startTime;
@@ -224,6 +229,21 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
    }
}

void AAVCAssembler::checkSpsUpdated(const sp<ABuffer> &buffer) {
    const uint8_t *data = buffer->data();
    unsigned nalType = data[0] & 0x1f;
    if (nalType == 0x7) {
        int32_t width = 0, height = 0;
        FindAVCDimensions(buffer, &width, &height);
        if (width != mWidth || height != mHeight) {
            mFirstIFrameProvided = false;
            mWidth = width;
            mHeight = height;
            ALOGD("found a new resolution (%u x %u)", mWidth, mHeight);
        }
    }
}

void AAVCAssembler::checkIFrameProvided(const sp<ABuffer> &buffer) {
    if (buffer->size() == 0) {
        return;
@@ -231,13 +251,25 @@ void AAVCAssembler::checkIFrameProvided(const sp<ABuffer> &buffer) {
    const uint8_t *data = buffer->data();
    unsigned nalType = data[0] & 0x1f;
    if (nalType == 0x5) {
        mFirstIFrameProvided = true;
        mLastIFrameProvidedAtMs = ALooper::GetNowUs() / 1000;
        if (!mFirstIFrameProvided) {
            mFirstIFrameProvided = true;

            uint32_t rtpTime;
            CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
        ALOGD("got First I-frame to be decoded. rtpTime=%u, size=%zu", rtpTime, buffer->size());
            ALOGD("got First I-frame to be decoded. rtpTime=%d, size=%zu", rtpTime, buffer->size());
        }
    }
}

bool AAVCAssembler::dropFramesUntilIframe(const sp<ABuffer> &buffer) {
    const uint8_t *data = buffer->data();
    unsigned nalType = data[0] & 0x1f;
    if (!mFirstIFrameProvided && nalType < 0x5) {
        return true;
    }

    return false;
}

void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
@@ -246,11 +278,23 @@ void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
    hexdump(buffer->data(), buffer->size());
#endif

    checkSpsUpdated(buffer);
    checkIFrameProvided(buffer);

    uint32_t rtpTime;
    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));

    if (dropFramesUntilIframe(buffer)) {
        sp<ARTPSource> source = nullptr;
        buffer->meta()->findObject("source", (sp<android::RefBase>*)&source);
        if (source != nullptr) {
            ALOGD("Issued FIR to get the I-frame");
            source->onIssueFIRByAssembler();
        }
        ALOGV("Dropping P-frame till I-frame provided. rtpTime %u", rtpTime);
        return;
    }

    if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
        submitAccessUnit();
    }
@@ -431,6 +475,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(

    size_t offset = 1;
    int32_t cvo = -1;
    sp<ARTPSource> source = nullptr;
    List<sp<ABuffer> >::iterator it = queue->begin();
    for (size_t i = 0; i < totalCount; ++i) {
        const sp<ABuffer> &buffer = *it;
@@ -442,6 +487,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(

        memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);

        buffer->meta()->findObject("source", (sp<android::RefBase>*)&source);
        buffer->meta()->findInt32("cvo", &cvo);
        offset += buffer->size() - 2;

@@ -453,6 +499,9 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
    if (cvo >= 0) {
        unit->meta()->setInt32("cvo", cvo);
    }
    if (source != nullptr) {
        unit->meta()->setObject("source", source);
    }

    addSingleNALUnit(unit);

+4 −0
Original line number Diff line number Diff line
@@ -48,10 +48,14 @@ private:
    bool mAccessUnitDamaged;
    bool mFirstIFrameProvided;
    uint64_t mLastIFrameProvidedAtMs;
    int32_t mWidth;
    int32_t mHeight;
    List<sp<ABuffer> > mNALUnits;

    int32_t addNack(const sp<ARTPSource> &source);
    void checkSpsUpdated(const sp<ABuffer> &buffer);
    void checkIFrameProvided(const sp<ABuffer> &buffer);
    bool dropFramesUntilIframe(const sp<ABuffer> &buffer);
    AssemblyStatus addNALUnit(const sp<ARTPSource> &source);
    void addSingleNALUnit(const sp<ABuffer> &buffer);
    AssemblyStatus addFragmentedNALUnit(List<sp<ABuffer> > *queue);
+1 −1
Original line number Diff line number Diff line
@@ -226,7 +226,7 @@ void ARTPSource::addFIR(const sp<ABuffer> &buffer) {
        // Send it if last FIR is not sent within a sec.
        send = true;
    } else if (mIssueFIRRequests && (usecsSinceLastFIR > 5000000)) {
        // A FIR issued periodically reagardless packet loss.
        // A FIR issued periodically regardless packet loss.
        // Send it if last FIR is not sent within 5 secs.
        send = true;
    }