Piotr Caban : qcap: Add Avi Mux IBaseFilter::Stop implementation.
Alexandre Julliard
julliard at winehq.org
Wed Feb 26 15:45:04 CST 2014
Module: wine
Branch: master
Commit: dddc278b4d4a8054ad41f4c056b21e044e95770b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=dddc278b4d4a8054ad41f4c056b21e044e95770b
Author: Piotr Caban <piotr at codeweavers.com>
Date: Wed Feb 26 13:36:45 2014 +0100
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 8ec15ba..a1c4f85 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; i<This->input_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; i<This->input_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)
More information about the wine-cvs
mailing list