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