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

Commit cfaeeec0 authored by Andreas Huber's avatar Andreas Huber
Browse files

Add support for mpeg2 transport streams to the RTSP implementation.

Change-Id: I409d7133a53a71e62523b1acc2b03302fcf824a5
parent dc91c885
Loading
Loading
Loading
Loading
+71 −5
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "AnotherPacketSource.h"
#include "MyHandler.h"

#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>

namespace android {
@@ -159,6 +160,13 @@ status_t NuPlayer::RTSPSource::dequeueAccessUnit(
}

sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
    if (mTSParser != NULL) {
        sp<MediaSource> source = mTSParser->getSource(
                audio ? ATSParser::AUDIO : ATSParser::VIDEO);

        return static_cast<AnotherPacketSource *>(source.get());
    }

    return audio ? mAudioTrack : mVideoTrack;
}

@@ -255,7 +263,12 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
        {
            size_t trackIndex;
            CHECK(msg->findSize("trackIndex", &trackIndex));

            if (mTSParser == NULL) {
                CHECK_LT(trackIndex, mTracks.size());
            } else {
                CHECK_EQ(trackIndex, 0u);
            }

            sp<ABuffer> accessUnit;
            CHECK(msg->findBuffer("accessUnit", &accessUnit));
@@ -267,6 +280,37 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
                break;
            }

            if (mTSParser != NULL) {
                size_t offset = 0;
                status_t err = OK;
                while (offset + 188 <= accessUnit->size()) {
                    err = mTSParser->feedTSPacket(
                            accessUnit->data() + offset, 188);
                    if (err != OK) {
                        break;
                    }

                    offset += 188;
                }

                if (offset < accessUnit->size()) {
                    err = ERROR_MALFORMED;
                }

                if (err != OK) {
                    sp<AnotherPacketSource> source = getSource(false /* audio */);
                    if (source != NULL) {
                        source->signalEOS(err);
                    }

                    source = getSource(true /* audio */);
                    if (source != NULL) {
                        source->signalEOS(err);
                    }
                }
                break;
            }

            TrackInfo *info = &mTracks.editItemAt(trackIndex);

            sp<AnotherPacketSource> source = info->mSource;
