0
0

Hi All,

1) Is WMA DRM encoded files supported(seems to me they are not)? if not are there any plans to add it and when?

2) I saw a post in the old fmod api forum that said fmod ex will support braodcast, Is it supported in the current version? if not are there any plans to add it and when?

the post URL is:

http://52.88.2.202/forum/viewtopic.php … =broadcast

10x

  • You must to post comments
0
0

Brett,

Correct me if I am wrong, I saw that I can code a File format plugin, so maybe I can write one for DRM WMA (or even for all WMA files) files, am I correct?

if I am correct what example do I need to look at?

10x

  • You must to post comments
0
0

Hi Brett,

I already have the special license protedted library for DRM from Microsoft. To use this library I have to use the Media File Format SDK which is also from Microsoft.

After I use Media File Format SDK to successfully login to the DRM protected file, can I simply use createStream API to let FMOD to stream it?
If not how can I implement this with the codec plugin? It will be very helpful if you can provide me any information or some pseudocode.

My for this process pseudocode is like that:

class AudioPlay : public IWMReaderCallback
{
// unrelated code

BOOL play(char* uri);
IWMReader *m_pReader; // reader object
BYTE *buffer; // it will be large enought
BYTE *pBufferWrite; // this is the current position for wirte
BYTE *pBufferRead; // this is the current position for read

//
// Methods of IWMReaderCallback
//
HRESULT STDMETHODCALLTYPE OnStatus(
/* [in] / WMT_STATUS Status,
/
[in] / HRESULT hr,
/
[in] / WMT_ATTR_DATATYPE dwType,
/
[in] */ BYTE __RPC_FAR *pValue,
/* [in] */ void __RPC_FAR *pvContext );

HRESULT STDMETHODCALLTYPE OnSample(
/* [in] / DWORD dwOutputNum,
/
[in] / QWORD cnsSampleTime,
/
[in] / QWORD cnsSampleDuration,
/
[in] / DWORD dwFlags,
/
[in] */ INSSBuffer __RPC_FAR *pSample,
/* [in] */ void __RPC_FAR *pvContext );
};

BOOL AudioPlay::play(char* uri)
{
// assume m_pReader is already created
_bstr_t wuri;
wuri = uri; // change to wide string
m_pReader->Open(wuri, this, NULL );
}

// this call back will do the job with DRM login
HRESULT AudioPlay::OnStatus(
/* [in] / WMT_STATUS Status,
/
[in] / HRESULT hr,
/
[in] / WMT_ATTR_DATATYPE dwType,
/
[in] */ BYTE __RPC_FAR *pValue,
/* [in] */ void __RPC_FAR *pvContext )
{
// unrelated code

case WMT_NO_RIGHTS:
case WMT_NO_RIGHTS_EX:
case WMT_NEEDS_INDIVIDUALIZATION:
case WMT_LICENSEURL_SIGNATURE_STATE:
case WMT_ACQUIRE_LICENSE:
case WMT_INDIVIDUALIZE:
// login in for DRM protected file
// assume the process successfully

// at this point can I call API here
CreateStream(strUri, FMOD_SOFTWARE, 0, &sound);
// or I have to use FMOD_OPENUSER with pcm read call back
createsoundexinfo.pcmreadcallback = pcmreadcallback;
CreateStram(0, FMOD_SOFTWARE | FMOD_OPENUSER, &createsoundexinfo, &sound);
sound->setUserData(this);
break;
}

// this call back will supply audio data with pcm format
// each time the audio data is available from stream
HRESULT AudioPlay::OnSample(
/* [in] / DWORD dwOutputNum,
/
[in] / QWORD cnsSampleTime,
/
[in] / QWORD cnsSampleDuration,
/
[in] / DWORD dwFlags,
/
[in] */ INSSBuffer __RPC_FAR *pSample,
/* [in] */ void __RPC_FAR *pvContext )
{
BYTE *pData = NULL;
DWORD cbData = 0;

// unrelated code

// get audio sample and save into buffer which is bigger enought
// and use the buffer to supply audio data in the pcm read callback
// function
// if create stream with FMOD_OPENUSER
pSample->GetBufferAndLength(&pData, &cbData);
CopyMemory(pBufferWrite, pData, cbData);
pBufferWrite += cbData;
}

