Ejemplo n.º 1
0
        private void WriteVBRHeader(bool isPlaceholder)
        {
            var buff = new byte[GetFrameLength(_mpegVersion, 64000, _sampleRate, 0)];

            if (!isPlaceholder)
            {
                uint header     = _firstFrameHeader;
                int  dataOffset = GetFrameDataOffset(_mpegVersion, _channelMode);
                header &= 0xFFFF0DFF;                                                                        // Clear bitrate and padding fields
                header |= 0x00010000;                                                                        // Set protection bit (indicates that CRC is NOT present)
                header |= (uint)((_mpegVersion == 3) ? 5 : 8) << 12;                                         // 64 kbit/sec
                General.CopyBytes(buff, 0, BitConverterBE.GetBytes(header));
                General.CopyBytes(buff, dataOffset, BitConverterBE.GetBytes(0x58696E67));                    // "Xing"
                General.CopyBytes(buff, dataOffset + 4, BitConverterBE.GetBytes((uint)0x7));                 // Flags
                General.CopyBytes(buff, dataOffset + 8, BitConverterBE.GetBytes((uint)_frameOffsets.Count)); // Frame count
                General.CopyBytes(buff, dataOffset + 12, BitConverterBE.GetBytes(_totalFrameLength));        // File length
                for (int i = 0; i < 100; i++)
                {
                    int frameIndex = (int)((i / 100.0) * _frameOffsets.Count);
                    buff[dataOffset + 16 + i] = (byte)((_frameOffsets[frameIndex] / (double)_totalFrameLength) * 256.0);
                }
            }

            _fs.Write(buff, 0, buff.Length);
        }
Ejemplo n.º 2
0
 private uint ReadUInt32()
 {
     var x = new byte[4];
     _fs.Read(x, 0, 4);
     _fileOffset += 4;
     return BitConverterBE.ToUInt32(x, 0);
 }
Ejemplo n.º 3
0
 private void WritePage()
 {
     if (_packetList.Count == 0)
     {
         return;
     }
     FlushPage(false);
     WriteToPage(BitConverterBE.GetBytes(0x4F676753U), 0, 4);         // "OggS"
     WriteToPage(0);                                                  // Stream structure version
     WriteToPage((byte)((_pageSequenceNumber == 0) ? 0x02 : 0));      // Page flags
     WriteToPage(_packetList[_packetList.Count - 1].GranulePosition); // Position in samples
     WriteToPage((uint)_serialNumber);                                // Stream serial number
     WriteToPage(_pageSequenceNumber);                                // Page sequence number
     WriteToPage((uint)0);                                            // Checksum
     WriteToPage((byte)_packetList.Count);                            // Page segment count
     foreach (OggPacket packet in _packetList)
     {
         WriteToPage((byte)packet.Data.Length);
     }
     foreach (OggPacket packet in _packetList)
     {
         WriteToPage(packet.Data, 0, packet.Data.Length);
     }
     _packetList.Clear();
     _packetListDataSize = 0;
     _pageSequenceNumber++;
 }
Ejemplo n.º 4
0
        public void WriteChunk(byte[] chunk, uint timeStamp)
        {
            if (chunk.Length < 1)
            {
                return;
            }

            if (chunk[0] == 0)
            { // Header
                if (chunk.Length < 3)
                {
                    return;
                }

                ulong bits = (ulong)BitConverterBE.ToUInt16(chunk, 1) << 48;

                _aacProfile      = BitHelper.Read(ref bits, 5) - 1;
                _sampleRateIndex = BitHelper.Read(ref bits, 4);
                _channelConfig   = BitHelper.Read(ref bits, 4);

                if ((_aacProfile < 0) || (_aacProfile > 3))
                {
                    throw new ExtractionException("Unsupported AAC profile.");
                }
                if (_sampleRateIndex > 12)
                {
                    throw new ExtractionException("Invalid AAC sample rate index.");
                }
                if (_channelConfig > 6)
                {
                    throw new ExtractionException("Invalid AAC channel configuration.");
                }
            }
            else
            { // Audio data
                int   dataSize = chunk.Length - 1;
                ulong bits     = 0;

                // Reference: WriteADTSHeader from FAAC's bitstream.c

                BitHelper.Write(ref bits, 12, 0xFFF);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 2, 0);
                BitHelper.Write(ref bits, 1, 1);
                BitHelper.Write(ref bits, 2, _aacProfile);
                BitHelper.Write(ref bits, 4, _sampleRateIndex);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 3, _channelConfig);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 13, 7 + dataSize);
                BitHelper.Write(ref bits, 11, 0x7FF);
                BitHelper.Write(ref bits, 2, 0);

                _fs.Write(BitConverterBE.GetBytes(bits), 1, 7);
                _fs.Write(chunk, 1, dataSize);
            }
        }
Ejemplo n.º 5
0
        private uint ReadUInt24()
        {
            var x = new byte[4];

            _fs.Read(x, 1, 3);
            _fileOffset += 3;
            return(BitConverterBE.ToUInt32(x, 0));
        }
