From 162ec7639cbd6caab54da89dbe3affaf66b2dfee Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sat, 27 Oct 2012 19:51:17 +0200 Subject: [PATCH] Add audio types to protocol, add aac decoding, extract language codes from TS and add version check --- audio.h | 10 +++ audioomx.cc | 150 ++++++++++++++++++++++++++++++++++++++++++++- audioomx.h | 20 +++++- audiowin.h | 14 +++++ channel.cc | 12 +--- channel.h | 5 +- demuxer.cc | 13 +++- demuxer.h | 1 + demuxerts.cc | 98 ++++++++++++++++++++++++----- demuxerts.h | 4 +- draintarget.h | 1 + player.cc | 8 +-- player.h | 4 +- playerlive.h | 2 +- playerliveradio.cc | 41 +++++++++++-- playerliveradio.h | 2 +- playerlivetv.cc | 34 +++++++--- playerlivetv.h | 2 +- vaudioselector.cc | 24 +++++--- vaudioselector.h | 1 + vconnect.cc | 11 +++- vdr.cc | 42 +++++++++++-- vdr.h | 2 +- vvideolivetv.cc | 2 +- vvideorec.cc | 49 +++++++-------- 25 files changed, 456 insertions(+), 96 deletions(-) diff --git a/audio.h b/audio.h index ab0a213..601c2e7 100644 --- a/audio.h +++ b/audio.h @@ -60,6 +60,16 @@ class Audio : public DrainTarget, public AbstractOption virtual int unMute()=0; virtual bool supportsAc3()=0; virtual bool maysupportAc3(){return false;} + virtual bool streamTypeSupported(int streamtype) + { + switch (streamtype) { + case 3: + case 4: + return true; + default: + return false; + }; + } int volumeUp(); int volumeDown(); diff --git a/audioomx.cc b/audioomx.cc index 684dee8..14627d9 100644 --- a/audioomx.cc +++ b/audioomx.cc @@ -37,11 +37,13 @@ AudioOMX::AudioOMX() canpass_ac3=false; canpass_mp2=false; canpass_mp3=false; + canpass_aac=false; canpass_pcm_mch=false; prefered_ac3=0; //0 stereo PCM, 1 passthrough 2 Multichannel PCM prefered_mp2=0; prefered_mp3=0; + prefered_aac=0; hdmi=true; omx_running=false; @@ -102,6 +104,13 @@ int AudioOMX::init(UCHAR tstreamType) { return 0; } + aaclatmcodec_libav = avcodec_find_decoder(CODEC_ID_AAC_LATM); + if (aaclatmcodec_libav == NULL) { + Log::getInstance()->log("Audio", Log::DEBUG, + "Find libav aac latm decoder failed"); + return 0; + } + int ret; ret=vc_tv_hdmi_audio_supported( EDID_AudioFormat_eMPEG1,2,EDID_AudioSampleRate_e48KHz,0); @@ -125,6 +134,14 @@ int AudioOMX::init(UCHAR tstreamType) { Log::getInstance()->log("Audio", Log::NOTICE, "TV hdmi supports AC3"); } + ret=vc_tv_hdmi_audio_supported( EDID_AudioFormat_eAAC,6,EDID_AudioSampleRate_e48KHz,0); + if (ret==0) { + canpass_aac=true; + //not implemented + Log::getInstance()->log("Audio", Log::NOTICE, + "TV hdmi supports AAC"); + } + canpass_pcm_mch=false; return 1; @@ -178,6 +195,18 @@ bool AudioOMX::loadOptionsfromServer(VDR* vdr) } } + name = vdr->configLoad("AudioOMX", "AACDecodingMode"); + + if (name != NULL) { + if (STRCASECMP(name, "PCM") == 0) { + prefered_aac = 0; + } else if (STRCASECMP(name, "Passthrough") == 0) { + prefered_aac = 1; + } else if (STRCASECMP(name, "PCMMultichannel") == 0) { + prefered_aac = 2; + } + } + name = vdr->configLoad("AudioOMX", "Mp3DecodingMode"); if (name != NULL) { @@ -256,6 +285,18 @@ bool AudioOMX::handleOptionChanges(Option* option) } } break; + case 5: { + if (STRCASECMP(option->options[option->userSetChoice], "PCM") == 0) { + prefered_aac = 0; + } else if (STRCASECMP(option->options[option->userSetChoice], + "Passthrough") == 0) { + prefered_aac = 1; + } else if (STRCASECMP(option->options[option->userSetChoice], + "PCMMultichannel") == 0) { + prefered_aac = 2; + } + } + break; }; return false; @@ -278,6 +319,20 @@ bool AudioOMX::saveOptionstoServer() break; }; + switch (prefered_aac) { + case 0: + VDR::getInstance()->configSave("AudioOMX", "AACDecodingMode", "PCM"); + break; + case 1: + VDR::getInstance()->configSave("AudioOMX", "AACDecodingMode", + "Passthrough"); + break; + case 2: + VDR::getInstance()->configSave("AudioOMX", "AACDecodingMode", + "PCMMultichannel"); + break; + }; + switch (prefered_mp2) { case 0: VDR::getInstance()->configSave("AudioOMX", "Mp2DecodingMode", "PCM"); @@ -353,6 +408,28 @@ bool AudioOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pa options->push_back(option); pane->addOptionLine(option); + /* char **aacopts = new char *[3]; + i = 0; + aacopts[i] = new char[strlen("PCM") + 1]; + strcpy(mp2opts[i], "PCM"); + i++; + if (canpass_aac) { + aacopts[i] = new char[strlen("Passthrough") + 1]; + strcpy(aacopts[i], "PassThrough"); + i++; + } + if (canpass_pcm_mch) { + aacopts[i] = new char[strlen("PCMMultichannel") + 1]; + strcpy(aacopts[i], "PCMMultichannel"); + i++; + } + option = new Option(5, tr("Mp2 HDMI Mode"), "AudioOMX", + "AACDecodingMode", Option::TYPE_TEXT, i, 0, 0, + aacopts, NULL, true, this); + options->push_back(option); + pane->addOptionLine(option); + + char **mp2opts = new char *[3]; i = 0; mp2opts[i] = new char[strlen("PCM") + 1]; @@ -393,7 +470,8 @@ bool AudioOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pa "Mp2DecodingMode", Option::TYPE_TEXT, i, 0, 0, mp3opts, NULL, true, this); options->push_back(option); - pane->addOptionLine(option); + pane->addOptionLine(option);*/ + // Comment unsupported modes out } @@ -525,6 +603,22 @@ int AudioOMX::ChangeAudioPortConfig(bool disport) //clock aka omx mutex needs to } } break; + case MPTYPE_AAC_LATM: { + if (prefered_aac == 2 && false) { //not supported yet + + } else { + Log::getInstance()->log("Audio", Log::DEBUG, + "ChangeAudioPortConfig debug %d %d",prefered_aac,canpass_aac); + if (prefered_aac == 1 && canpass_aac) { + passthrough = true; + encoding=OMX_AUDIO_CodingAAC; + } else { + passthrough = false; + encoding=OMX_AUDIO_CodingPCM; + } + } + } + break; case MPTYPE_AC3_PRE13: case MPTYPE_AC3: { if (prefered_ac3 == 2 && false) { //not supported yet @@ -711,6 +805,23 @@ int AudioOMX::InitDecoderLibAV() return 0; } + aaclatmcodec_context_libav = avcodec_alloc_context3(aaclatmcodec_libav); + if (!aaclatmcodec_context_libav) { + Log::getInstance()->log("Audio", Log::DEBUG, "Alloc avcodec for aac decoding context failed!"); + return 0; + } + + aaclatmcodec_context_libav->flags |= CODEC_FLAG_TRUNCATED; + aaclatmcodec_context_libav->request_channels=2; + + avc_ret = avcodec_open2(aaclatmcodec_context_libav, aaclatmcodec_libav, NULL); + if (avc_ret < 0) { + Log::getInstance()->log("Audio", Log::DEBUG, "Opening libav codec failed \n"); + libav_mutex.Unlock(); + return 0; + } + + mp23codec_context_libav = avcodec_alloc_context3(mp23codec_libav); if (!ac3codec_context_libav) { Log::getInstance()->log("Audio", Log::DEBUG, "Alloc avcodec for mp23 decoding context failed!"); @@ -746,7 +857,13 @@ void AudioOMX::DeinitDecoderLibAV() { avcodec_close(ac3codec_context_libav); av_free(ac3codec_context_libav); ac3codec_context_libav = NULL; + + avcodec_close(aaclatmcodec_context_libav); + av_free(aaclatmcodec_context_libav); + aaclatmcodec_context_libav = NULL; + av_free(decode_frame_libav); + avcodec_close(mp23codec_context_libav); av_free(mp23codec_context_libav); mp23codec_context_libav = NULL; @@ -1470,6 +1587,23 @@ unsigned int AudioOMX::AdvanceAc3AudioSync(const UCHAR *data,unsigned int size,u return size; } +unsigned int AudioOMX::AdvanceAacLatmAudioSync(const UCHAR *data,unsigned int size,unsigned int *framesize) +{ + if (size<=4) return size; // silly; + unsigned int test=0; + *framesize=20000; //if we do not find a start code do not decompress + while (test+4frame_size<0) framesize=1152; //Maximum framesize else framesize=current_context->frame_size; }break; + case MPTYPE_AAC_LATM: { + current_context = aaclatmcodec_context_libav; + } break; case MPTYPE_AC3: case MPTYPE_AC3_PRE13: { current_context = ac3codec_context_libav; @@ -1790,6 +1933,11 @@ UINT AudioOMX::DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, incoming_paket_libav.size,&gotframesize); } break; + case MPTYPE_AAC_LATM: { + adv = AdvanceAacLatmAudioSync(incoming_paket_libav.data, + incoming_paket_libav.size,&gotframesize); + } + break; }; if (adv > 0) { incoming_paket_libav.data += adv; diff --git a/audioomx.h b/audioomx.h index 360a093..30032e4 100644 --- a/audioomx.h +++ b/audioomx.h @@ -61,7 +61,20 @@ class AudioOMX : public Audio int mute(); int unMute(); bool supportsAc3() { return true; } - virtual bool maysupportAc3(){return true;} + bool maysupportAc3(){return true;} + bool streamTypeSupported(int streamtype) + { + switch (streamtype) { + case 0x11: //AAC LATM packaging + case 0x6A://ac3 + case 3: //mpeg 1 layer 1 and 2 + case 4: + return true; + default: + return false; + }; + } + //Writing Data to Audiodevice virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); @@ -100,12 +113,14 @@ class AudioOMX : public Audio bool hdmi; // use hdmi as audio output bool passthrough; // use audio passthrough for the current audio type + bool canpass_aac; bool canpass_ac3; bool canpass_mp2; bool canpass_mp3; bool canpass_pcm_mch; + int prefered_aac; int prefered_ac3; //0 stereo PCM, 1 passthrough 2 Multichannel PCM int prefered_mp2; int prefered_mp3; @@ -118,6 +133,7 @@ class AudioOMX : public Audio unsigned int AdvanceAc3AudioSync(const UCHAR *data,unsigned int size,unsigned int *framesize); + unsigned int AdvanceAacLatmAudioSync(const UCHAR *data,unsigned int size,unsigned int *framesize); unsigned int AdvanceMpAudioSync(const UCHAR *data,unsigned int size,unsigned int *framesize); @@ -158,6 +174,8 @@ class AudioOMX : public Audio bool omx_first_frame; Mutex libav_mutex; + AVCodec *aaclatmcodec_libav; + AVCodecContext *aaclatmcodec_context_libav; AVCodec *ac3codec_libav; AVCodecContext *ac3codec_context_libav; AVCodec *mp23codec_libav; diff --git a/audiowin.h b/audiowin.h index 69e66d8..e1b087c 100644 --- a/audiowin.h +++ b/audiowin.h @@ -78,6 +78,20 @@ class AudioWin : public Audio virtual bool supportsAc3(); virtual bool maysupportAc3(){return true;} // We are not sure maybe we support this, allows the player to select ac3, if there is no other option + + virtual bool streamTypeSupported(int streamtype) + { + switch (streamtype) { + case 0x6A: + case 3: + case 4: + return true; + default: + return false; + }; + } + + private: MediaPacket mediapacket; public: diff --git a/channel.cc b/channel.cc index 8f2f5bc..0754581 100644 --- a/channel.cc +++ b/channel.cc @@ -46,9 +46,6 @@ Channel::~Channel() if (name) delete[] name; index = -1; // just in case - for(ULONG i = 0; i < numAPids; i++) delete[] apids[i].name; - for(ULONG i = 0; i < numDPids; i++) delete[] dpids[i].name; - for(ULONG i = 0; i < numSPids; i++) delete[] spids[i].name; } void Channel::loadPids() @@ -56,11 +53,8 @@ void Channel::loadPids() // Clear the list if this is a reload if (numAPids) { - for(ULONG i = 0; i < numAPids; i++) delete[] apids[i].name; apids.clear(); - for(ULONG i = 0; i < numDPids; i++) delete[] dpids[i].name; dpids.clear(); - for(ULONG i = 0; i < numSPids; i++) delete[] spids[i].name; spids.clear(); vpid = 0; tpid = 0; @@ -80,14 +74,14 @@ void Channel::loadPids() number, vpid, numAPids, numDPids, numSPids, tpid); for (ULONG i = 0; i < numAPids; i++) { - Log::getInstance()->log("Channel", Log::DEBUG, "APid %lu %s", apids[i].pid, apids[i].name); + Log::getInstance()->log("Channel", Log::DEBUG, "APid %lu %s %d", apids[i].pid, apids[i].desc,apids[i].type); } for (ULONG i = 0; i < numDPids; i++) { - Log::getInstance()->log("Channel", Log::DEBUG, "DPid %lu %s", dpids[i].pid, dpids[i].name); + Log::getInstance()->log("Channel", Log::DEBUG, "DPid %lu %s %d", dpids[i].pid, dpids[i].desc,dpids[i].type); } for (ULONG i = 0; i < numSPids; i++) { - Log::getInstance()->log("Channel", Log::DEBUG, "SPid %lu %s", spids[i].pid, spids[i].name); + Log::getInstance()->log("Channel", Log::DEBUG, "SPid %lu %s %d %d %d", spids[i].pid, spids[i].desc,spids[i].type,spids[i].data1,spids[i].data2); } } diff --git a/channel.h b/channel.h index c3688f2..bb9ea8f 100644 --- a/channel.h +++ b/channel.h @@ -32,7 +32,10 @@ using namespace std; typedef struct _apid { ULONG pid; - char* name; + char desc[10]; + ULONG type; + ULONG data1; + ULONG data2; } apid; typedef vector APidList; diff --git a/demuxer.cc b/demuxer.cc index 6aef0d1..a3700bc 100644 --- a/demuxer.cc +++ b/demuxer.cc @@ -425,6 +425,7 @@ Demuxer::Demuxer() packetnum=0; h264 = false; fps = 25.0; + astreamtype=4; } Demuxer::~Demuxer() @@ -478,6 +479,7 @@ void Demuxer::reset() ispre_1_3_19 = false; h264 = false; packetnum=0; + astreamtype=4; for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++) { @@ -597,7 +599,16 @@ bool Demuxer::submitPacket(PESPacket& packet) avail_mpaudchan[packet_type - PESTYPE_AUD0] = true; if (audio_current == packet_type && !aud_seeking) { - sent = audiostream.put(&packetdata[0], packet.getSize(), MPTYPE_MPEG_AUDIO,packetnum); + UCHAR type=MPTYPE_MPEG_AUDIO; + switch (astreamtype) + { + case 3: + case 4: + type=MPTYPE_MPEG_AUDIO; break; + case 0x11: + type=MPTYPE_AAC_LATM; break; + }; + sent = audiostream.put(&packetdata[0], packet.getSize(), type,packetnum); if (sent) packetnum++; } else diff --git a/demuxer.h b/demuxer.h index b1474ee..2d65ea2 100644 --- a/demuxer.h +++ b/demuxer.h @@ -204,6 +204,7 @@ class Demuxer bool aud_seeking; bool h264; int video_current, audio_current, teletext_current, subtitle_current; + int astreamtype; // Video stream information void setAspectRatio(enum AspectRatio); diff --git a/demuxerts.cc b/demuxerts.cc index def7222..ec83d11 100644 --- a/demuxerts.cc +++ b/demuxerts.cc @@ -22,6 +22,7 @@ #include "log.h" #include "video.h" #include "vdr.h" +#include "audio.h" #define PTS_JUMP_MARGIN 10000 #define PTS_ALLOWANCE 90000 @@ -105,10 +106,11 @@ void DemuxerTS::setVID(int p_vID) vActive = false; } -void DemuxerTS::setAID(int p_aID, int type) +void DemuxerTS::setAID(int p_aID, int type, int streamtype) { aID = p_aID; atype = type; + astreamtype = streamtype; switch (atype) { case 1: @@ -395,8 +397,9 @@ int DemuxerTS::processTS(UCHAR* buf) { foundpid = foundpid & 0x1FFF; //clear upper 3 bits bool notfound=false; + bool nolang=true; int pos=0; - // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x", foundpid); + // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x %x", foundpid,streamtype); switch (streamtype) { case 0x1B: //MPEG 4 for future use @@ -412,15 +415,35 @@ int DemuxerTS::processTS(UCHAR* buf) // Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid); }break; + case 0x0F: //AAC ADTS packaging + case 0x11: // LATM packaging case 3: case 4: { //audio apid newapid; newapid.pid = foundpid; - newapid.name = NULL; //set it in player + newapid.desc[0]=0; + newapid.type=streamtype; + pos=0; + nolang=true; + while (pos< eslength && nolang) { + switch (buf[p+pos]) { + case 0x0A: { + newapid.desc[0]=buf[p+pos+2]; + newapid.desc[1]=buf[p+pos+3]; + newapid.desc[2]=buf[p+pos+4]; + newapid.desc[3]=0; + nolang=false; + // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDLANG is %s", newapid.desc); + } break; + }; + + pos+=2+buf[p+pos+1]; + } + new_channelinfo.apids.push_back(newapid); new_channelinfo.numAPids++; - if (getAID() == 0) { //set unset AID to first audio pid that reports itself - setAID(foundpid,0); + if (getAID() == 0 && Audio::getInstance()->streamTypeSupported(streamtype)) { //set unset AID to first audio pid that reports itself + setAID(foundpid,0,streamtype); Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set audio PID to %x", foundpid); } } break; @@ -428,29 +451,57 @@ int DemuxerTS::processTS(UCHAR* buf) case 6: { //Private Data apid newapid; newapid.pid = foundpid; - newapid.name = NULL; //set it in player + newapid.desc[0]=0; //set it in player pos=0; notfound=true; + nolang=true; + int type=0; - while (pos< eslength && notfound) { + while (pos< eslength && (notfound || nolang)) { switch (buf[p+pos]) { + case 0x7A: // Enhanced Ac3 Desriptor case 0x6A: {//Ac3 descriptor - new_channelinfo.dpids.push_back(newapid); - new_channelinfo.numDPids++; + newapid.type=buf[p+pos]; + type=1; + notfound=false; } break; case 0x59: {//SubtitlingDescriptor - new_channelinfo.spids.push_back(newapid); - new_channelinfo.numSPids++; + type=2; + newapid.type=buf[p+pos]; + newapid.desc[0]=buf[p+pos+2]; + newapid.desc[1]=buf[p+pos+3]; + newapid.desc[2]=buf[p+pos+4]; + newapid.desc[3]=0; + newapid.data1=(buf[p+pos+5]<<8) |(buf[p+pos+6]); + newapid.data2=(buf[p+pos+7]<<8) |(buf[p+pos+8]); + // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDSUB is %s", newapid.desc); notfound=false; + nolang=false; } break; + case 0x0A: { + newapid.desc[0]=buf[p+pos+2]; + newapid.desc[1]=buf[p+pos+3]; + newapid.desc[2]=buf[p+pos+4]; + newapid.desc[3]=0; + nolang=false; + // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDLANG is %s", newapid.desc); + } break; case 0x56: { + type=3; new_channelinfo.tpid=foundpid; notfound=false; } break; }; pos+=2+buf[p+pos+1]; } + if (type==1) { + new_channelinfo.dpids.push_back(newapid); + new_channelinfo.numDPids++; + } else if (type==2) { + new_channelinfo.spids.push_back(newapid); + new_channelinfo.numSPids++; + } } break; default://TODO how about subtitles and second audio pids @@ -475,14 +526,33 @@ int DemuxerTS::processTS(UCHAR* buf) } } if (! audioPIDpresent) { + bool found=false; if (channelinfo.numAPids>0) { - setAID(channelinfo.apids[0].pid,0); - } else if (channelinfo.numDPids>0) { - setAID(channelinfo.dpids[0].pid,1); + int j=0; + while (jstreamTypeSupported(channelinfo.apids[j].type)) { + found =true; + setAID(channelinfo.apids[j].pid,0,channelinfo.apids[j].type); + } + j++; + } + + } + if (channelinfo.numDPids>0 && !found) { + int j=0; + while (jstreamTypeSupported(channelinfo.dpids[j].type)) { + found =true; + setAID(channelinfo.dpids[j].pid,1,channelinfo.dpids[j].type); + } + i++; + } } } channelinfo=new_channelinfo; + + havechannelinfo=true; return 1; diff --git a/demuxerts.h b/demuxerts.h index 24e5b4d..fa5c01b 100644 --- a/demuxerts.h +++ b/demuxerts.h @@ -40,7 +40,7 @@ class DemuxerTS : public Demuxer int findPTS(UCHAR* buf, int len, ULLONG* dest); void setVID(int p_vID); void setTID(int p_tID); - void setAID(int p_aID, int type); + void setAID(int p_aID, int type, int streamtype); void setSubID(int p_subID); int getVID() { return vID; } int getTID() { return tID; } @@ -54,7 +54,7 @@ class DemuxerTS : public Demuxer ULONG getPacketNum(); UINT stripAudio(UCHAR* buf, UINT len); static bool scanForVideo(UCHAR* buf, UINT len, bool &ish264); - Channel getChannelInfo() {return channelinfo;}; + Channel *getChannelInfo() {return &channelinfo;}; private: diff --git a/draintarget.h b/draintarget.h index 9e2032a..bb8f32e 100644 --- a/draintarget.h +++ b/draintarget.h @@ -31,6 +31,7 @@ #define MPTYPE_MPEG_AUDIO_LAYER3 0x04 //for media mp3 playback #define MPTYPE_TELETEXT 0x05 //for EBU VBI teletext #define MPTYPE_VIDEO_H264 0x06 +#define MPTYPE_AAC_LATM 0x07 diff --git a/player.cc b/player.cc index 1650ed4..ddff93f 100644 --- a/player.cc +++ b/player.cc @@ -225,13 +225,13 @@ int *Player::getTeletxtSubtitlePages() return teletext->getSubtitlePages(); } -void Player::setAudioChannel(int newChannel, int type) +void Player::setAudioChannel(int newChannel, int type, int streamtype) { if (is_pesrecording) { demuxer->setAudioStream(newChannel); return; } else { - ((DemuxerTS*)demuxer)->setAID(newChannel,type); + ((DemuxerTS*)demuxer)->setAID(newChannel,type,streamtype); return; } } @@ -265,11 +265,11 @@ void Player::turnSubtitlesOn(bool ison) { } -Channel Player::getDemuxerChannel() { +Channel * Player::getDemuxerChannel() { if (!is_pesrecording) { return ((DemuxerTS*) demuxer)->getChannelInfo(); } - return Channel(); //Should not happen! + return NULL; //Should not happen! } diff --git a/player.h b/player.h index 9658544..5c9d7f7 100644 --- a/player.h +++ b/player.h @@ -59,7 +59,7 @@ class Player : public Thread_TYPE, public Callback void setStartFrame(ULONG frameNum); void setLengthBytes(ULLONG length); void setLengthFrames(ULONG length); - void setAudioChannel(int newChannel, int type); + void setAudioChannel(int newChannel, int type, int streamtype); void setSubtitleChannel(int newChannel); bool toggleSubtitles(); void turnSubtitlesOn(bool ison); @@ -88,7 +88,7 @@ class Player : public Thread_TYPE, public Callback int getCurrentAudioChannel(); int getCurrentSubtitleChannel(); bool isPesRecording() { return is_pesrecording; } - Channel getDemuxerChannel(); + Channel *getDemuxerChannel(); TeletextDecoderVBIEBU * getTeletextDecoder() { return teletext; } diff --git a/playerlive.h b/playerlive.h index 601ddef..3cbe69d 100644 --- a/playerlive.h +++ b/playerlive.h @@ -46,7 +46,7 @@ class PlayerLive virtual void go(ULONG index)=0; virtual void setChannel(ULONG index)=0; virtual void stop()=0; - virtual void setAudioChannel(int newChannel,int type)=0; + virtual void setAudioChannel(int newChannel,int type,int streamtype)=0; virtual void setSubtitleChannel(int newChannel)=0; virtual bool* getDemuxerMpegAudioChannels()=0; diff --git a/playerliveradio.cc b/playerliveradio.cc index 90af2b5..0a2fe57 100644 --- a/playerliveradio.cc +++ b/playerliveradio.cc @@ -111,9 +111,9 @@ int PlayerLiveRadio::getCurrentSubtitleChannel(){ return demuxer->getSubID(); } -void PlayerLiveRadio::setAudioChannel(int newChannel, int type) +void PlayerLiveRadio::setAudioChannel(int newChannel, int type,int streamtype) { - demuxer->setAID(newChannel, type); + demuxer->setAID(newChannel, type,streamtype); } void PlayerLiveRadio::setSubtitleChannel(int newChannel) @@ -404,16 +404,45 @@ void PlayerLiveRadio::threadMethod() Channel* chan = (*chanList)[i.channelIndex]; chan->loadPids(); + bool found=false; + if (chan->numAPids > 0) { - demuxer->setAID(chan->apids[0].pid,0); - logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid); + int j=0; + while (jnumAPids && !found) { + if (Audio::getInstance()->streamTypeSupported(chan->apids[j].type)) { + demuxer->setAID(chan->apids[j].pid,0,chan->apids[j].type); + audio->setStreamType(Audio::MPEG2_PES); + logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u %u", chan->vpid, chan->apids[j].pid,chan->apids[j].type); + found=true; + } + j++; + } } - else + + if (!found) { - logger->log("PlayerLiveRadio", Log::WARN, "Demuxer no pids!"); + if (chan->numDPids > 0 && audio->maysupportAc3()) + { + int j=0; + while (jnumDPids && !found) { + if (Audio::getInstance()->streamTypeSupported(chan->dpids[j].type)) { + demuxer->setAID(chan->dpids[j].pid,1,chan->dpids[j].type); + audio->setStreamType(Audio::MPEG2_PES); + logger->log("PlayerLiveRadio", Log::DEBUG, "Demuxer pids: %u %u (ac3) %u", chan->vpid, chan->dpids[j].pid,chan->dpids[j].type); + found=true; + } + j++; + } + } + else + { + logger->log("PlayerLiveRadio", Log::WARN, "Demuxer no pids!"); + } } + + int streamSuccess = vdr->streamChannel(chan->number, this); if (!checkError() && !streamSuccess) { diff --git a/playerliveradio.h b/playerliveradio.h index 9a3865a..4c5b783 100644 --- a/playerliveradio.h +++ b/playerliveradio.h @@ -60,7 +60,7 @@ class PlayerLiveRadio : public PlayerLive, public Thread_TYPE, public Callback, virtual void go(ULONG index); virtual void setChannel(ULONG index); virtual void stop(); - virtual void setAudioChannel(int newChannel, int type); + virtual void setAudioChannel(int newChannel, int type,int streamtype); virtual void setSubtitleChannel(int newChannel); virtual bool* getDemuxerMpegAudioChannels(); diff --git a/playerlivetv.cc b/playerlivetv.cc index e964489..7d42f72 100644 --- a/playerlivetv.cc +++ b/playerlivetv.cc @@ -135,9 +135,9 @@ int PlayerLiveTV::getCurrentAudioChannel() return demuxer->getAID(); } -void PlayerLiveTV::setAudioChannel(int newChannel, int type) +void PlayerLiveTV::setAudioChannel(int newChannel, int type,int streamtype) { - demuxer->setAID(newChannel,type); + demuxer->setAID(newChannel,type,streamtype); } void PlayerLiveTV::setSubtitleChannel(int newChannel) @@ -708,18 +708,36 @@ void PlayerLiveTV::threadMethod() demuxer->setVID(chan->vpid); video->seth264mode(chan->vstreamtype==0x1b); + bool found=false; + if (chan->numAPids > 0) { - demuxer->setAID(chan->apids[0].pid,0); - audio->setStreamType(Audio::MPEG2_PES); - logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid); + int j=0; + while (jnumAPids && !found) { + if (Audio::getInstance()->streamTypeSupported(chan->apids[j].type)) { + demuxer->setAID(chan->apids[j].pid,0,chan->apids[j].type); + audio->setStreamType(Audio::MPEG2_PES); + logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u %u", chan->vpid, chan->apids[j].pid,chan->apids[j].type); + found=true; + } + j++; + } } - else + + if (!found) { if (chan->numDPids > 0 && audio->maysupportAc3()) { - demuxer->setAID(chan->dpids[0].pid,1); - logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u (ac3)", chan->vpid, chan->dpids[0].pid); + int j=0; + while (jnumDPids && !found) { + if (Audio::getInstance()->streamTypeSupported(chan->dpids[j].type)) { + demuxer->setAID(chan->dpids[j].pid,1,chan->dpids[j].type); + audio->setStreamType(Audio::MPEG2_PES); + logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u (ac3) %u", chan->vpid, chan->dpids[j].pid,chan->dpids[j].type); + found=true; + } + j++; + } } else { diff --git a/playerlivetv.h b/playerlivetv.h index 1ed46d0..4fba1c8 100644 --- a/playerlivetv.h +++ b/playerlivetv.h @@ -67,7 +67,7 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub virtual void go(ULONG index); virtual void setChannel(ULONG index); virtual void stop(); - virtual void setAudioChannel(int newChannel,int type); + virtual void setAudioChannel(int newChannel,int type,int streamtype); virtual void setSubtitleChannel(int newChannel); virtual bool toggleSubtitles(); virtual void turnSubtitlesOn(bool ison); diff --git a/vaudioselector.cc b/vaudioselector.cc index c6103c7..4ed9c87 100644 --- a/vaudioselector.cc +++ b/vaudioselector.cc @@ -305,8 +305,8 @@ VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudio { AudioSubtitleChannel* sc = new AudioSubtitleChannel(); sc->type = 0x10; - sc->name = new char[strlen(channel->spids[i].name) + 1]; - strcpy(sc->name, channel->spids[i].name); + sc->name = new char[strlen(channel->spids[i].desc) + 1]; + strcpy(sc->name, channel->spids[i].desc); sc->pestype = channel->spids[i].pid; scl.push_back(sc); } @@ -361,10 +361,11 @@ VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudio { AudioSubtitleChannel* ac = new AudioSubtitleChannel(); ac->type = 0; - ac->name = new char[strlen(channel->apids[i].name) + 1]; - strcpy(ac->name, channel->apids[i].name); + ac->name = new char[strlen(channel->apids[i].desc) + 1]; + strcpy(ac->name, channel->apids[i].desc); ac->pestype = channel->apids[i].pid; - acl.push_back(ac); + ac->streamtype=channel->apids[i].type; + if (Audio::getInstance()->streamTypeSupported(ac->streamtype))acl.push_back(ac); } if (Audio::getInstance()->supportsAc3()) @@ -373,10 +374,11 @@ VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudio { AudioSubtitleChannel* ac = new AudioSubtitleChannel(); ac->type = 1; - ac->name = new char[strlen(channel->dpids[i].name) + 1]; - strcpy(ac->name, channel->dpids[i].name); + ac->name = new char[strlen(channel->dpids[i].desc) + 1]; + strcpy(ac->name, channel->dpids[i].desc); ac->pestype = channel->dpids[i].pid; - acl.push_back(ac); + ac->streamtype=channel->dpids[i].type; + if (Audio::getInstance()->streamTypeSupported(ac->streamtype))acl.push_back(ac); } } @@ -510,7 +512,8 @@ int VAudioSelector::handleCommand(int command) m->from = this; m->to = parent; m->message = Message::SUBTITLE_CHANGE_CHANNEL; - m->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ; + m->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 + |(((AudioSubtitleChannel*)asl.getCurrentOptionData())->streamtype &0xFF)<<24 ; Command::getInstance()->postMessageNoLock(m); } else { asl.down(); @@ -520,7 +523,8 @@ int VAudioSelector::handleCommand(int command) m->from = this; m->to = parent; m->message = Message::AUDIO_CHANGE_CHANNEL; - m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ; + m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 + |(((AudioSubtitleChannel*)asl.getCurrentOptionData())->streamtype &0xFF)<<24 ; Command::getInstance()->postMessageNoLock(m); } diff --git a/vaudioselector.h b/vaudioselector.h index bf2f36d..63efe33 100644 --- a/vaudioselector.h +++ b/vaudioselector.h @@ -45,6 +45,7 @@ class AudioSubtitleChannel int type; char* name; int pestype; + int streamtype; }; diff --git a/vconnect.cc b/vconnect.cc index 7c5e427..7c0b66e 100644 --- a/vconnect.cc +++ b/vconnect.cc @@ -161,12 +161,19 @@ void VConnect::threadMethod() if (success) { logger->log("VConnect", Log::DEBUG, "Connected ok, doing login"); - success = vdr->doLogin(); + unsigned int version_server,version_client; + success = vdr->doLogin(&version_server,&version_client); if (!success) { vdr->disconnect(); - setOneLiner(tr("Login failed")); + if (version_server!=version_client) { + char buffer[1024]; + sprintf(buffer,"Protocoll mismatch s: %x c: %x",version_server,version_client); + setOneLiner(buffer); + } else { + setOneLiner(tr("Login failed")); + } delay = 3000; } } diff --git a/vdr.cc b/vdr.cc index 19128ab..1798c3b 100644 --- a/vdr.cc +++ b/vdr.cc @@ -38,6 +38,8 @@ #include "video.h" #include "osd.h" +#define VOMP_PROTOCOLL_VERSION 0x00000100 + VDR* VDR::instance = NULL; //prepare a request //will create a request package from a command variable and fill this @@ -593,7 +595,7 @@ bool VDR_PacketReceiver::call(void* userTag) ///////////////////////////////////////////////////////////////////////////// -int VDR::doLogin() +int VDR::doLogin(unsigned int* v_server,unsigned int* v_client) { VDR_RequestPacket vrp; if (!vrp.init(VDR_LOGIN, true, 6)) return 0; @@ -610,8 +612,19 @@ int VDR::doLogin() long vdrTimeOffset = vresp->extractLONG(); logger->log("VDR", Log::DEBUG, "offset = %i", vdrTimeOffset); + unsigned int version=vresp->extractULONG(); + + *v_server=version; + *v_client=VOMP_PROTOCOLL_VERSION; + delete vresp; + if (version!=VOMP_PROTOCOLL_VERSION) { + + return 0; + + } + // Set the time and zone on the MVP only #if !defined(WIN32) && !defined(__ANDROID__) @@ -1242,7 +1255,9 @@ void VDR::getChannelPids(Channel* channel) { apid newapid; newapid.pid = vresp->extractULONG(); - newapid.name = vresp->extractString(); + char * name=vresp->extractString(); + strncpy(newapid.desc,name,9); + delete [] name; channel->apids.push_back(newapid); } @@ -1252,7 +1267,9 @@ void VDR::getChannelPids(Channel* channel) { apid newdpid; newdpid.pid = vresp->extractULONG(); - newdpid.name = vresp->extractString(); + char * name=vresp->extractString(); + strncpy(newdpid.desc,name,9); + delete [] name; channel->dpids.push_back(newdpid); } @@ -1262,10 +1279,27 @@ void VDR::getChannelPids(Channel* channel) { apid newspid; newspid.pid = vresp->extractULONG(); - newspid.name = vresp->extractString(); + char * name=vresp->extractString(); + strncpy(newspid.desc,name,9); + delete [] name; channel->spids.push_back(newspid); } channel->tpid = vresp->extractULONG(); + // extension + for (ULONG i = 0; i < channel->numAPids; i++) + { + channel->apids[i].type = vresp->extractULONG(); + } + for (ULONG i = 0; i < channel->numDPids; i++) + { + channel->dpids[i].type = vresp->extractULONG(); + } + for (ULONG i = 0; i < channel->numSPids; i++) + { + channel->spids[i].type = vresp->extractULONG(); + channel->spids[i].data1 = vresp->extractULONG(); + channel->spids[i].data2 = vresp->extractULONG(); + } delete vresp; diff --git a/vdr.h b/vdr.h index 01f6b0f..5a5172d 100644 --- a/vdr.h +++ b/vdr.h @@ -152,7 +152,7 @@ class VDR : public Thread_TYPE, public EventDispatcher, public MediaProvider, pu // configSave // setEventTimer - int doLogin(); + int doLogin(unsigned int* v_server,unsigned int* v_client); bool getRecordingsList(RecMan* recman); RecInfo* getRecInfo(char* fileName); int deleteRecording(char* fileName); diff --git a/vvideolivetv.cc b/vvideolivetv.cc index b199843..69e8a49 100644 --- a/vvideolivetv.cc +++ b/vvideolivetv.cc @@ -997,7 +997,7 @@ void VVideoLiveTV::processMessage(Message* m) else if (m->message == Message::AUDIO_CHANGE_CHANNEL) { Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %i", m->parameter); - player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16); + player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16,(m->parameter & 0xFF000000)>>24); } else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL) { diff --git a/vvideorec.cc b/vvideorec.cc index 65b45f9..56142bb 100644 --- a/vvideorec.cc +++ b/vvideorec.cc @@ -568,7 +568,7 @@ void VVideoRec::processMessage(Message* m) else if (m->message == Message::AUDIO_CHANGE_CHANNEL) { Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received change audio channel to %i", m->parameter); - player->setAudioChannel(m->parameter&0xFFFF,(m->parameter&0xFF0000)>> 16 ); + player->setAudioChannel(m->parameter&0xFFFF,(m->parameter&0xFF0000)>> 16,(m->parameter&0xFF000000)>> 24 ); } else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL) { @@ -681,18 +681,18 @@ void VVideoRec::doAudioSelector() subtitleChannel, subtitleType, myRec->recInfo); } else { // Draw the selector - Channel temp_channel=player->getDemuxerChannel(); - RecInfo *cur_info= myRec->recInfo; - unsigned char numchan_recinfo = cur_info->numComponents; + Channel *temp_channel=player->getDemuxerChannel(); + // RecInfo *cur_info= myRec->recInfo; + /* unsigned char numchan_recinfo = cur_info->numComponents; unsigned char numchan_subtitles_siz = temp_channel.numSPids; ULONG mp_audcounter = 0; ULONG ac3_counter = 0; - int dvb_subcounter = 1; + int dvb_subcounter = 1;*/ + int i; - unsigned char type; + /*unsigned char type; char* lang; char* description; - int i; for (i = 0; i < numchan_recinfo; i++) { apid* ac = NULL; @@ -732,32 +732,29 @@ void VVideoRec::doAudioSelector() } } - } - for (i=0;iname==NULL) { - ac->name = new char[strlen(tr("unknown")) + 1]; - strcpy(ac->name, tr("unknown")); + }*/ + for (i=0;inumAPids;i++) { + apid *ac=&temp_channel->apids[i]; + if (ac->desc[0]==0) { + strncpy(ac->desc, tr("unknown"),9); } } - for (i=0;iname==NULL) { - ac->name = new char[strlen(tr("unknown")) + 1]; - strcpy(ac->name, tr("unknown")); + for (i=0;inumDPids;i++) { + apid *ac=&temp_channel->dpids[i]; + if (ac->desc[0]==0) { + strncpy(ac->desc, tr("unknown"),9); } } - for (i=0;iname==NULL) { - ac->name = new char[strlen(tr("unknown")) + 1]; - strcpy(ac->name, tr("unknown")); + for (i=0;inumSPids;i++) { + apid *ac=&temp_channel->spids[i]; + if (ac->desc[0]==0) { + strncpy(ac->desc, tr("unknown"),9); } } - vas = new VAudioSelector(this,&temp_channel , (player)->getCurrentAudioChannel(), + vas = new VAudioSelector(this,temp_channel , (player)->getCurrentAudioChannel(), subtitleType,subtitleChannel,player->getTeletxtSubtitlePages()); - for (i=0;iname; ac->name=NULL; @@ -771,7 +768,7 @@ void VVideoRec::doAudioSelector() apid *ac=&temp_channel.spids[i]; delete[] ac->name; ac->name=NULL; - } + }*/ } -- 2.39.5