From dddc278b4d4a8054ad41f4c056b21e044e95770b Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Wed, 26 Feb 2014 13:36:45 +0100 Subject: [PATCH] qcap: Add Avi Mux IBaseFilter::Stop implementation. --- dlls/qcap/avimux.c | 139 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 2 deletions(-) diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c index 8ec15ba777c..a1c4f859068 100644 --- a/dlls/qcap/avimux.c +++ b/dlls/qcap/avimux.c @@ -444,8 +444,143 @@ static HRESULT queue_sample(AviMux *avimux, AviMuxIn *avimuxin, IMediaSample *sa static HRESULT WINAPI AviMux_Stop(IBaseFilter *iface) { AviMux *This = impl_from_IBaseFilter(iface); - FIXME("(%p)\n", This); - return E_NOTIMPL; + HRESULT hr; + int i; + + TRACE("(%p)\n", This); + + if(This->filter.state == State_Stopped) + return S_OK; + + if(This->out->stream) { + AVIEXTHEADER dmlh; + RIFFCHUNK rc; + RIFFLIST rl; + int idx1_off, empty_stream; + + empty_stream = This->out->cur_stream; + for(i=empty_stream+1; ; i++) { + if(i >= This->input_pin_no-1) + i = 0; + if(i == empty_stream) + break; + + This->out->cur_stream = i; + hr = flush_queue(This, This->in[This->out->cur_stream], TRUE); + if(FAILED(hr)) + return hr; + } + + idx1_off = This->out->size; + rc.fcc = ckidAVIOLDINDEX; + rc.cb = This->idx1_entries * sizeof(*This->idx1); + hr = out_write(This, &rc, sizeof(rc)); + if(FAILED(hr)) + return hr; + hr = out_write(This, This->idx1, This->idx1_entries * sizeof(*This->idx1)); + if(FAILED(hr)) + return hr; + /* native writes 8 '\0' characters after the end of RIFF data */ + i = 0; + hr = out_write(This, &i, sizeof(i)); + if(FAILED(hr)) + return hr; + hr = out_write(This, &i, sizeof(i)); + if(FAILED(hr)) + return hr; + + for(i=0; iinput_pin_no; i++) { + if(!This->in[i]->pin.pin.pConnectedTo) + continue; + + hr = out_seek(This, This->in[i]->ix_off); + if(FAILED(hr)) + return hr; + + This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].qwOffset = This->in[i]->ix_off; + This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].dwSize = sizeof(This->in[i]->ix_data); + This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].dwDuration = This->in[i]->strh.dwLength; + if(This->in[i]->indx->nEntriesInUse) { + This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].dwDuration -= + This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse-1].dwDuration; + } + This->in[i]->indx->nEntriesInUse++; + hr = out_write(This, This->in[i]->ix, sizeof(This->in[i]->ix_data)); + if(FAILED(hr)) + return hr; + } + + hr = out_seek(This, 0); + if(FAILED(hr)) + return hr; + + rl.fcc = FCC('R','I','F','F'); + rl.cb = This->out->size-sizeof(RIFFCHUNK)-2*sizeof(int); + rl.fccListType = FCC('A','V','I',' '); + hr = out_write(This, &rl, sizeof(rl)); + if(FAILED(hr)) + return hr; + + rl.fcc = FCC('L','I','S','T'); + rl.cb = This->out->movi_off - sizeof(RIFFLIST) - sizeof(RIFFCHUNK); + rl.fccListType = FCC('h','d','r','l'); + hr = out_write(This, &rl, sizeof(rl)); + if(FAILED(hr)) + return hr; + + /* FIXME: set This->avih.dwMaxBytesPerSec value */ + This->avih.dwTotalFrames = (This->stop-This->start) / 10 / This->avih.dwMicroSecPerFrame; + hr = out_write(This, &This->avih, sizeof(This->avih)); + if(FAILED(hr)) + return hr; + + for(i=0; iinput_pin_no; i++) { + if(!This->in[i]->pin.pin.pConnectedTo) + continue; + + rl.cb = sizeof(FOURCC) + sizeof(AVISTREAMHEADER) + sizeof(RIFFCHUNK) + + This->in[i]->strf->cb + sizeof(This->in[i]->indx_data); + rl.fccListType = ckidSTREAMLIST; + hr = out_write(This, &rl, sizeof(rl)); + if(FAILED(hr)) + return hr; + + hr = out_write(This, &This->in[i]->strh, sizeof(AVISTREAMHEADER)); + if(FAILED(hr)) + return hr; + + hr = out_write(This, This->in[i]->strf, sizeof(RIFFCHUNK) + This->in[i]->strf->cb); + if(FAILED(hr)) + return hr; + + hr = out_write(This, This->in[i]->indx, sizeof(This->in[i]->indx_data)); + if(FAILED(hr)) + return hr; + } + + rl.cb = sizeof(dmlh) + sizeof(FOURCC); + rl.fccListType = ckidODML; + hr = out_write(This, &rl, sizeof(rl)); + if(FAILED(hr)) + return hr; + + memset(&dmlh, 0, sizeof(dmlh)); + dmlh.fcc = ckidAVIEXTHEADER; + dmlh.cb = sizeof(dmlh) - sizeof(RIFFCHUNK); + dmlh.dwGrandFrames = This->in[0]->strh.dwLength; + hr = out_write(This, &dmlh, sizeof(dmlh)); + + rl.cb = idx1_off - This->out->movi_off - sizeof(RIFFCHUNK); + rl.fccListType = FCC('m','o','v','i'); + out_write(This, &rl, sizeof(rl)); + out_flush(This); + + IStream_Release(This->out->stream); + This->out->stream = NULL; + } + + This->filter.state = State_Stopped; + return S_OK; } static HRESULT WINAPI AviMux_Pause(IBaseFilter *iface)