FMOD_RESULT F_CALLBACK pcmreadcallback(FMOD_SOUND sound, void *data, unsigned int datalen)
{
AudioPlay
pPlayer;

pPlayer = (AudioPlay*)(sound->getUserData());
assert(pPlayer);
// copy audio data from audio player’s read buffer to *data with datalen
// if there is no enought data then put 0 to silent it.
memset(data, 0, datalen);
memcpy(data, pPlayer->pBufferRead, len);
// len is the actual data length from read buffer
pPlayer->pBufferRead += len;
return FMOD_OK;
}

Thanks

Tom

  • You must to post comments
0
0

fmod’s read function for ASF looks like this (it uses the codec read callback interface, i just wrapped it to use a C++ object so here is the member function it calls).

[code:306mj704]
FMOD_RESULT CodecASF::readInternal(void *buffer, unsigned int sizebytes, unsigned int *bytesread)
{
FMOD_RESULT result = FMOD_OK;
HRESULT hr = S_OK;
INSSBuffer *pSample = NULL;
QWORD cnsDuration = 0;
DWORD dwFlags = 0;
DWORD dwOutputNum = 0;
WORD wStreamNum = 0;
BYTE *pdwBuffer;
DWORD dwLength;

*bytesread = 0;

hr = mReader->GetNextSample( mAudioStreamNum, &pSample, &mSampleTime, &cnsDuration, &dwFlags, &dwOutputNum, &wStreamNum );
if( FAILED( hr ) )
{
    if( NS_E_NO_MORE_SAMPLES == hr )
    {
        return FMOD_ERR_FILE_EOF;
    }
    else
    {
        return FMOD_ERR_FILE_BAD;
    }
}

pSample->GetBufferAndLength(&pdwBuffer, &dwLength);

memcpy(buffer, pdwBuffer, dwLength);

*bytesread = dwLength;

pSample->Release();

return result;  

}
[/code:306mj704]

  • You must to post comments
0
0

Hi Brett,

Thanks for the example.

My previous post might not so clear. So this time I will try to make it as clear and simple as possible.

  1. My objective is to stream audio file from the Internet site. And the audio file is DRM protected. I assume that Sound::readData() can not decode the raw data from DRM protected audio file. (If this asumption is not correct, for heaven’s sake I am saved! In this case I can simply call createSound or createStream.) ๐Ÿ˜€

  2. I already have the DRM enabled library from Microsoft and the code for playback the DRM protected file is ready. Assume this part of code have no error. (Hopefully, let’s just concentrate on other parts). ๐Ÿ˜€

  3. Because the audio file is on the Internet so I have to use IWMReader interface. IWMSyncReader does not support open file from the Internet. (I’ve test on this and it is true).

  4. Because FMOD library is not able to decode DRM protected audio file so I have to use OnSample() method of IWMReaderCallback interface to get PCM format audio data. And use ‘pcm read callback’ funtion to playback the audio.

  5. I have a internal memory buffer for PCM audio data. The buffer is large enought to hold all the PCM data. And every time OnSample() method called the PCM data are writed into the buffer at correct address.
    At first a pointer ‘pBufferRead’ is set to NULL. After 10 OnSample() method has been called this pointer set to the beginning the internal memory buffer. This is to make sure that when ‘pcm read callback’ funtion called by FMOD there is already enought PCM audio data available.

The following is the high-level pseudocode.

[code:1peoe4bo]

// ... on main thread...
// create sound and playback with pcm read callback function
FMOD_MODE mode = FMOD_SOFTWARE | FMOD_OPENUSER | FMOD_CREATESTREAM | FMOD_OPENONLY;
// assume createsoundexinfo is correct
system.createSound(0, mode, &createsoundexinfo, &sound);
// mBuffer is the internal PCM memory buffer object
sound.setUserData(mBuffer);
system.playSound(...);

// pcm read callback
FMOD_RESULT F_CALLBACK
pcmreadcallback(FMOD_SOUND *sound, void *data, unsigned int datalen)
{
FMOD::Sound *pSound;
MemBuffer *pBuffer;

pSound = (FMOD::Sound*)sound;
pSound->getUserData((void**)(&pBuffer));
if (pBuffer)
{
// getData() will copy the PCM data from memory
// into data with datalen.
// and move the read buffer pointer advance ‘datalen’
pBuffer->getData(data, datalen);
}
return FMOD_OK;
}

