Esempio n. 1
0
        internal static LanguageItem Create(Section section, int offset, int length)
        {
            // Test for length
            if (length < 4) return null;

            // Create
            return new LanguageItem(section, offset);
        }
Esempio n. 2
0
        internal static TeletextItem Create(Section section, int offset, int length)
        {
            // Check
            if (length < 5) return null;

            // Create
            return new TeletextItem(section, offset);
        }
Esempio n. 3
0
        private LanguageItem(Section section, int offset)
        {
            // Load the string
            ISOLanguage = section.ReadString(offset, 3);

            // Load the effect
            Effect = (AudioTypes)section[offset + 3];
        }
Esempio n. 4
0
        /// <summary>
        /// Create a duration representation from the <see cref="Section"/>
        /// raw data.
        /// </summary>
        /// <remarks>
        /// Please refer to the original document for the encoding algorithm used, e.g
        /// e.g. <i>ETSI EN 300 468 V1.6.1 (2004-06)</i> or alternate versions.
        /// </remarks>
        /// <param name="section">The raw data holder.</param>
        /// <param name="offset">The offset to the first of three bytes in
        /// the raw data.</param>
        /// <returns>The corresponding duration.</returns>
        public static TimeSpan DecodeDuration(Section section, int offset)
        {
            // Read all parts
            int d0 = FromBCD(section[offset + 0]);
            int d1 = FromBCD(section[offset + 1]);
            int d2 = FromBCD(section[offset + 2]);

            // Calculate
            return new TimeSpan(d0, d1, d2);
        }
Esempio n. 5
0
        private TeletextItem(Section section, int offset)
        {
            // Load
            ISOLanguage = section.ReadString(offset + 0, 3);
            Type = (TeletextTypes)(section[offset + 3]>>3);
            MagazineNumber = (byte)(section[offset + 3]&0x7);

            // Decode
            PageNumberBCD = section[offset + 4];
        }
Esempio n. 6
0
        /// <summary>
        /// Create a GMT/UTC time representation from the <see cref="Section"/>
        /// raw data.
        /// </summary>
        /// <remarks>
        /// Please refer to the original document for the encoding algorithm used, e.g
        /// e.g. <i>ETSI EN 300 468 V1.6.1 (2004-06)</i> or alternate versions.
        /// </remarks>
        /// <param name="section">The raw data holder.</param>
        /// <param name="offset">The offset to the first of five bytes in
        /// the raw data.</param>
        /// <returns>The corresponding GMT/UTC date and time.</returns>
        public static DateTime DecodeTime(Section section, int offset)
        {
            // Read all parts
            byte t0 = section[offset + 0];
            byte t1 = section[offset + 1];
            int t2 = FromBCD(section[offset + 2]);
            int t3 = FromBCD(section[offset + 3]);
            int t4 = FromBCD(section[offset + 4]);

            // Calculate
            return new DateTime(1970, 1, 1, t2, t3, t4).AddDays(MergeBytesToWord(t1, t0) - 40587);
        }
        /// <summary>
        /// Erzeugt eine neue Beschreibung.
        /// </summary>
        /// <param name="section">Der SI Bereich, in dem die Information gefunden wurde.</param>
        /// <param name="offset">Der Index des ersten Bytes dieser Information in den Rohdaten des SI Bereichs.</param>
        /// <param name="length">Die Anzahl der Bytes für diese Information.</param>
        /// <returns>Die zugehörige Information oder <i>null</i>, wenn eine Rekonstruktion nicht möglich war.</returns>
        public static CellInformation Create( Section section, int offset, int length )
        {
            // Check minimum length
            if (length < 10)
                return null;

            // Correct length
            length -= 10;

            // Read length of extension data
            int extlen = section[offset + 9];

            // Validate
            if (extlen > length)
                return null;

            // Read direct data
            ushort cellId = Tools.MergeBytesToWord( section[offset + 1], section[offset + 0] );
            int latitude = Tools.MergeBytesToWord( section[offset + 3], section[offset + 2] );
            int longitude = Tools.MergeBytesToWord( section[offset + 5], section[offset + 4] );

            // Read to be merged data
            int ext0 = section[offset + 6];
            int ext1 = section[offset + 7];
            int ext2 = section[offset + 8];

            // Merge extends
            int latitude_ext = (ext1 >> 4) + 16 * ext0;
            int longitude_ext = ext2 + 256 * (ext1 & 0x0f);

            // Create new
            CellInformation info = new CellInformation 
            { 
                Length = 10 + extlen,
                Identifier = cellId,
                Latitude = Rescale(latitude, 16, 90),
                Longitude = Rescale(longitude, 16, 180),
                LatitudeExtension = Rescale(latitude_ext, 13, 90),
                LongitudeExtension = Rescale(longitude_ext, 13, 180)
            };

            // Report
            return info;
        }
