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

Commit 01836304 authored by Kim Sungyeon's avatar Kim Sungyeon Committed by Automerger Merge Worker
Browse files

VT: ARTPWriter: Enhanced ARTPWriter as a RTP output am: 65ff0dfa am: dabe7858

Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/952477

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ie782bd6e87e735edb4600d277230e8b7b98800a1
parents 9301400c dabe7858
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -247,6 +247,8 @@ enum {

    // Treat empty track as malformed for MediaRecorder.
    kKeyEmptyTrackMalFormed = 'nemt', // bool (int32_t)
    kKeySps              = 'sSps', // int32_t, indicates that a buffer is sps.
    kKeyPps              = 'sPps', // int32_t, indicates that a buffer is pps.
};

enum {
+210 −14
Original line number Diff line number Diff line
@@ -35,6 +35,18 @@
#define PT      97
#define PT_STR  "97"

#define H264_NALU_MASK 0x1F
#define H264_NALU_SPS 0x7
#define H264_NALU_PPS 0x8
#define H264_NALU_IFRAME 0x5
#define H264_NALU_PFRAME 0x1
#define UDP_HEADER_SIZE 8
#define RTP_HEADER_SIZE 12
#define RTP_HEADER_EXT_SIZE 1
#define RTP_FU_HEADER_SIZE 2
#define RTP_PAYLOAD_ROOM_SIZE 140


namespace android {

// static const size_t kMaxPacketSize = 65507;  // maximum payload in UDP over IP
@@ -55,8 +67,10 @@ ARTPWriter::ARTPWriter(int fd)
    mLooper->registerHandler(mReflector);
    mLooper->start();

    mSocket = socket(AF_INET, SOCK_DGRAM, 0);
    CHECK_GE(mSocket, 0);
    mRTPSocket = socket(AF_INET, SOCK_DGRAM, 0);
    CHECK_GE(mRTPSocket, 0);
    mRTCPSocket = socket(AF_INET, SOCK_DGRAM, 0);
    CHECK_GE(mRTCPSocket, 0);

    memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
    mRTPAddr.sin_family = AF_INET;
@@ -72,6 +86,83 @@ ARTPWriter::ARTPWriter(int fd)

    mRTCPAddr = mRTPAddr;
    mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
    mSPSBuf = NULL;
    mPPSBuf = NULL;

#if LOG_TO_FILES
    mRTPFd = open(
            "/data/misc/rtpout.bin",
            O_WRONLY | O_CREAT | O_TRUNC,
            0644);
    CHECK_GE(mRTPFd, 0);

