Esempio n. 1
0
        /// <summary>
        /// Assume that all the StreamMgrs provided are configured with the correct time range. Do not assume
        /// contiguous data, or compatible media types.
        /// </summary>
        /// <param name="audioMgr"></param>
        /// <param name="log"></param>
        public AudioMixer(StreamMgr[] audioMgr, LogMgr log)
        {
            fileStreamPlayer = null;
            this.audioMgr    = audioMgr;
            this.log         = log;
            refTime          = long.MinValue;
            inbufs           = new ArrayList();

            if (audioMgr.Length == 0)
            {
                return;
            }


            /// Examine the uncompressed MT's for each audioMgr, and implement a voting system so that the
            /// media type that is dominant for this mixer is the one we use, and other incompatible MT's
            /// are ignored in the mix.  Log a warning at places where the MT changes.
            /// Remember that each audioMgr may itself have multiple FileStreamPlayers which have different uncompressed
            /// media types.
            /// Finally we need to make our uncompressed MT available to the caller for use in configuring the writer.
            /// Later on let's look at ways to convert any common uncompressed types so that they are compatible.
            AudioCompatibilityMgr audioCompatibilityMgr = new AudioCompatibilityMgr();

            foreach (StreamMgr astream in audioMgr)
            {
                astream.CheckUncompressedAudioTypes(audioCompatibilityMgr);
            }

            this.uncompressedMediaType = audioCompatibilityMgr.GetDominantType();
            String warning = audioCompatibilityMgr.GetWarningString();

            if (warning != "")
            {
                log.WriteLine(warning);
                log.ErrorLevel = 5;
            }
            incompatibleGuids = audioCompatibilityMgr.GetIncompatibleGuids();

            // Here we also want to collect a "native" (compressed) profile corresponding to one of the "compatible"
            // streams.  This is useful in case we need to recompress.  Note this profile can be created if we have
            // a stream ID.
            compatibleStreamID = audioCompatibilityMgr.GetCompatibleStreamID();

            this.bitsPerSample  = this.uncompressedMediaType.WaveFormatEx.BitsPerSample;
            this.bytesPerSample = bitsPerSample / 8;
            this.ticksPerSample = ((uint)Constants.TicksPerSec) / (this.uncompressedMediaType.WaveFormatEx.SamplesPerSec * this.uncompressedMediaType.WaveFormatEx.Channels);
            limit = (long)((ulong)1 << (int)bitsPerSample) / 2 - 1;             //clip level

            buffers = new SampleBuffer[audioMgr.Length];
            for (int i = 0; i < buffers.Length; i++)
            {
                buffers[i] = new SampleBuffer(audioMgr[i], ticksPerSample, incompatibleGuids, this.uncompressedMediaType.WaveFormatEx.Channels);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Recompress audio from mixer into a temp file using the native profile.  This is used to implement mixing
        /// in the 'norecompression' scenario.
        /// </summary>
        /// <param name="progressTracker"></param>
        /// <returns></returns>
        public bool Recompress(ProgressTracker progressTracker)
        {
            cancel = false;

            if (audioMgr.Length == 0)
            {
                return(false);
            }

            //String useProfile;
            ProfileData profileData = null;

            if (this.compatibleStreamID >= 0)
            {
                profileData = ProfileUtility.StreamIdToProfileData(compatibleStreamID, MSR.LST.Net.Rtp.PayloadType.dynamicAudio);
                //Debug.WriteLine("Mixer.Recompress: using audio profile from streamID: " + compatibleStreamID.ToString());
            }
            else
            {
                //Under what circumstances could we get here??
                profileData = audioMgr[0].StreamProfileData;
            }

            WMWriter wmWriter = new WMWriter();

            wmWriter.Init();

            if (!wmWriter.ConfigProfile(profileData))
            {
                return(false);
            }

            String tempFileName = Utility.GetTempFilePath("wma");

            wmWriter.ConfigFile(tempFileName);
            wmWriter.GetInputProps();
            wmWriter.ConfigAudio(audioMgr[0].GetUncompressedAudioMediaType());

            wmWriter.Start();

            //Write samples
            progressTracker.CurrentValue = 0;
            BufferChunk audioSample = null;
            long        audioTime = long.MaxValue;
            long        refTime = 0, endTime = 0;
            long        lastWriteTime = 0;

            while (!cancel)
            {
                if (audioSample == null)
                {
                    endTime = audioTime;
                    if (!GetNextSample(out audioSample, out audioTime))
                    {
                        break;
                    }
                }

                if (audioSample != null)
                {
                    //write audio
                    if (refTime == 0)
                    {
                        refTime = audioTime;
                    }
                    //Debug.WriteLine("mixer.Recompress write audio: " + (audioTime-refTime).ToString() + ";length=" + audioSample.Length.ToString());
                    lastWriteTime = audioTime - refTime;
                    wmWriter.WriteAudio((uint)audioSample.Length, audioSample, (ulong)(audioTime - refTime));
                    audioSample = null;
                }
                else
                {
                    break;
                }
                progressTracker.CurrentValue = (int)(lastWriteTime / (Constants.TicksPerSec));
            }

            wmWriter.Stop();
            wmWriter.Cleanup();
            wmWriter = null;

            //Prepare a filestreamPlayer to read back compressed samples.
            fileStreamPlayer = new FileStreamPlayer(tempFileName, refTime, endTime, true, -1);

            return(true);
        }
        /// <summary>
        /// Write each stream from DBStreamPlayer to a WM file, then create FileStreamPlayers for each.
        /// It is necessary to do this before reading uncompressed samples, or using any of the
        /// methods that return uncompressed MediaTypes.
        /// This can be a long-running process.  It can be cancelled with the Stop method.
        /// </summary>
        /// <returns>False if we failed to configure the native profile</returns>
        public bool ToRawWMFile(ProgressTracker progressTracker)
        {
            if (cancel)
            {
                return(true);
            }

            String tmpfile = "";

            fileStreamPlayers = new FileStreamPlayer[streamPlayers.Length];
            for (int i = 0; i < streams.Length; i++)
            {
                streamProfileData = ProfileUtility.StreamIdToProfileData(streams[i], payload);
                if (payload == PayloadType.dynamicVideo)
                {
                    tmpfile = Utility.GetTempFilePath("wmv");
                    //nativeProfile = ProfileUtility.MakeNativeVideoProfile(streams[i]);
                }
                else
                {
                    tmpfile = Utility.GetTempFilePath("wma");
                    //nativeProfile = ProfileUtility.MakeNativeAudioProfile(streams[i]);
                }
                WMWriter wmWriter = new WMWriter();
                wmWriter.Init();
                //if (!wmWriter.ConfigProfile(nativeProfile,"",0))
                if (!wmWriter.ConfigProfile(StreamProfileData))
                {
                    return(false);
                }
                wmWriter.ConfigFile(tmpfile);
                wmWriter.ConfigNullProps();
                //wmWriter.SetCodecInfo(payload);
                wmWriter.Start();

                long        streamTime    = long.MaxValue;
                long        refTime       = 0;
                long        endTime       = 0;
                long        lastWriteTime = 0;
                BufferChunk frame;
                BufferChunk sample;
                bool        keyframe;
                bool        discontinuity;
                discontinuity = true;
                //Catch exceptions to work around the rare case of data corruption.
                //Oddly in one case where this occurred it did not occur if the segments were short enough
                while (streamPlayers[i].GetNextFrame(out frame, out streamTime))
                {
                    try {
                        sample = ProfileUtility.FrameToSample(frame, out keyframe);
                    }
                    catch {
                        DateTime dt = new DateTime(streamTime);
                        Console.WriteLine("Possible data corruption in stream: " + this.payload + ";" + this.cname +
                                          " at " + dt.ToString() + " (" + streamTime.ToString() + ")");
                        continue;
                    }
                    if (refTime == 0)
                    {
                        refTime = streamTime;
                    }
                    lastWriteTime = streamTime - refTime;
                    try {
                        if (payload == PayloadType.dynamicVideo)
                        {
                            //Debug.WriteLine("Write video: " + (streamTime-refTime).ToString() + ";length=" + sample.Length.ToString());
                            wmWriter.WriteCompressedVideo((ulong)(streamTime - refTime), (uint)sample.Length, (byte[])sample, keyframe, discontinuity);
                        }
                        else
                        {
                            //Debug.WriteLine("Write audio: " + (streamTime-refTime).ToString() + ";length=" + sample.Length.ToString());
                            wmWriter.WriteCompressedAudio((ulong)(streamTime - refTime), (uint)sample.Length, (byte[])sample);
                        }
                    }
                    catch {
                        DateTime dt = new DateTime(streamTime);
                        Console.WriteLine("Failed to write.  Possible data corruption in stream: " + this.payload + ";" + this.cname +
                                          " at " + dt.ToString() + " (" + streamTime.ToString() + ")");
                    }

                    if (discontinuity)
                    {
                        discontinuity = false;
                    }
                    endTime = streamTime;
                    if (cancel)
                    {
                        break;
                    }

                    progressTracker.CurrentValue = (int)(lastWriteTime / Constants.TicksPerSec);
                    //Debug.WriteLine("StreamMgr.ToRawWMFile: ProgressTracker currentValue=" + progressTracker.CurrentValue.ToString() +
                    //    ";streamTime=" + streamTime.ToString());
                }

                wmWriter.Stop();
                wmWriter.Cleanup();
                wmWriter = null;

                fileStreamPlayers[i] = new FileStreamPlayer(tmpfile, refTime, endTime, false, streams[i]);
                if (cancel)
                {
                    break;
                }
            }
            return(true);
        }