// when OnSample() called
HRESULT
MSAudioPlayerWin32::OnSample
(
/* [in] / DWORD dwOutputNum,
/
[in] / QWORD cnsSampleTime,
/
[in] / QWORD cnsSampleDuration,
/
[in] / DWORD dwFlags,
/
[in] */ INSSBuffer __RPC_FAR *pSample,
/* [in] */ void __RPC_FAR *pvContext
)
{
BYTE *pData = NULL;
DWORD cbData = 0;
HRESULT hr = S_OK;

// Get the sample from the buffer object.
hr = pSample->GetBufferAndLength(&pData, &cbData);
if (FAILED(hr))
{
return hr;
}

// pBufferWirte is the write buffer pointer
// pBuffer is the internal PCM memory buffer
if (NULL == pBufferWrite)
{
pBufferWrite = pBuffer;
}

// copy PCM data into internal memory
memcpy(pBufferWrite, pData, cbData);

// pBufferRead is the read buffer pointer.
if (pBufferRead == NULL)
{
// bufferCount is the count for this method called
if (bufferingCount == 10)
{
// if 10 times called then set read buffer
pBufferRead = pBuffer;
}
m_bufferingCount++;
}

// make write buffer to correct address for next time writing
pBufferWrite += cbData;
return S_OK;
}

[/code:1peoe4bo]

The code above have problems. OnSample() called regularlly untill the playback finished. The function pcmreadcallback called regularlly untill the playback finished. However there are lots of silents during the playback.

I find that the PCM data length on OnSample() and pcmreadcallback() is different. On pcmreadcallback it is always 16384 byte and OnSample() it is different around 20k byte.

I wonder is it possible to set the data length in advance at runtime for pcmreadcallback? For example when OnSample() I know the PCM data length is 21330 byte can I set the data length for the next pcmreadcallback is 21330 byte?

Or can you recommend another approch for solve stream the DRM protected audio from Internet?

Or can you give pro and con for using pcmreadcallback and codec plugin and file callback relative to my concern?

  • You must to post comments
0
0

[quote="tomfang2000":kp87onba]The code above have problems. OnSample() called regularlly untill the playback finished. The function pcmreadcallback called regularlly untill the playback finished. However there are lots of silents during the playback.

I find that the PCM data length on OnSample() and pcmreadcallback() is different. On pcmreadcallback it is always 16384 byte and OnSample() it is different around 20k byte.

I wonder is it possible to set the data length in advance at runtime for pcmreadcallback? For example when OnSample() I know the PCM data length is 21330 byte can I set the data length for the next pcmreadcallback is 21330 byte?

Or can you recommend another approch for solve stream the DRM protected audio from Internet?

Or can you give pro and con for using pcmreadcallback and codec plugin and file callback relative to my concern?[/quote:kp87onba]It sounds like you just need to make sure and buffer a large chunk of audio using OnSample() before starting actual playback. I’m pretty sure FMod’s streamer code does the same thing internally.

Since OnSample() seems to be realtime, you may want to see if the API has any sort of non-realtime playback support for DRM’d streams (for the purpose of prebuffering, etc) so that you can build up a nice big chunk of samples before starting the stream without having to spend multiple seconds letting it play back at 1.0x speed.

  • You must to post comments
0
0

Thanks Janus.

Actually the problem seems I allocate too much buffer in FMOD ๐Ÿ˜€

I allocate 1 seconds buffer for pcm 44100, 16 bits. So the pcm read callback try to buffering 1 second pcm data. And in IWMReader instance the output buffer is smaller than 1 second. In this case the FMOD’s pcm read call back starves with sound data. After I use the FMOD’s default buffer size (400 ms) it playback well.

BTW, OnSample() is not exactly realtime, it will be called in one group into the memory to reach the output buffer. And there is no way to set the playback rate other than 1.0 which is normal playback rate if the source audio file is on the Internet.

Thanks again for your help.

  • You must to post comments
Showing 6 results
Your Answer

Please first to submit.