Ejemplo n.º 6
0
        public void WriteChunk(byte[] chunk, uint timeStamp, int frameType)
        {
            int offset, len;

            offset = 0;
            len    = chunk.Length;
            if (_codecID == 4)
            {
                offset = 1;
                len   -= 1;
            }
            if (_codecID == 5)
            {
                offset = 4;
                if (len >= 4)
                {
                    int alphaOffset = (int)BitConverterBE.ToUInt32(chunk, 0) & 0xFFFFFF;
                    if (!_isAlphaWriter)
                    {
                        len = alphaOffset;
                    }
                    else
                    {
                        offset += alphaOffset;
                        len    -= offset;
                    }
                }
                else
                {
                    len = 0;
                }
            }
            len = Math.Max(len, 0);
            len = Math.Min(len, chunk.Length - offset);

            _index.Add((frameType == 1) ? (uint)0x10 : 0);
            _index.Add(_moviDataSize + 4);
            _index.Add((uint)len);

            if ((_width == 0) && (_height == 0))
            {
                GetFrameSize(chunk);
            }

            WriteFourCC("00dc");
            _bw.Write(len);
            _bw.Write(chunk, offset, len);

            if ((len % 2) != 0)
            {
                _bw.Write((byte)0);
                len++;
            }
            _moviDataSize += (uint)len + 8;
            _frameCount++;
        }
Ejemplo n.º 7
0
        private void GetFrameSize(byte[] chunk)
        {
            switch (_codecID)
            {
            case 2:
            {
                // Reference: flv_h263_decode_picture_header from libavcodec's h263.c

                if (chunk.Length < 10)
                {
                    return;
                }

                if ((chunk[0] != 0) || (chunk[1] != 0))
                {
                    return;
                }

                ulong x = BitConverterBE.ToUInt64(chunk, 2);
                int   format;

                if (BitHelper.Read(ref x, 1) != 1)
                {
                    return;
                }
                BitHelper.Read(ref x, 5);
                BitHelper.Read(ref x, 8);

                format = BitHelper.Read(ref x, 3);
                switch (format)
                {
                case 0:
                    _width  = BitHelper.Read(ref x, 8);
                    _height = BitHelper.Read(ref x, 8);
                    break;

                case 1:
                    _width  = BitHelper.Read(ref x, 16);
                    _height = BitHelper.Read(ref x, 16);
                    break;

                case 2:
                    _width  = 352;
                    _height = 288;
                    break;

                case 3:
                    _width  = 176;
                    _height = 144;
                    break;

                case 4:
                    _width  = 128;
                    _height = 96;
                    break;

                case 5:
                    _width  = 320;
                    _height = 240;
                    break;

                case 6:
                    _width  = 160;
                    _height = 120;
                    break;

                default:
                    return;
                }
            }
            break;

            case 5:
            case 4:
            {
                // Reference: vp6_parse_header from libavcodec's vp6.c

                int skip = (_codecID == 4) ? 1 : 4;
                if (chunk.Length < (skip + 8))
                {
                    return;
                }
                ulong x = BitConverterBE.ToUInt64(chunk, skip);

                int deltaFrameFlag     = BitHelper.Read(ref x, 1);
                int quant              = BitHelper.Read(ref x, 6);
                int separatedCoeffFlag = BitHelper.Read(ref x, 1);
                int subVersion         = BitHelper.Read(ref x, 5);
                int filterHeader       = BitHelper.Read(ref x, 2);
                int interlacedFlag     = BitHelper.Read(ref x, 1);

                if (deltaFrameFlag != 0)
                {
                    return;
                }
                if ((separatedCoeffFlag != 0) || (filterHeader == 0))
                {
                    BitHelper.Read(ref x, 16);
                }

                _height = BitHelper.Read(ref x, 8) * 16;
                _width  = BitHelper.Read(ref x, 8) * 16;

                // chunk[0] contains the width and height (4 bits each, respectively) that should
                // be cropped off during playback, which will be non-zero if the encoder padded
                // the frames to a macroblock boundary.  But if you use this adjusted size in the
                // AVI header, DirectShow seems to ignore it, and it can cause stride or chroma
                // alignment problems with VFW if the width/height aren't multiples of 4.
                if (!_isAlphaWriter)
                {
                    int cropX = chunk[0] >> 4;
                    int cropY = chunk[0] & 0x0F;
                    if (((cropX != 0) || (cropY != 0)) && !_isAlphaWriter)
                    {
                        _warnings.Add(String.Format("Suggested cropping: {0} pixels from right, {1} pixels from bottom.", cropX, cropY));
                    }
                }
            }
            break;
            }
        }
