Piotr Caban : qcap: Add partial Avi Mux IBaseFilter::Run implementation.

Alexandre Julliard julliard at winehq.org
Tue Feb 25 16:58:15 CST 2014


Module: wine
Branch: master
Commit: 053b1f6f60d666a4cd28f475f08576722eed1c31
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=053b1f6f60d666a4cd28f475f08576722eed1c31

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Tue Feb 25 12:22:53 2014 +0100

qcap: Add partial Avi Mux IBaseFilter::Run implementation.

---

 dlls/qcap/avimux.c |  170 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 168 insertions(+), 2 deletions(-)

diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c
index 20f830a..dde634e 100644
--- a/dlls/qcap/avimux.c
+++ b/dlls/qcap/avimux.c
@@ -25,6 +25,7 @@
 #include "winbase.h"
 #include "wtypes.h"
 #include "dshow.h"
+#include "vfw.h"
 #include "aviriff.h"
 
 #include "qcap_main.h"
@@ -34,11 +35,17 @@
 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
 
 #define MAX_PIN_NO 128
+#define AVISUPERINDEX_ENTRIES 2000
+#define AVISTDINDEX_ENTRIES 4000
 #define ALIGN(x) ((x+1)/2*2)
 
 typedef struct {
     BaseOutputPin pin;
     IQualityControl IQualityControl_iface;
+
+    int movi_off;
+    int size;
+    IStream *stream;
 } AviMuxOut;
 
 typedef struct {
@@ -47,6 +54,9 @@ typedef struct {
     IPropertyBag IPropertyBag_iface;
     IQualityControl IQualityControl_iface;
 
+    REFERENCE_TIME avg_time_per_frame;
+    int stream_id;
+
     /* strl chunk */
     AVISTREAMHEADER strh;
     struct {
@@ -54,6 +64,13 @@ typedef struct {
         DWORD cb;
         BYTE data[1];
     } *strf;
+    AVISUPERINDEX *indx;
+    BYTE indx_data[FIELD_OFFSET(AVISUPERINDEX, aIndex[AVISUPERINDEX_ENTRIES])];
+
+    /* movi chunk */
+    int ix_off;
+    AVISTDINDEX *ix;
+    BYTE ix_data[FIELD_OFFSET(AVISTDINDEX, aIndex[AVISTDINDEX_ENTRIES])];
 } AviMuxIn;
 
 typedef struct {
@@ -71,6 +88,13 @@ typedef struct {
     AviMuxOut *out;
     int input_pin_no;
     AviMuxIn *in[MAX_PIN_NO-1];
+
+    REFERENCE_TIME start, stop;
+    AVIMAINHEADER avih;
+
+    int idx1_entries;
+    int idx1_size;
+    AVIINDEXENTRY *idx1;
 } AviMux;
 
 static HRESULT create_input_pin(AviMux*);
@@ -159,12 +183,33 @@ static ULONG WINAPI AviMux_Release(IBaseFilter *iface)
         for(i=0; i<This->input_pin_no; i++)
             BaseInputPinImpl_Release(&This->in[i]->pin.pin.IPin_iface);
 
+        HeapFree(GetProcessHeap(), 0, This->idx1);
         HeapFree(GetProcessHeap(), 0, This);
         ObjectRefCount(FALSE);
     }
     return ref;
 }
 
+static inline HRESULT idx1_add_entry(AviMux *avimux, DWORD ckid, DWORD flags, DWORD off, DWORD len)
+{
+    if(avimux->idx1_entries == avimux->idx1_size) {
+        AVIINDEXENTRY *new_idx = HeapReAlloc(GetProcessHeap(), 0, avimux->idx1,
+                sizeof(*avimux->idx1)*2*avimux->idx1_size);
+        if(!new_idx)
+            return E_OUTOFMEMORY;
+
+        avimux->idx1_size *= 2;
+        avimux->idx1 = new_idx;
+    }
+
+    avimux->idx1[avimux->idx1_entries].ckid = ckid;
+    avimux->idx1[avimux->idx1_entries].dwFlags = flags;
+    avimux->idx1[avimux->idx1_entries].dwChunkOffset = off;
+    avimux->idx1[avimux->idx1_entries].dwChunkLength = len;
+    avimux->idx1_entries++;
+    return S_OK;
+}
+
 static HRESULT WINAPI AviMux_Stop(IBaseFilter *iface)
 {
     AviMux *This = impl_from_IBaseFilter(iface);
@@ -182,8 +227,124 @@ static HRESULT WINAPI AviMux_Pause(IBaseFilter *iface)
 static HRESULT WINAPI AviMux_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
 {
     AviMux *This = impl_from_IBaseFilter(iface);
-    FIXME("(%p)->(0x%x%08x)\n", This, (ULONG)(tStart >> 32), (ULONG)tStart);
-    return E_NOTIMPL;
+    HRESULT hr;
+    int i, stream_id;
+
+    TRACE("(%p)->(0x%x%08x)\n", This, (ULONG)(tStart >> 32), (ULONG)tStart);
+
+    if(This->filter.state == State_Running)
+        return S_OK;
+
+    if(This->mode != INTERLEAVE_FULL) {
+        FIXME("mode not supported (%d)\n", This->mode);
+        return E_NOTIMPL;
+    }
+
+    if(tStart)
+        FIXME("tStart parameter ignored\n");
+
+    for(i=0; i<This->input_pin_no; i++) {
+        IMediaSeeking *ms;
+        LONGLONG cur, stop;
+
+        if(!This->in[i]->pin.pin.pConnectedTo)
+            continue;
+
+        hr = IPin_QueryInterface(This->in[i]->pin.pin.pConnectedTo,
+                &IID_IMediaSeeking, (void**)&ms);
+        if(FAILED(hr))
+            continue;
+
+        hr = IMediaSeeking_GetPositions(ms, &cur, &stop);
+        if(FAILED(hr)) {
+            IMediaSeeking_Release(ms);
+            continue;
+        }
+
+        FIXME("Use IMediaSeeking to fill stream header\n");
+        IMediaSeeking_Release(ms);
+    }
+
+    if(This->out->pin.pMemInputPin) {
+        hr = IMemInputPin_QueryInterface(This->out->pin.pMemInputPin,
+                &IID_IStream, (void**)&This->out->stream);
+        if(FAILED(hr))
+            return hr;
+    }
+
+    This->idx1_entries = 0;
+    if(!This->idx1_size) {
+        This->idx1_size = 1024;
+        This->idx1 = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->idx1)*This->idx1_size);
+        if(!This->idx1)
+            return E_OUTOFMEMORY;
+    }
+
+    This->out->size = 3*sizeof(RIFFLIST) + sizeof(AVIMAINHEADER) + sizeof(AVIEXTHEADER);
+    This->start = -1;
+    This->stop = -1;
+    memset(&This->avih, 0, sizeof(This->avih));
+    for(i=0; i<This->input_pin_no; i++) {
+        if(!This->in[i]->pin.pin.pConnectedTo)
+            continue;
+
+        This->avih.dwStreams++;
+        This->out->size += sizeof(RIFFLIST) + sizeof(AVISTREAMHEADER) + sizeof(RIFFCHUNK)
+            + This->in[i]->strf->cb + sizeof(This->in[i]->indx_data);
+
+        This->in[i]->strh.dwScale = MulDiv(This->in[i]->avg_time_per_frame, This->interleave, 10000000);
+        This->in[i]->strh.dwRate = This->interleave;
+
+        hr = IMemAllocator_Commit(This->in[i]->pin.pAllocator);
+        if(FAILED(hr)) {
+            if(This->out->stream) {
+                IStream_Release(This->out->stream);
+                This->out->stream = NULL;
+            }
+            return hr;
+        }
+    }
+
+    This->out->movi_off = This->out->size;
+    This->out->size += sizeof(RIFFLIST);
+
+    idx1_add_entry(This, FCC('7','F','x','x'), 0, This->out->movi_off+sizeof(RIFFLIST), 0);
+
+    stream_id = 0;
+    for(i=0; i<This->input_pin_no; i++) {
+        if(!This->in[i]->pin.pin.pConnectedTo)
+            continue;
+
+        This->in[i]->ix_off = This->out->size;
+        This->out->size += sizeof(This->in[i]->ix_data);
+        This->in[i]->ix->fcc = FCC('i','x','0'+stream_id/10,'0'+stream_id%10);
+        This->in[i]->ix->cb = sizeof(This->in[i]->ix_data) - sizeof(RIFFCHUNK);
+        This->in[i]->ix->wLongsPerEntry = 2;
+        This->in[i]->ix->bIndexSubType = 0;
+        This->in[i]->ix->bIndexType = AVI_INDEX_OF_CHUNKS;
+        This->in[i]->ix->dwChunkId = FCC('0'+stream_id/10,'0'+stream_id%10,'d','b');
+        This->in[i]->ix->qwBaseOffset = 0;
+
+        This->in[i]->indx->fcc = ckidAVISUPERINDEX;
+        This->in[i]->indx->cb = sizeof(This->in[i]->indx_data) - sizeof(RIFFCHUNK);
+        This->in[i]->indx->wLongsPerEntry = 4;
+        This->in[i]->indx->bIndexSubType = 0;
+        This->in[i]->indx->bIndexType = AVI_INDEX_OF_INDEXES;
+        This->in[i]->indx->dwChunkId = This->in[i]->ix->dwChunkId;
+        This->in[i]->stream_id = stream_id++;
+    }
+
+    This->avih.fcc = ckidMAINAVIHEADER;
+    This->avih.cb = sizeof(AVIMAINHEADER) - sizeof(RIFFCHUNK);
+    /* TODO: Use first video stream */
+    This->avih.dwMicroSecPerFrame = This->in[0]->avg_time_per_frame/10;
+    This->avih.dwPaddingGranularity = 1;
+    This->avih.dwFlags = AVIF_TRUSTCKTYPE | AVIF_HASINDEX;
+    This->avih.dwWidth = ((BITMAPINFOHEADER*)This->in[0]->strf->data)->biWidth;
+    This->avih.dwHeight = ((BITMAPINFOHEADER*)This->in[0]->strf->data)->biHeight;
+
+    This->filter.state = State_Running;
+    return S_OK;
 }
 
 static HRESULT WINAPI AviMux_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum)
