Пример #1
0
        private static int WriteVideoStreamHeader(RiffWriter rw, VideoStreamInfo vsi)
        {
            rw.BeginChunk(AviDemux.ID_strh);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write(AviDemux.FCC_vids);
            bw.Write(vsi.codecFourCC);
            bw.Write((int)0);              // dwFlags
            bw.Write((short)0);            // wPriority
            bw.Write((short)0);            // wLanguage
            bw.Write((int)0);              // dwInitialFrames
            int scale, rate;

            FindScaleAndRate(out scale, out rate, vsi.framerate);
            bw.Write(scale);             // dwScale
            bw.Write(rate);              // dwRate
            bw.Write((int)0);            // dwStart
            bw.Write(vsi.frameCount);    // dwLength. that's how many frames will be in this RIFF element, written over later
            bw.Write((int)0);            // dwSuggestedBufferSize, not suggesting any value
            bw.Write((int)-1);           // dwQuality = -1 meaning "default quality"
            bw.Write((int)0);            // dwSampleSize = 0 for video
            bw.Write((short)0);
            bw.Write((short)0);
            bw.Write((short)vsi.width);
            bw.Write((short)vsi.height);
            rw.EndChunk();
            return(offset);
        }
Пример #2
0
        private static int WriteDmlhHeader(RiffWriter rw, int totalFrames)
        {
            rw.BeginChunk(AviDemux.ID_dmlh);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);

            rw.binaryWriter.Write(totalFrames);              // will be written over later
            rw.EndChunk();
            return(offset);
        }
Пример #3
0
        private static void WriteChunkIndex(RiffWriter rw, AviStreamIndex index, int superIndexChunkOffset, ref int superIndexEntryCount, long indexBaseOffset, int maxSuperindexEntries)
        {
            var bw = rw.binaryWriter;

            // the offset where this index will be written
            long streamIndexOffset = bw.Seek(0, SeekOrigin.Current);

            // update stream superindex
            superIndexEntryCount++;
            if (superIndexEntryCount > maxSuperindexEntries)
            {
                throw new MpException("Not enough space was reserved for superindex. Please increase maxSuperindexEntries");
            }

            bw.Seek(superIndexChunkOffset + 1 * 4, SeekOrigin.Begin);
            bw.Write(superIndexEntryCount);              // overwrite nEntriesInUse
            bw.Seek(superIndexChunkOffset + 6 * 4 + (superIndexEntryCount - 1) * 16, SeekOrigin.Begin);
            bw.Write(streamIndexOffset);
            bw.Write(32 + 8 * index.entries.Count);     // dwSize
            bw.Write(index.entries.Count);              // dwDuration in stream ticks. @todo this is OK only for video, for audio stream this should be ???

            // write stream chunk index
            // @xxx MSDN suggests not seeking BaseStream when using BinaryWriter, but there are no Seek(long)
            //      in BinaryWriter. According to this forum post, BinaryWriter.Seek is just a wrapper
            //      to BinaryWriter.BaseStream.Seek, so all should be ok.
            //      http://www.pcreview.co.uk/forums/binarywriter-seek-vs-binarywriter-basestream-seek-t1223754.html
            bw.BaseStream.Seek(streamIndexOffset, SeekOrigin.Begin);

            rw.BeginChunk((RiffParser.ToFourCC("ix__") & 0x0000FFFF) | ((index.streamId << 16) & 0xFFFF0000));
            bw.Write((short)2);                         // wLongsPerEntry is always 2 here
            bw.Write((byte)0);                          // bIndexSubType is always 0 here
            bw.Write((byte)AviStreamIndex.Type.CHUNKS); // bIndexType = AVI_INDEX_OF_CHUNKS
            bw.Write(index.entries.Count);              // nEntriesInUse.
            bw.Write(index.streamId);                   // dwChunkId ("##dc" and similar)
            bw.Write(indexBaseOffset);                  // qwBaseOffset
            bw.Write((int)0);                           // dwReserved3

            foreach (var entry in index.entries)
            {
                long offset = entry.chunkOffset - indexBaseOffset;
                if (offset > int.MaxValue)
                {
                    throw new MpException("Internal error. Can't write index, because chunk offset won't fit into 31 bits: " + offset);
                }
                bw.Write((uint)offset);                  // bit31==0 indicating that this is a keyframe
                bw.Write(entry.chunkLength);
            }
            rw.EndChunk();

            index.globalOffset += index.entries.Count;
            index.entries.Clear();
        }