Ejemplo n.º 8
0
        private void ParseMP3Frames(byte[] buff)
        {
            int[] MPEG1BitRate     = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 };
            int[] MPEG2XBitRate    = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 };
            int[] MPEG1SampleRate  = { 44100, 48000, 32000, 0 };
            int[] MPEG20SampleRate = { 22050, 24000, 16000, 0 };
            int[] MPEG25SampleRate = { 11025, 12000, 8000, 0 };

            int offset = 0;
            int length = buff.Length;

            while (length >= 4)
            {
                ulong header;
                int   mpegVersion, layer, bitRate, sampleRate, padding, channelMode;
                int   frameLen;

                header = (ulong)BitConverterBE.ToUInt32(buff, offset) << 32;
                if (BitHelper.Read(ref header, 11) != 0x7FF)
                {
                    break;
                }
                mpegVersion = BitHelper.Read(ref header, 2);
                layer       = BitHelper.Read(ref header, 2);
                BitHelper.Read(ref header, 1);
                bitRate    = BitHelper.Read(ref header, 4);
                sampleRate = BitHelper.Read(ref header, 2);
                padding    = BitHelper.Read(ref header, 1);
                BitHelper.Read(ref header, 1);
                channelMode = BitHelper.Read(ref header, 2);

                if ((mpegVersion == 1) || (layer != 1) || (bitRate == 0) || (bitRate == 15) || (sampleRate == 3))
                {
                    break;
                }

                bitRate = ((mpegVersion == 3) ? MPEG1BitRate[bitRate] : MPEG2XBitRate[bitRate]) * 1000;

                if (mpegVersion == 3)
                {
                    sampleRate = MPEG1SampleRate[sampleRate];
                }
                else if (mpegVersion == 2)
                {
                    sampleRate = MPEG20SampleRate[sampleRate];
                }
                else
                {
                    sampleRate = MPEG25SampleRate[sampleRate];
                }

                frameLen = GetFrameLength(mpegVersion, bitRate, sampleRate, padding);
                if (frameLen > length)
                {
                    break;
                }

                bool isVBRHeaderFrame = false;
                if (_frameOffsets.Count == 0)
                {
                    // Check for an existing VBR header just to be safe (I haven't seen any in FLVs)
                    int o = offset + GetFrameDataOffset(mpegVersion, channelMode);
                    if (BitConverterBE.ToUInt32(buff, o) == 0x58696E67)
                    { // "Xing"
                        isVBRHeaderFrame = true;
                        _delayWrite      = false;
                        _hasVBRHeader    = true;
                    }
                }

                if (!isVBRHeaderFrame)
                {
                    if (_firstBitRate == 0)
                    {
                        _firstBitRate     = bitRate;
                        _mpegVersion      = mpegVersion;
                        _sampleRate       = sampleRate;
                        _channelMode      = channelMode;
                        _firstFrameHeader = BitConverterBE.ToUInt32(buff, offset);
                    }
                    else if (!_isVBR && (bitRate != _firstBitRate))
                    {
                        _isVBR = true;
                        if (_hasVBRHeader)
                        {
                        }
                        else if (_delayWrite)
                        {
                            WriteVBRHeader(true);
                            _writeVBRHeader = true;
                            _delayWrite     = false;
                        }
                        else
                        {
                            _warnings.Add("Detected VBR too late, cannot add VBR header.");
                        }
                    }
                }

                _frameOffsets.Add(_totalFrameLength + (uint)offset);

                offset += frameLen;
                length -= frameLen;
            }

            _totalFrameLength += (uint)buff.Length;
        }
Ejemplo n.º 9
0
        public void WriteChunk(byte[] chunk, uint timeStamp, int frameType)
        {
            if (chunk.Length < 4)
            {
                return;
            }

            // Reference: decode_frame from libavcodec's h264.c

            if (chunk[0] == 0)
            { // Headers
                if (chunk.Length < 10)
                {
                    return;
                }

                int offset, spsCount, ppsCount;

                offset         = 8;
                _nalLengthSize = (chunk[offset++] & 0x03) + 1;
                spsCount       = chunk[offset++] & 0x1F;
                ppsCount       = -1;

                while (offset <= chunk.Length - 2)
                {
                    if ((spsCount == 0) && (ppsCount == -1))
                    {
                        ppsCount = chunk[offset++];
                        continue;
                    }

                    if (spsCount > 0)
                    {
                        spsCount--;
                    }
                    else if (ppsCount > 0)
                    {
                        ppsCount--;
                    }
                    else
                    {
                        break;
                    }

                    int len = BitConverterBE.ToUInt16(chunk, offset);
                    offset += 2;
                    if (offset + len > chunk.Length)
                    {
                        break;
                    }
                    _fs.Write(_startCode, 0, _startCode.Length);
                    _fs.Write(chunk, offset, len);
                    offset += len;
                }
            }
            else
            { // Video data
                int offset = 4;

                if (_nalLengthSize != 2)
                {
                    _nalLengthSize = 4;
                }

                while (offset <= chunk.Length - _nalLengthSize)
                {
                    int len = (_nalLengthSize == 2) ?
                              BitConverterBE.ToUInt16(chunk, offset) :
                              (int)BitConverterBE.ToUInt32(chunk, offset);
                    offset += _nalLengthSize;
                    if (offset + len > chunk.Length)
                    {
                        break;
                    }
                    _fs.Write(_startCode, 0, _startCode.Length);
                    _fs.Write(chunk, offset, len);
                    offset += len;
                }
            }
        }