30 namespace WindowsMediaCodec
37 : ComBaseClassHelper <IStream> (0), source (in)
41 JUCE_COMRESULT Commit (DWORD) {
return S_OK; }
42 JUCE_COMRESULT Write (
const void*, ULONG, ULONG*) {
return E_NOTIMPL; }
43 JUCE_COMRESULT Clone (IStream**) {
return E_NOTIMPL; }
44 JUCE_COMRESULT SetSize (ULARGE_INTEGER) {
return E_NOTIMPL; }
45 JUCE_COMRESULT Revert() {
return E_NOTIMPL; }
46 JUCE_COMRESULT LockRegion (ULARGE_INTEGER, ULARGE_INTEGER, DWORD) {
return E_NOTIMPL; }
47 JUCE_COMRESULT UnlockRegion (ULARGE_INTEGER, ULARGE_INTEGER, DWORD) {
return E_NOTIMPL; }
49 JUCE_COMRESULT Read (
void* dest, ULONG numBytes, ULONG* bytesRead)
51 auto numRead = source.
read (dest, numBytes);
53 if (bytesRead !=
nullptr)
56 return (numRead == (
int) numBytes) ? S_OK : S_FALSE;
59 JUCE_COMRESULT Seek (LARGE_INTEGER position, DWORD origin, ULARGE_INTEGER* resultPosition)
61 auto newPos = (int64) position.QuadPart;
63 if (origin == STREAM_SEEK_CUR)
67 else if (origin == STREAM_SEEK_END)
77 if (resultPosition !=
nullptr)
78 resultPosition->QuadPart = newPos;
80 return source.
setPosition (newPos) ? S_OK : E_NOTIMPL;
83 JUCE_COMRESULT CopyTo (IStream* destStream, ULARGE_INTEGER numBytesToDo,
84 ULARGE_INTEGER* bytesRead, ULARGE_INTEGER* bytesWritten)
86 uint64 totalCopied = 0;
87 int64 numBytes = numBytesToDo.QuadPart;
93 auto numToCopy = (int) jmin ((int64)
sizeof (buffer), (int64) numBytes);
94 auto numRead = source.
read (buffer, numToCopy);
99 destStream->Write (buffer, numRead,
nullptr);
100 totalCopied += numRead;
103 if (bytesRead !=
nullptr) bytesRead->QuadPart = totalCopied;
104 if (bytesWritten !=
nullptr) bytesWritten->QuadPart = totalCopied;
109 JUCE_COMRESULT Stat (STATSTG* stat, DWORD)
112 return STG_E_INVALIDPOINTER;
115 stat->type = STGTY_STREAM;
116 stat->cbSize.QuadPart = jmax ((int64) 0, source.
getTotalLength());
123 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (
JuceIStream)
127 static const char* wmFormatName =
"Windows Media";
128 static const char*
const extensions[] = {
".mp3",
".wmv",
".asf",
".wm",
".wma", 0 };
136 wmvCoreLib (
"Wmvcore.dll")
138 JUCE_LOAD_WINAPI_FUNCTION (wmvCoreLib, WMCreateSyncReader, wmCreateSyncReader,
139 HRESULT, (IUnknown*, DWORD, IWMSyncReader**))
141 if (wmCreateSyncReader !=
nullptr)
143 checkCoInitialiseCalled();
145 HRESULT hr = wmCreateSyncReader (
nullptr, WMT_RIGHT_PLAYBACK, wmSyncReader.resetAndGetPointerAddress());
153 hr = wmSyncReader->GetStreamNumberForOutput (0, &streamNum);
154 hr = wmSyncReader->SetReadStreamSamples (streamNum,
false);
156 scanFileForDetails();
163 if (wmSyncReader !=
nullptr)
164 wmSyncReader->Close();
167 bool readSamples (
int** destSamples,
int numDestChannels,
int startOffsetInDestBuffer,
168 int64 startSampleInFile,
int numSamples)
override
173 checkCoInitialiseCalled();
180 while (numSamples > 0)
182 if (! bufferedRange.
contains (startSampleInFile))
184 const bool hasJumped = (startSampleInFile != bufferedRange.
getEnd());
187 wmSyncReader->SetRange ((QWORD) (startSampleInFile * 10000000 / (int64)
sampleRate), 0);
189 ComSmartPtr<INSSBuffer> sampleBuffer;
190 QWORD sampleTime, duration;
191 DWORD flags, outputNum;
194 HRESULT hr = wmSyncReader->GetNextSample (1, sampleBuffer.resetAndGetPointerAddress(),
195 &sampleTime, &duration, &flags, &outputNum, &streamNum);
197 if (sampleBuffer !=
nullptr)
199 BYTE* rawData =
nullptr;
200 DWORD dataLength = 0;
201 hr = sampleBuffer->GetBufferAndLength (&rawData, &dataLength);
211 bufferedRange.
setLength ((int64) (dataLength / stride));
214 memcpy (buffer.
getData(), rawData, (
size_t) dataLength);
216 else if (hr == NS_E_NO_MORE_SAMPLES)
218 bufferedRange.
setStart (startSampleInFile);
229 auto offsetInBuffer = (int) (startSampleInFile - bufferedRange.
getStart());
230 auto* rawData =
static_cast<const int16*
> (addBytesToPointer (buffer.
getData(), offsetInBuffer * stride));
231 auto numToDo = jmin (numSamples, (
int) (bufferedRange.
getLength() - offsetInBuffer));
233 for (
int i = 0; i < numDestChannels; ++i)
235 jassert (destSamples[i] !=
nullptr);
238 const int16* src = rawData + srcChan;
239 int*
const dst = destSamples[i] + startOffsetInDestBuffer;
241 for (
int j = 0; j < numToDo; ++j)
243 dst[j] = ((uint32) *src) << 16;
248 startSampleInFile += numToDo;
249 startOffsetInDestBuffer += numToDo;
250 numSamples -= numToDo;
258 ComSmartPtr<IWMSyncReader> wmSyncReader;
262 void checkCoInitialiseCalled()
267 void scanFileForDetails()
269 ComSmartPtr<IWMHeaderInfo> wmHeaderInfo;
270 HRESULT hr = wmSyncReader.QueryInterface (wmHeaderInfo);
274 QWORD lengthInNanoseconds = 0;
275 WORD lengthOfLength =
sizeof (lengthInNanoseconds);
277 WMT_ATTR_DATATYPE wmAttrDataType;
278 hr = wmHeaderInfo->GetAttributeByName (&streamNum, L
"Duration", &wmAttrDataType,
279 (BYTE*) &lengthInNanoseconds, &lengthOfLength);
281 ComSmartPtr<IWMProfile> wmProfile;
282 hr = wmSyncReader.QueryInterface (wmProfile);
286 ComSmartPtr<IWMStreamConfig> wmStreamConfig;
287 hr = wmProfile->GetStream (0, wmStreamConfig.resetAndGetPointerAddress());
291 ComSmartPtr<IWMMediaProps> wmMediaProperties;
292 hr = wmStreamConfig.QueryInterface (wmMediaProperties);
297 hr = wmMediaProperties->GetMediaType (0, &sizeMediaType);
300 mediaType.
malloc (sizeMediaType, 1);
301 hr = wmMediaProperties->GetMediaType (mediaType, &sizeMediaType);
303 if (mediaType->majortype == WMMEDIATYPE_Audio)
305 auto* inputFormat =
reinterpret_cast<WAVEFORMATEX*
> (mediaType->pbFormat);
309 bitsPerSample = inputFormat->wBitsPerSample != 0 ? inputFormat->wBitsPerSample : 16;
318 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WMAudioReader)
324 WindowsMediaAudioFormat::WindowsMediaAudioFormat()
325 : AudioFormat (TRANS (WindowsMediaCodec::wmFormatName),
326 StringArray (WindowsMediaCodec::extensions))
330 WindowsMediaAudioFormat::~WindowsMediaAudioFormat() {}
344 if (r->sampleRate > 0)
347 if (! deleteStreamIfOpeningFails)