Loading include/media/mediaplayer.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, }; // ---------------------------------------------------------------------------- Loading include/media/stagefright/MediaDefs.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading media/libmedia/mediaplayer.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading media/libmediaplayerservice/nuplayer/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -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 \ Loading media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +110 −30 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ #include "AnotherPacketSource.h" #include "LiveDataSource.h" #include "LiveSession.h" #include <media/IMediaHTTPService.h> #include <media/stagefright/foundation/ABuffer.h> Loading @@ -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 { Loading @@ -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; Loading Loading @@ -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(); } } Loading @@ -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; } Loading Loading @@ -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 Loading
include/media/mediaplayer.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, }; // ---------------------------------------------------------------------------- Loading
include/media/stagefright/MediaDefs.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
media/libmedia/mediaplayer.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
media/libmediaplayerservice/nuplayer/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -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 \ Loading
media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +110 −30 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ #include "AnotherPacketSource.h" #include "LiveDataSource.h" #include "LiveSession.h" #include <media/IMediaHTTPService.h> #include <media/stagefright/foundation/ABuffer.h> Loading @@ -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 { Loading @@ -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; Loading Loading @@ -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(); } } Loading @@ -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; } Loading Loading @@ -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