Esempio n. 8
0
        /// <summary>
        /// Find the handler <see cref="Type"/> for a table identifier and create 
        /// a new instance of it.
        /// <seealso cref="JMS.DVB.EPG.Section.TableIdentifier"/>
        /// </summary>
        /// <param name="section">The related <see cref="Section"/>.</param>
        /// <returns>A new instance of the corresponding handler class. The <see cref="IsValid"/>
        /// of the instance reports if the table is consistent and should be used.</returns>
        static public Table Create( Section section )
        {
            // Attach to the type
            Type pHandler = (Type) m_HandlerForIdentifier[section.TableIdentifier];

            // Create
            return (Table) Activator.CreateInstance( pHandler, new object[] { section } );
        }
Esempio n. 9
0
        /// <summary>
        /// Erzeugt eine neue Informationsinstanz.
        /// </summary>
        /// <param name="section">Die SI Tabelle, in der die Informationen abgelegt sind.</param>
        /// <param name="offset">Das erste Byte, das Informationen zu Untertiteln enthält.</param>
        private SubtitleInfo( Section section, int offset )
        {
            // Load the language
            ISOLanguage = section.ReadString( offset, 3 );

            // Load the type
            Type = (SubtitleTypes) section[offset + 3];

            // Load pages
            CompositionPage = Tools.MergeBytesToWord( section[offset + 5], section[offset + 4] );
            AncillaryPage = Tools.MergeBytesToWord( section[offset + 7], section[offset + 6] );
        }