Пример #4
0
        private static void WriteAudioFormatHeader(RiffWriter rw, AudioStreamInfo asi)
        {
            rw.BeginChunk(AviDemux.ID_strf);
            var bw = rw.binaryWriter;

            bw.Write((ushort)asi.audioFormat);                        // wFormatTag
            bw.Write((short)asi.channels);                            // nChannels
            bw.Write(asi.sampleRate);                                 // nSamplesPerSec
            bw.Write(asi.sampleRate * asi.sampleSize * asi.channels); // nAvgBytesPerSec @xxx true for PCM audio only, but this is a "soft" property
            bw.Write((short)asi.sampleSize);                          // nBlockAlign
            bw.Write((short)(8 * asi.sampleSize / asi.channels));     // wBitsPerSample
            bw.Write((short)0);                                       // cbSize. no extra coded info
            rw.EndChunk();
        }
Пример #5
0
        private static int WriteDummySuperIndex(RiffWriter rw, uint streamId, int entriesToReserve)
        {
            rw.BeginChunk(AviDemux.ID_indx);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write((short)4);                             // wLongsPerEntry is always 4 for super index
            bw.Write((byte)0);                              // bIndexSubType is always 0 for super index
            bw.Write((byte)AviStreamIndex.Type.SUPERINDEX); // bIndexType = AVI_INDEX_OF_INDEXES
            bw.Write((int)0);                               // nEntriesInUse. this'll be updated later!
            bw.Write(streamId);                             // dwChunkId ("##dc" and similar)
            // write 3 reserved UINTs and reserve some space for entries
            bw.Write(new byte[4 * 3 + entriesToReserve * 16]);
            rw.EndChunk();
            return(offset);
        }
Пример #6
0
        private static void WriteVideoFormatHeader(RiffWriter rw, VideoStreamInfo vsi)
        {
            rw.BeginChunk(AviDemux.ID_strf);
            var bw = rw.binaryWriter;

            bw.Write((int)40);                                       // biSize
            bw.Write(vsi.width);                                     // biWidth
            bw.Write(vsi.height);                                    // biHeight
            bw.Write((short)1);                                      // biPlanes
            bw.Write((short)vsi.bitsPerPixel);
            bw.Write(vsi.codecFourCC);                               // biCompression
            bw.Write(vsi.width * vsi.height * vsi.bitsPerPixel / 8); // biSizeImage
            bw.Write((int)0);                                        // biXPelsPerMeter
            bw.Write((int)0);                                        // biYPelsPerMeter
            bw.Write((int)0);                                        // biClrUsed
            bw.Write((int)0);                                        // biClrImportant
            rw.EndChunk();
        }
Пример #7
0
        private static int WriteMainHeader(RiffWriter rw, VideoStreamInfo vsi, bool hasAudioStream)
        {
            rw.BeginChunk(AviDemux.ID_avih);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write(Mathf.RoundToInt(1000000f / vsi.framerate));                           // swMicroSecPerFrame
            bw.Write((int)0);                                                               // dwMaxBytesPerSec
            bw.Write((int)0);                                                               // dwPaddingGranularity
            bw.Write((int)(AVIMainHeader.AVIF_HASINDEX | AVIMainHeader.AVIF_MUSTUSEINDEX)); // dwFlags. Maybe use AVIMainHeader.AVIF_MUSTUSEINDEX too?
            bw.Write(vsi.frameCount);                                                       // dwTotalFrames. this will be written over later!
            bw.Write((int)0);                                                               // dwInitialFrames
            bw.Write(hasAudioStream ? 2 : 1);
            bw.Write((int)0);                                                               // dwSuggestedBufferSize, not suggesting any value
            bw.Write(vsi.width);
            bw.Write(vsi.height);
            bw.Write((long)0);              // dwReserver0 and dwReserver1
            bw.Write((long)0);              // dwReserver2 and dwReserver3
            rw.EndChunk();
            return(offset);
        }
Пример #8
0
        private static int WriteAudioStreamHeader(RiffWriter rw, AudioStreamInfo asi)
        {
            rw.BeginChunk(AviDemux.ID_strh);
            int offset = (int)rw.binaryWriter.Seek(0, SeekOrigin.Current);
            var bw     = rw.binaryWriter;

            bw.Write(AviDemux.FCC_auds);
            bw.Write(asi.codecFourCC);
            bw.Write((int)0);              // dwFlags
            bw.Write((short)0);            // wPriority
            bw.Write((short)0);            // wLanguage
            bw.Write((int)0);              // dwInitialFrames
            bw.Write((int)1);              // dwScale
            bw.Write(asi.sampleRate);      // dwRate @xxx This is true for PCM audio only!
            bw.Write((int)0);              // dwStart
            bw.Write(asi.sampleCount);     // dwLength. will be written over later
            bw.Write((int)0);              // dwSuggestedBufferSize, not suggesting it
            bw.Write((int)-1);             // dwQuality = -1 meaning "default quality"
            bw.Write(asi.sampleSize);      // dwSampleSize
            bw.Write((long)0);             // rcFrame
            rw.EndChunk();
            return(offset);
        }