@@ -1653,6 +1814,10 @@ static HRESULT create_input_pin(AviMux *avimux)
 
     memset(&avimux->in[avimux->input_pin_no]->strh, 0, sizeof(avimux->in[avimux->input_pin_no]->strh));
     avimux->in[avimux->input_pin_no]->strf = NULL;
+    memset(&avimux->in[avimux->input_pin_no]->indx_data, 0, sizeof(avimux->in[avimux->input_pin_no]->indx_data));
+    memset(&avimux->in[avimux->input_pin_no]->ix_data, 0, sizeof(avimux->in[avimux->input_pin_no]->ix_data));
+    avimux->in[avimux->input_pin_no]->indx = (AVISUPERINDEX*)&avimux->in[avimux->input_pin_no]->indx_data;
+    avimux->in[avimux->input_pin_no]->ix = (AVISTDINDEX*)avimux->in[avimux->input_pin_no]->ix_data;
 
     avimux->input_pin_no++;
     return S_OK;
@@ -1699,6 +1864,7 @@ IUnknown* WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr)
         return NULL;
     }
     avimux->out->IQualityControl_iface.lpVtbl = &AviMuxOut_QualityControlVtbl;
+    avimux->out->stream = NULL;
 
     hr = create_input_pin(avimux);
     if(FAILED(hr)) {




More information about the wine-cvs mailing list