private void DecodeTransponderData(byte[] section, int endOfSection, ref int pointer)
        {
            if (pointer + 6 > endOfSection)
            {
                throw new Exception(string.Format("NIT: corruption detected at transponder data, pointer = {0}, end of section = {1}", pointer, endOfSection));
            }
            bool isMpeg2Transport            = ((section[pointer] & 0x80) == 0);
            bool isVerticalRightPolarisation = ((section[pointer] & 0x40) != 0);
            int  transponderNumber           = (section[pointer++] & 0x3f);
            byte cdsReference = section[pointer++];

            Log.Log.Debug("NIT: transponder data, is MPEG 2 transport = {0}, is vertical/right polarisation = {1}, transponder number = {2}, CDS reference = {3}",
                          isMpeg2Transport, isVerticalRightPolarisation, transponderNumber, cdsReference);
            if (isMpeg2Transport)
            {
                byte mmsReference = section[pointer++];
                int  vctId        = (section[pointer] << 8) + section[pointer + 1];
                pointer += 2;
                bool isRootTransponder = ((section[pointer++] & 0x80) != 0);
                Log.Log.Debug("NIT: MPEG 2 transponder data, MMS reference = {0}, VCT ID = 0x{1:x}, is root transponder = {2}", mmsReference, vctId, isRootTransponder);
            }
            else
            {
                bool             isWideBandwidthVideo = ((section[pointer] & 0x80) != 0);
                WaveformStandard waveformStandard     = (WaveformStandard)(section[pointer++] & 0x1f);
                bool             isWideBandwidthAudio = ((section[pointer] & 0x80) != 0);
                bool             isCompandedAudio     = ((section[pointer] & 0x40) != 0);
                MatrixMode       matrixMode           = (MatrixMode)((section[pointer] >> 4) & 0x03);
                int subcarrier2Offset = 10 * (((section[pointer] & 0x0f) << 6) + (section[pointer + 1] >> 2)); // kHz
                pointer++;
                int subcarrier1Offset = 10 * (((section[pointer] & 0x03) << 8) + section[pointer + 1]);
                pointer += 2;
                Log.Log.Debug("NIT: non-MPEG 2 transponder data, is WB video = {0}, waveform standard = {1}, is WB audio = {2}, is companded audio = {3}, matrix mode = {4}, subcarrier 2 offset = {5} kHz, subcarrier 1 offset = {6} kHz",
                              isWideBandwidthVideo, waveformStandard, isWideBandwidthAudio, isCompandedAudio, matrixMode, subcarrier2Offset, subcarrier1Offset);
            }
        }