Пример #9
0
 private static int WriteVideoStreamHeader(RiffWriter rw, VideoStreamInfo vsi)
 {
     rw.BeginChunk (AviDemux.ID_strh);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write (AviDemux.FCC_vids);
     bw.Write (vsi.codecFourCC);
     bw.Write ((int)0); // dwFlags
     bw.Write ((short)0); // wPriority
     bw.Write ((short)0); // wLanguage
     bw.Write ((int)0); // dwInitialFrames
     int scale, rate;
     FindScaleAndRate (out scale, out rate, vsi.framerate);
     bw.Write (scale); // dwScale
     bw.Write (rate); // dwRate
     bw.Write ((int)0); // dwStart
     bw.Write (vsi.frameCount); // dwLength. that's how many frames will be in this RIFF element, written over later
     bw.Write ((int)0); // dwSuggestedBufferSize, not suggesting any value
     bw.Write ((int)-1); // dwQuality = -1 meaning "default quality"
     bw.Write ((int)0); // dwSampleSize = 0 for video
     bw.Write ((short)0);
     bw.Write ((short)0);
     bw.Write ((short)vsi.width);
     bw.Write ((short)vsi.height);
     rw.EndChunk ();
     return offset;
 }
Пример #10
0
 private static int WriteMainHeader(RiffWriter rw, VideoStreamInfo vsi, bool hasAudioStream)
 {
     rw.BeginChunk (AviDemux.ID_avih);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write (Mathf.RoundToInt (1000000f / vsi.framerate)); // swMicroSecPerFrame
     bw.Write ((int)0); // dwMaxBytesPerSec
     bw.Write ((int)0); // dwPaddingGranularity
     bw.Write ((int)(AVIMainHeader.AVIF_HASINDEX | AVIMainHeader.AVIF_MUSTUSEINDEX)); // dwFlags. Maybe use AVIMainHeader.AVIF_MUSTUSEINDEX too?
     bw.Write (vsi.frameCount); // dwTotalFrames. this will be written over later!
     bw.Write ((int)0); // dwInitialFrames
     bw.Write (hasAudioStream ? 2 : 1);
     bw.Write ((int)0); // dwSuggestedBufferSize, not suggesting any value
     bw.Write (vsi.width);
     bw.Write (vsi.height);
     bw.Write ((long)0); // dwReserver0 and dwReserver1
     bw.Write ((long)0); // dwReserver2 and dwReserver3
     rw.EndChunk ();
     return offset;
 }
Пример #11
0
 private static void WriteVideoFormatHeader(RiffWriter rw, VideoStreamInfo vsi)
 {
     rw.BeginChunk (AviDemux.ID_strf);
     var bw = rw.binaryWriter;
     bw.Write ((int)40); // biSize
     bw.Write (vsi.width); // biWidth
     bw.Write (vsi.height); // biHeight
     bw.Write ((short)1); // biPlanes
     bw.Write ((short)vsi.bitsPerPixel);
     bw.Write (vsi.codecFourCC); // biCompression
     bw.Write (vsi.width * vsi.height * vsi.bitsPerPixel / 8); // biSizeImage
     bw.Write ((int)0); // biXPelsPerMeter
     bw.Write ((int)0); // biYPelsPerMeter
     bw.Write ((int)0); // biClrUsed
     bw.Write ((int)0); // biClrImportant
     rw.EndChunk ();
 }
Пример #12
0
 private static int WriteDummySuperIndex(RiffWriter rw, uint streamId, int entriesToReserve)
 {
     rw.BeginChunk (AviDemux.ID_indx);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write ((short)4); // wLongsPerEntry is always 4 for super index
     bw.Write ((byte)0); // bIndexSubType is always 0 for super index
     bw.Write ((byte)AviStreamIndex.Type.SUPERINDEX); // bIndexType = AVI_INDEX_OF_INDEXES
     bw.Write ((int)0); // nEntriesInUse. this'll be updated later!
     bw.Write (streamId); // dwChunkId ("##dc" and similar)
     // write 3 reserved UINTs and reserve some space for entries
     bw.Write (new byte[4 * 3 + entriesToReserve * 16]);
     rw.EndChunk ();
     return offset;
 }
Пример #13
0
 private static int WriteDmlhHeader(RiffWriter rw, int totalFrames)
 {
     rw.BeginChunk (AviDemux.ID_dmlh);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     rw.binaryWriter.Write (totalFrames); // will be written over later
     rw.EndChunk ();
     return offset;
 }
