Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create RDS stream only if audio stream actually contains RDS data. #382

Merged
merged 1 commit into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pvr.hts/addon.xml.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon
id="pvr.hts"
version="4.4.0"
version="4.4.1"
name="Tvheadend HTSP Client"
provider-name="Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld">
<requires>@ADDON_DEPENDS@</requires>
Expand Down
3 changes: 3 additions & 0 deletions pvr.hts/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
4.4.1
- Fix creation of RDS streams. Must only be done if audio stream actually contains RDS data.

4.4.0
- Add support for Radio Data System (RDS)
- Enable async EPG data transfer by default
Expand Down
74 changes: 60 additions & 14 deletions src/tvheadend/HTSPDemuxer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,21 @@ void HTSPDemuxer::ProcessRDS(uint32_t idx, const void* bin, size_t binlen)
uint8_t rdslen = data[offset - 1];
if (rdslen > 0)
{
const uint32_t rdsIdx = idx - TVH_STREAM_INDEX_OFFSET;
if (m_streamStat.find(rdsIdx) == m_streamStat.end())
{
// No RDS stream yet. Create and announce it.
if (!AddRDSStream(idx, rdsIdx))
return;

// Update streams.
Logger::Log(LogLevel::LEVEL_DEBUG, "demux stream change");

DemuxPacket* pktSpecial = PVR->AllocateDemuxPacket(0);
pktSpecial->iStreamId = DMX_SPECIALID_STREAMCHANGE;
m_pktBuffer.Push(pktSpecial);
}

DemuxPacket* pkt = PVR->AllocateDemuxPacket(rdslen);
if (!pkt)
return;
Expand All @@ -415,7 +430,7 @@ void HTSPDemuxer::ProcessRDS(uint32_t idx, const void* bin, size_t binlen)

memcpy(pkt->pData, rdsdata, rdslen);
pkt->iSize = rdslen;
pkt->iStreamId = idx - TVH_STREAM_INDEX_OFFSET;
pkt->iStreamId = rdsIdx;

m_pktBuffer.Push(pkt);
delete [] rdsdata;
Expand Down Expand Up @@ -513,10 +528,50 @@ void HTSPDemuxer::ParseMuxPacket ( htsmsg_t *m )
PVR->FreeDemuxPacket(pkt);
}

bool HTSPDemuxer::AddStream(const char* type, uint32_t idx, htsmsg_field_t *f)
bool HTSPDemuxer::AddRDSStream(uint32_t audioIdx, uint32_t rdsIdx)
{
CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName(type);
xbmc_codec_t codec = codecDescriptor.Codec();
for (const auto& stream : m_streams)
{
if (stream.iPID != audioIdx)
continue;

// Found the stream with the embedded RDS data. Create corresponding RDS stream.
const CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName("rds");
const xbmc_codec_t codec = codecDescriptor.Codec();

if (codec.codec_type == XBMC_CODEC_TYPE_UNKNOWN)
return false;

m_streamStat[rdsIdx] = 0;

PVR_STREAM_PROPERTIES::PVR_STREAM rdsStream = {};
rdsStream.iCodecType = codec.codec_type;
rdsStream.iCodecId = codec.codec_id;
rdsStream.iPID = rdsIdx;
strncpy(rdsStream.strLanguage, stream.strLanguage, sizeof(rdsStream.strLanguage) - 1);

// We can only use PVR_STREAM_MAX_STREAMS streams
if (m_streams.size() < PVR_STREAM_MAX_STREAMS)
{
Logger::Log(LogLevel::LEVEL_DEBUG, " id: %d, type rds, codec: %u", rdsIdx, rdsStream.iCodecId);
m_streams.emplace_back(rdsStream);
return true;
}
else
{
Logger::Log(LogLevel::LEVEL_INFO, "Maximum stream limit reached ignoring id: %d, type rds, codec: %u",
rdsIdx, rdsStream.iCodecId);
return false;
}
}
// stream with embedded RDS data not found
return false;
}

bool HTSPDemuxer::AddTVHStream(uint32_t idx, const char* type, htsmsg_field_t *f)
{
const CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName(type);
const xbmc_codec_t codec = codecDescriptor.Codec();

if (codec.codec_type == XBMC_CODEC_TYPE_UNKNOWN)
return false;
Expand Down Expand Up @@ -555,15 +610,6 @@ bool HTSPDemuxer::AddStream(const char* type, uint32_t idx, htsmsg_field_t *f)
stream.iSampleRate = htsmsg_get_u32_or_default(&f->hmf_msg, "rate", 48000);
}

/* RDS data */
if (stream.iCodecType == XBMC_CODEC_TYPE_AUDIO &&
!strcmp("MPEG2AUDIO", type))
{
// Add RDS stream for the mpeg2 audio stream. It can contain embedded RDS data.
if (!AddStream("rds", idx - TVH_STREAM_INDEX_OFFSET, f))
return false;
}

/* Video */
if (stream.iCodecType == XBMC_CODEC_TYPE_VIDEO)
{
Expand Down Expand Up @@ -639,7 +685,7 @@ void HTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m )
continue;

idx += TVH_STREAM_INDEX_OFFSET;
AddStream(type, idx, f);
AddTVHStream(idx, type, f);
}

/* Update streams */
Expand Down
4 changes: 2 additions & 2 deletions src/tvheadend/HTSPDemuxer.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class HTSPDemuxer
void ParseTimeshiftStatus(htsmsg_t *m);
void ParseDescrambleInfo(htsmsg_t *m);

bool AddStream(const char* type, uint32_t idx, htsmsg_field_t *f);

bool AddTVHStream(uint32_t idx, const char* type, htsmsg_field_t *f);
bool AddRDSStream(uint32_t audioIdx, uint32_t rdsIdx);
void ProcessRDS(uint32_t idx, const void* bin, size_t binlen);

mutable P8PLATFORM::CMutex m_mutex;
Expand Down