    mRTCPFd = open(
            "/data/misc/rtcpout.bin",
            O_WRONLY | O_CREAT | O_TRUNC,
            0644);
    CHECK_GE(mRTCPFd, 0);
#endif
}

ARTPWriter::ARTPWriter(int fd, String8& localIp, int localPort, String8& remoteIp,
    int remotePort)
    : mFlags(0),
      mFd(dup(fd)),
      mLooper(new ALooper),
      mReflector(new AHandlerReflector<ARTPWriter>(this)) {
    CHECK_GE(fd, 0);

    mLooper->setName("rtp writer");
    mLooper->registerHandler(mReflector);
    mLooper->start();

    mRTPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    CHECK_GE(mRTPSocket, 0);
    mRTCPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    CHECK_GE(mRTCPSocket, 0);

    // socket need to be SO_REUSEADDR to avoid "Address already in use" error.
    int sockopt = 1;
    setsockopt(mRTPSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
    setsockopt(mRTPSocket, SOL_SOCKET, SO_REUSEPORT, (int *)&sockopt, sizeof(sockopt));
    setsockopt(mRTCPSocket, SOL_SOCKET, SO_REUSEADDR, (int *)&sockopt, sizeof(sockopt));
    setsockopt(mRTCPSocket, SOL_SOCKET, SO_REUSEPORT, (int *)&sockopt, sizeof(sockopt));

    // binding rtp socket to assign source ip/port.
    memset(mLocalAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
    mLocalAddr.sin_family = AF_INET;
    mLocalAddr.sin_addr.s_addr = inet_addr(localIp.string());
    mLocalAddr.sin_port = htons((unsigned short int)localPort);
    if (bind(mRTPSocket, (struct sockaddr*)&mLocalAddr, sizeof(mLocalAddr)) == -1) {
        ALOGE("failed to bind rtp %s:%d err=%s", localIp.string(),
                ntohs(mLocalAddr.sin_port), strerror(errno));
    } else {
        ALOGD("succeed to bind rtp %s:%d", localIp.string(), ntohs(mLocalAddr.sin_port));
    }
    // binding rtcp socket to assign source ip/port.
    mLocalAddr.sin_port = htons(ntohs(mLocalAddr.sin_port) + 1);
    if (bind(mRTCPSocket, (struct sockaddr*)&mLocalAddr, sizeof(mLocalAddr)) == -1) {
        ALOGE("failed to bind rtcp %s:%d", localIp.string(), ntohs(mLocalAddr.sin_port));
    } else {
        ALOGD("succeed to bind rtcp %s:%d", localIp.string(), ntohs(mLocalAddr.sin_port) | 1);
    }
    mLocalAddr.sin_port = htons(ntohs(mLocalAddr.sin_port) - 1);

    // update client settings
    memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
    mRTPAddr.sin_family = AF_INET;
    mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.string());
    mRTPAddr.sin_port = htons((unsigned short int)remotePort);

    mRTCPAddr = mRTPAddr;
    mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);

    ALOGD("localIp=%s, rtp=%d, rtcp=%d", localIp.string(), localPort, localPort+1);
    ALOGD("remoteIp=%s, rtp=%d, rtcp=%d", remoteIp.string(), ntohs(mRTPAddr.sin_port),
            ntohs(mRTCPAddr.sin_port));

    mSPSBuf = NULL;
    mPPSBuf = NULL;

#if LOG_TO_FILES
    mRTPFd = open(
@@ -97,11 +188,24 @@ ARTPWriter::~ARTPWriter() {
    mRTPFd = -1;
#endif

    close(mSocket);
    mSocket = -1;
    close(mRTPSocket);
    mRTPSocket = -1;

    close(mRTCPSocket);
    mRTCPSocket = -1;

    close(mFd);
    mFd = -1;

    if(mSPSBuf != NULL) {
        mSPSBuf->release();
        mSPSBuf = NULL;
    }

    if(mPPSBuf != NULL) {
        mPPSBuf->release();
        mPPSBuf = NULL;
    }
}

status_t ARTPWriter::addSource(const sp<MediaSource> &source) {
@@ -123,7 +227,7 @@ status_t ARTPWriter::start(MetaData * /* params */) {
    mFlags &= ~kFlagEOS;
    mSourceID = rand();
    mSeqNo = UniformRand(65536);
    mRTPTimeBase = rand();
    mRTPTimeBase = 0;
    mNumRTPSent = 0;
    mNumRTPOctetsSent = 0;
    mLastRTPTime = 0;
@@ -173,9 +277,12 @@ status_t ARTPWriter::pause() {
    return OK;
}

static void StripStartcode(MediaBufferBase *buffer) {
// return size of SPS if there is more NAL unit found following to SPS.
static uint32_t StripStartcode(MediaBufferBase *buffer) {
    uint32_t nalSize = 0;

    if (buffer->range_length() < 4) {
        return;
        return 0;
    }

    const uint8_t *ptr =
@@ -185,6 +292,56 @@ static void StripStartcode(MediaBufferBase *buffer) {
        buffer->set_range(
                buffer->range_offset() + 4, buffer->range_length() - 4);
    }

    ptr = (const uint8_t *)buffer->data() + buffer->range_offset();

    if ((*ptr & H264_NALU_MASK) == H264_NALU_SPS) {
        for (uint32_t i = 0; i < buffer->range_length(); i++) {

            if (!memcmp(ptr + i, "\x00\x00\x00\x01", 4)) {
                // Now, we found one more NAL unit in the media buffer.
                // Mostly, it will be a PPS.
                nalSize = i;
                ALOGV("SPS found. size=%d", nalSize);
            }
        }
    }

    return nalSize;
}

static void SpsPpsParser(MediaBufferBase *mediaBuffer,
    MediaBufferBase **spsBuffer, MediaBufferBase **ppsBuffer, uint32_t spsSize) {

    if (mediaBuffer == NULL || mediaBuffer->range_length() < 4)
        return;

    if((*spsBuffer) != NULL) {
        (*spsBuffer)->release();
        (*spsBuffer) = NULL;
    }

    if((*ppsBuffer) != NULL) {
        (*ppsBuffer)->release();
        (*ppsBuffer) = NULL;
    }

    // we got sps/pps but startcode of sps is striped.
    (*spsBuffer) = MediaBufferBase::Create(spsSize);
    int32_t ppsSize = mediaBuffer->range_length() - spsSize - 4/*startcode*/;
    (*ppsBuffer) = MediaBufferBase::Create(ppsSize);
    memcpy((*spsBuffer)->data(),
            (const uint8_t *)mediaBuffer->data() + mediaBuffer->range_offset(),
            spsSize);

    if (ppsSize > 0) {
        ALOGV("PPS found. size=%d", (int)ppsSize);
        mediaBuffer->set_range(mediaBuffer->range_offset() + spsSize + 4/*startcode*/,
                mediaBuffer->range_length() - spsSize - 4/*startcode*/);
        memcpy((*ppsBuffer)->data(),
                (const uint8_t *)mediaBuffer->data() + mediaBuffer->range_offset(),
                ppsSize);
    }
}

void ARTPWriter::onMessageReceived(const sp<AMessage> &msg) {
@@ -280,8 +437,12 @@ void ARTPWriter::onRead(const sp<AMessage> &msg) {
        ALOGV("read buffer of size %zu", mediaBuf->range_length());

        if (mMode == H264) {
            StripStartcode(mediaBuf);
            uint32_t spsSize = 0;
            if ((spsSize = StripStartcode(mediaBuf)) > 0) {
                SpsPpsParser(mediaBuf, &mSPSBuf, &mPPSBuf, spsSize);
            } else {
                sendAVCData(mediaBuf);
            }
        } else if (mMode == H263) {
            sendH263Data(mediaBuf);
        } else if (mMode == AMR_NB || mMode == AMR_WB) {
@@ -310,7 +471,7 @@ void ARTPWriter::onSendSR(const sp<AMessage> &msg) {

void ARTPWriter::send(const sp<ABuffer> &buffer, bool isRTCP) {
    ssize_t n = sendto(
            mSocket, buffer->data(), buffer->size(), 0,
            isRTCP ? mRTCPSocket : mRTPSocket, buffer->data(), buffer->size(), 0,
            (const struct sockaddr *)(isRTCP ? &mRTCPAddr : &mRTPAddr),
            sizeof(mRTCPAddr));

@@ -569,6 +730,26 @@ void ARTPWriter::sendBye() {
    send(buffer, true /* isRTCP */);
}

void ARTPWriter::sendSPSPPSIfIFrame(MediaBufferBase *mediaBuf, int64_t timeUs) {
    const uint8_t *mediaData =
        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();

    if ((mediaData[0] & H264_NALU_MASK) != H264_NALU_IFRAME)
        return;

    if (mSPSBuf != NULL) {
        mSPSBuf->meta_data().setInt64(kKeyTime, timeUs);
        mSPSBuf->meta_data().setInt32(kKeySps, 1);
        sendAVCData(mSPSBuf);
    }

    if (mPPSBuf != NULL) {
        mPPSBuf->meta_data().setInt64(kKeyTime, timeUs);
        mPPSBuf->meta_data().setInt32(kKeyPps, 1);
        sendAVCData(mPPSBuf);
    }
}

void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
    // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
    CHECK_GE(kMaxPacketSize, 12u + 2u);
@@ -576,17 +757,30 @@ void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
    int64_t timeUs;
    CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));

    sendSPSPPSIfIFrame(mediaBuf, timeUs);

    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);

    const uint8_t *mediaData =
        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();

    int32_t sps, pps;
    bool isSpsPps = false;
    if (mediaBuf->meta_data().findInt32(kKeySps, &sps) ||
            mediaBuf->meta_data().findInt32(kKeyPps, &pps)) {
        isSpsPps = true;
    }

    sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
    if (mediaBuf->range_length() + 12 <= buffer->capacity()) {
    if (mediaBuf->range_length() + UDP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_PAYLOAD_ROOM_SIZE
            <= buffer->capacity()) {
        // The data fits into a single packet
        uint8_t *data = buffer->data();
        data[0] = 0x80;
        data[1] = (1 << 7) | PT;  // M-bit
        if (isSpsPps)
            data[1] = PT;  // Marker bit should not be set in case of sps/pps
        else
            data[1] = (1 << 7) | PT;
        data[2] = (mSeqNo >> 8) & 0xff;
        data[3] = mSeqNo & 0xff;
        data[4] = rtpTime >> 24;
@@ -618,9 +812,11 @@ void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
        while (offset < mediaBuf->range_length()) {
            size_t size = mediaBuf->range_length() - offset;
            bool lastPacket = true;
            if (size + 12 + 2 > buffer->capacity()) {
            if (size + UDP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_FU_HEADER_SIZE +
                    RTP_PAYLOAD_ROOM_SIZE > buffer->capacity()) {
                lastPacket = false;
                size = buffer->capacity() - 12 - 2;
                size = buffer->capacity() - UDP_HEADER_SIZE - RTP_HEADER_SIZE -
                    RTP_FU_HEADER_SIZE - RTP_PAYLOAD_ROOM_SIZE;
            }

            uint8_t *data = buffer->data();
+8 −1
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ class MediaBuffer;

struct ARTPWriter : public MediaWriter {
    explicit ARTPWriter(int fd);
    explicit ARTPWriter(int fd, String8& localIp, int localPort,
                                String8& remoteIp, int remotePort);

    virtual status_t addSource(const sp<MediaSource> &source);
    virtual bool reachedEOS();
@@ -76,7 +78,8 @@ private:
    sp<ALooper> mLooper;
    sp<AHandlerReflector<ARTPWriter> > mReflector;

    int mSocket;
    int mRTPSocket, mRTCPSocket;
    struct sockaddr_in mLocalAddr;
    struct sockaddr_in mRTPAddr;
    struct sockaddr_in mRTCPAddr;

@@ -84,6 +87,9 @@ private:
    AString mSeqParamSet;
    AString mPicParamSet;

    MediaBufferBase *mSPSBuf;
    MediaBufferBase *mPPSBuf;

    uint32_t mSourceID;
    uint32_t mSeqNo;
    uint32_t mRTPTimeBase;
@@ -114,6 +120,7 @@ private:
    void dumpSessionDesc();

    void sendBye();
    void sendSPSPPSIfIFrame(MediaBufferBase *mediaBuf, int64_t timeUs);
    void sendAVCData(MediaBufferBase *mediaBuf);
    void sendH263Data(MediaBufferBase *mediaBuf);
    void sendAMRData(MediaBufferBase *mediaBuf);