Пример #14
0
        private static void WriteChunkIndex(RiffWriter rw, AviStreamIndex index, int superIndexChunkOffset, ref int superIndexEntryCount, long indexBaseOffset, int maxSuperindexEntries)
        {
            var bw = rw.binaryWriter;

            // the offset where this index will be written
            long streamIndexOffset = bw.Seek (0, SeekOrigin.Current);

            // update stream superindex
            superIndexEntryCount++;
            if (superIndexEntryCount > maxSuperindexEntries) {
                throw new MpException ("Not enough space was reserved for superindex. Please increase maxSuperindexEntries");
            }

            bw.Seek (superIndexChunkOffset + 1 * 4, SeekOrigin.Begin);
            bw.Write (superIndexEntryCount); // overwrite nEntriesInUse
            bw.Seek (superIndexChunkOffset + 6 * 4 + (superIndexEntryCount - 1) * 16, SeekOrigin.Begin);
            bw.Write (streamIndexOffset);
            bw.Write (32 + 8 * index.entries.Count); // dwSize
            bw.Write (index.entries.Count); // dwDuration in stream ticks. @todo this is OK only for video, for audio stream this should be ???

            // write stream chunk index
            // @xxx MSDN suggests not seeking BaseStream when using BinaryWriter, but there are no Seek(long)
            //      in BinaryWriter. According to this forum post, BinaryWriter.Seek is just a wrapper
            //      to BinaryWriter.BaseStream.Seek, so all should be ok.
            //      http://www.pcreview.co.uk/forums/binarywriter-seek-vs-binarywriter-basestream-seek-t1223754.html
            bw.BaseStream.Seek (streamIndexOffset, SeekOrigin.Begin);

            rw.BeginChunk ((RiffParser.ToFourCC ("ix__") & 0x0000FFFF) | ((index.streamId << 16) & 0xFFFF0000));
            bw.Write ((short)2); // wLongsPerEntry is always 2 here
            bw.Write ((byte)0); // bIndexSubType is always 0 here
            bw.Write ((byte)AviStreamIndex.Type.CHUNKS); // bIndexType = AVI_INDEX_OF_CHUNKS
            bw.Write (index.entries.Count); // nEntriesInUse.
            bw.Write (index.streamId); // dwChunkId ("##dc" and similar)
            bw.Write (indexBaseOffset); // qwBaseOffset
            bw.Write ((int)0); // dwReserved3

            foreach (var entry in index.entries) {
                long offset = entry.chunkOffset - indexBaseOffset;
                if (offset > int.MaxValue) {
                    throw new MpException ("Internal error. Can't write index, because chunk offset won't fit into 31 bits: " + offset);
                }
                bw.Write ((uint)offset); // bit31==0 indicating that this is a keyframe
                bw.Write (entry.chunkLength);
            }
            rw.EndChunk ();

            index.globalOffset += index.entries.Count;
            index.entries.Clear ();
        }
Пример #15
0
 private static int WriteAudioStreamHeader(RiffWriter rw, AudioStreamInfo asi)
 {
     rw.BeginChunk (AviDemux.ID_strh);
     int offset = (int)rw.binaryWriter.Seek (0, SeekOrigin.Current);
     var bw = rw.binaryWriter;
     bw.Write (AviDemux.FCC_auds);
     bw.Write (asi.codecFourCC);
     bw.Write ((int)0); // dwFlags
     bw.Write ((short)0); // wPriority
     bw.Write ((short)0); // wLanguage
     bw.Write ((int)0); // dwInitialFrames
     bw.Write ((int)1); // dwScale
     bw.Write (asi.sampleRate); // dwRate @xxx This is true for PCM audio only!
     bw.Write ((int)0); // dwStart
     bw.Write (asi.sampleCount); // dwLength. will be written over later
     bw.Write ((int)0); // dwSuggestedBufferSize, not suggesting it
     bw.Write ((int)-1); // dwQuality = -1 meaning "default quality"
     bw.Write (asi.sampleSize); // dwSampleSize
     bw.Write ((long)0); // rcFrame
     rw.EndChunk ();
     return offset;
 }
Пример #16
0
 private static void WriteAudioFormatHeader(RiffWriter rw, AudioStreamInfo asi)
 {
     rw.BeginChunk (AviDemux.ID_strf);
     var bw = rw.binaryWriter;
     bw.Write ((ushort)asi.audioFormat); // wFormatTag
     bw.Write ((short)asi.channels); // nChannels
     bw.Write (asi.sampleRate); // nSamplesPerSec
     bw.Write (asi.sampleRate * asi.sampleSize * asi.channels); // nAvgBytesPerSec @xxx true for PCM audio only, but this is a "soft" property
     bw.Write ((short)asi.sampleSize); // nBlockAlign
     bw.Write ((short)(8 * asi.sampleSize / asi.channels)); // wBitsPerSample
     bw.Write ((short)0); // cbSize. no extra coded info
     rw.EndChunk ();
 }