locked
Creating an IRandomAccessStream from a memory buffer for use with MediaElement

    Question

  • The application I'm porting the Metro stores all of it's data in a pack file. I'm trying to get .wav files loading via our pack file to play back through a MediaElement by coercing a memory buffer into an IRandomAccessStream interface and then calling SetSource on MediaElement with my IRandomAccessStream. I have some code pieced together from various samples which does compile and run without error but no sound is played back. Is there an example of how I should approach this problem?

    This is what I have so far:

    class NativeBuffer : public Microsoft::WRL::RuntimeClass<
       Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRtClassicComMix >,
       ABI::Windows::Storage::Streams::IBuffer,
       Windows::Storage::Streams::IBufferByteAccess >
    {
    
    public:
       virtual ~NativeBuffer()
       {
       }
       
       STDMETHODIMP RuntimeClassInitialize(unsigned char* buffer, unsigned int size)
       {
          _capacity = size;
          _length = size;
          _buffer = buffer;
          return S_OK;
       }
       
       STDMETHODIMP Buffer( byte **value)
       {
          *value = _buffer;
          return S_OK;
       }
       
       STDMETHODIMP get_Capacity(UINT32 *value)
       {
          *value = _capacity;
          return S_OK;
       }
       
       STDMETHODIMP get_Length(UINT32 *value)
       {
          *value = _length;
          return S_OK;
       }
       
       STDMETHODIMP put_Length(UINT32 value)
       {
          if (value > _capacity)
             return E_INVALIDARG;
          _length = value;
          return S_OK;
       }
    private:
       unsigned char* _buffer;
       size_t _capacity;
       size_t _length;
    };
    
    IBuffer^ CreateBuffer(unsigned char* buffer, unsigned int size)
    {
       Microsoft::WRL::ComPtr<NativeBuffer> nativeBuffer;
       Microsoft::WRL::MakeAndInitialize<NativeBuffer>(&nativeBuffer, buffer, size);
       auto iinspectable = (IInspectable*)reinterpret_cast<IInspectable*>(nativeBuffer.Get());
       return reinterpret_cast<IBuffer^>(iinspectable);
    }
    
    // attempt to use .wav data from memory buffer
    IBuffer^ buffer = CreateBuffer(fileData.data(),    fileData.size());
    InMemoryRandomAccessStream^ audioStream = ref new InMemoryRandomAccessStream();
    DataWriter^ dataWriter = ref new DataWriter(audioStream);
    dataWriter->WriteBuffer(buffer);
    dataWriter->StoreAsync();
    // when store is finished
    dataWriter->FlushAsync();
    // when flush is finished
    mediaElement->AutoPlay = false;
    mediaElement->SetSource(audioStream, mimeType);
    Tuesday, June 26, 2012 2:36 AM

Answers

  • Hello Cameron,

    You can't stream from an InMemoryRandomAccessStream buffer to a MediaElement control. There is really no need for you to do this. You can simply set the URL of your file source and the MediaElement will take care of the rest. We currently support Microsoft's RTSP streaming protocol and Microsoft's HTTP streaming. We also have a Smooth Streaming port of the SMRF player for Metro.

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Thursday, June 28, 2012 7:35 PM
    Moderator

All replies

  • Hello,

    The dataWriter->StoreAsync(); is an asynchronous method, you should use create_task and then to do the next step for this operator.

    You can follow this sample codes
    Media Play To sample
    http://code.msdn.microsoft.com/windowsapps/Media-PlayTo-Sample-fedcb0f9#content
    PlayTo::Scenario1::videoFile_Click function.

    And
    http://msdn.microsoft.com/en-US/library/windows/apps/xaml/hh465191

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, June 27, 2012 7:39 AM
  • Sorry, I wasn't clear. I removed the syncronisation from my code listed above for readability. We are waiting for StoreAsync and FlushAsync to finish before setting source.

    I'll take a look at those samples and see if they help.

    Wednesday, June 27, 2012 10:47 PM
  • I checked out that sample. Unfortunately it doesn't demonstrate what I'm trying to achieve, that is streaming from a memory buffer.
    Thursday, June 28, 2012 1:33 AM
  • Hello Cameron,

    You can't stream from an InMemoryRandomAccessStream buffer to a MediaElement control. There is really no need for you to do this. You can simply set the URL of your file source and the MediaElement will take care of the rest. We currently support Microsoft's RTSP streaming protocol and Microsoft's HTTP streaming. We also have a Smooth Streaming port of the SMRF player for Metro.

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Thursday, June 28, 2012 7:35 PM
    Moderator
  • I can't believe you don't allow playing from a memory stream.  I have an app that requires playing a video from a byte[] that is NOT a file or a web uri.  What should I do now?
    Thursday, September 25, 2014 1:20 AM
  • Hello,

    I would recommend that you take a look at creating your own media stream source. This will allow you to control the flow of data to the underlying MF topology. Creating a stream source is fairly easy. See the sample code linked below.

    MediaStreamSource

    http://msdn.microsoft.com/en-us/library/windows/apps/windows.media.core.mediastreamsource.aspx

    MediaStreamSource

    http://code.msdn.microsoft.com/windowsapps/MediaStreamSource-media-dfd55dff

    I hope this helps,

    James


    Windows SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Tuesday, September 30, 2014 12:01 AM
    Moderator