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,
|
: ATSParser::DISCONTINUITY_FORMATCHANGE,
|
||||||
extra);
|
extra);
|
||||||
} else {
|
} 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;
|
mOffset += n;
|
||||||
|
|||||||
@@ -86,7 +86,15 @@ bool NuPlayer::StreamingSource::feedMoreTSData() {
|
|||||||
: ATSParser::DISCONTINUITY_FORMATCHANGE,
|
: ATSParser::DISCONTINUITY_FORMATCHANGE,
|
||||||
extra);
|
extra);
|
||||||
} else {
|
} 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(
|
bool parsePID(
|
||||||
unsigned pid, unsigned payload_unit_start_indicator,
|
unsigned pid, unsigned payload_unit_start_indicator,
|
||||||
ABitReader *br);
|
ABitReader *br, status_t *err);
|
||||||
|
|
||||||
void signalDiscontinuity(
|
void signalDiscontinuity(
|
||||||
DiscontinuityType type, const sp<AMessage> &extra);
|
DiscontinuityType type, const sp<AMessage> &extra);
|
||||||
@@ -77,7 +77,7 @@ private:
|
|||||||
bool mFirstPTSValid;
|
bool mFirstPTSValid;
|
||||||
uint64_t mFirstPTS;
|
uint64_t mFirstPTS;
|
||||||
|
|
||||||
void parseProgramMap(ABitReader *br);
|
status_t parseProgramMap(ABitReader *br);
|
||||||
|
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(Program);
|
DISALLOW_EVIL_CONSTRUCTORS(Program);
|
||||||
};
|
};
|
||||||
@@ -140,14 +140,17 @@ ATSParser::Program::Program(
|
|||||||
|
|
||||||
bool ATSParser::Program::parsePID(
|
bool ATSParser::Program::parsePID(
|
||||||
unsigned pid, unsigned payload_unit_start_indicator,
|
unsigned pid, unsigned payload_unit_start_indicator,
|
||||||
ABitReader *br) {
|
ABitReader *br, status_t *err) {
|
||||||
|
*err = OK;
|
||||||
|
|
||||||
if (pid == mProgramMapPID) {
|
if (pid == mProgramMapPID) {
|
||||||
if (payload_unit_start_indicator) {
|
if (payload_unit_start_indicator) {
|
||||||
unsigned skip = br->getBits(8);
|
unsigned skip = br->getBits(8);
|
||||||
br->skipBits(skip * 8);
|
br->skipBits(skip * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseProgramMap(br);
|
*err = parseProgramMap(br);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +183,7 @@ struct StreamInfo {
|
|||||||
unsigned mPID;
|
unsigned mPID;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ATSParser::Program::parseProgramMap(ABitReader *br) {
|
status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
|
||||||
unsigned table_id = br->getBits(8);
|
unsigned table_id = br->getBits(8);
|
||||||
LOGV(" table_id = %u", table_id);
|
LOGV(" table_id = %u", table_id);
|
||||||
CHECK_EQ(table_id, 0x02u);
|
CHECK_EQ(table_id, 0x02u);
|
||||||
@@ -283,7 +286,60 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PIDsChanged) {
|
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) {
|
for (size_t i = 0; i < infos.size(); ++i) {
|
||||||
@@ -294,13 +350,10 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
|
|||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
sp<Stream> stream = new Stream(this, info.mPID, info.mType);
|
sp<Stream> stream = new Stream(this, info.mPID, info.mType);
|
||||||
mStreams.add(info.mPID, stream);
|
mStreams.add(info.mPID, stream);
|
||||||
|
|
||||||
if (PIDsChanged) {
|
|
||||||
sp<AMessage> extra;
|
|
||||||
stream->signalDiscontinuity(DISCONTINUITY_FORMATCHANGE, extra);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
|
sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
|
||||||
@@ -724,11 +777,11 @@ ATSParser::ATSParser(uint32_t flags)
|
|||||||
ATSParser::~ATSParser() {
|
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);
|
CHECK_EQ(size, kTSPacketSize);
|
||||||
|
|
||||||
ABitReader br((const uint8_t *)data, kTSPacketSize);
|
ABitReader br((const uint8_t *)data, kTSPacketSize);
|
||||||
parseTS(&br);
|
return parseTS(&br);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATSParser::signalDiscontinuity(
|
void ATSParser::signalDiscontinuity(
|
||||||
@@ -806,7 +859,7 @@ void ATSParser::parseProgramAssociationTable(ABitReader *br) {
|
|||||||
MY_LOGV(" CRC = 0x%08x", br->getBits(32));
|
MY_LOGV(" CRC = 0x%08x", br->getBits(32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATSParser::parsePID(
|
status_t ATSParser::parsePID(
|
||||||
ABitReader *br, unsigned PID,
|
ABitReader *br, unsigned PID,
|
||||||
unsigned payload_unit_start_indicator) {
|
unsigned payload_unit_start_indicator) {
|
||||||
if (PID == 0) {
|
if (PID == 0) {
|
||||||
@@ -815,13 +868,18 @@ void ATSParser::parsePID(
|
|||||||
br->skipBits(skip * 8);
|
br->skipBits(skip * 8);
|
||||||
}
|
}
|
||||||
parseProgramAssociationTable(br);
|
parseProgramAssociationTable(br);
|
||||||
return;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
for (size_t i = 0; i < mPrograms.size(); ++i) {
|
for (size_t i = 0; i < mPrograms.size(); ++i) {
|
||||||
|
status_t err;
|
||||||
if (mPrograms.editItemAt(i)->parsePID(
|
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;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -830,6 +888,8 @@ void ATSParser::parsePID(
|
|||||||
if (!handled) {
|
if (!handled) {
|
||||||
LOGV("PID 0x%04x not handled.", PID);
|
LOGV("PID 0x%04x not handled.", PID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATSParser::parseAdaptationField(ABitReader *br) {
|
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("---");
|
LOGV("---");
|
||||||
|
|
||||||
unsigned sync_byte = br->getBits(8);
|
unsigned sync_byte = br->getBits(8);
|
||||||
@@ -870,8 +930,10 @@ void ATSParser::parseTS(ABitReader *br) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (adaptation_field_control == 1 || adaptation_field_control == 3) {
|
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) {
|
sp<MediaSource> ATSParser::getSource(SourceType type) {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ struct ATSParser : public RefBase {
|
|||||||
|
|
||||||
ATSParser(uint32_t flags = 0);
|
ATSParser(uint32_t flags = 0);
|
||||||
|
|
||||||
void feedTSPacket(const void *data, size_t size);
|
status_t feedTSPacket(const void *data, size_t size);
|
||||||
|
|
||||||
void signalDiscontinuity(
|
void signalDiscontinuity(
|
||||||
DiscontinuityType type, const sp<AMessage> &extra);
|
DiscontinuityType type, const sp<AMessage> &extra);
|
||||||
@@ -89,12 +89,12 @@ private:
|
|||||||
void parseProgramMap(ABitReader *br);
|
void parseProgramMap(ABitReader *br);
|
||||||
void parsePES(ABitReader *br);
|
void parsePES(ABitReader *br);
|
||||||
|
|
||||||
void parsePID(
|
status_t parsePID(
|
||||||
ABitReader *br, unsigned PID,
|
ABitReader *br, unsigned PID,
|
||||||
unsigned payload_unit_start_indicator);
|
unsigned payload_unit_start_indicator);
|
||||||
|
|
||||||
void parseAdaptationField(ABitReader *br);
|
void parseAdaptationField(ABitReader *br);
|
||||||
void parseTS(ABitReader *br);
|
status_t parseTS(ABitReader *br);
|
||||||
|
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(ATSParser);
|
DISALLOW_EVIL_CONSTRUCTORS(ATSParser);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -210,13 +210,10 @@ status_t MPEG2TSExtractor::feedMore() {
|
|||||||
|
|
||||||
if (n < (ssize_t)kTSPacketSize) {
|
if (n < (ssize_t)kTSPacketSize) {
|
||||||
return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
|
return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
|
||||||
} else {
|
|
||||||
mParser->feedTSPacket(packet, kTSPacketSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mOffset += n;
|
mOffset += n;
|
||||||
|
return mParser->feedTSPacket(packet, kTSPacketSize);
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) {
|
void MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) {
|
||||||
|
|||||||
Reference in New Issue
Block a user