Exemple #1
0
        internal DecoderConfiguration(ref Reader reader)
        {
            var dcd = reader.readStructure <DecoderConfigDescriptor>();

            objectType         = (eObjectType)dcd.objectTypeIndication;
            streamType         = (eStreamType)dcd.streamType;
            upStream           = dcd.upStream;
            decodingBufferSize = dcd.bufferSizeDB;
            maximumBitrate     = dcd.maxBitrate;
            averageBitrate     = dcd.avgBitrate;

            // The reader gotta be positioned at the start of AudioSpecificConfig tag.
            // See ISO/IEC 14496-1 annex "E" for more info on tags and sizes.
            eDescriptorTag tag = (eDescriptorTag)reader.readByte();

            if (tag != eDescriptorTag.DecoderSpecificInfo)
            {
                throw new ArgumentException($"Expected eDescriptorTag.DecoderSpecificInfo, got { tag } instead");
            }
            int cb = reader.readSize();

            if (reader.bytesLeft < cb)
            {
                throw new EndOfStreamException($"DecoderSpecificInfo has size { cb } in the header, yet the stream only has { reader.bytesLeft } unread bytes left");
            }
            audioSpecificConfig = new byte[cb];
            reader.readBytes(audioSpecificConfig.AsSpan());
        }
Exemple #2
0
        public MP4AudioSampleEntry(Mp4Reader mp4, int bytesLeft) :
            base(mp4, ref bytesLeft)
        {
            Span <byte> bytes = stackalloc byte[bytesLeft];

            mp4.read(bytes);

            int  atomSize = BitConverter.ToInt32(bytes).endian();
            uint atomTag  = BitConverter.ToUInt32(bytes.Slice(4));

            switch (atomTag)
            {
            case (uint)eAudioBoxType.esds:
                break;

            default:
                throw new NotImplementedException();
            }

            // Skip header, version and flags
            bytes = bytes.Slice(12);

            Reader streamReader = new Reader(bytes);

            if (streamReader.EOF)
            {
                throw new ArgumentException($"The `esds` atom is empty");
            }

            // Read tag and size
            eDescriptorTag tag = streamReader.readTag();

            if (eDescriptorTag.ElementaryStream != tag)
            {
                throw new ArgumentException($"The `esds` atom is expected to contain an elementary stream descriptor, got { tag } instead");
            }
            int size = streamReader.readSize();

            // Create a reader for the content
            Reader esdReader = streamReader.readSubStream(size);

            // Read ElementaryStreamDescriptor
            ElementaryStreamDescriptor esd = esdReader.readStructure <ElementaryStreamDescriptor>();

            id       = esd.id;
            flags    = esd.flags;
            priority = esd.priority;

            if (esd.flags.HasFlag(eDescriptorFlags.DependentStream))
            {
                dependsOn = esdReader.readStructure <ushort>().endian();
            }

            if (esd.flags.HasFlag(eDescriptorFlags.URL))
            {
                byte        urlLength = esdReader.readByte();
                Span <byte> urlBuffer = stackalloc byte[urlLength];
                esdReader.readBytes(urlBuffer);
                unsafe
                {
                    fixed(byte *ptr = urlBuffer)
                    url = StringMarshal.copy(ptr, urlLength);
                }
            }

            if (esd.flags.HasFlag(eDescriptorFlags.OCRstream))
            {
                esId = esdReader.readStructure <ushort>().endian();
            }

            while (!esdReader.EOF)
            {
                tag  = esdReader.readTag();
                size = esdReader.readSize();
                Reader ss = esdReader.readSubStream(size);
                switch (tag)
                {
                case eDescriptorTag.DecoderConfiguration:
                    decoderConfig = new DecoderConfiguration(ref ss);
                    break;

                case eDescriptorTag.SyncLayerConfiguration:
                    syncLayerConfig = new SyncLayerConfiguration(ref ss);
                    break;

                case eDescriptorTag.ProfileLevelIndicationIndex:
                    profileLevelIndicationindex = ss.readByte();
                    break;

                case eDescriptorTag.IPIdentificationPointer:
                case eDescriptorTag.IPMPPointer:
                case eDescriptorTag.Language:
                case eDescriptorTag.QoS:
                case eDescriptorTag.Registration:
                    // Because of the way we implemented readSubStream, this break will skip them gracefully.
                    // TODO: support at least language, likely to be seen in the wild
                    break;

                default:
                    throw new NotSupportedException();
                }
            }

            // TODO: the esdReader has EOF, but the outer one, streamReader, might have not. It might contain moar stuff.
            // You can test for `if( !streamReader.EOF )` here, and parse even moar garbage carefully designed by these ISO/IEC committees and documented in many thousands of pages of these PDFs they sell.
        }