Esempio n. 10
0
        /// <summary>
        /// Parse some EPG information and try to extract the data of the current
        /// service group.
        /// </summary>
        /// <param name="section">Currently parsed SI table.</param>
        private void EPGSectionFound(Section section)
        {
            // Test
            Tables.EIT eit = section.Table as Tables.EIT;

            // Not us
            if ( null == eit ) return;

            // Process all events
            foreach ( EventEntry evt in eit.Entries )
            {
                // What to add
                ArrayList ids = new ArrayList(), names = new ArrayList();

                // Make sure that this is us
                bool found = false;

                // Run over
                foreach ( Descriptor descr in evt.Descriptors )
                {
                    // Check type
                    Descriptors.Linkage info = descr as Descriptors.Linkage;
                    if ( null == info ) continue;

                    // Check type (PREMIERE)
                    if ( 176 != info.LinkType ) continue;

                    // Create identifier
                    Identifier id = new Identifier(info.OriginalNetworkIdentifier, info.TransportStreamIdentifier, info.ServiceIdentifier);

                    // Try to locate the related station
                    Station real = DVBDevice.FindStation(id);
                    if ( null == real )
                    {
                        // Could be service channel
                        id = new Identifier(info.ServiceIdentifier, 0xffff, info.ServiceIdentifier);
                        real = DVBDevice.FindStation(id);

                        // Try again
                        if ( null == real ) continue;
                    }

                    // Check the first one
                    if ( !found ) found = Equals(id, CurrentPortal);

                    // Remember
                    names.Add(string.Format("{0},{1}", names.Count, CodePage.GetString(info.PrivateData)));
                    ids.Add(id);
                }

                // Register
                if ( found )
                    lock (m_ServiceNames)
                        for ( int i = ids.Count ; i-- > 0 ; )
                            m_ServiceNames[ids[i]] = names[i];
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Create a GMT/UTC date representation from the <see cref="Section"/>
        /// raw data.
        /// </summary>
        /// <remarks>
        /// Please refer to the original document for the encoding algorithm used, e.g
        /// e.g. <i>ETSI EN 300 468 V1.6.1 (2004-06)</i> or alternate versions.
        /// </remarks>
        /// <param name="section">The raw data holder.</param>
        /// <param name="offset">The offset to the first of two bytes in
        /// the raw data.</param>
        /// <returns>The corresponding GMT/UTC date and.</returns>
        static public DateTime DecodeDate( Section section, int offset )
        {
            // Read all parts
            byte t0 = section[offset + 0];
            byte t1 = section[offset + 1];

            // Calculate
            return new DateTime( 1970, 1, 1, 0, 0, 0 ).AddDays( MergeBytesToWord( t1, t0 ) - 40587 );
        }
        /// <summary>
        /// Ermittelt aus der aktuellen <i>Program Map Table</i> die Informationen zum
        /// Porgramm des eingehenden Transport Streams. 
        /// </summary>
        /// <remarks>
        /// Dabei wird das Bild- und das gewünschte Tonsignal ermittelt und in den Transport
        /// Stream für den DirectShow Graphen übertragen. Dieser kann so mit festen PIDs
        /// arbeiten, wodurch die weitere Handhabung im DVB.NET DirectShow Graphen vereinfacht wird.
        /// Man kann die Arbeit dieser Methode daher als Auswahl der Tonspur und PID Mapping
        /// beschreiben.
        /// </remarks>
        /// <param name="pmt">Eine SI Tabelle.</param>
        private void ProcessPMT( Section pmt )
        {
            // Not active
            if (!IsRunning)
                return;

            // Validate
            if (!pmt.IsValid)
                return;

            // Attach to table
            PMT table = pmt.Table as PMT;

            // Validate
            if (null == table)
                return;
            if (!table.IsValid)
                return;
            if (null == table.ProgramEntries)
                return;
            if (table.ProgramEntries.Length < 1)
                return;

            // Remember
            m_CurrentService = table.ProgramNumber;

            // All audio
            List<AudioItem> audios = new List<AudioItem>();

            // Video and audio
            ushort video = 0, audio = 0, ttx = 0;
            bool mpeg4 = false, ac3 = false;

            // Process all programs
            foreach (ProgramEntry program in table.ProgramEntries)
                if ((program.StreamType == StreamTypes.Audio11172) || (program.StreamType == StreamTypes.Audio13818))
                {
                    // Remember MP2
                    audios.Add( new AudioItem( program, false, audios.Count ) );
                }
                else if ((program.StreamType == StreamTypes.Video13818) || (program.StreamType == StreamTypes.H264))
                {
                    // Only first video
                    if (0 != video)
                        continue;

                    // Remember
                    mpeg4 = (StreamTypes.H264 == program.StreamType);
                    video = program.ElementaryPID;
                }
                else if (program.StreamType == StreamTypes.PrivateData)
                {
                    // Modes
                    bool ac3Found = false, ttxFound = false;

                    // Scan descriptors
                    foreach (Descriptor descriptor in program.Descriptors)
                        if (!ac3Found && (descriptor is AC3))
                        {
                            // Add to list
                            audios.Add( new AudioItem( program, true, audios.Count ) );

                            // Done
                            ac3Found = true;
                        }
                        else if (!ttxFound && (descriptor is Teletext))
                        {
                            // Remember
                            ttx = program.ElementaryPID;

                            // Done
                            ttxFound = true;
                        }
                }

            // Always update name list
            m_AudioNames = audios.ConvertAll<string>( item => item.Name ).ToArray();

            // Read the audio index
            int audioIndex = AudioIndex;

            // Reset to default
            if ((audioIndex < 0) || (audioIndex >= audios.Count)) audioIndex = 0;

            // Check result
            if (audioIndex < audios.Count)
            {
                // Load item
                AudioItem item = audios[AudioIndex];

                // Copy all
                audio = item.PID;
                ac3 = item.AC3;
            }

            // Check changes
            bool videoDecChanged = (mpeg4 != m_MPEG4) || m_RestartAV;
            bool videoChanged = (video != m_Video) || m_RestartAV;
            bool audioChanged = (audio != m_Audio) || m_RestartAV;
            bool audioDecChanged = (ac3 != m_AC3) || m_RestartAV;
            bool ttxChanged = (ttx != m_TTX) || m_RestartAV;

            // No change at all
            if (!videoChanged)
                if (!videoDecChanged)
                    if (!audioChanged)
                        if (!audioDecChanged)
                            if (!ttxChanged)
                                return;

            // Discard old
            if (null != m_TSParser)
            {
                // De-register
                if (videoChanged && (0 != m_Video))
                    m_TSParser.RemoveFilter( m_Video );
                if (audioChanged && (0 != m_Audio))
                    m_TSParser.RemoveFilter( m_Audio );
                if (ttxChanged && (0 != m_TTX))
                    m_TSParser.RemoveFilter( m_TTX );
            }

            // Check for enforcement
            bool first = ((0 == m_Video) && (0 == m_Audio)) || m_RestartAV;

            // Change
            AudioIndex = audioIndex;
            m_RestartAV = false;
            m_Video = video;
            m_Audio = audio;
            m_MPEG4 = mpeg4;
            m_AC3 = ac3;
            m_TTX = ttx;

            // Register new
            if (null != m_TSParser)
            {
                // De-register
                if (videoChanged && (0 != m_Video))
                    m_TSParser.SetFilter( m_Video, false, AddVideo );
                if (audioChanged && (0 != m_Audio))
                    m_TSParser.SetFilter( m_Audio, false, AddAudio );
                if (ttxChanged && (0 != m_TTX))
                    m_TSParser.SetFilter( m_TTX, false, m_TTXStream.AddPayload );
            }

            // Attach to client
            var streamChanged = StreamChanged;
            if (streamChanged != null)
                streamChanged( first || videoDecChanged || audioDecChanged );
        }
        /// <summary>
        /// Versucht, aus der aktuellen <i>Program Access Table</i> das Programm des
        /// eingehenden Transport Streams zu ermitteln.
        /// </summary>
        /// <remarks>
        /// Nur das erste Programm wird berücksichtigt.
        /// </remarks>
        /// <param name="pat">Eine SI Tabelle.</param>
        private void ProcessPAT( Section pat )
        {
            // Not active
            if (!IsRunning)
                return;

            // Validate
            if (!pat.IsValid)
                return;

            // Attach to table
            PAT table = pat.Table as PAT;

            // Validate
            if (null == table)
                return;
            if (!table.IsValid)
                return;
            if (null == table.ProgramIdentifier)
                return;

            // Get the first
            IEnumerator<KeyValuePair<ushort, ushort>> programEnum = table.ProgramIdentifier.GetEnumerator();
            if (!programEnum.MoveNext())
                return;

            // Compare current PMT
            if (m_CurrentPMT == programEnum.Current.Value)
                return;

            // Remove the audio names
            m_AudioNames = new string[0];

            // Stop current PMT
            if (0 != m_CurrentPMT)
                m_TSParser.RemoveFilter( m_CurrentPMT );

            // Re-create parser
            m_PMTParser = new Parser();

            // Connect to handler
            m_PMTParser.SectionFound += ProcessPMT;

            // Change
            m_CurrentPMT = programEnum.Current.Value;
            m_CurrentService = null;
            CurrentEntry = null;
            NextEntry = null;

            // Create PMT
            m_TSParser.SetFilter( m_CurrentPMT, true, m_PMTParser.OnData );
        }
        /// <summary>
        /// Prüft, ob in der Programmzeitschrift Daten zur aktuellen Aufzeichnung vorliegen.
        /// </summary>
        /// <param name="section">Eintrag aus der Programmzeitschrift.</param>
        private void ProcessEPG( Section section )
        {
            // Not valid
            if (null == section)
                return;
            if (!section.IsValid)
                return;

            // Get the table
            EIT eit = section.Table as EIT;

            // Not valid
            if (null == eit)
                return;
            if (!eit.IsValid)
                return;

            // See if filter is active
            int? service = m_CurrentService;

            // Only current events are of interest
            if (!service.HasValue)
                return;
            if (service.Value != eit.ServiceIdentifier)
                return;

            // Set flags
            bool gotCurrent = false, gotNext = false;

            // Find all
            foreach (EventEntry entry in eit.Entries)
            {
                // Check for current
                if (!gotCurrent)
                    if (EventStatus.Running == entry.Status)
                    {
                        // Remember
                        CurrentEntry = entry;
                        gotCurrent = true;

                        // Done
                        if (gotNext)
                            break;
                        else
                            continue;
                    }

                // Check for next
                if (!gotNext)
                    if (EventStatus.NotRunning == entry.Status)
                    {
                        // Remember
                        NextEntry = entry;
                        gotNext = true;

                        // Done
                        if (gotCurrent)
                            break;
                    }
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Called for each section the driver parsed from the stream.
        /// </summary>
        /// <param name="section">Section parsed.</param>
        protected override void OnSectionFound(Section section)
        {
            // We are already done
            if (m_Complete.WaitOne(0, false)) return;

            // Not useable
            if ((null == section) || !section.IsValid) return;

            // Be safe
            try
            {
                // Nothing to do
                if ((null == section.Table) || !section.Table.IsValid) return;

                // Call implementation
                if (OnTableFound(section.Table)) m_Complete.Set();
            }
            catch
            {
                // Ignore any error
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Fire <see cref="SectionFound"/>.
        /// </summary>
        /// <param name="section">A <see cref="Section"/> constructed from
        /// the raw input stream.</param>
        protected virtual void OnSectionFound(Section section)
        {
            // Load
            SectionFoundHandler handler = SectionFound;

            // Send
            if (null != handler) handler(section);
        }
Esempio n. 17
0
        /// <summary>
        /// Erzeugt eine neue Informationsinstanz.
        /// </summary>
        /// <param name="section">Die SI Tabelle, in der die Informationen abgelegt sind.</param>
        /// <param name="offset">Das erste Byte, das Informationen zu Untertiteln enthält.</param>
        /// <param name="length">Die Anzahl der Bytes, die für die Beschreibung zur Verfügung stehen.</param>
        /// <returns>Die Informationsinstanz oder <i>null</i>, wenn keine aus den Daten erstellt
        /// werden konnte.</returns>
        internal static SubtitleInfo Create( Section section, int offset, int length )
        {
            // Test for length
            if (length < 8) return null;

            // Create
            return new SubtitleInfo( section, offset );
        }
Esempio n. 18
0
        /// <summary>
        /// Initialize the instance.
        /// </summary>
        /// <param name="section">The related <see cref="Section"/>.</param>
        protected Table( Section section )
        {
            // Remember
            m_Section = section;

            // Direct load
            Version = (section[2] >> 1) & 0x1f;
            IsCurrent = (0 != (section[2] & 1));
            SectionNumber = section[3];
            LastSectionNumber = section[4];
        }
Esempio n. 19
0
        private void SectionFound( Section section )
        {
            // Check
            if ((null == section) || !section.IsValid) return;

            // Test all
            if (ProcessEITEvents( section.Table as EIT )) return;
            if (ProcessCITEvents( section.Table as CITPremiere )) return;
        }