Пример #2
0
        private void DecodeVirtualChannelMap(byte[] section, int endOfSection, ref int pointer, AtscTransmissionMedium transmissionMedium, int vctId)
        {
            // Virtual channel formats depend on transmission medium.
            if (pointer + 7 > endOfSection)
            {
                throw new Exception(string.Format("S-VCT: corruption detected at virtual channel map, pointer = {0}, end of section = {1}", pointer, endOfSection));
            }

            bool freqSpecIncluded    = ((section[pointer] & 0x80) != 0);
            bool symbolRateIncluded  = ((section[pointer] & 0x40) != 0);
            bool descriptorsIncluded = ((section[pointer++] & 0x20) != 0);
            bool splice         = ((section[pointer++] & 0x80) != 0);
            uint activationTime = 0;

            for (byte b = 0; b < 4; b++)
            {
                activationTime = activationTime << 8;
                activationTime = section[pointer++];
            }
            byte numberOfVcRecords = section[pointer++];

            Log.Log.Debug("S-VCT: virtual channel map, transmission medium = {0}, freq. spec. included = {1}, symbol rate included = {2}, descriptors included = {3}, splice = {4}, activation time = {5}, number of VC records = {6}",
                          transmissionMedium, freqSpecIncluded, symbolRateIncluded, descriptorsIncluded, splice, activationTime, numberOfVcRecords);

            for (byte i = 0; i < numberOfVcRecords; i++)
            {
                if (pointer + 9 > endOfSection)
                {
                    throw new Exception(string.Format("S-VCT: detected number of virtual channel records {0} is invalid, pointer = {1}, end of section = {2}, loop = {3}", numberOfVcRecords, pointer, endOfSection, i));
                }

                int virtualChannelNumber = ((section[pointer] & 0x0f) << 8) + section[pointer + 1];
                pointer += 2;
                _channelDefinitions.Add(virtualChannelNumber);
                bool          applicationVirtualChannel = ((section[pointer] & 0x80) != 0);
                int           bitstreamSelect           = ((section[pointer] & 0x40) >> 6); // broadcast reserved
                int           pathSelect    = ((section[pointer] & 0x20) >> 5);             // satellite, SMATV, broadcast reserved
                TransportType transportType = (TransportType)((section[pointer] & 0x10) >> 4);
                ChannelType   channelType   = (ChannelType)(section[pointer++] & 0x0f);
                int           sourceId      = (section[pointer] << 8) + section[pointer + 1];
                pointer += 2;
                Log.Log.Debug("S-VCT: virtual channel number = {0}, application virtual channel = {1}, bitstream select = {2}, path select = {3}, transport type = {4}, channel type = {5}, source ID = 0x{6:x}",
                              virtualChannelNumber, applicationVirtualChannel, bitstreamSelect, pathSelect, transportType, channelType, sourceId);

                if (channelType == ChannelType.NvodAccess)
                {
                    int nvodChannelBase = ((section[pointer] & 0x0f) << 8) + section[pointer + 1];
                    pointer += 2;
                    if (transmissionMedium == AtscTransmissionMedium.Smatv)
                    {
                        pointer += 3;
                    }
                    else if (transmissionMedium != AtscTransmissionMedium.OverTheAir)
                    {
                        pointer += 2;
                    }
                    Log.Log.Debug("S-VCT: NVOD channel base = 0x{0:x}", nvodChannelBase);
                }
                else
                {
                    switch (transmissionMedium)
                    {
                    case AtscTransmissionMedium.Satellite:
                        if (transportType == TransportType.Mpeg2)
                        {
                            byte satellite     = section[pointer++];
                            int  transponder   = (section[pointer++] & 0x3f);
                            int  programNumber = (section[pointer] << 8) + section[pointer + 1];
                            pointer += 2;
                            Log.Log.Debug("S-VCT: satellite = {0}, transponder = {1}, program number = 0x{2:x}", satellite, transponder, programNumber);
                        }
                        else
                        {
                            byte satellite   = section[pointer++];
                            int  transponder = (section[pointer++] & 0x3f);
                            pointer += 2;
                            Log.Log.Debug("S-VCT: satellite = {0}, transponder = {1}", satellite, transponder);
                        }
                        break;

                    case AtscTransmissionMedium.Smatv:
                        if (transportType == TransportType.Mpeg2)
                        {
                            byte cdsReference  = section[pointer++];
                            int  programNumber = (section[pointer] << 8) + section[pointer + 1];
                            pointer += 2;
                            byte mmsReference = section[pointer++];
                            pointer++;
                            Log.Log.Debug("S-VCT: CDS reference = {0}, program number = 0x{1:x}, MMS reference = {2}", cdsReference, programNumber, mmsReference);
                        }
                        else
                        {
                            byte             cdsReference         = section[pointer++];
                            bool             scrambled            = ((section[pointer] & 0x80) != 0);
                            VideoStandard    videoStandard        = (VideoStandard)(section[pointer++] & 0x0f);
                            bool             isWideBandwidthVideo = ((section[pointer] & 0x80) != 0);
                            WaveformStandard waveformStandard     = (WaveformStandard)(section[pointer++] & 0x1f);
                            bool             isWideBandwidthAudio = ((section[pointer] & 0x80) != 0);
                            bool             isCompandedAudio     = ((section[pointer] & 0x40) != 0);
                            MatrixMode       matrixMode           = (MatrixMode)((section[pointer] >> 4) & 0x03);
                            int subcarrier2Offset = 10 * (((section[pointer] & 0x0f) << 6) + (section[pointer + 1] >> 2)); // kHz
                            pointer++;
                            int subcarrier1Offset = 10 * (((section[pointer] & 0x03) << 8) + section[pointer + 1]);
                            pointer += 2;
                            Log.Log.Debug("S-VCT: CDS reference = {0}, scrambled = {1}, video standard = {2}, is WB video = {3}, waveform standard = {4}, is WB audio = {5}, is companded audio = {6}, matrix mode = {7}, subcarrier 2 offset = {8} kHz, subcarrier 1 offset = {9} kHz",
                                          cdsReference, scrambled, videoStandard, isWideBandwidthVideo, waveformStandard, isWideBandwidthAudio,
                                          isCompandedAudio, matrixMode, subcarrier2Offset, subcarrier1Offset);
                        }
                        break;

                    case AtscTransmissionMedium.OverTheAir:
                        if (transportType == TransportType.Mpeg2)
                        {
                            int programNumber = (section[pointer] << 8) + section[pointer + 1];
                            pointer += 2;
                            Log.Log.Debug("S-VCT: program number = 0x{0:x}", programNumber);
                        }
                        else
                        {
                            bool          scrambled     = ((section[pointer] & 0x80) != 0);
                            VideoStandard videoStandard = (VideoStandard)(section[pointer++] & 0x0f);
                            pointer++;
                            Log.Log.Debug("S-VCT: scrambled = {0}, video standard = {1}", scrambled, videoStandard);
                        }
                        break;

                    case AtscTransmissionMedium.Cable:
                    case AtscTransmissionMedium.Mmds:
                        if (transportType == TransportType.Mpeg2)
                        {
                            byte cdsReference  = section[pointer++];
                            int  programNumber = (section[pointer] << 8) + section[pointer + 1];
                            pointer += 2;
                            byte mmsReference = section[pointer++];
                            Log.Log.Debug("S-VCT: CDS reference = {0}, program number = 0x{1:x}, MMS reference = {2}", cdsReference, programNumber, mmsReference);
                            if (OnChannelDetail != null)
                            {
                                OnChannelDetail(transmissionMedium, vctId, virtualChannelNumber, applicationVirtualChannel, bitstreamSelect,
                                                pathSelect, channelType, sourceId, cdsReference, programNumber, mmsReference);
                            }
                        }
                        else
                        {
                            byte          cdsReference  = section[pointer++];
                            bool          scrambled     = ((section[pointer] & 0x80) != 0);
                            VideoStandard videoStandard = (VideoStandard)(section[pointer++] & 0x0f);
                            pointer += 2;
                            Log.Log.Debug("S-VCT: CDS reference = {0}, scrambled = {1}, video standard = {2}", cdsReference, scrambled, videoStandard);
                        }
                        break;

                    default:
                        throw new Exception(string.Format("S-VCT: unsupported transmission medium {0}", transmissionMedium));
                    }
                }

                if (freqSpecIncluded || transmissionMedium == AtscTransmissionMedium.OverTheAir)
                {
                    int frequencyUnit = 10; // kHz
                    if ((section[pointer] & 0x80) != 0)
                    {
                        frequencyUnit = 125;                                                                          // kHz
                    }
                    int carrierFrequency = frequencyUnit * (((section[pointer] & 0x7f) << 8) + section[pointer + 1]); // kHz
                    pointer += 2;
                    Log.Log.Debug("S-VCT: frequency, unit = {0} kHz, carrier = {1} kHz", frequencyUnit, carrierFrequency);
                }
                if (symbolRateIncluded && transmissionMedium != AtscTransmissionMedium.OverTheAir)
                {
                    // s/s
                    int symbolRate = ((section[pointer] & 0x0f) << 24) + (section[pointer + 1] << 16) + (section[pointer + 2] << 8) + section[pointer + 3];
                    pointer += 4;
                    Log.Log.Debug("S-VCT: symbol rate = {0} s/s", symbolRate);
                }
                if (descriptorsIncluded)
                {
                    if (pointer >= endOfSection)
                    {
                        throw new Exception(string.Format("S-VCT: invalid section length at virtual channel map descriptor count, pointer = {0}, end of section = {1}, loop = {2}", pointer, endOfSection, i));
                    }
                    byte descriptorCount = section[pointer++];
                    for (byte d = 0; d < descriptorCount; d++)
                    {
                        if (pointer + 2 > endOfSection)
                        {
                            throw new Exception(string.Format("S-VCT: detected virtual channel map descriptor count {0} is invalid, pointer = {1}, end of section = {2}, loop = {3}, inner loop = {4}", descriptorCount, pointer, endOfSection, i, d));
                        }
                        byte tag    = section[pointer++];
                        byte length = section[pointer++];
                        Log.Log.Debug("S-VCT: virtual channel map descriptor, tag = 0x{0:x}, length = {1}", tag, length);
                        if (pointer + length > endOfSection)
                        {
                            throw new Exception(string.Format("S-VCT: invalid virtual channel map descriptor length {0}, pointer = {1}, end of section = {2}, loop = {3}, inner loop = {4}", length, pointer, endOfSection, i, d));
                        }
                        pointer += length;
                    }
                }
            }
        }