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

Commit bfb03d24 authored by Robert Shih's avatar Robert Shih Committed by Android (Google) Code Review
Browse files

Merge "stagefright: initial timed id3 support in hls"

parents 9767a47d 0852843d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ enum media_event_type {
    MEDIA_ERROR             = 100,
    MEDIA_INFO              = 200,
    MEDIA_SUBTITLE_DATA     = 201,
    MEDIA_META_DATA         = 202,
};

// Generic error codes for the media player framework.  Errors are fatal, the
@@ -183,6 +184,7 @@ enum media_track_type {
    MEDIA_TRACK_TYPE_AUDIO = 2,
    MEDIA_TRACK_TYPE_TIMEDTEXT = 3,
    MEDIA_TRACK_TYPE_SUBTITLE = 4,
    MEDIA_TRACK_TYPE_METADATA = 5,
};

// ----------------------------------------------------------------------------
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ extern const char *MEDIA_MIMETYPE_TEXT_3GPP;
extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP;
extern const char *MEDIA_MIMETYPE_TEXT_VTT;
extern const char *MEDIA_MIMETYPE_TEXT_CEA_608;
extern const char *MEDIA_MIMETYPE_DATA_METADATA;

}  // namespace android

+3 −0
Original line number Diff line number Diff line
@@ -857,6 +857,9 @@ void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
    case MEDIA_SUBTITLE_DATA:
        ALOGV("Received subtitle data message");
        break;
    case MEDIA_META_DATA:
        ALOGV("Received timed metadata message");
        break;
    default:
        ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
        break;
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ LOCAL_SRC_FILES:= \
        StreamingSource.cpp             \

LOCAL_C_INCLUDES := \
	$(TOP)/frameworks/av/media/libstagefright                     \
	$(TOP)/frameworks/av/media/libstagefright/httplive            \
	$(TOP)/frameworks/av/media/libstagefright/include             \
	$(TOP)/frameworks/av/media/libstagefright/mpeg2ts             \
+110 −30
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@

#include "AnotherPacketSource.h"
#include "LiveDataSource.h"
#include "LiveSession.h"

#include <media/IMediaHTTPService.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -30,6 +29,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaDefs.h>

namespace android {

@@ -44,7 +44,10 @@ NuPlayer::HTTPLiveSource::HTTPLiveSource(
      mFlags(0),
      mFinalResult(OK),
      mOffset(0),
      mFetchSubtitleDataGeneration(0) {
      mFetchSubtitleDataGeneration(0),
      mFetchMetaDataGeneration(0),
      mHasMetadata(false),
      mMetadataSelected(false) {
    if (headers) {
        mExtraHeaders = *headers;

@@ -142,19 +145,49 @@ sp<AMessage> NuPlayer::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
ssize_t NuPlayer::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
    if (mLiveSession == NULL) {
        return -1;
    } else if (type == MEDIA_TRACK_TYPE_METADATA) {
        // MEDIA_TRACK_TYPE_METADATA is always last track
        // mMetadataSelected can only be true when mHasMetadata is true
        return mMetadataSelected ? (mLiveSession->getTrackCount() - 1) : -1;
    } else {
        return mLiveSession->getSelectedTrack(type);
    }
}

status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
    status_t err = mLiveSession->selectTrack(trackIndex, select);
    if (mLiveSession == NULL) {
        return INVALID_OPERATION;
    }

    status_t err = INVALID_OPERATION;
    bool postFetchMsg = false, isSub = false;
    if (trackIndex != mLiveSession->getTrackCount() - 1) {
        err = mLiveSession->selectTrack(trackIndex, select);
        postFetchMsg = select;
        isSub = true;
    } else {
        // metadata track
        if (mHasMetadata) {
            if (mMetadataSelected && !select) {
                err = OK;
            } else if (!mMetadataSelected && select) {
                postFetchMsg = true;
                err = OK;
            } else {
                err = BAD_VALUE; // behave as LiveSession::selectTrack
            }

            mMetadataSelected = select;
        }
    }

    if (err == OK) {
        mFetchSubtitleDataGeneration++;
        if (select) {
            sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
            msg->setInt32("generation", mFetchSubtitleDataGeneration);
        int32_t &generation = isSub ? mFetchSubtitleDataGeneration : mFetchMetaDataGeneration;
        generation++;
        if (postFetchMsg) {
            int32_t what = isSub ? kWhatFetchSubtitleData : kWhatFetchMetaData;
            sp<AMessage> msg = new AMessage(what, this);
            msg->setInt32("generation", generation);
            msg->post();
        }
    }
@@ -169,44 +202,78 @@ status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
    return mLiveSession->seekTo(seekTimeUs);
}

void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSessionNotify:
        {
            onSessionNotify(msg);
            break;
        }
void NuPlayer::HTTPLiveSource::pollForRawData(
        const sp<AMessage> &msg, int32_t currentGeneration,
        LiveSession::StreamType fetchType, int32_t pushWhat) {

        case kWhatFetchSubtitleData:
        {
    int32_t generation;
    CHECK(msg->findInt32("generation", &generation));

            if (generation != mFetchSubtitleDataGeneration) {
                // stale
                break;
    if (generation != currentGeneration) {
        return;
    }

    sp<ABuffer> buffer;
            if (mLiveSession->dequeueAccessUnit(
                    LiveSession::STREAMTYPE_SUBTITLES, &buffer) == OK) {
    while (mLiveSession->dequeueAccessUnit(fetchType, &buffer) == OK) {

        sp<AMessage> notify = dupNotify();
                notify->setInt32("what", kWhatSubtitleData);
        notify->setInt32("what", pushWhat);
        notify->setBuffer("buffer", buffer);
                notify->post();

                int64_t timeUs, baseUs, durationUs, delayUs;
        int64_t timeUs, baseUs, delayUs;
        CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
                CHECK(buffer->meta()->findInt64("durationUs", &durationUs));
        delayUs = baseUs + timeUs - ALooper::GetNowUs();

        if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
            notify->post();
            msg->post(delayUs > 0ll ? delayUs : 0ll);
            return;
        } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
            if (delayUs < -1000000ll) { // 1 second
                continue;
            }
            notify->post();
            // push all currently available metadata buffers in each invocation of pollForRawData
            // continue;
        } else {
            TRESPASS();
        }
    }

    // try again in 1 second
    msg->post(1000000ll);
}

void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSessionNotify:
        {
            onSessionNotify(msg);
            break;
        }

        case kWhatFetchSubtitleData:
        {
            pollForRawData(
                    msg, mFetchSubtitleDataGeneration,
                    /* fetch */ LiveSession::STREAMTYPE_SUBTITLES,
                    /* push */ kWhatSubtitleData);

            break;
        }

        case kWhatFetchMetaData:
        {
            if (!mMetadataSelected) {
                break;
            }

            pollForRawData(
                    msg, mFetchMetaDataGeneration,
                    /* fetch */ LiveSession::STREAMTYPE_METADATA,
                    /* push */ kWhatTimedMetaData);

            break;
        }

@@ -309,6 +376,19 @@ void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
            break;
        }

        case LiveSession::kWhatMetadataDetected:
        {
            if (!mHasMetadata) {
                mHasMetadata = true;

                sp<AMessage> notify = dupNotify();
                // notification without buffer triggers MEDIA_INFO_METADATA_UPDATE
                notify->setInt32("what", kWhatTimedMetaData);
                notify->post();
            }
            break;
        }

        case LiveSession::kWhatError:
        {
            break;
Loading