1. frameworks\base\media\java\android\media\MediaFile.java
public static final int FILE_TYPE_HTTPLIVE = 44;
private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_HTTPLIVE;
增加:
addFileType("M3U", FILE_TYPE_M3U, "application/x-mpegurl");
addFileType("M3U8", FILE_TYPE_HTTPLIVE, "application/vnd.apple.mpegurl");
addFileType("M3U8", FILE_TYPE_HTTPLIVE, "audio/mpegurl");
addFileType("M3U8", FILE_TYPE_HTTPLIVE, "audio/x-mpegurl");
2. frameworks\base\media\libstagefright\httplive\LiveSource.cpp
bool LiveSource::seekTo(int64_t seekTimeUs) {
/*int32_t targetDuration;
if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) {
return false;
}*/
int64_t index = 0; //seekTimeSecs / targetDuration;
//jeff add for duration.
int32_t totalDuration = 0;
for (size_t i = 0; i < mPlaylist->size(); ++i) {
AString uri;
sp<AMessage> meta;
mPlaylist->itemAt(i, &uri, &meta);
int32_t duration = 0;
CHECK(meta->findInt32("duration", &duration));
totalDuration += duration;
if(totalDuration > seekTimeSecs ) {
index = i;
break;
}
}
int64_t LiveSource::getTimeBase(int64_t timeUs) const {
int32_t val;
int64_t timeBase = 0;
int32_t totalDuration = 0;
int32_t duration = 0;
int32_t timeSec;
LOGV("LiveSource::getTimeBase() mPlaylistIndex=%d",mPlaylistIndex);
timeSec = timeUs/1000000ll;
for (size_t i = 0; i < mPlaylistIndex; ++i) {
AString uri;
sp<AMessage> meta;
mPlaylist->itemAt(i, &uri, &meta);
if (meta->findInt32("discontinuity", &val) && val != 0) {
LOGV("LiveSource::getTimeBase() timeSec=%d, totalDuration=%d",timeSec,totalDuration);
if(timeSec < totalDuration) {
break;
}
timeBase = totalDuration;
}
else{
duration = 0;
CHECK(meta->findInt32("duration", &duration));
totalDuration += duration;
}
LOGV("LiveSource::getTimeBase() i=%d, duration=%d",i,duration);
}
timeBase = timeBase * 1000000ll;
return timeBase;
}
void LiveSource::determineSeekability() {
mDurationUs = -1;
if (!mPlaylist->isComplete()) {
return;
}
#if 0
int32_t targetDuration;
if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) {
return;
}
mDurationUs = targetDuration * 1000000ll * mPlaylist->size();
LOGV("LiveSource::determineSeekability() targetDuration=%d, mDurationUs=%lld",targetDuration,mDurationUs);
#endif
//jeff add for duration.
int32_t totalDuration = 0;
for (size_t i = 0; i < mPlaylist->size(); ++i) {
AString uri;
sp<AMessage> meta;
mPlaylist->itemAt(i, &uri, &meta);
int32_t duration = 0;
CHECK(meta->findInt32("duration", &duration));
totalDuration += duration;
}
mDurationUs = totalDuration * 1000000ll;
LOGV("LiveSource::determineSeekability() mDurationUs=%lld",mDurationUs);
}
3. frameworks\base\media\libstagefright\include\LiveSource.h
int64_t getTimeBase(int64_t timeUs) const;
4. frameworks\base\media\libstagefright\mpeg2ts\AnotherPacketSource.cpp
//#define LOG_NDEBUG 0
#define LOG_TAG "AnotherPacketSource"
#include <utils/Log.h>
namespace android {
uint64_t timePassUs;
uint64_t timeLastUs;
bool
newSegment;
AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
: mFormat(meta),
mEOSResult(OK) {
timePassUs = 0;
timeLastUs = 0;
newSegment = false;
}
void AnotherPacketSource::setTimeBase(int64_t timeBase)
{
timePassUs = timeBase;
newSegment = false;
}
status_t AnotherPacketSource::read(
MediaBuffer **out, const ReadOptions *) {
if (buffer->meta()->findInt32("discontinuity", &discontinuity)
&& discontinuity) {
timePassUs += timeLastUs;
timePassUs = (timePassUs/1000000ll) * 1000000ll;
//newSegment = true;
LOGV("******discontinuity timePassUs=%lld us (%.2f secs) timeLastUs=%lld us (%.2f secs)", timePassUs, timePassUs / 1E6, timeLastUs, timeLastUs / 1E6);
return INFO_DISCONTINUITY;
} else {
uint64_t timeUs;
CHECK(buffer->meta()->findInt64(
"time", (int64_t *)&timeUs));
timeLastUs = timeUs;
/*if(newSegment) {
if((uint32_t)(timeUs/1000000ll) < 5){ //5s.
newSegment = false;
timeUs += timePassUs;
}
}
else*/ {
timeUs += timePassUs;
}
LOGV("-----read() timeUs=%lld us (%.2f secs)", timeUs, timeUs / 1E6);
5. frameworks\base\media\libstagefright\mpeg2ts\AnotherPacketSource.h
void setTimeBase(int64_t timeBase);
6. frameworks\base\media\libstagefright\mpeg2ts\MPEG2TSExtractor.cpp
status_t MPEG2TSSource::read(
MediaBuffer **out, const ReadOptions *options) {
if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
if (mExtractor->mLiveSource != NULL) {
int64_t timeBase;
timeBase =mExtractor->mLiveSource->getTimeBase(seekTimeUs);
mImpl->setTimeBase(timeBase);
LOGI("read() setTimeBase %lld",timeBase);
}
}
return mImpl->read(out, options);
}
7. frameworks\base\media\libstagefright\AwesomePlayer.cpp
status_t AwesomePlayer::setDataSource_l(
const char *uri, const KeyedVector<String8, String8> *headers) {
reset_l();
mUri = uri;
if (!strncmp("http://", uri, 7)) {
// Hack to support http live.
size_t len = strlen(uri);
if (!strcasecmp(&uri[len - 5], ".m3u8")
|| strstr(&uri[7], "m3u8") != NULL) {
mUri = "httplive://";
mUri.append(&uri[7]);
}
}
void AwesomePlayer::onVideoEvent() {
if (latenessUs > 200000) { //40000
// We're more than 40ms late.
LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
mVideoBuffer->release();
mVideoBuffer = NULL;
postVideoEvent_l();
return;
}
8. packages\apps\Browser\src\com\android\browser\BrowserSettings.java
伪装成iPad
private int userAgent = 3; //jeff. 0;
userAgent = Integer.parseInt(p.getString("user_agent", "3")); //jeff. "0"