Module: wine Branch: master Commit: 5e4cb217d61f7460a4dcc353d3f8030414ac8d04 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5e4cb217d61f7460a4dcc353d3...
Author: Aric Stewart aric@codeweavers.com Date: Tue May 22 11:17:09 2012 -0500
wineqtdecoder: Recreate audio extraction session when we run out of frames.
---
dlls/wineqtdecoder/qtsplitter.c | 77 +++++++++++++++++++++++++++++++++------ 1 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c index b21f198..9b94d7a 100644 --- a/dlls/wineqtdecoder/qtsplitter.c +++ b/dlls/wineqtdecoder/qtsplitter.c @@ -479,25 +479,43 @@ kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, return err; }
-static DWORD WINAPI QTSplitter_thread(LPVOID data) +static DWORD WINAPI QTSplitter_loading_thread(LPVOID data) { QTSplitter *This = (QTSplitter *)data; - HRESULT hr = S_OK; - TimeValue next_time; - CVPixelBufferRef pixelBuffer = NULL; - OSStatus err; - TimeRecord tr;
if (This->pAudio_Pin) { /* according to QA1469 a movie has to be fully loaded before we - can reliably start the Extraction session */ + can reliably start the Extraction session.
- while(GetMovieLoadState(This->pQTMovie) < kMovieLoadStateComplete) - MoviesTask(This->pQTMovie,1000); + If loaded earlier then we only get an extraction session for + the part of the movie that is loaded at that time.
- QT_Create_Extract_Session(This); + We are trying to load as much of the movie as we can before we + start extracting. However we can recreate the extraction session + again when we run out of loaded extraction frames. But we want + to try to minimize that. + */ + + while(GetMovieLoadState(This->pQTMovie) < kMovieLoadStateComplete) + { + EnterCriticalSection(&This->csReceive); + MoviesTask(This->pQTMovie, 100); + LeaveCriticalSection(&This->csReceive); + Sleep(0); + } } + return 0; +} + +static DWORD WINAPI QTSplitter_thread(LPVOID data) +{ + QTSplitter *This = (QTSplitter *)data; + HRESULT hr = S_OK; + TimeValue next_time; + CVPixelBufferRef pixelBuffer = NULL; + OSStatus err; + TimeRecord tr;
WaitForSingleObject(This->runEvent, -1);
@@ -507,7 +525,12 @@ static DWORD WINAPI QTSplitter_thread(LPVOID data) GetMovieNextInterestingTime(This->pQTMovie, nextTimeEdgeOK | nextTimeStep, 0, NULL, This->movie_time, 1, &next_time, NULL);
GetMovieTime(This->pQTMovie, &tr); + + if (This->pAudio_Pin) + QT_Create_Extract_Session(This); + LeaveCriticalSection(&This->csReceive); + do { LONGLONG tStart=0, tStop=0; @@ -585,6 +608,32 @@ static DWORD WINAPI QTSplitter_thread(LPVOID data) aData.mBuffers[0].mData = ptr;
err = MovieAudioExtractionFillBuffer(This->aSession, &frames, &aData, &flags); + if (frames == 0) + { + TimeRecord etr; + + /* Ran out of frames, Restart the extraction session */ + TRACE("Restarting extraction session\n"); + MovieAudioExtractionEnd(This->aSession); + This->aSession = NULL; + QT_Create_Extract_Session(This); + + etr = tr; + etr.value = SInt64ToWide(This->movie_time); + MovieAudioExtractionSetProperty(This->aSession, + kQTPropertyClass_MovieAudioExtraction_Movie, + kQTMovieAudioExtractionMoviePropertyID_CurrentTime, + sizeof(TimeRecord), &etr ); + + frames = pvi->nSamplesPerSec * duration; + aData.mNumberBuffers = 1; + aData.mBuffers[0].mNumberChannels = pvi->nChannels; + aData.mBuffers[0].mDataByteSize = data_size; + aData.mBuffers[0].mData = ptr; + + MovieAudioExtractionFillBuffer(This->aSession, &frames, &aData, &flags); + } + TRACE("Got %i frames\n",(int)frames);
IMediaSample_SetActualDataLength(sample, frames * pvi->nBlockAlign); @@ -992,10 +1041,16 @@ static HRESULT QT_Process_Movie(QTSplitter* filter)
TRACE("Movie duration is %s\n",wine_dbgstr_longlong(filter->sourceSeeking.llDuration));
+ thread = CreateThread(NULL, 0, QTSplitter_loading_thread, filter, 0, &tid); + if (thread) + { + TRACE("Created loading thread 0x%08x\n", tid); + CloseHandle(thread); + } thread = CreateThread(NULL, 0, QTSplitter_thread, filter, 0, &tid); if (thread) { - TRACE("Created thread 0x%08x\n", tid); + TRACE("Created processing thread 0x%08x\n", tid); CloseHandle(thread); } else