首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ByteStream源在SharpDX.MediaFoundation悬挂中的应用

ByteStream源在SharpDX.MediaFoundation悬挂中的应用
EN

Stack Overflow用户
提问于 2022-05-27 16:47:05
回答 1查看 58关注 0票数 0

我一直试图让一个定制的音频流与SharpDX.MediaFoundation一起工作。

为此,我将音频对象封装在实现System.IO.Stream的类中,如下所示:

代码语言:javascript
复制
public class AudioReaderWaveStream : System.IO.Stream
{
    byte[] waveHeader = new byte[44];
    AudioCore.IAudioReader reader = null;
    ulong readHandle = 0xffffffff;

    long readPosition = 0;

    public AudioReaderWaveStream(AudioCore.CEditedAudio content)
    {
        reader = content as AudioCore.IAudioReader;
        readHandle = reader.OpenDevice();

        int sampleRate = 0;
        short channels = 0;
        content.GetFormat(out sampleRate, out channels);

        System.IO.MemoryStream memStream = new System.IO.MemoryStream(waveHeader);
        using (System.IO.BinaryWriter bw = new System.IO.BinaryWriter(memStream))
        {
            bw.Write("RIFF".ToCharArray());
            bw.Write((Int32)Length - 8);
            bw.Write("WAVE".ToCharArray());
            bw.Write("fmt ".ToCharArray());
            bw.Write((Int32)16);
            bw.Write((Int16)3);
            bw.Write((Int16)1);
            bw.Write((Int32)sampleRate);
            bw.Write((Int32)sampleRate * 4);
            bw.Write((Int16)4);
            bw.Write((Int16)32);
            bw.Write("data".ToCharArray());
            bw.Write((Int32)reader.GetSampleCount() * 4);
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (readHandle != 0xffffffff)
        {
            reader.CloseDevice(readHandle);
            readHandle = 0xfffffffff;
        }
        base.Dispose(disposing);
    }

    ~AudioReaderWaveStream()
    {
        Dispose();
    }

    public override bool CanRead
    {
        get
        {
            return true;
        }
    }

    public override bool CanSeek
    {
        get
        {
            return true;
        }
    }

    public override bool CanWrite
    {
        get
        {
            return false;
        }
    }


    public override long Length
    {
        get
        {
            // Number of float samples + header of 44 bytes.
            return (reader.GetSampleCount() * 4) + 44;
        }
    }

    public override long Position
    {
        get
        {
            return readPosition;
        }
        set
        {
            readPosition = value;
        }
    }

    public override void Flush()
    {
        //throw new NotImplementedException();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (count <= 0)
            return 0;

        int retCount = count;
        if (Position < 44)
        {
            int headerCount = count;
            if ( Position + count >= 44 )
            {
                headerCount = 44 - (int)Position;
            }
            Array.Copy(waveHeader, Position, buffer, offset, headerCount);
            offset += headerCount;
            Position += headerCount;
            count -= headerCount;
        }
        if (count > 0)
        {
            float[] readBuffer = new float[count/4];
            reader.Seek(readHandle, Position - 44);
            reader.ReadAudio(readHandle, readBuffer);

            Array.Copy(readBuffer, 0, buffer, offset, count);
        }
        return retCount;
    }

    public override long Seek(long offset, System.IO.SeekOrigin origin)
    {
        if (origin == System.IO.SeekOrigin.Begin)
        {
            readPosition = offset;
        }
        else if (origin == System.IO.SeekOrigin.Current)
        {
            readPosition += offset;
        }
        else
        {
            readPosition = Length - offset;
        }
        return readPosition;
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }
}

然后,我接受这个对象并使用它创建一个源解析器,如下所示:

代码语言:javascript
复制
// Create a source resolver.
SharpDX.MediaFoundation.ByteStream      sdxByteStream   = new ByteStream( ARWS );
SharpDX.MediaFoundation.SourceResolver  resolver        = new SharpDX.MediaFoundation.SourceResolver();
ComObject                               source          = (ComObject)resolver.CreateObjectFromStream( sdxByteStream, "File.wav",  SourceResolverFlags.MediaSource );

然而,每次我这样做时,它都挂在CreateObjectFromStream调用上。我在SharpDX中查看了一下,以了解发生了什么,当它通过CreateObjectFromByteStream调用底层接口时,实际的挂起似乎发生了。我还查看了从字节流中读取哪些数据。它读取前16个字节,其中包括“RIFF”、RIFF大小、“WAVE”和“fmt”。那就没别的事了。

有没有人知道我可能做错了什么。我尝试过各种组合的SourceResolverFlags,但似乎没有什么不同。它只是挂着。

它确实让我想起了线程间的编组,但是所有的媒体基金会调用都是从同一个线程发出的,所以我不认为是这样的。我也相当肯定,MediaFoundation使用免费线程,所以这应该不会是一个问题。

有人知道我可能做错了什么吗?

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2022-05-30 14:33:24

好的,我想出了一个解决办法。看起来我可能有一个COM线程问题。读取发生在线程中,并且该线程正在返回调用函数的主线程。

因此,我使用了调用的异步版本,并在必要时执行一个Application.DoEvents()来传递控件。

代码语言:javascript
复制
Callback cb     = new Callback( resolver );
IUnknown cancel = null;
resolver.BeginCreateObjectFromByteStream( sdxByteStream, "File.wav", (int)(SourceResolverFlags.MediaSource | SourceResolverFlags.ByteStream), null, out cancel, cb, null );
 if ( cancel != null )
 {
     cancel.Dispose();
 }

 while( cb.MediaSource == null )
 {
     System.Windows.Forms.Application.DoEvents();
 }

 SharpDX.MediaFoundation.MediaSource     mediaSource     = cb.MediaSource;

我真的恨COM的线程模型..。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72408648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档