wineqtdecoder: Add processing for audio in the movie.
This commit is contained in:
parent
2c9875e4c1
commit
f1da93da80
@ -151,12 +151,16 @@ typedef struct QTSplitter {
|
|||||||
|
|
||||||
QTInPin pInputPin;
|
QTInPin pInputPin;
|
||||||
QTOutPin *pVideo_Pin;
|
QTOutPin *pVideo_Pin;
|
||||||
|
QTOutPin *pAudio_Pin;
|
||||||
|
|
||||||
ALLOCATOR_PROPERTIES props;
|
ALLOCATOR_PROPERTIES props;
|
||||||
|
|
||||||
Movie pQTMovie;
|
Movie pQTMovie;
|
||||||
QTVisualContextRef vContext;
|
QTVisualContextRef vContext;
|
||||||
|
|
||||||
|
MovieAudioExtractionRef aSession;
|
||||||
|
HANDLE runEvent;
|
||||||
|
|
||||||
DWORD outputSize;
|
DWORD outputSize;
|
||||||
FILTER_STATE state;
|
FILTER_STATE state;
|
||||||
} QTSplitter;
|
} QTSplitter;
|
||||||
@ -165,7 +169,7 @@ static const IPinVtbl QT_OutputPin_Vtbl;
|
|||||||
static const IPinVtbl QT_InputPin_Vtbl;
|
static const IPinVtbl QT_InputPin_Vtbl;
|
||||||
static const IBaseFilterVtbl QT_Vtbl;
|
static const IBaseFilterVtbl QT_Vtbl;
|
||||||
|
|
||||||
static HRESULT QT_AddPin(QTSplitter *This, const PIN_INFO *piOutput, const AM_MEDIA_TYPE *amt);
|
static HRESULT QT_AddPin(QTSplitter *This, const PIN_INFO *piOutput, const AM_MEDIA_TYPE *amt, BOOL video);
|
||||||
static HRESULT QT_RemoveOutputPins(QTSplitter *This);
|
static HRESULT QT_RemoveOutputPins(QTSplitter *This);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -188,8 +192,10 @@ static IPin* WINAPI QT_GetPin(BaseFilter *iface, int pos)
|
|||||||
if (This->pVideo_Pin)
|
if (This->pVideo_Pin)
|
||||||
IPin_AddRef((IPin*)This->pVideo_Pin);
|
IPin_AddRef((IPin*)This->pVideo_Pin);
|
||||||
return (IPin*)This->pVideo_Pin;
|
return (IPin*)This->pVideo_Pin;
|
||||||
case 2: /* TODO: Audio */
|
case 2:
|
||||||
return NULL;
|
if (This->pAudio_Pin)
|
||||||
|
IPin_AddRef((IPin*)This->pAudio_Pin);
|
||||||
|
return (IPin*)This->pAudio_Pin;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -199,6 +205,7 @@ static LONG WINAPI QT_GetPinCount(BaseFilter *iface)
|
|||||||
{
|
{
|
||||||
QTSplitter *This = (QTSplitter *)iface;
|
QTSplitter *This = (QTSplitter *)iface;
|
||||||
int c = 1;
|
int c = 1;
|
||||||
|
if (This->pAudio_Pin) c++;
|
||||||
if (This->pVideo_Pin) c++;
|
if (This->pVideo_Pin) c++;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -230,7 +237,10 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *punkout, HRESULT *phr)
|
|||||||
BaseFilter_Init(&This->filter, &QT_Vtbl, &CLSID_QTSplitter, (DWORD_PTR)(__FILE__ ": QTSplitter.csFilter"), &BaseFuncTable);
|
BaseFilter_Init(&This->filter, &QT_Vtbl, &CLSID_QTSplitter, (DWORD_PTR)(__FILE__ ": QTSplitter.csFilter"), &BaseFuncTable);
|
||||||
|
|
||||||
This->pVideo_Pin = NULL;
|
This->pVideo_Pin = NULL;
|
||||||
|
This->pAudio_Pin = NULL;
|
||||||
This->state = State_Stopped;
|
This->state = State_Stopped;
|
||||||
|
This->aSession = NULL;
|
||||||
|
This->runEvent = CreateEventW(NULL, 0, 0, NULL);
|
||||||
|
|
||||||
piInput = &This->pInputPin.pin.pinInfo;
|
piInput = &This->pInputPin.pin.pinInfo;
|
||||||
piInput->dir = PINDIR_INPUT;
|
piInput->dir = PINDIR_INPUT;
|
||||||
@ -273,6 +283,9 @@ static void QT_Destroy(QTSplitter *This)
|
|||||||
DisposeMovie(This->pQTMovie);
|
DisposeMovie(This->pQTMovie);
|
||||||
if (This->vContext)
|
if (This->vContext)
|
||||||
QTVisualContextRelease(This->vContext);
|
QTVisualContextRelease(This->vContext);
|
||||||
|
if (This->aSession)
|
||||||
|
MovieAudioExtractionEnd(This->aSession);
|
||||||
|
CloseHandle(This->runEvent);
|
||||||
|
|
||||||
ExitMovies();
|
ExitMovies();
|
||||||
CoTaskMemFree(This);
|
CoTaskMemFree(This);
|
||||||
@ -339,7 +352,89 @@ static HRESULT WINAPI QT_Pause(IBaseFilter *iface)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD WINAPI QTSplitter_thread_reader(LPVOID data)
|
static OSErr QT_Create_Extract_Session(QTSplitter *filter)
|
||||||
|
{
|
||||||
|
AudioStreamBasicDescription aDesc;
|
||||||
|
OSErr err;
|
||||||
|
|
||||||
|
err = MovieAudioExtractionBegin(filter->pQTMovie, 0, &filter->aSession);
|
||||||
|
if (err != noErr)
|
||||||
|
{
|
||||||
|
ERR("Failed to begin Extraction session %i\n",err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = MovieAudioExtractionGetProperty(filter->aSession,
|
||||||
|
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||||
|
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
|
||||||
|
sizeof(AudioStreamBasicDescription), &aDesc, NULL);
|
||||||
|
|
||||||
|
if (err != noErr)
|
||||||
|
{
|
||||||
|
MovieAudioExtractionEnd(filter->aSession);
|
||||||
|
filter->aSession = NULL;
|
||||||
|
ERR("Failed to get session description %i\n",err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
aDesc.mFormatID = kAudioFormatLinearPCM;
|
||||||
|
aDesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger +
|
||||||
|
kAudioFormatFlagIsPacked;
|
||||||
|
aDesc.mFramesPerPacket = 1;
|
||||||
|
aDesc.mChannelsPerFrame = 2;
|
||||||
|
aDesc.mBitsPerChannel = 16;
|
||||||
|
aDesc.mBytesPerFrame = (aDesc.mBitsPerChannel * aDesc.mChannelsPerFrame) / 8;
|
||||||
|
aDesc.mBytesPerPacket = aDesc.mBytesPerFrame * aDesc.mFramesPerPacket;
|
||||||
|
aDesc.mSampleRate = 48000;
|
||||||
|
|
||||||
|
err = MovieAudioExtractionSetProperty(filter->aSession,
|
||||||
|
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||||
|
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
|
||||||
|
sizeof(AudioStreamBasicDescription), &aDesc);
|
||||||
|
|
||||||
|
if (aDesc.mFormatID != kAudioFormatLinearPCM)
|
||||||
|
{
|
||||||
|
ERR("Not PCM Wave\n");
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
if (aDesc.mFormatFlags != kLinearPCMFormatFlagIsSignedInteger +
|
||||||
|
kAudioFormatFlagIsPacked)
|
||||||
|
{
|
||||||
|
ERR("Unhandled Flags\n");
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
if (aDesc.mFramesPerPacket != 1)
|
||||||
|
{
|
||||||
|
ERR("Unhandled Frames per packet %li\n",aDesc.mFramesPerPacket);
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
if (aDesc.mChannelsPerFrame != 2)
|
||||||
|
{
|
||||||
|
ERR("Unhandled channel count %li\n",aDesc.mChannelsPerFrame);
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
if (aDesc.mBitsPerChannel != 16)
|
||||||
|
{
|
||||||
|
ERR("Unhandled bits per channel %li\n",aDesc.mBitsPerChannel);
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
if (aDesc.mSampleRate != 48000)
|
||||||
|
{
|
||||||
|
ERR("Unhandled sample rate %f\n",aDesc.mSampleRate);
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != noErr)
|
||||||
|
{
|
||||||
|
ERR("Failed to create Extraction Session\n");
|
||||||
|
MovieAudioExtractionEnd(filter->aSession);
|
||||||
|
filter->aSession = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI QTSplitter_thread(LPVOID data)
|
||||||
{
|
{
|
||||||
QTSplitter *This = (QTSplitter *)data;
|
QTSplitter *This = (QTSplitter *)data;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
@ -348,9 +443,21 @@ static DWORD WINAPI QTSplitter_thread_reader(LPVOID data)
|
|||||||
OSStatus err;
|
OSStatus err;
|
||||||
TimeRecord tr;
|
TimeRecord tr;
|
||||||
|
|
||||||
|
if (This->pAudio_Pin)
|
||||||
|
{
|
||||||
|
/* according to QA1469 a movie has to be fully loaded before we
|
||||||
|
can reliably start the Extraction session */
|
||||||
|
|
||||||
|
while(GetMovieLoadState(This->pQTMovie) < kMovieLoadStateComplete)
|
||||||
|
MoviesTask(This->pQTMovie,1000);
|
||||||
|
|
||||||
|
QT_Create_Extract_Session(This);
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSingleObject(This->runEvent, -1);
|
||||||
|
|
||||||
This->state = State_Running;
|
This->state = State_Running;
|
||||||
GetMovieTime(This->pQTMovie, &tr);
|
GetMovieTime(This->pQTMovie, &tr);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
LONGLONG tStart=0, tStop=0;
|
LONGLONG tStart=0, tStop=0;
|
||||||
@ -379,8 +486,90 @@ static DWORD WINAPI QTSplitter_thread_reader(LPVOID data)
|
|||||||
time = (float)next_time / tr.scale;
|
time = (float)next_time / tr.scale;
|
||||||
tStop = time * 10000000;
|
tStop = time * 10000000;
|
||||||
|
|
||||||
|
/* Deliver Audio */
|
||||||
|
if (This->pAudio_Pin && ((BaseOutputPin*)This->pAudio_Pin)->pin.pConnectedTo && This->aSession)
|
||||||
|
{
|
||||||
|
int data_size=0;
|
||||||
|
BYTE* ptr;
|
||||||
|
IMediaSample *sample = NULL;
|
||||||
|
AudioBufferList aData;
|
||||||
|
UInt32 flags;
|
||||||
|
UInt32 frames;
|
||||||
|
WAVEFORMATEX* pvi;
|
||||||
|
float duration;
|
||||||
|
static int audio_frame_size = 0;
|
||||||
|
|
||||||
|
pvi = (WAVEFORMATEX*)This->pAudio_Pin->pmt->pbFormat;
|
||||||
|
|
||||||
|
if (audio_frame_size == 0)
|
||||||
|
audio_frame_size = (pvi->wBitsPerSample * pvi->nChannels) / 8;
|
||||||
|
|
||||||
|
tr.value = SInt64ToWide(movie_time);
|
||||||
|
|
||||||
|
err = MovieAudioExtractionSetProperty(This->aSession,
|
||||||
|
kQTPropertyClass_MovieAudioExtraction_Movie,
|
||||||
|
kQTMovieAudioExtractionMoviePropertyID_CurrentTime,
|
||||||
|
sizeof(TimeRecord), &tr);
|
||||||
|
|
||||||
|
if (err != noErr)
|
||||||
|
{
|
||||||
|
ERR("Failed to set audio media time\n");
|
||||||
|
goto audio_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->pAudio_Pin, &sample, NULL, NULL, 0);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
ERR("Audio: Unable to get delivery buffer (%x)\n", hr);
|
||||||
|
goto audio_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = IMediaSample_GetPointer(sample, &ptr);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
ERR("Audio: Unable to get pointer to buffer (%x)\n", hr);
|
||||||
|
goto audio_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
duration = (float)next_time / tr.scale;
|
||||||
|
time = (float)movie_time / tr.scale;
|
||||||
|
duration -= time;
|
||||||
|
frames = pvi->nSamplesPerSec * duration;
|
||||||
|
TRACE("Need audio for %f seconds (%li frames)\n",duration,frames);
|
||||||
|
|
||||||
|
data_size = IMediaSample_GetSize(sample);
|
||||||
|
if (data_size < frames * audio_frame_size )
|
||||||
|
FIXME("Audio buffer is too small\n");
|
||||||
|
|
||||||
|
aData.mNumberBuffers = 1;
|
||||||
|
aData.mBuffers[0].mNumberChannels = pvi->nChannels;
|
||||||
|
aData.mBuffers[0].mDataByteSize = data_size;
|
||||||
|
aData.mBuffers[0].mData = ptr;
|
||||||
|
|
||||||
|
err = MovieAudioExtractionFillBuffer(This->aSession, &frames, &aData, &flags);
|
||||||
|
TRACE("Got %i frames\n",(int)frames);
|
||||||
|
|
||||||
|
IMediaSample_SetActualDataLength(sample, frames * audio_frame_size);
|
||||||
|
|
||||||
|
IMediaSample_SetMediaTime(sample, &tStart, &tStop);
|
||||||
|
if (tStart)
|
||||||
|
IMediaSample_SetTime(sample, &tStart, &tStop);
|
||||||
|
else
|
||||||
|
IMediaSample_SetTime(sample, NULL, NULL);
|
||||||
|
|
||||||
|
hr = OutputQueue_Receive(This->pAudio_Pin->queue, sample);
|
||||||
|
TRACE("Audio Delivered (%x)\n",hr);
|
||||||
|
|
||||||
|
audio_error:
|
||||||
|
if (sample)
|
||||||
|
IMediaSample_Release(sample);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TRACE("Audio Pin not connected or no Audio\n");
|
||||||
|
|
||||||
/* Deliver Video */
|
/* Deliver Video */
|
||||||
if (QTVisualContextIsNewImageAvailable(This->vContext,0))
|
if (This->pVideo_Pin && QTVisualContextIsNewImageAvailable(This->vContext,0))
|
||||||
{
|
{
|
||||||
err = QTVisualContextCopyImageForTime(This->vContext, NULL, NULL, &pixelBuffer);
|
err = QTVisualContextCopyImageForTime(This->vContext, NULL, NULL, &pixelBuffer);
|
||||||
if (err == noErr)
|
if (err == noErr)
|
||||||
@ -437,12 +626,17 @@ static DWORD WINAPI QTSplitter_thread_reader(LPVOID data)
|
|||||||
CVPixelBufferRelease(pixelBuffer);
|
CVPixelBufferRelease(pixelBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
TRACE("No video to deliver\n");
|
||||||
|
|
||||||
movie_time = next_time;
|
movie_time = next_time;
|
||||||
} while (hr == S_OK);
|
} while (hr == S_OK);
|
||||||
|
|
||||||
This->state = State_Stopped;
|
This->state = State_Stopped;
|
||||||
OutputQueue_EOS(This->pVideo_Pin->queue);
|
if (This->pAudio_Pin)
|
||||||
|
OutputQueue_EOS(This->pAudio_Pin->queue);
|
||||||
|
if (This->pVideo_Pin)
|
||||||
|
OutputQueue_EOS(This->pVideo_Pin->queue);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -452,7 +646,6 @@ static HRESULT WINAPI QT_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
|
|||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
QTSplitter *This = (QTSplitter *)iface;
|
QTSplitter *This = (QTSplitter *)iface;
|
||||||
HRESULT hr_any = VFW_E_NOT_CONNECTED;
|
HRESULT hr_any = VFW_E_NOT_CONNECTED;
|
||||||
DWORD tid;
|
|
||||||
|
|
||||||
TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
|
TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
|
||||||
|
|
||||||
@ -463,12 +656,15 @@ static HRESULT WINAPI QT_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
|
|||||||
hr = BaseOutputPinImpl_Active((BaseOutputPin *)This->pVideo_Pin);
|
hr = BaseOutputPinImpl_Active((BaseOutputPin *)This->pVideo_Pin);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
hr_any = hr;
|
hr_any = hr;
|
||||||
|
if (This->pAudio_Pin)
|
||||||
|
hr = BaseOutputPinImpl_Active((BaseOutputPin *)This->pAudio_Pin);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr_any = hr;
|
||||||
|
|
||||||
hr = hr_any;
|
hr = hr_any;
|
||||||
LeaveCriticalSection(&This->filter.csFilter);
|
LeaveCriticalSection(&This->filter.csFilter);
|
||||||
|
|
||||||
CreateThread(NULL, 0, QTSplitter_thread_reader, This, 0, &tid);
|
SetEvent(This->runEvent);
|
||||||
TRACE("Created thread 0x%08x\n",tid);
|
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -522,6 +718,13 @@ static HRESULT QT_RemoveOutputPins(QTSplitter *This)
|
|||||||
IPin_Release((IPin*)This->pVideo_Pin);
|
IPin_Release((IPin*)This->pVideo_Pin);
|
||||||
This->pVideo_Pin = NULL;
|
This->pVideo_Pin = NULL;
|
||||||
}
|
}
|
||||||
|
if (This->pAudio_Pin)
|
||||||
|
{
|
||||||
|
hr = BaseOutputPinImpl_BreakConnect(&This->pAudio_Pin->pin);
|
||||||
|
TRACE("Disconnect: %08x\n", hr);
|
||||||
|
IPin_Release((IPin*)This->pAudio_Pin);
|
||||||
|
This->pAudio_Pin = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
BaseFilterImpl_IncrementPinVersion((BaseFilter*)This);
|
BaseFilterImpl_IncrementPinVersion((BaseFilter*)This);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@ -631,7 +834,7 @@ static HRESULT QT_Process_Video_Track(QTSplitter* filter, Track trk)
|
|||||||
piOutput.pFilter = (IBaseFilter *)filter;
|
piOutput.pFilter = (IBaseFilter *)filter;
|
||||||
lstrcpyW(piOutput.achName,szwVideoOut);
|
lstrcpyW(piOutput.achName,szwVideoOut);
|
||||||
|
|
||||||
hr = QT_AddPin(filter, &piOutput, &amt);
|
hr = QT_AddPin(filter, &piOutput, &amt, TRUE);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
ERR("Failed to add Video Track\n");
|
ERR("Failed to add Video Track\n");
|
||||||
else
|
else
|
||||||
@ -640,6 +843,45 @@ static HRESULT QT_Process_Video_Track(QTSplitter* filter, Track trk)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT QT_Process_Audio_Track(QTSplitter* filter, Track trk)
|
||||||
|
{
|
||||||
|
AM_MEDIA_TYPE amt;
|
||||||
|
WAVEFORMATEX* pvi;
|
||||||
|
PIN_INFO piOutput;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
static const WCHAR szwAudioOut[] = {'A','u','d','i','o',0};
|
||||||
|
|
||||||
|
ZeroMemory(&amt, sizeof(amt));
|
||||||
|
amt.formattype = FORMAT_WaveFormatEx;
|
||||||
|
amt.majortype = MEDIATYPE_Audio;
|
||||||
|
amt.subtype = MEDIASUBTYPE_PCM;
|
||||||
|
amt.bTemporalCompression = 0;
|
||||||
|
|
||||||
|
amt.cbFormat = sizeof(WAVEFORMATEX);
|
||||||
|
amt.pbFormat = CoTaskMemAlloc(amt.cbFormat);
|
||||||
|
ZeroMemory(amt.pbFormat, amt.cbFormat);
|
||||||
|
pvi = (WAVEFORMATEX*)amt.pbFormat;
|
||||||
|
|
||||||
|
pvi->cbSize = sizeof(WAVEFORMATEX);
|
||||||
|
pvi->wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
pvi->nChannels = 2;
|
||||||
|
pvi->nSamplesPerSec = 48000;
|
||||||
|
pvi->wBitsPerSample = 16;
|
||||||
|
pvi->nBlockAlign = (pvi->nChannels * pvi->wBitsPerSample) / 8;
|
||||||
|
pvi->nAvgBytesPerSec = pvi->nSamplesPerSec * pvi->nBlockAlign;
|
||||||
|
|
||||||
|
piOutput.dir = PINDIR_OUTPUT;
|
||||||
|
piOutput.pFilter = (IBaseFilter *)filter;
|
||||||
|
lstrcpyW(piOutput.achName,szwAudioOut);
|
||||||
|
|
||||||
|
hr = QT_AddPin(filter, &piOutput, &amt, FALSE);
|
||||||
|
if (FAILED(hr))
|
||||||
|
ERR("Failed to add Audio Track\n");
|
||||||
|
else
|
||||||
|
TRACE("Audio Pin %p\n",filter->pAudio_Pin);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT QT_Process_Movie(QTSplitter* filter)
|
static HRESULT QT_Process_Movie(QTSplitter* filter)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
@ -648,6 +890,7 @@ static HRESULT QT_Process_Movie(QTSplitter* filter)
|
|||||||
Handle dataRef = NULL;
|
Handle dataRef = NULL;
|
||||||
Track trk;
|
Track trk;
|
||||||
short id = 0;
|
short id = 0;
|
||||||
|
DWORD tid;
|
||||||
|
|
||||||
TRACE("Trying movie connect\n");
|
TRACE("Trying movie connect\n");
|
||||||
|
|
||||||
@ -655,7 +898,9 @@ static HRESULT QT_Process_Movie(QTSplitter* filter)
|
|||||||
ptrDataRefRec.streamSubtype = filter->pInputPin.subType;
|
ptrDataRefRec.streamSubtype = filter->pInputPin.subType;
|
||||||
PtrToHand( &ptrDataRefRec, &dataRef, sizeof(WineDataRefRecord));
|
PtrToHand( &ptrDataRefRec, &dataRef, sizeof(WineDataRefRecord));
|
||||||
|
|
||||||
err = NewMovieFromDataRef(&filter->pQTMovie, newMovieActive|newMovieDontInteractWithUser|newMovieDontAutoUpdateClock|newMovieDontAskUnresolvedDataRefs|newMovieIdleImportOK, &id, dataRef, 'WINE');
|
err = NewMovieFromDataRef(&filter->pQTMovie, newMovieActive|newMovieDontInteractWithUser|newMovieDontAutoUpdateClock|newMovieDontAskUnresolvedDataRefs|newMovieAsyncOK, &id, dataRef, 'WINE');
|
||||||
|
|
||||||
|
DisposeHandle(dataRef);
|
||||||
|
|
||||||
if (err != noErr)
|
if (err != noErr)
|
||||||
{
|
{
|
||||||
@ -679,6 +924,14 @@ static HRESULT QT_Process_Movie(QTSplitter* filter)
|
|||||||
if (!SUCCEEDED(hr))
|
if (!SUCCEEDED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
trk = GetMovieIndTrackType(filter->pQTMovie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly);
|
||||||
|
TRACE("%p is a audio track\n",trk);
|
||||||
|
if (trk)
|
||||||
|
hr = QT_Process_Audio_Track(filter, trk);
|
||||||
|
|
||||||
|
CreateThread(NULL, 0, QTSplitter_thread, filter, 0, &tid);
|
||||||
|
TRACE("Created thread 0x%08x\n",tid);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1032,16 +1285,19 @@ static const OutputQueueFuncTable output_OutputQueueFuncTable = {
|
|||||||
OutputQueueImpl_ThreadProc
|
OutputQueueImpl_ThreadProc
|
||||||
};
|
};
|
||||||
|
|
||||||
static HRESULT QT_AddPin(QTSplitter *This, const PIN_INFO *piOutput, const AM_MEDIA_TYPE *amt)
|
static HRESULT QT_AddPin(QTSplitter *This, const PIN_INFO *piOutput, const AM_MEDIA_TYPE *amt, BOOL video)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IPin **target;
|
IPin **target;
|
||||||
|
|
||||||
target = (IPin**)&This->pVideo_Pin;
|
if (video)
|
||||||
|
target = (IPin**)&This->pVideo_Pin;
|
||||||
|
else
|
||||||
|
target = (IPin**)&This->pAudio_Pin;
|
||||||
|
|
||||||
if (*target != NULL)
|
if (*target != NULL)
|
||||||
{
|
{
|
||||||
ERR("We we already have a video pin\n");
|
FIXME("We already have a %s pin\n",(video)?"video":"audio");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user