@@ -296,14 +340,28 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {

        case MyHandler::kWhatEOS:
        {
            size_t trackIndex;
            CHECK(msg->findSize("trackIndex", &trackIndex));
            CHECK_LT(trackIndex, mTracks.size());

            int32_t finalResult;
            CHECK(msg->findInt32("finalResult", &finalResult));
            CHECK_NE(finalResult, (status_t)OK);

            if (mTSParser != NULL) {
                sp<AnotherPacketSource> source = getSource(false /* audio */);
                if (source != NULL) {
                    source->signalEOS(finalResult);
                }

                source = getSource(true /* audio */);
                if (source != NULL) {
                    source->signalEOS(finalResult);
                }

                return;
            }

            size_t trackIndex;
            CHECK(msg->findSize("trackIndex", &trackIndex));
            CHECK_LT(trackIndex, mTracks.size());

            TrackInfo *info = &mTracks.editItemAt(trackIndex);
            sp<AnotherPacketSource> source = info->mSource;
            if (source != NULL) {
@@ -364,6 +422,14 @@ void NuPlayer::RTSPSource::onConnected() {
        const char *mime;
        CHECK(format->findCString(kKeyMIMEType, &mime));

        if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
            // Very special case for MPEG2 Transport Streams.
            CHECK_EQ(numTracks, 1u);

            mTSParser = new ATSParser;
            return;
        }

        bool isAudio = !strncasecmp(mime, "audio/", 6);
        bool isVideo = !strncasecmp(mime, "video/", 6);

+4 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@

#include "NuPlayerSource.h"

#include "ATSParser.h"

#include <media/stagefright/foundation/AHandlerReflector.h>

namespace android {
@@ -99,6 +101,8 @@ private:
    sp<AnotherPacketSource> mAudioTrack;
    sp<AnotherPacketSource> mVideoTrack;

    sp<ATSParser> mTSParser;

    int32_t mSeekGeneration;

    sp<AnotherPacketSource> getSource(bool audio);
+119 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "AMPEG2TSAssembler"
#include <utils/Log.h>

#include "AMPEG2TSAssembler.h"

#include "ARTPSource.h"
#include "ASessionDescription.h"

#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>

namespace android {

AMPEG2TSAssembler::AMPEG2TSAssembler(
        const sp<AMessage> &notify, const char *desc, const AString &params)
    : mNotifyMsg(notify),
      mNextExpectedSeqNoValid(false),
      mNextExpectedSeqNo(0) {
}

AMPEG2TSAssembler::~AMPEG2TSAssembler() {
}

ARTPAssembler::AssemblyStatus AMPEG2TSAssembler::assembleMore(
        const sp<ARTPSource> &source) {
    return addPacket(source);
}

ARTPAssembler::AssemblyStatus AMPEG2TSAssembler::addPacket(
        const sp<ARTPSource> &source) {
    List<sp<ABuffer> > *queue = source->queue();

    if (queue->empty()) {
        return NOT_ENOUGH_DATA;
    }

    if (mNextExpectedSeqNoValid) {
        List<sp<ABuffer> >::iterator it = queue->begin();
        while (it != queue->end()) {
            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
                break;
            }

            it = queue->erase(it);
        }

        if (queue->empty()) {
            return NOT_ENOUGH_DATA;
        }
    }

    sp<ABuffer> buffer = *queue->begin();

    if (!mNextExpectedSeqNoValid) {
        mNextExpectedSeqNoValid = true;
        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
        ALOGV("Not the sequence number I expected");

        return WRONG_SEQUENCE_NUMBER;
    }

    // hexdump(buffer->data(), buffer->size());

    if ((buffer->size() % 188) > 0) {
        queue->erase(queue->begin());
        ++mNextExpectedSeqNo;

        ALOGV("Not a multiple of transport packet size.");

        return MALFORMED_PACKET;
    }

    sp<AMessage> msg = mNotifyMsg->dup();
    msg->setBuffer("access-unit", buffer);
    msg->post();

    queue->erase(queue->begin());
    ++mNextExpectedSeqNo;

    return OK;
}

void AMPEG2TSAssembler::packetLost() {
    CHECK(mNextExpectedSeqNoValid);
    ++mNextExpectedSeqNo;
}

void AMPEG2TSAssembler::onByeReceived() {
    sp<AMessage> msg = mNotifyMsg->dup();
    msg->setInt32("eos", true);
    msg->post();
}

}  // namespace android

+54 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef A_MPEG2_TS_ASSEMBLER_H_

#define A_MPEG2_TS_ASSEMBLER_H_

#include "ARTPAssembler.h"

namespace android {

struct AMessage;
struct AString;
struct MetaData;

struct AMPEG2TSAssembler : public ARTPAssembler {
    AMPEG2TSAssembler(
            const sp<AMessage> &notify,
            const char *desc, const AString &params);

protected:
    virtual ~AMPEG2TSAssembler();

    virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
    virtual void onByeReceived();
    virtual void packetLost();

private:
    sp<AMessage> mNotifyMsg;
    bool mNextExpectedSeqNoValid;
    uint32_t mNextExpectedSeqNo;

    AssemblyStatus addPacket(const sp<ARTPSource> &source);

    DISALLOW_EVIL_CONSTRUCTORS(AMPEG2TSAssembler);
};

}  // namespace android

#endif  // A_MPEG2_TS_ASSEMBLER_H_
+2 −0
Original line number Diff line number Diff line
@@ -566,6 +566,8 @@ APacketSource::APacketSource(
                codecSpecificData->data(), codecSpecificData->size());
    } else if (ARawAudioAssembler::Supports(desc.c_str())) {
        ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat);
    } else if (!strncasecmp("MP2T/", desc.c_str(), 5)) {
        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
    } else {
        mInitCheck = ERROR_UNSUPPORTED;
    }
Loading