Merge "I have one HLS stream that switches stream PIDs from one bandwidth to the next"
This commit is contained in:
committed by
Android (Google) Code Review
commit
9100473a7e
@@ -124,7 +124,14 @@ bool NuPlayer::HTTPLiveSource::feedMoreTSData() {
|
||||
: ATSParser::DISCONTINUITY_FORMATCHANGE,
|
||||
extra);
|
||||
} else {
|
||||
mTSParser->feedTSPacket(buffer, sizeof(buffer));
|
||||
status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
|
||||
|
||||
if (err != OK) {
|
||||
LOGE("TS Parser returned error %d", err);
|
||||
mTSParser->signalEOS(err);
|
||||
mEOS = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mOffset += n;
|
||||
|
||||
@@ -86,7 +86,15 @@ bool NuPlayer::StreamingSource::feedMoreTSData() {
|
||||
: ATSParser::DISCONTINUITY_FORMATCHANGE,
|
||||
extra);
|
||||
} else {
|
||||
mTSParser->feedTSPacket(buffer, sizeof(buffer));
|
||||
status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
|
||||
|
||||
if (err != OK) {
|
||||
LOGE("TS Parser returned error %d", err);
|
||||
|
||||
mTSParser->signalEOS(err);
|
||||
mEOS = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ struct ATSParser::Program : public RefBase {
|
||||
|
||||
bool parsePID(
|
||||
unsigned pid, unsigned payload_unit_start_indicator,
|
||||
ABitReader *br);
|
||||
ABitReader *br, status_t *err);
|
||||
|
||||
void signalDiscontinuity(
|
||||
DiscontinuityType type, const sp<AMessage> &extra);
|
||||
@@ -77,7 +77,7 @@ private:
|
||||
bool mFirstPTSValid;
|
||||
uint64_t mFirstPTS;
|
||||
|
||||
void parseProgramMap(ABitReader *br);
|
||||
status_t parseProgramMap(ABitReader *br);
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(Program);
|
||||
};
|
||||
@@ -140,14 +140,17 @@ ATSParser::Program::Program(
|
||||
|
||||
bool ATSParser::Program::parsePID(
|
||||
unsigned pid, unsigned payload_unit_start_indicator,
|
||||
ABitReader *br) {
|
||||
ABitReader *br, status_t *err) {
|
||||
*err = OK;
|
||||
|
||||
if (pid == mProgramMapPID) {
|
||||
if (payload_unit_start_indicator) {
|
||||
unsigned skip = br->getBits(8);
|
||||
br->skipBits(skip * 8);
|
||||
}
|
||||
|
||||
parseProgramMap(br);
|
||||
*err = parseProgramMap(br);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -180,7 +183,7 @@ struct StreamInfo {
|
||||
unsigned mPID;
|
||||
};
|
||||
|
||||
void ATSParser::Program::parseProgramMap(ABitReader *br) {
|
||||
status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
|
||||
unsigned table_id = br->getBits(8);
|
||||
LOGV(" table_id = %u", table_id);
|
||||
CHECK_EQ(table_id, 0x02u);
|
||||
@@ -283,7 +286,60 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
|
||||
}
|
||||
|
||||
if (PIDsChanged) {
|
||||
mStreams.clear();
|
||||
#if 0
|
||||
LOGI("before:");
|
||||
for (size_t i = 0; i < mStreams.size(); ++i) {
|
||||
sp<Stream> stream = mStreams.editValueAt(i);
|
||||
|
||||
LOGI("PID 0x%08x => type 0x%02x", stream->pid(), stream->type());
|
||||
}
|
||||
|
||||
LOGI("after:");
|
||||
for (size_t i = 0; i < infos.size(); ++i) {
|
||||
StreamInfo &info = infos.editItemAt(i);
|
||||
|
||||
LOGI("PID 0x%08x => type 0x%02x", info.mPID, info.mType);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The only case we can recover from is if we have two streams
|
||||
// and they switched PIDs.
|
||||
|
||||
bool success = false;
|
||||
|
||||
if (mStreams.size() == 2 && infos.size() == 2) {
|
||||
const StreamInfo &info1 = infos.itemAt(0);
|
||||
const StreamInfo &info2 = infos.itemAt(1);
|
||||
|
||||
sp<Stream> s1 = mStreams.editValueAt(0);
|
||||
sp<Stream> s2 = mStreams.editValueAt(1);
|
||||
|
||||
bool caseA =
|
||||
info1.mPID == s1->pid() && info1.mType == s2->type()
|
||||
&& info2.mPID == s2->pid() && info2.mType == s1->type();
|
||||
|
||||
bool caseB =
|
||||
info1.mPID == s2->pid() && info1.mType == s1->type()
|
||||
&& info2.mPID == s1->pid() && info2.mType == s2->type();
|
||||
|
||||
if (caseA || caseB) {
|
||||
unsigned pid1 = s1->pid();
|
||||
unsigned pid2 = s2->pid();
|
||||
s1->setPID(pid2);
|
||||
s2->setPID(pid1);
|
||||
|
||||
mStreams.clear();
|
||||
mStreams.add(s1->pid(), s1);
|
||||
mStreams.add(s2->pid(), s2);
|
||||
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
LOGI("Stream PIDs changed and we cannot recover.");
|
||||
return ERROR_MALFORMED;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < infos.size(); ++i) {
|
||||
@@ -294,13 +350,10 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
|
||||
if (index < 0) {
|
||||
sp<Stream> stream = new Stream(this, info.mPID, info.mType);
|
||||
mStreams.add(info.mPID, stream);
|
||||
|
||||
if (PIDsChanged) {
|
||||
sp<AMessage> extra;
|
||||
stream->signalDiscontinuity(DISCONTINUITY_FORMATCHANGE, extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
|
||||
@@ -724,11 +777,11 @@ ATSParser::ATSParser(uint32_t flags)
|
||||
ATSParser::~ATSParser() {
|
||||
}
|
||||
|
||||
void ATSParser::feedTSPacket(const void *data, size_t size) {
|
||||
status_t ATSParser::feedTSPacket(const void *data, size_t size) {
|
||||
CHECK_EQ(size, kTSPacketSize);
|
||||
|
||||
ABitReader br((const uint8_t *)data, kTSPacketSize);
|
||||
parseTS(&br);
|
||||
return parseTS(&br);
|
||||
}
|
||||
|
||||
void ATSParser::signalDiscontinuity(
|
||||
@@ -806,7 +859,7 @@ void ATSParser::parseProgramAssociationTable(ABitReader *br) {
|
||||
MY_LOGV(" CRC = 0x%08x", br->getBits(32));
|
||||
}
|
||||
|
||||
void ATSParser::parsePID(
|
||||
status_t ATSParser::parsePID(
|
||||
ABitReader *br, unsigned PID,
|
||||
unsigned payload_unit_start_indicator) {
|
||||
if (PID == 0) {
|
||||
@@ -815,13 +868,18 @@ void ATSParser::parsePID(
|
||||
br->skipBits(skip * 8);
|
||||
}
|
||||
parseProgramAssociationTable(br);
|
||||
return;
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
for (size_t i = 0; i < mPrograms.size(); ++i) {
|
||||
status_t err;
|
||||
if (mPrograms.editItemAt(i)->parsePID(
|
||||
PID, payload_unit_start_indicator, br)) {
|
||||
PID, payload_unit_start_indicator, br, &err)) {
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
@@ -830,6 +888,8 @@ void ATSParser::parsePID(
|
||||
if (!handled) {
|
||||
LOGV("PID 0x%04x not handled.", PID);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ATSParser::parseAdaptationField(ABitReader *br) {
|
||||
@@ -839,7 +899,7 @@ void ATSParser::parseAdaptationField(ABitReader *br) {
|
||||
}
|
||||
}
|
||||
|
||||
void ATSParser::parseTS(ABitReader *br) {
|
||||
status_t ATSParser::parseTS(ABitReader *br) {
|
||||
LOGV("---");
|
||||
|
||||
unsigned sync_byte = br->getBits(8);
|
||||
@@ -870,8 +930,10 @@ void ATSParser::parseTS(ABitReader *br) {
|
||||
}
|
||||
|
||||
if (adaptation_field_control == 1 || adaptation_field_control == 3) {
|
||||
parsePID(br, PID, payload_unit_start_indicator);
|
||||
return parsePID(br, PID, payload_unit_start_indicator);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
sp<MediaSource> ATSParser::getSource(SourceType type) {
|
||||
|
||||
@@ -49,7 +49,7 @@ struct ATSParser : public RefBase {
|
||||
|
||||
ATSParser(uint32_t flags = 0);
|
||||
|
||||
void feedTSPacket(const void *data, size_t size);
|
||||
status_t feedTSPacket(const void *data, size_t size);
|
||||
|
||||
void signalDiscontinuity(
|
||||
DiscontinuityType type, const sp<AMessage> &extra);
|
||||
@@ -89,12 +89,12 @@ private:
|
||||
void parseProgramMap(ABitReader *br);
|
||||
void parsePES(ABitReader *br);
|
||||
|
||||
void parsePID(
|
||||
status_t parsePID(
|
||||
ABitReader *br, unsigned PID,
|
||||
unsigned payload_unit_start_indicator);
|
||||
|
||||
void parseAdaptationField(ABitReader *br);
|
||||
void parseTS(ABitReader *br);
|
||||
status_t parseTS(ABitReader *br);
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ATSParser);
|
||||
};
|
||||
|
||||
@@ -210,13 +210,10 @@ status_t MPEG2TSExtractor::feedMore() {
|
||||
|
||||
if (n < (ssize_t)kTSPacketSize) {
|
||||
return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
|
||||
} else {
|
||||
mParser->feedTSPacket(packet, kTSPacketSize);
|
||||
}
|
||||
|
||||
mOffset += n;
|
||||
|
||||
return OK;
|
||||
return mParser->feedTSPacket(packet, kTSPacketSize);
|
||||
}
|
||||
|
||||
void MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) {
|
||||
|
||||
Reference in New Issue
Block a user