CodecVector CHTSPData::GetTranscodingCodecs(void) { htsmsg_t *msg; htsmsg_field_t *f; CodecVector v; CHTSResult result; msg = htsmsg_create_map(); htsmsg_add_str(msg, "method", "getCodecs"); ReadResult(msg, result); if (result.status != PVR_ERROR_NO_ERROR) { XBMC->Log(LOG_DEBUG, "%s - failed to getCodecs", __FUNCTION__); return v; } msg = htsmsg_get_list(result.message, "encoders"); if(!msg) { XBMC->Log(LOG_DEBUG, "%s - failed to get encoders", __FUNCTION__); return v; } HTSMSG_FOREACH(f, msg) { if (f->hmf_type != HMF_STR) continue; CodecDescriptor codec = CodecDescriptor::GetCodecByName(f->hmf_str); if (codec.Codec().codec_type != XBMC_CODEC_TYPE_UNKNOWN) v.push_back(codec); } return v; }
void CHTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m ) { vector<XbmcPvrStream> streams; htsmsg_t *l; htsmsg_field_t *f; DemuxPacket *pkt; /* Validate */ if ((l = htsmsg_get_list(m, "streams")) == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed subscriptionStart: 'streams' missing"); return; } m_streamStat.clear(); /* Process each */ HTSMSG_FOREACH(f, l) { uint32_t idx, u32; const char *type; XbmcPvrStream stream; if (f->hmf_type != HMF_MAP) continue; if ((type = htsmsg_get_str(&f->hmf_msg, "type")) == NULL) continue; if (htsmsg_get_u32(&f->hmf_msg, "index", &idx)) continue; /* Find stream */ m_streamStat[idx] = 0; m_streams.GetStreamData(idx, &stream); Logger::Log(LogLevel::LEVEL_DEBUG, "demux subscription start"); CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName(type); xbmc_codec_t codec = codecDescriptor.Codec(); if (codec.codec_type != XBMC_CODEC_TYPE_UNKNOWN) { stream.iCodecType = codec.codec_type; stream.iCodecId = codec.codec_id; stream.iPhysicalId = idx; /* Subtitle ID */ if ((stream.iCodecType == XBMC_CODEC_TYPE_SUBTITLE) && !strcmp("DVBSUB", type)) { uint32_t composition_id = 0, ancillary_id = 0; htsmsg_get_u32(&f->hmf_msg, "composition_id", &composition_id); htsmsg_get_u32(&f->hmf_msg, "ancillary_id" , &ancillary_id); stream.iIdentifier = (composition_id & 0xffff) | ((ancillary_id & 0xffff) << 16); } /* Language */ if (stream.iCodecType == XBMC_CODEC_TYPE_SUBTITLE || stream.iCodecType == XBMC_CODEC_TYPE_AUDIO) { const char *language; if ((language = htsmsg_get_str(&f->hmf_msg, "language")) != NULL) strncpy(stream.strLanguage, language, sizeof(stream.strLanguage) - 1); } /* Audio data */ if (stream.iCodecType == XBMC_CODEC_TYPE_AUDIO) { stream.iChannels = htsmsg_get_u32_or_default(&f->hmf_msg, "channels", 2); stream.iSampleRate = htsmsg_get_u32_or_default(&f->hmf_msg, "rate", 48000); } /* Video */ if (stream.iCodecType == XBMC_CODEC_TYPE_VIDEO) { stream.iWidth = htsmsg_get_u32_or_default(&f->hmf_msg, "width", 0); stream.iHeight = htsmsg_get_u32_or_default(&f->hmf_msg, "height", 0); /* Ignore this message if the stream details haven't been determined yet, a new message will be sent once they have. This is fixed in some versions of tvheadend and is here for backward compatibility. */ if (stream.iWidth == 0 || stream.iHeight == 0) { Logger::Log(LogLevel::LEVEL_DEBUG, "Ignoring subscriptionStart, stream details missing"); return; } /* Setting aspect ratio to zero will cause XBMC to handle changes in it */ stream.fAspect = 0.0f; if ((u32 = htsmsg_get_u32_or_default(&f->hmf_msg, "duration", 0)) > 0) { stream.iFPSScale = u32; stream.iFPSRate = DVD_TIME_BASE; } } streams.push_back(stream); Logger::Log(LogLevel::LEVEL_DEBUG, " id: %d, type %s, codec: %u", idx, type, stream.iCodecId); } }
void CHTSPDemux::ParseSubscriptionStart(htsmsg_t *m) { vector<PVR_STREAM_PROPERTIES::PVR_STREAM> newStreams; htsmsg_t *streams; htsmsg_field_t *f; uint32_t subs; if(htsmsg_get_u32(m, "subscriptionId", &subs)) { XBMC->Log(LOG_ERROR, "%s - invalid subscription id", __FUNCTION__); return; } m_subs = subs; if((streams = htsmsg_get_list(m, "streams")) == NULL) { XBMC->Log(LOG_ERROR, "%s - malformed message", __FUNCTION__); return; } HTSMSG_FOREACH(f, streams) { uint32_t index; const char* type; htsmsg_t* sub; if (newStreams.size() >= PVR_STREAM_MAX_STREAMS) { XBMC->Log(LOG_ERROR, "%s - max amount of streams reached", __FUNCTION__); break; } if (f->hmf_type != HMF_MAP) continue; sub = &f->hmf_msg; if ((type = htsmsg_get_str(sub, "type")) == NULL) continue; if (htsmsg_get_u32(sub, "index", &index)) continue; bool bValidStream(true); PVR_STREAM_PROPERTIES::PVR_STREAM newStream; m_streams.GetStreamData(index, &newStream); CodecDescriptor codecId = CodecDescriptor::GetCodecByName(type); if (codecId.Codec().codec_type != XBMC_CODEC_TYPE_UNKNOWN) { newStream.iCodecType = codecId.Codec().codec_type; newStream.iCodecId = codecId.Codec().codec_id; if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_SUBTITLE) { uint32_t composition_id = 0, ancillary_id = 0; htsmsg_get_u32(sub, "composition_id", &composition_id); htsmsg_get_u32(sub, "ancillary_id" , &ancillary_id); newStream.iIdentifier = (composition_id & 0xffff) | ((ancillary_id & 0xffff) << 16); HTSPSetDemuxStreamInfoLanguage(newStream, sub); } } else { bValidStream = false; } if (bValidStream) { XBMC->Log(LOG_DEBUG, "%s - id: %d, type: %s, codec: %u", __FUNCTION__, index, codecId.Name().c_str(), codecId.Codec().codec_id); newStream.iPhysicalId = index; if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_AUDIO) { HTSPSetDemuxStreamInfoAudio(newStream, sub); HTSPSetDemuxStreamInfoLanguage(newStream, sub); } else if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_VIDEO) HTSPSetDemuxStreamInfoVideo(newStream, sub); newStreams.push_back(newStream); } else { XBMC->Log(LOG_DEBUG, "%s - id: %d, type: %s, ignored", __FUNCTION__, index, type); } }
void cVNSIDemux::StreamChange(cResponsePacket *resp) { std::vector<XbmcPvrStream> newStreams; while (!resp->end()) { uint32_t pid = resp->extract_U32(); const char* type = resp->extract_String(); XbmcPvrStream newStream; m_streams.GetStreamData(pid, &newStream); CodecDescriptor codecId = CodecDescriptor::GetCodecByName(type); if (codecId.Codec().codec_type != XBMC_CODEC_TYPE_UNKNOWN) { newStream.iPhysicalId = pid; newStream.iCodecType = codecId.Codec().codec_type; newStream.iCodecId = codecId.Codec().codec_id; } else { return; } if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_AUDIO) { const char *language = resp->extract_String(); newStream.iChannels = resp->extract_U32(); newStream.iSampleRate = resp->extract_U32(); newStream.iBlockAlign = resp->extract_U32(); newStream.iBitRate = resp->extract_U32(); newStream.iBitsPerSample = resp->extract_U32(); newStream.strLanguage[0] = language[0]; newStream.strLanguage[1] = language[1]; newStream.strLanguage[2] = language[2]; newStream.strLanguage[3] = 0; newStream.iIdentifier = -1; newStreams.push_back(newStream); } else if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_VIDEO) { newStream.iFPSScale = resp->extract_U32(); newStream.iFPSRate = resp->extract_U32(); newStream.iHeight = resp->extract_U32(); newStream.iWidth = resp->extract_U32(); newStream.fAspect = (float)resp->extract_Double(); newStream.strLanguage[0] = 0; newStream.strLanguage[1] = 0; newStream.strLanguage[2] = 0; newStream.strLanguage[3] = 0; newStream.iIdentifier = -1; newStreams.push_back(newStream); } else if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_SUBTITLE) { const char *language = resp->extract_String(); uint32_t composition_id = resp->extract_U32(); uint32_t ancillary_id = resp->extract_U32(); newStream.strLanguage[0] = language[0]; newStream.strLanguage[1] = language[1]; newStream.strLanguage[2] = language[2]; newStream.strLanguage[3] = 0; newStream.iIdentifier = (composition_id & 0xffff) | ((ancillary_id & 0xffff) << 16); newStreams.push_back(newStream); delete[] language; } else if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_RDS) { const char *language = resp->extract_String(); uint32_t rel_channel_pid = resp->extract_U32(); newStream.strLanguage[0] = language[0]; newStream.strLanguage[1] = language[1]; newStream.strLanguage[2] = language[2]; newStream.strLanguage[3] = 0; newStream.iIdentifier = -1; newStreams.push_back(newStream); delete[] language; } else { m_streams.Clear(); delete[] type; return; } delete[] type; } m_streams.UpdateStreams(newStreams); }