ReactOS 0.4.15-dev-7788-g1ad9096
avisplit.c File Reference
#include "quartz_private.h"
#include "pin.h"
#include "uuids.h"
#include "vfw.h"
#include "aviriff.h"
#include "vfwmsgs.h"
#include "amvideo.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include <math.h>
#include <assert.h>
#include "parser.h"
Include dependency graph for avisplit.c:

Go to the source code of this file.

Classes

struct  StreamData
 
struct  AVISplitterImpl
 
struct  thread_args
 

Macros

#define TWOCCFromFOURCC(fcc)   HIWORD(fcc)
 
#define ckidINFO   mmioFOURCC('I','N','F','O')
 
#define ckidREC   mmioFOURCC('R','E','C',' ')
 

Typedefs

typedef struct StreamData StreamData
 
typedef struct AVISplitterImpl AVISplitterImpl
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (quartz)
 
static AVISplitterImplimpl_from_IMediaSeeking (IMediaSeeking *iface)
 
static HRESULT AVISplitter_SendEndOfFile (AVISplitterImpl *This, DWORD streamnumber)
 
static HRESULT AVISplitter_next_request (AVISplitterImpl *This, DWORD streamnumber)
 
static HRESULT AVISplitter_Receive (AVISplitterImpl *This, IMediaSample *sample, DWORD streamnumber)
 
static DWORD WINAPI AVISplitter_thread_reader (LPVOID data)
 
static HRESULT AVISplitter_Sample (LPVOID iface, IMediaSample *pSample, DWORD_PTR cookie)
 
static HRESULT AVISplitter_done_process (LPVOID iface)
 
static HRESULT AVISplitter_first_request (LPVOID iface)
 
static HRESULT AVISplitter_QueryAccept (LPVOID iface, const AM_MEDIA_TYPE *pmt)
 
static HRESULT AVISplitter_ProcessIndex (AVISplitterImpl *This, AVISTDINDEX **index, LONGLONG qwOffset, DWORD cb)
 
static HRESULT AVISplitter_ProcessOldIndex (AVISplitterImpl *This)
 
static HRESULT AVISplitter_ProcessStreamList (AVISplitterImpl *This, const BYTE *pData, DWORD cb, ALLOCATOR_PROPERTIES *props)
 
static HRESULT AVISplitter_ProcessODML (AVISplitterImpl *This, const BYTE *pData, DWORD cb)
 
static HRESULT AVISplitter_InitializeStreams (AVISplitterImpl *This)
 
static HRESULT AVISplitter_Disconnect (LPVOID iface)
 
static HRESULT AVISplitter_InputPin_PreConnect (IPin *iface, IPin *pConnectPin, ALLOCATOR_PROPERTIES *props)
 
static HRESULT AVISplitter_Flush (LPVOID iface)
 
static ULONG WINAPI AVISplitter_Release (IBaseFilter *iface)
 
static HRESULT WINAPI AVISplitter_seek (IMediaSeeking *iface)
 
HRESULT AVISplitter_create (IUnknown *pUnkOuter, LPVOID *ppv)
 

Variables

static const IBaseFilterVtbl AVISplitterImpl_Vtbl
 

Macro Definition Documentation

◆ ckidINFO

#define ckidINFO   mmioFOURCC('I','N','F','O')

Definition at line 52 of file avisplit.c.

◆ ckidREC

#define ckidREC   mmioFOURCC('R','E','C',' ')

Definition at line 53 of file avisplit.c.

◆ TWOCCFromFOURCC

#define TWOCCFromFOURCC (   fcc)    HIWORD(fcc)

Definition at line 49 of file avisplit.c.

Typedef Documentation

◆ AVISplitterImpl

◆ StreamData

Function Documentation

◆ AVISplitter_create()

HRESULT AVISplitter_create ( IUnknown pUnkOuter,
LPVOID ppv 
)

Definition at line 1430 of file avisplit.c.

1431{
1432 HRESULT hr;
1434
1435 TRACE("(%p, %p)\n", pUnkOuter, ppv);
1436
1437 *ppv = NULL;
1438
1439 if (pUnkOuter)
1440 return CLASS_E_NOAGGREGATION;
1441
1442 /* Note: This memory is managed by the transform filter once created */
1444
1445 This->streams = NULL;
1446 This->oldindex = NULL;
1447
1449
1450 if (FAILED(hr))
1451 return hr;
1452
1453 *ppv = &This->Parser.filter.IBaseFilter_iface;
1454
1455 return hr;
1456}
static HRESULT AVISplitter_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE *pmt)
Definition: avisplit.c:545
static HRESULT WINAPI AVISplitter_seek(IMediaSeeking *iface)
Definition: avisplit.c:1285
static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample *pSample, DWORD_PTR cookie)
Definition: avisplit.c:394
static HRESULT AVISplitter_Disconnect(LPVOID iface)
Definition: avisplit.c:1241
static HRESULT AVISplitter_done_process(LPVOID iface)
Definition: avisplit.c:514
static const IBaseFilterVtbl AVISplitterImpl_Vtbl
Definition: avisplit.c:1411
static HRESULT AVISplitter_Flush(LPVOID iface)
Definition: avisplit.c:1215
static HRESULT AVISplitter_first_request(LPVOID iface)
Definition: avisplit.c:429
static HRESULT AVISplitter_InputPin_PreConnect(IPin *iface, IPin *pConnectPin, ALLOCATOR_PROPERTIES *props)
Definition: avisplit.c:1027
#define NULL
Definition: types.h:112
HRESULT Parser_Create(ParserImpl *pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID *pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, SourceSeeking_ChangeStop stop, SourceSeeking_ChangeStart start, SourceSeeking_ChangeRate rate)
Definition: parser.c:96
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define FAILED(hr)
Definition: intsafe.h:51
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662

◆ AVISplitter_Disconnect()

static HRESULT AVISplitter_Disconnect ( LPVOID  iface)
static

Definition at line 1241 of file avisplit.c.

1242{
1243 AVISplitterImpl *This = iface;
1244 ULONG x;
1245
1246 /* TODO: Remove other memory that's allocated during connect */
1247 CoTaskMemFree(This->oldindex);
1248 This->oldindex = NULL;
1249
1250 for (x = 0; x < This->Parser.cStreams; ++x)
1251 {
1252 DWORD i;
1253
1254 StreamData *stream = &This->streams[x];
1255
1256 for (i = 0; i < stream->entries; ++i)
1257 CoTaskMemFree(stream->stdindex[i]);
1258
1259 CoTaskMemFree(stream->stdindex);
1260 CloseHandle(stream->packet_queued);
1261 }
1262 CoTaskMemFree(This->streams);
1263 This->streams = NULL;
1264 return S_OK;
1265}
#define CloseHandle
Definition: compat.h:739
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
#define S_OK
Definition: intsafe.h:52
Definition: parse.h:23
uint32_t ULONG
Definition: typedefs.h:59

Referenced by AVISplitter_create(), and AVISplitter_InputPin_PreConnect().

◆ AVISplitter_done_process()

static HRESULT AVISplitter_done_process ( LPVOID  iface)
static

Definition at line 514 of file avisplit.c.

515{
516 AVISplitterImpl *This = iface;
517 DWORD x;
518 ULONG ref;
519
520 for (x = 0; x < This->Parser.cStreams; ++x)
521 {
522 StreamData *stream = This->streams + x;
523
524 TRACE("Waiting for %u to terminate\n", x);
525 /* Make the thread return first */
526 SetEvent(stream->packet_queued);
527 assert(WaitForSingleObject(stream->thread, 100000) != WAIT_TIMEOUT);
528 CloseHandle(stream->thread);
529 stream->thread = NULL;
530
531 if (stream->sample)
532 {
533 ref = IMediaSample_Release(stream->sample);
534 assert(ref == 0);
535 }
536 stream->sample = NULL;
537
538 ResetEvent(stream->packet_queued);
539 }
540 TRACE("All threads are now terminated\n");
541
542 return S_OK;
543}
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define assert(x)
Definition: debug.h:53
Definition: send.c:48
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714

Referenced by AVISplitter_create().

◆ AVISplitter_first_request()

static HRESULT AVISplitter_first_request ( LPVOID  iface)
static

Definition at line 429 of file avisplit.c.

430{
431 AVISplitterImpl *This = iface;
432 HRESULT hr = S_OK;
433 DWORD x;
434 IMediaSample *sample = NULL;
435 BOOL have_sample = FALSE;
436
437 TRACE("(%p)->()\n", This);
438
439 for (x = 0; x < This->Parser.cStreams; ++x)
440 {
441 StreamData *stream = This->streams + x;
442
443 /* Nothing should be running at this point */
444 assert(!stream->thread);
445
446 assert(!sample);
447 /* It could be we asked the thread to terminate, and the thread
448 * already terminated before receiving the deathwish */
449 ResetEvent(stream->packet_queued);
450
451 stream->pos_next = stream->pos;
452 stream->index_next = stream->index;
453
454 /* This was sent after stopped->paused or stopped->playing, so set seek */
455 stream->seek = TRUE;
456
457 /* There should be a packet queued from AVISplitter_next_request last time
458 * It needs to be done now because this is the only way to ensure that every
459 * stream will have at least 1 packet processed
460 * If this is done after the threads start it could go all awkward and we
461 * would have no guarantees that it's successful at all
462 */
463
464 if (have_sample)
465 {
466 DWORD_PTR dwUser = ~0;
467 hr = IAsyncReader_WaitForNext(This->Parser.pInputPin->pReader, 10000, &sample, &dwUser);
468 assert(hr == S_OK);
469 assert(sample);
470
471 AVISplitter_Sample(iface, sample, dwUser);
472 IMediaSample_Release(sample);
473 }
474
476 TRACE("-->%08x\n", hr);
477
478 /* Could be an EOF instead */
479 have_sample = (hr == S_OK);
480 if (hr == S_FALSE)
482
483 if (FAILED(hr) && hr != VFW_E_NOT_CONNECTED)
484 break;
485 hr = S_OK;
486 }
487
488 /* FIXME: Don't do this for each pin that sent an EOF */
489 for (x = 0; x < This->Parser.cStreams && SUCCEEDED(hr); ++x)
490 {
491 struct thread_args *args;
492 DWORD tid;
493
494 if ((This->streams[x].stdindex && This->streams[x].index_next >= This->streams[x].entries) ||
495 (!This->streams[x].stdindex && This->streams[x].index_next))
496 {
497 This->streams[x].thread = NULL;
498 continue;
499 }
500
501 args = CoTaskMemAlloc(sizeof(*args));
502 args->This = This;
503 args->stream = x;
504 This->streams[x].thread = CreateThread(NULL, 0, AVISplitter_thread_reader, args, 0, &tid);
505 TRACE("Created stream %u thread 0x%08x\n", x, tid);
506 }
507
508 if (FAILED(hr))
509 ERR("Horsemen of the apocalypse came to bring error 0x%08x\n", hr);
510
511 return hr;
512}
static DWORD WINAPI AVISplitter_thread_reader(LPVOID data)
Definition: avisplit.c:356
static HRESULT AVISplitter_SendEndOfFile(AVISplitterImpl *This, DWORD streamnumber)
Definition: avisplit.c:128
static HRESULT AVISplitter_next_request(AVISplitterImpl *This, DWORD streamnumber)
Definition: avisplit.c:148
#define ERR(fmt,...)
Definition: debug.h:110
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
unsigned int BOOL
Definition: ntddk_ex.h:94
#define SUCCEEDED(hr)
Definition: intsafe.h:50
static TfClientId tid
#define args
Definition: format.c:66
Definition: match.c:390
ULARGE_INTEGER pos
Definition: request.c:4380
AVISplitterImpl * This
Definition: avisplit.c:99
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define VFW_E_NOT_CONNECTED
Definition: vfwmsgs.h:48
#define S_FALSE
Definition: winerror.h:2357

Referenced by AVISplitter_create().

◆ AVISplitter_Flush()

static HRESULT AVISplitter_Flush ( LPVOID  iface)
static

Definition at line 1215 of file avisplit.c.

1216{
1217 AVISplitterImpl *This = iface;
1218 DWORD x;
1219 ULONG ref;
1220
1221 TRACE("(%p)->()\n", This);
1222
1223 for (x = 0; x < This->Parser.cStreams; ++x)
1224 {
1225 StreamData *stream = This->streams + x;
1226
1227 if (stream->sample)
1228 {
1229 ref = IMediaSample_Release(stream->sample);
1230 assert(ref == 0);
1231 }
1232 stream->sample = NULL;
1233
1234 ResetEvent(stream->packet_queued);
1235 assert(!stream->thread);
1236 }
1237
1238 return S_OK;
1239}

Referenced by AVISplitter_create(), and AVISplitter_Release().

◆ AVISplitter_InitializeStreams()

static HRESULT AVISplitter_InitializeStreams ( AVISplitterImpl This)
static

Definition at line 921 of file avisplit.c.

922{
923 unsigned int x;
924
925 if (This->oldindex)
926 {
927 DWORD nMax, n;
928
929 for (x = 0; x < This->Parser.cStreams; ++x)
930 {
931 This->streams[x].frames = 0;
932 This->streams[x].pos = ~0;
933 This->streams[x].index = 0;
934 }
935
936 nMax = This->oldindex->cb / sizeof(This->oldindex->aIndex[0]);
937
938 /* Ok, maybe this is more of an exercise to see if I interpret everything correctly or not, but that is useful for now. */
939 for (n = 0; n < nMax; ++n)
940 {
941 DWORD streamId = StreamFromFOURCC(This->oldindex->aIndex[n].dwChunkId);
942 if (streamId >= This->Parser.cStreams)
943 {
944 FIXME("Stream id %s ignored\n", debugstr_an((char*)&This->oldindex->aIndex[n].dwChunkId, 4));
945 continue;
946 }
947 if (This->streams[streamId].pos == ~0U)
948 This->streams[streamId].pos = n;
949
950 if (This->streams[streamId].streamheader.dwSampleSize)
951 This->streams[streamId].frames += This->oldindex->aIndex[n].dwSize / This->streams[streamId].streamheader.dwSampleSize;
952 else
953 ++This->streams[streamId].frames;
954 }
955
956 for (x = 0; x < This->Parser.cStreams; ++x)
957 {
958 if ((DWORD)This->streams[x].frames != This->streams[x].streamheader.dwLength)
959 {
960 FIXME("stream %u: frames found: %u, frames meant to be found: %u\n", x, (DWORD)This->streams[x].frames, This->streams[x].streamheader.dwLength);
961 }
962 }
963
964 }
965 else if (!This->streams[0].entries)
966 {
967 for (x = 0; x < This->Parser.cStreams; ++x)
968 {
969 This->streams[x].frames = This->streams[x].streamheader.dwLength;
970 }
971 /* MS Avi splitter does seek through the whole file, we should! */
972 ERR("We should be manually seeking through the entire file to build an index, because the index is missing!!!\n");
973 return E_NOTIMPL;
974 }
975
976 /* Not much here yet */
977 for (x = 0; x < This->Parser.cStreams; ++x)
978 {
979 StreamData *stream = This->streams + x;
980 DWORD y;
981 DWORD64 frames = 0;
982
983 stream->seek = TRUE;
984
985 if (stream->stdindex)
986 {
987 stream->index = 0;
988 stream->pos = 0;
989 for (y = 0; y < stream->entries; ++y)
990 {
991 if (stream->streamheader.dwSampleSize)
992 {
993 DWORD z;
994
995 for (z = 0; z < stream->stdindex[y]->nEntriesInUse; ++z)
996 {
997 UINT len = stream->stdindex[y]->aIndex[z].dwSize & ~(1u << 31);
998 frames += len / stream->streamheader.dwSampleSize + !!(len % stream->streamheader.dwSampleSize);
999 }
1000 }
1001 else
1002 frames += stream->stdindex[y]->nEntriesInUse;
1003 }
1004 }
1005 else frames = stream->frames;
1006
1007 frames *= stream->streamheader.dwScale;
1008 /* Keep accuracy as high as possible for duration */
1009 This->Parser.sourceSeeking.llDuration = frames * 10000000;
1010 This->Parser.sourceSeeking.llDuration /= stream->streamheader.dwRate;
1011 This->Parser.sourceSeeking.llStop = This->Parser.sourceSeeking.llDuration;
1012 This->Parser.sourceSeeking.llCurrent = 0;
1013
1014 frames /= stream->streamheader.dwRate;
1015
1016 TRACE("Duration: %d days, %d hours, %d minutes and %d.%03u seconds\n", (DWORD)(frames / 86400),
1017 (DWORD)((frames % 86400) / 3600), (DWORD)((frames % 3600) / 60), (DWORD)(frames % 60),
1018 (DWORD)(This->Parser.sourceSeeking.llDuration/10000) % 1000);
1019 }
1020
1021 return S_OK;
1022}
#define U(x)
Definition: wordpad.c:45
#define FIXME(fmt,...)
Definition: debug.h:111
#define E_NOTIMPL
Definition: ddrawi.h:99
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble n
Definition: glext.h:7729
GLenum GLsizei len
Definition: glext.h:6722
GLdouble GLdouble z
Definition: glext.h:5874
unsigned int UINT
Definition: ndis.h:50
uint64_t DWORD64
Definition: typedefs.h:67
#define StreamFromFOURCC(fcc)
Definition: vfw.h:919

Referenced by AVISplitter_InputPin_PreConnect().

◆ AVISplitter_InputPin_PreConnect()

static HRESULT AVISplitter_InputPin_PreConnect ( IPin iface,
IPin pConnectPin,
ALLOCATOR_PROPERTIES props 
)
static

Definition at line 1027 of file avisplit.c.

1028{
1030 HRESULT hr;
1031 RIFFLIST list;
1032 LONGLONG pos = 0; /* in bytes */
1033 BYTE * pBuffer;
1034 RIFFCHUNK * pCurrentChunk;
1036 ULONG x;
1037 DWORD indexes;
1038
1039 AVISplitterImpl * pAviSplit = (AVISplitterImpl *)This->pin.pinInfo.pFilter;
1040
1041 hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
1042 pos += sizeof(list);
1043
1044 if (list.fcc != FOURCC_RIFF)
1045 {
1046 ERR("Input stream not a RIFF file\n");
1047 return E_FAIL;
1048 }
1049 if (list.fccListType != formtypeAVI)
1050 {
1051 ERR("Input stream not an AVI RIFF file\n");
1052 return E_FAIL;
1053 }
1054
1055 hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
1056 if (list.fcc != FOURCC_LIST)
1057 {
1058 ERR("Expected LIST chunk, but got %.04s\n", (LPSTR)&list.fcc);
1059 return E_FAIL;
1060 }
1061 if (list.fccListType != listtypeAVIHEADER)
1062 {
1063 ERR("Header list expected. Got: %.04s\n", (LPSTR)&list.fccListType);
1064 return E_FAIL;
1065 }
1066
1067 pBuffer = HeapAlloc(GetProcessHeap(), 0, list.cb - sizeof(RIFFLIST) + sizeof(RIFFCHUNK));
1068 hr = IAsyncReader_SyncRead(This->pReader, pos + sizeof(list), list.cb - sizeof(RIFFLIST) + sizeof(RIFFCHUNK), pBuffer);
1069
1070 pAviSplit->AviHeader.cb = 0;
1071
1072 /* Stream list will set the buffer size here, so set a default and allow an override */
1073 props->cbBuffer = 0x20000;
1074
1075 for (pCurrentChunk = (RIFFCHUNK *)pBuffer; (BYTE *)pCurrentChunk + sizeof(*pCurrentChunk) < pBuffer + list.cb; pCurrentChunk = (RIFFCHUNK *)(((BYTE *)pCurrentChunk) + sizeof(*pCurrentChunk) + pCurrentChunk->cb))
1076 {
1077 RIFFLIST * pList;
1078
1079 switch (pCurrentChunk->fcc)
1080 {
1081 case ckidMAINAVIHEADER:
1082 /* AVIMAINHEADER includes the structure that is pCurrentChunk at the moment */
1083 memcpy(&pAviSplit->AviHeader, pCurrentChunk, sizeof(pAviSplit->AviHeader));
1084 break;
1085 case FOURCC_LIST:
1086 pList = (RIFFLIST *)pCurrentChunk;
1087 switch (pList->fccListType)
1088 {
1089 case ckidSTREAMLIST:
1090 hr = AVISplitter_ProcessStreamList(pAviSplit, (BYTE *)pCurrentChunk + sizeof(RIFFLIST), pCurrentChunk->cb + sizeof(RIFFCHUNK) - sizeof(RIFFLIST), props);
1091 break;
1092 case ckidODML:
1093 hr = AVISplitter_ProcessODML(pAviSplit, (BYTE *)pCurrentChunk + sizeof(RIFFLIST), pCurrentChunk->cb + sizeof(RIFFCHUNK) - sizeof(RIFFLIST));
1094 break;
1095 }
1096 break;
1097 case ckidAVIPADDING:
1098 /* ignore */
1099 break;
1100 default:
1101 FIXME("unrecognised header list type: %.04s\n", (LPSTR)&pCurrentChunk->fcc);
1102 }
1103 }
1105
1106 if (pAviSplit->AviHeader.cb != sizeof(pAviSplit->AviHeader) - sizeof(RIFFCHUNK))
1107 {
1108 ERR("Avi Header wrong size!\n");
1109 return E_FAIL;
1110 }
1111
1112 /* Skip any chunks until we find the LIST chunk */
1113 do
1114 {
1115 pos += sizeof(RIFFCHUNK) + list.cb;
1116 hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
1117 }
1118 while (hr == S_OK && (list.fcc != FOURCC_LIST || list.fccListType != listtypeAVIMOVIE));
1119
1120 if (hr != S_OK)
1121 {
1122 ERR("Failed to find LIST chunk from AVI file\n");
1123 return E_FAIL;
1124 }
1125
1126 IAsyncReader_Length(This->pReader, &total, &avail);
1127
1128 /* FIXME: AVIX files are extended beyond the FOURCC chunk "AVI ", and thus won't be played here,
1129 * once I get one of the files I'll try to fix it */
1130 This->rtStart = pAviSplit->CurrentChunkOffset = MEDIATIME_FROM_BYTES(pos + sizeof(RIFFLIST));
1131 pos += list.cb + sizeof(RIFFCHUNK);
1132
1133 pAviSplit->EndOfFile = This->rtStop = MEDIATIME_FROM_BYTES(pos);
1134 if (pos > total)
1135 {
1136 ERR("File smaller (%s) then EndOfFile (%s)\n", wine_dbgstr_longlong(total), wine_dbgstr_longlong(pAviSplit->EndOfFile));
1137 return E_FAIL;
1138 }
1139
1140 hr = IAsyncReader_SyncRead(This->pReader, BYTES_FROM_MEDIATIME(pAviSplit->CurrentChunkOffset), sizeof(pAviSplit->CurrentChunk), (BYTE *)&pAviSplit->CurrentChunk);
1141
1142 props->cbAlign = 1;
1143 props->cbPrefix = 0;
1144 /* Comrades, prevent shortage of buffers, or you will feel the consequences! DA! */
1145 props->cBuffers = 2 * pAviSplit->Parser.cStreams;
1146
1147 /* Now peek into the idx1 index, if available */
1148 if (hr == S_OK && (total - pos) > sizeof(RIFFCHUNK))
1149 {
1150 memset(&list, 0, sizeof(list));
1151
1152 hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
1153 if (list.fcc == ckidAVIOLDINDEX)
1154 {
1155 pAviSplit->oldindex = CoTaskMemRealloc(pAviSplit->oldindex, list.cb + sizeof(RIFFCHUNK));
1156 if (pAviSplit->oldindex)
1157 {
1158 hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(RIFFCHUNK) + list.cb, (BYTE *)pAviSplit->oldindex);
1159 if (hr == S_OK)
1160 {
1161 hr = AVISplitter_ProcessOldIndex(pAviSplit);
1162 }
1163 else
1164 {
1165 CoTaskMemFree(pAviSplit->oldindex);
1166 pAviSplit->oldindex = NULL;
1167 hr = S_OK;
1168 }
1169 }
1170 }
1171 }
1172
1173 indexes = 0;
1174 for (x = 0; x < pAviSplit->Parser.cStreams; ++x)
1175 if (pAviSplit->streams[x].entries)
1176 ++indexes;
1177
1178 if (indexes)
1179 {
1180 CoTaskMemFree(pAviSplit->oldindex);
1181 pAviSplit->oldindex = NULL;
1182 if (indexes < pAviSplit->Parser.cStreams)
1183 {
1184 /* This error could possible be survived by switching to old type index,
1185 * but I would rather find out why it doesn't find everything here
1186 */
1187 ERR("%d indexes expected, but only have %d\n", indexes, pAviSplit->Parser.cStreams);
1188 indexes = 0;
1189 }
1190 }
1191 else if (pAviSplit->oldindex)
1192 indexes = pAviSplit->Parser.cStreams;
1193
1194 if (!indexes && pAviSplit->AviHeader.dwFlags & AVIF_MUSTUSEINDEX)
1195 {
1196 FIXME("No usable index was found!\n");
1197 hr = E_FAIL;
1198 }
1199
1200 /* Now, set up the streams */
1201 if (hr == S_OK)
1202 hr = AVISplitter_InitializeStreams(pAviSplit);
1203
1204 if (hr != S_OK)
1205 {
1206 AVISplitter_Disconnect(pAviSplit);
1207 return E_FAIL;
1208 }
1209
1210 TRACE("AVI File ok\n");
1211
1212 return hr;
1213}
static int avail
Definition: adh-main.c:39
#define AVIF_MUSTUSEINDEX
Definition: aviriff.h:47
#define ckidMAINAVIHEADER
Definition: aviriff.h:53
#define ckidSTREAMLIST
Definition: aviriff.h:81
#define ckidAVIOLDINDEX
Definition: aviriff.h:127
#define ckidODML
Definition: aviriff.h:71
struct _riffchunk RIFFCHUNK
static HRESULT AVISplitter_ProcessOldIndex(AVISplitterImpl *This)
Definition: avisplit.c:607
static HRESULT AVISplitter_ProcessODML(AVISplitterImpl *This, const BYTE *pData, DWORD cb)
Definition: avisplit.c:884
static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl *This, const BYTE *pData, DWORD cb, ALLOCATOR_PROPERTIES *props)
Definition: avisplit.c:678
static HRESULT AVISplitter_InitializeStreams(AVISplitterImpl *This)
Definition: avisplit.c:921
Definition: list.h:37
#define E_FAIL
Definition: ddrawi.h:102
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define HeapFree(x, y, z)
Definition: compat.h:735
FxChildList * pList
size_t total
LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, SIZE_T size)
Definition: ifs.c:460
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define FOURCC_RIFF
Definition: mmsystem.h:564
#define FOURCC_LIST
Definition: mmsystem.h:565
static PullPin * impl_PullPin_from_IPin(IPin *iface)
Definition: pin.h:132
#define MEDIATIME_FROM_BYTES(x)
#define BYTES_FROM_MEDIATIME(time)
PVOID pBuffer
#define list
Definition: rosglue.h:35
#define memset(x, y, z)
Definition: compat.h:39
StreamData * streams
Definition: avisplit.c:95
AVIOLDINDEX * oldindex
Definition: avisplit.c:92
LONGLONG EndOfFile
Definition: avisplit.c:88
AVIMAINHEADER AviHeader
Definition: avisplit.c:89
ParserImpl Parser
Definition: avisplit.c:85
LONGLONG CurrentChunkOffset
Definition: avisplit.c:87
RIFFCHUNK CurrentChunk
Definition: avisplit.c:86
ULONG cStreams
Definition: parser.h:40
Definition: pin.h:71
DWORD entries
Definition: avisplit.c:64
DWORD cb
Definition: aviriff.h:57
DWORD dwFlags
Definition: aviriff.h:61
int64_t LONGLONG
Definition: typedefs.h:68
#define listtypeAVIMOVIE
Definition: vfw.h:898
#define listtypeAVIHEADER
Definition: vfw.h:890
#define ckidAVIPADDING
Definition: vfw.h:916
#define formtypeAVI
Definition: vfw.h:889
static const WCHAR props[]
Definition: wbemdisp.c:288
char * LPSTR
Definition: xmlstorage.h:182
unsigned char BYTE
Definition: xxhash.c:193

Referenced by AVISplitter_create().

◆ AVISplitter_next_request()

static HRESULT AVISplitter_next_request ( AVISplitterImpl This,
DWORD  streamnumber 
)
static

Definition at line 148 of file avisplit.c.

149{
150 StreamData *stream = This->streams + streamnumber;
151 PullPin *pin = This->Parser.pInputPin;
152 IMediaSample *sample = NULL;
153 HRESULT hr;
154 ULONG ref;
155
156 TRACE("(%p, %u)->()\n", This, streamnumber);
157
158 hr = IMemAllocator_GetBuffer(pin->pAlloc, &sample, NULL, NULL, 0);
159 if (hr != S_OK)
160 ERR("... %08x?\n", hr);
161
162 if (SUCCEEDED(hr))
163 {
164 LONGLONG rtSampleStart;
165 /* Add 4 for the next header, which should hopefully work */
166 LONGLONG rtSampleStop;
167
168 stream->pos = stream->pos_next;
169 stream->index = stream->index_next;
170
171 IMediaSample_SetDiscontinuity(sample, stream->seek);
172 stream->seek = FALSE;
173 if (stream->preroll)
174 {
175 --stream->preroll;
176 IMediaSample_SetPreroll(sample, TRUE);
177 }
178 else
179 IMediaSample_SetPreroll(sample, FALSE);
180 IMediaSample_SetSyncPoint(sample, TRUE);
181
182 if (stream->stdindex)
183 {
184 AVISTDINDEX *index = stream->stdindex[stream->index];
185 AVISTDINDEX_ENTRY *entry = &index->aIndex[stream->pos];
186
187 /* End of file */
188 if (stream->index >= stream->entries)
189 {
190 TRACE("END OF STREAM ON %u\n", streamnumber);
191 IMediaSample_Release(sample);
192 return S_FALSE;
193 }
194
195 rtSampleStart = index->qwBaseOffset;
196 rtSampleStart += entry->dwOffset;
197 rtSampleStart = MEDIATIME_FROM_BYTES(rtSampleStart);
198
199 ++stream->pos_next;
200 if (index->nEntriesInUse == stream->pos_next)
201 {
202 stream->pos_next = 0;
203 ++stream->index_next;
204 }
205
206 rtSampleStop = rtSampleStart + MEDIATIME_FROM_BYTES(entry->dwSize & ~(1u << 31));
207
208 TRACE("offset(%u) size(%u)\n", (DWORD)BYTES_FROM_MEDIATIME(rtSampleStart), (DWORD)BYTES_FROM_MEDIATIME(rtSampleStop - rtSampleStart));
209 }
210 else if (This->oldindex)
211 {
212 DWORD flags = This->oldindex->aIndex[stream->pos].dwFlags;
213 DWORD size = This->oldindex->aIndex[stream->pos].dwSize;
214
215 /* End of file */
216 if (stream->index)
217 {
218 TRACE("END OF STREAM ON %u\n", streamnumber);
219 IMediaSample_Release(sample);
220 return S_FALSE;
221 }
222
223 rtSampleStart = MEDIATIME_FROM_BYTES(This->offset);
224 rtSampleStart += MEDIATIME_FROM_BYTES(This->oldindex->aIndex[stream->pos].dwOffset);
225 rtSampleStop = rtSampleStart + MEDIATIME_FROM_BYTES(size);
226 if (flags & AVIIF_MIDPART)
227 {
228 FIXME("Only stand alone frames are currently handled correctly!\n");
229 }
230 if (flags & AVIIF_LIST)
231 {
232 FIXME("Not sure if this is handled correctly\n");
233 rtSampleStart += MEDIATIME_FROM_BYTES(sizeof(RIFFLIST));
234 rtSampleStop += MEDIATIME_FROM_BYTES(sizeof(RIFFLIST));
235 }
236 else
237 {
238 rtSampleStart += MEDIATIME_FROM_BYTES(sizeof(RIFFCHUNK));
239 rtSampleStop += MEDIATIME_FROM_BYTES(sizeof(RIFFCHUNK));
240 }
241
242 /* Slow way of finding next index */
243 do {
244 stream->pos_next++;
245 } while (stream->pos_next * sizeof(This->oldindex->aIndex[0]) < This->oldindex->cb
246 && StreamFromFOURCC(This->oldindex->aIndex[stream->pos_next].dwChunkId) != streamnumber);
247
248 /* End of file soon */
249 if (stream->pos_next * sizeof(This->oldindex->aIndex[0]) >= This->oldindex->cb)
250 {
251 stream->pos_next = 0;
252 ++stream->index_next;
253 }
254 }
255 else /* TODO: Generate an index automagically */
256 {
257 ERR("CAN'T PLAY WITHOUT AN INDEX! SOS! SOS! SOS!\n");
258 assert(0);
259 }
260
261 if (rtSampleStart != rtSampleStop)
262 {
263 IMediaSample_SetTime(sample, &rtSampleStart, &rtSampleStop);
264 hr = IAsyncReader_Request(pin->pReader, sample, streamnumber);
265
266 if (FAILED(hr))
267 {
268 ref = IMediaSample_Release(sample);
269 assert(ref == 0);
270 }
271 }
272 else
273 {
274 stream->sample = sample;
275 IMediaSample_SetActualDataLength(sample, 0);
276 SetEvent(stream->packet_queued);
277 }
278 }
279 else
280 {
281 if (sample)
282 {
283 ERR("There should be no sample!\n");
284 ref = IMediaSample_Release(sample);
285 assert(ref == 0);
286 }
287 }
288 TRACE("--> %08x\n", hr);
289
290 return hr;
291}
#define AVIIF_LIST
Definition: aviriff.h:130
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLbitfield flags
Definition: glext.h:7161
uint32_t entry
Definition: isohybrid.c:63
Definition: aviriff.h:214
Definition: regsvr.c:104
#define AVIIF_MIDPART
Definition: vfw.h:981

Referenced by AVISplitter_first_request(), and AVISplitter_thread_reader().

◆ AVISplitter_ProcessIndex()

static HRESULT AVISplitter_ProcessIndex ( AVISplitterImpl This,
AVISTDINDEX **  index,
LONGLONG  qwOffset,
DWORD  cb 
)
static

Definition at line 552 of file avisplit.c.

553{
555 DWORD x;
556 int rest;
557
558 *index = NULL;
559 if (cb < sizeof(AVISTDINDEX))
560 {
561 FIXME("size %u too small\n", cb);
562 return E_INVALIDARG;
563 }
564
566 if (!pIndex)
567 return E_OUTOFMEMORY;
568
569 IAsyncReader_SyncRead((impl_PullPin_from_IPin(This->Parser.ppPins[0]))->pReader, qwOffset, cb, (BYTE *)pIndex);
570 rest = cb - sizeof(AVISUPERINDEX) + sizeof(RIFFCHUNK) + sizeof(pIndex->aIndex);
571
572 TRACE("FOURCC: %s\n", debugstr_an((char *)&pIndex->fcc, 4));
573 TRACE("wLongsPerEntry: %hd\n", pIndex->wLongsPerEntry);
574 TRACE("bIndexSubType: %u\n", pIndex->bIndexSubType);
575 TRACE("bIndexType: %u\n", pIndex->bIndexType);
576 TRACE("nEntriesInUse: %u\n", pIndex->nEntriesInUse);
577 TRACE("dwChunkId: %.4s\n", (char *)&pIndex->dwChunkId);
578 TRACE("qwBaseOffset: %s\n", wine_dbgstr_longlong(pIndex->qwBaseOffset));
579 TRACE("dwReserved_3: %u\n", pIndex->dwReserved_3);
580
581 if (pIndex->bIndexType != AVI_INDEX_OF_CHUNKS
582 || pIndex->wLongsPerEntry != 2
583 || rest < (pIndex->nEntriesInUse * sizeof(DWORD) * pIndex->wLongsPerEntry)
584 || (pIndex->bIndexSubType != AVI_INDEX_SUB_DEFAULT))
585 {
586 FIXME("Invalid index chunk encountered: %u/%u, %u/%u, %u/%u, %u/%u\n",
587 pIndex->bIndexType, AVI_INDEX_OF_CHUNKS, pIndex->wLongsPerEntry, 2,
588 rest, (DWORD)(pIndex->nEntriesInUse * sizeof(DWORD) * pIndex->wLongsPerEntry),
589 pIndex->bIndexSubType, AVI_INDEX_SUB_DEFAULT);
590 *index = NULL;
591 return E_INVALIDARG;
592 }
593
594 for (x = 0; x < pIndex->nEntriesInUse; ++x)
595 {
596 BOOL keyframe = !(pIndex->aIndex[x].dwSize >> 31);
597 DWORDLONG offset = pIndex->qwBaseOffset + pIndex->aIndex[x].dwOffset;
598 TRACE("dwOffset: %s\n", wine_dbgstr_longlong(offset));
599 TRACE("dwSize: %u\n", (pIndex->aIndex[x].dwSize & ~(1u << 31)));
600 TRACE("Frame is a keyframe: %s\n", keyframe ? "yes" : "no");
601 }
602
603 *index = pIndex;
604 return S_OK;
605}
struct _avisuperindex AVISUPERINDEX
#define AVI_INDEX_SUB_DEFAULT
Definition: aviriff.h:178
#define AVI_INDEX_OF_CHUNKS
Definition: aviriff.h:173
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
GLintptr offset
Definition: glext.h:5920
unsigned long long DWORDLONG
Definition: intsafe.h:93
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
_Out_ PULONG _Out_ PULONG pIndex
Definition: ndis.h:4565

Referenced by AVISplitter_ProcessStreamList().

◆ AVISplitter_ProcessODML()

static HRESULT AVISplitter_ProcessODML ( AVISplitterImpl This,
const BYTE pData,
DWORD  cb 
)
static

Definition at line 884 of file avisplit.c.

885{
886 const RIFFCHUNK * pChunk;
887
888 for (pChunk = (const RIFFCHUNK *)pData;
889 ((const BYTE *)pChunk >= pData) && ((const BYTE *)pChunk + sizeof(RIFFCHUNK) < pData + cb) && (pChunk->cb > 0);
890 pChunk = (const RIFFCHUNK *)((const BYTE*)pChunk + sizeof(RIFFCHUNK) + pChunk->cb)
891 )
892 {
893 switch (pChunk->fcc)
894 {
895 case ckidAVIEXTHEADER:
896 {
897 int x;
898 const AVIEXTHEADER * pExtHdr = (const AVIEXTHEADER *)pChunk;
899
900 TRACE("processing extension header\n");
901 if (pExtHdr->cb != sizeof(AVIEXTHEADER) - sizeof(RIFFCHUNK))
902 {
903 FIXME("Size: %u\n", pExtHdr->cb);
904 break;
905 }
906 TRACE("dwGrandFrames: %u\n", pExtHdr->dwGrandFrames);
907 for (x = 0; x < 61; ++x)
908 if (pExtHdr->dwFuture[x])
909 FIXME("dwFuture[%i] = %u (0x%08x)\n", x, pExtHdr->dwFuture[x], pExtHdr->dwFuture[x]);
910 This->ExtHeader = *pExtHdr;
911 break;
912 }
913 default:
914 FIXME("unknown chunk type \"%.04s\" ignored\n", (LPCSTR)&pChunk->fcc);
915 }
916 }
917
918 return S_OK;
919}
#define ckidAVIEXTHEADER
Definition: aviriff.h:72
DWORD dwGrandFrames
Definition: aviriff.h:77
DWORD dwFuture[61]
Definition: aviriff.h:78
DWORD cb
Definition: aviriff.h:76
FOURCC fcc
Definition: aviriff.h:27
DWORD cb
Definition: aviriff.h:28
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
const char * LPCSTR
Definition: xmlstorage.h:183

Referenced by AVISplitter_InputPin_PreConnect().

◆ AVISplitter_ProcessOldIndex()

static HRESULT AVISplitter_ProcessOldIndex ( AVISplitterImpl This)
static

Definition at line 607 of file avisplit.c.

608{
609 ULONGLONG mov_pos = BYTES_FROM_MEDIATIME(This->CurrentChunkOffset) - sizeof(DWORD);
610 AVIOLDINDEX *pAviOldIndex = This->oldindex;
611 int relative = -1;
612 DWORD x;
613
614 for (x = 0; x < pAviOldIndex->cb / sizeof(pAviOldIndex->aIndex[0]); ++x)
615 {
616 DWORD temp, temp2 = 0, offset, chunkid;
617 PullPin *pin = This->Parser.pInputPin;
618
619 offset = pAviOldIndex->aIndex[x].dwOffset;
620 chunkid = pAviOldIndex->aIndex[x].dwChunkId;
621
622 TRACE("dwChunkId: %.4s\n", (char *)&chunkid);
623 TRACE("dwFlags: %08x\n", pAviOldIndex->aIndex[x].dwFlags);
624 TRACE("dwOffset (%s): %08x\n", relative ? "relative" : "absolute", offset);
625 TRACE("dwSize: %08x\n", pAviOldIndex->aIndex[x].dwSize);
626
627 /* Only scan once, or else this will take too long */
628 if (relative == -1)
629 {
630 IAsyncReader_SyncRead(pin->pReader, offset, sizeof(DWORD), (BYTE *)&temp);
631 relative = (chunkid != temp);
632
633 if (chunkid == mmioFOURCC('7','F','x','x')
634 && ((char *)&temp)[0] == 'i' && ((char *)&temp)[1] == 'x')
635 relative = FALSE;
636
637 if (relative)
638 {
639 if (offset + mov_pos < BYTES_FROM_MEDIATIME(This->EndOfFile))
640 IAsyncReader_SyncRead(pin->pReader, offset + mov_pos, sizeof(DWORD), (BYTE *)&temp2);
641
642 if (chunkid == mmioFOURCC('7','F','x','x')
643 && ((char *)&temp2)[0] == 'i' && ((char *)&temp2)[1] == 'x')
644 {
645 /* Do nothing, all is great */
646 }
647 else if (temp2 != chunkid)
648 {
649 ERR("Faulty index or bug in handling: Wanted FCC: %s, Abs FCC: %s (@ %x), Rel FCC: %s (@ %s)\n",
650 debugstr_an((char *)&chunkid, 4), debugstr_an((char *)&temp, 4), offset,
651 debugstr_an((char *)&temp2, 4), wine_dbgstr_longlong(mov_pos + offset));
652 relative = -1;
653 }
654 else
655 TRACE("Scanned dwChunkId: %s\n", debugstr_an((char *)&temp2, 4));
656 }
657 else if (!relative)
658 TRACE("Scanned dwChunkId: %s\n", debugstr_an((char *)&temp, 4));
659 }
660 /* Only dump one packet */
661 else break;
662 }
663
664 if (relative == -1)
665 {
666 FIXME("Dropping index: no idea whether it is relative or absolute\n");
667 CoTaskMemFree(This->oldindex);
668 This->oldindex = NULL;
669 }
670 else if (!relative)
671 This->offset = 0;
672 else
673 This->offset = (DWORD)mov_pos;
674
675 return S_OK;
676}
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
#define DWORD
Definition: nt_native.h:44
static calc_node_t temp
Definition: rpn_ieee.c:38
struct _avioldindex::_avioldindex_entry aIndex[ANYSIZE_ARRAY]
DWORD cb
Definition: aviriff.h:138
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by AVISplitter_InputPin_PreConnect().

◆ AVISplitter_ProcessStreamList()

static HRESULT AVISplitter_ProcessStreamList ( AVISplitterImpl This,
const BYTE pData,
DWORD  cb,
ALLOCATOR_PROPERTIES props 
)
static

Definition at line 678 of file avisplit.c.

679{
680 PIN_INFO piOutput;
681 const RIFFCHUNK * pChunk;
682 HRESULT hr;
683 AM_MEDIA_TYPE amt;
684 float fSamplesPerSec = 0.0f;
685 DWORD dwSampleSize = 0;
686 DWORD dwLength = 0;
687 DWORD nstdindex = 0;
688 static const WCHAR wszStreamTemplate[] = {'S','t','r','e','a','m',' ','%','0','2','d',0};
690
691 ZeroMemory(&amt, sizeof(amt));
692 piOutput.dir = PINDIR_OUTPUT;
693 piOutput.pFilter = &This->Parser.filter.IBaseFilter_iface;
694 wsprintfW(piOutput.achName, wszStreamTemplate, This->Parser.cStreams);
695 This->streams = CoTaskMemRealloc(This->streams, sizeof(StreamData) * (This->Parser.cStreams+1));
696 stream = This->streams + This->Parser.cStreams;
697 ZeroMemory(stream, sizeof(*stream));
698
699 for (pChunk = (const RIFFCHUNK *)pData;
700 ((const BYTE *)pChunk >= pData) && ((const BYTE *)pChunk + sizeof(RIFFCHUNK) < pData + cb) && (pChunk->cb > 0);
701 pChunk = (const RIFFCHUNK *)((const BYTE*)pChunk + sizeof(RIFFCHUNK) + pChunk->cb)
702 )
703 {
704 switch (pChunk->fcc)
705 {
706 case ckidSTREAMHEADER:
707 {
708 const AVISTREAMHEADER * pStrHdr = (const AVISTREAMHEADER *)pChunk;
709 TRACE("processing stream header\n");
710 stream->streamheader = *pStrHdr;
711
712 fSamplesPerSec = (float)pStrHdr->dwRate / (float)pStrHdr->dwScale;
713 CoTaskMemFree(amt.pbFormat);
714 amt.pbFormat = NULL;
715 amt.cbFormat = 0;
716
717 switch (pStrHdr->fccType)
718 {
719 case streamtypeVIDEO:
720 amt.formattype = FORMAT_VideoInfo;
721 break;
722 case streamtypeAUDIO:
723 amt.formattype = FORMAT_WaveFormatEx;
724 break;
725 default:
726 FIXME("fccType %.4s not handled yet\n", (const char *)&pStrHdr->fccType);
727 amt.formattype = FORMAT_None;
728 }
729 amt.majortype = MEDIATYPE_Video;
730 amt.majortype.Data1 = pStrHdr->fccType;
731 amt.subtype = MEDIATYPE_Video;
732 amt.subtype.Data1 = pStrHdr->fccHandler;
733 TRACE("Subtype FCC: %.04s\n", (LPCSTR)&pStrHdr->fccHandler);
734 amt.lSampleSize = pStrHdr->dwSampleSize;
735 amt.bFixedSizeSamples = (amt.lSampleSize != 0);
736
737 /* FIXME: Is this right? */
738 if (!amt.lSampleSize)
739 {
740 amt.lSampleSize = 1;
741 dwSampleSize = 1;
742 }
743
744 amt.bTemporalCompression = IsEqualGUID(&amt.majortype, &MEDIATYPE_Video); /* FIXME? */
745 dwSampleSize = pStrHdr->dwSampleSize;
746 dwLength = pStrHdr->dwLength;
747 if (!dwLength)
748 dwLength = This->AviHeader.dwTotalFrames;
749
750 if (pStrHdr->dwSuggestedBufferSize && pStrHdr->dwSuggestedBufferSize > props->cbBuffer)
751 props->cbBuffer = pStrHdr->dwSuggestedBufferSize;
752
753 break;
754 }
755 case ckidSTREAMFORMAT:
756 TRACE("processing stream format data\n");
757 if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo))
758 {
759 VIDEOINFOHEADER * pvi;
760 /* biCompression member appears to override the value in the stream header.
761 * i.e. the stream header can say something completely contradictory to what
762 * is in the BITMAPINFOHEADER! */
763 if (pChunk->cb < sizeof(BITMAPINFOHEADER))
764 {
765 ERR("Not enough bytes for BITMAPINFOHEADER\n");
766 return E_FAIL;
767 }
768 amt.cbFormat = sizeof(VIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER) + pChunk->cb;
769 amt.pbFormat = CoTaskMemAlloc(amt.cbFormat);
770 ZeroMemory(amt.pbFormat, amt.cbFormat);
771 pvi = (VIDEOINFOHEADER *)amt.pbFormat;
772 pvi->AvgTimePerFrame = (LONGLONG)(10000000.0 / fSamplesPerSec);
773
774 CopyMemory(&pvi->bmiHeader, pChunk + 1, pChunk->cb);
775 if (pvi->bmiHeader.biCompression)
776 amt.subtype.Data1 = pvi->bmiHeader.biCompression;
777 }
778 else if (IsEqualIID(&amt.formattype, &FORMAT_WaveFormatEx))
779 {
780 amt.cbFormat = pChunk->cb;
781 if (amt.cbFormat < sizeof(WAVEFORMATEX))
782 amt.cbFormat = sizeof(WAVEFORMATEX);
783 amt.pbFormat = CoTaskMemAlloc(amt.cbFormat);
784 ZeroMemory(amt.pbFormat, amt.cbFormat);
785 CopyMemory(amt.pbFormat, pChunk + 1, pChunk->cb);
786 }
787 else
788 {
789 amt.cbFormat = pChunk->cb;
790 amt.pbFormat = CoTaskMemAlloc(amt.cbFormat);
791 CopyMemory(amt.pbFormat, pChunk + 1, amt.cbFormat);
792 }
793 break;
794 case ckidSTREAMNAME:
795 TRACE("processing stream name\n");
796 /* FIXME: this doesn't exactly match native version (we omit the "##)" prefix), but hey... */
797 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)(pChunk + 1), pChunk->cb, piOutput.achName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0]));
798 break;
800 FIXME("process stream handler data\n");
801 break;
802 case ckidAVIPADDING:
803 TRACE("JUNK chunk ignored\n");
804 break;
806 {
807 const AVISUPERINDEX *pIndex = (const AVISUPERINDEX *)pChunk;
808 DWORD x;
809 UINT rest = pIndex->cb - sizeof(AVISUPERINDEX) + sizeof(RIFFCHUNK) + sizeof(pIndex->aIndex[0]) * ANYSIZE_ARRAY;
810
811 if (pIndex->cb < sizeof(AVISUPERINDEX) - sizeof(RIFFCHUNK))
812 {
813 FIXME("size %u\n", pIndex->cb);
814 break;
815 }
816
817 if (nstdindex++ > 0)
818 {
819 ERR("Stream %d got more than 1 superindex?\n", This->Parser.cStreams);
820 break;
821 }
822
823 TRACE("wLongsPerEntry: %hd\n", pIndex->wLongsPerEntry);
824 TRACE("bIndexSubType: %u\n", pIndex->bIndexSubType);
825 TRACE("bIndexType: %u\n", pIndex->bIndexType);
826 TRACE("nEntriesInUse: %u\n", pIndex->nEntriesInUse);
827 TRACE("dwChunkId: %.4s\n", (const char *)&pIndex->dwChunkId);
828 if (pIndex->dwReserved[0])
829 TRACE("dwReserved[0]: %u\n", pIndex->dwReserved[0]);
830 if (pIndex->dwReserved[1])
831 TRACE("dwReserved[1]: %u\n", pIndex->dwReserved[1]);
832 if (pIndex->dwReserved[2])
833 TRACE("dwReserved[2]: %u\n", pIndex->dwReserved[2]);
834
835 if (pIndex->bIndexType != AVI_INDEX_OF_INDEXES
836 || pIndex->wLongsPerEntry != 4
837 || rest < (pIndex->nEntriesInUse * sizeof(DWORD) * pIndex->wLongsPerEntry)
838 || (pIndex->bIndexSubType != AVI_INDEX_SUB_2FIELD && pIndex->bIndexSubType != AVI_INDEX_SUB_DEFAULT))
839 {
840 FIXME("Invalid index chunk encountered\n");
841 break;
842 }
843
844 stream->entries = pIndex->nEntriesInUse;
845 stream->stdindex = CoTaskMemRealloc(stream->stdindex, sizeof(*stream->stdindex) * stream->entries);
846 for (x = 0; x < pIndex->nEntriesInUse; ++x)
847 {
848 TRACE("qwOffset: %s\n", wine_dbgstr_longlong(pIndex->aIndex[x].qwOffset));
849 TRACE("dwSize: %u\n", pIndex->aIndex[x].dwSize);
850 TRACE("dwDuration: %u (unreliable)\n", pIndex->aIndex[x].dwDuration);
851
852 AVISplitter_ProcessIndex(This, &stream->stdindex[x], pIndex->aIndex[x].qwOffset, pIndex->aIndex[x].dwSize);
853 }
854 break;
855 }
856 default:
857 FIXME("unknown chunk type \"%.04s\" ignored\n", (LPCSTR)&pChunk->fcc);
858 }
859 }
860
861 if (IsEqualGUID(&amt.formattype, &FORMAT_WaveFormatEx))
862 {
863 amt.subtype = MEDIATYPE_Video;
864 amt.subtype.Data1 = ((WAVEFORMATEX *)amt.pbFormat)->wFormatTag;
865 }
866
867 dump_AM_MEDIA_TYPE(&amt);
868 TRACE("fSamplesPerSec = %f\n", (double)fSamplesPerSec);
869 TRACE("dwSampleSize = %x\n", dwSampleSize);
870 TRACE("dwLength = %x\n", dwLength);
871
872 stream->fSamplesPerSec = fSamplesPerSec;
873 stream->dwSampleSize = dwSampleSize;
874 stream->dwLength = dwLength; /* TODO: Use this for mediaseeking */
875 stream->packet_queued = CreateEventW(NULL, 0, 0, NULL);
876
877 hr = Parser_AddPin(&(This->Parser), &piOutput, props, &amt);
878 CoTaskMemFree(amt.pbFormat);
879
880
881 return hr;
882}
struct tagVIDEOINFOHEADER VIDEOINFOHEADER
#define streamtypeAUDIO
Definition: aviriff.h:93
#define ckidAVISUPERINDEX
Definition: aviriff.h:194
#define AVI_INDEX_SUB_2FIELD
Definition: aviriff.h:179
#define streamtypeVIDEO
Definition: aviriff.h:92
#define ckidSTREAMHEADER
Definition: aviriff.h:88
#define AVI_INDEX_OF_INDEXES
Definition: aviriff.h:172
#define ckidSTREAMFORMAT
Definition: aviriff.h:125
static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, AVISTDINDEX **index, LONGLONG qwOffset, DWORD cb)
Definition: avisplit.c:552
@ PINDIR_OUTPUT
Definition: axcore.idl:42
HRESULT Parser_AddPin(ParserImpl *This, const PIN_INFO *piOutput, ALLOCATOR_PROPERTIES *props, const AM_MEDIA_TYPE *amt)
Definition: parser.c:446
#define CP_ACP
Definition: compat.h:109
#define MultiByteToWideChar
Definition: compat.h:110
static DWORD DWORD * dwLength
Definition: fusion.c:86
static float(__cdecl *square_half_float)(float x
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *pmt)
Definition: enummedia.c:38
DWORD biCompression
Definition: amvideo.idl:35
DWORD dwSampleSize
Definition: aviriff.h:114
FOURCC fccHandler
Definition: aviriff.h:103
FOURCC fccType
Definition: aviriff.h:102
DWORD dwSuggestedBufferSize
Definition: aviriff.h:112
DWORD dwLength
Definition: aviriff.h:111
BITMAPINFOHEADER bmiHeader
Definition: amvideo.idl:189
REFERENCE_TIME AvgTimePerFrame
Definition: amvideo.idl:187
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
#define ckidSTREAMNAME
Definition: vfw.h:896
#define ckidSTREAMHANDLERDATA
Definition: vfw.h:895
#define ZeroMemory
Definition: winbase.h:1712
#define CopyMemory
Definition: winbase.h:1710
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by AVISplitter_InputPin_PreConnect().

◆ AVISplitter_QueryAccept()

static HRESULT AVISplitter_QueryAccept ( LPVOID  iface,
const AM_MEDIA_TYPE pmt 
)
static

Definition at line 545 of file avisplit.c.

546{
547 if (IsEqualIID(&pmt->majortype, &MEDIATYPE_Stream) && IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_Avi))
548 return S_OK;
549 return S_FALSE;
550}

Referenced by AVISplitter_create().

◆ AVISplitter_Receive()

static HRESULT AVISplitter_Receive ( AVISplitterImpl This,
IMediaSample sample,
DWORD  streamnumber 
)
static

Definition at line 293 of file avisplit.c.

294{
295 Parser_OutputPin *pin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1+streamnumber]);
296 HRESULT hr;
297 LONGLONG start, stop, rtstart, rtstop;
298 StreamData *stream = &This->streams[streamnumber];
299
300 start = pin->dwSamplesProcessed;
301 start *= stream->streamheader.dwScale;
302 start *= 10000000;
303 start /= stream->streamheader.dwRate;
304
305 if (stream->streamheader.dwSampleSize)
306 {
307 ULONG len = IMediaSample_GetActualDataLength(sample);
308 ULONG size = stream->streamheader.dwSampleSize;
309
310 pin->dwSamplesProcessed += len / size;
311 }
312 else
313 ++pin->dwSamplesProcessed;
314
315 stop = pin->dwSamplesProcessed;
316 stop *= stream->streamheader.dwScale;
317 stop *= 10000000;
318 stop /= stream->streamheader.dwRate;
319
320 if (IMediaSample_IsDiscontinuity(sample) == S_OK) {
321 IPin *victim;
322 EnterCriticalSection(&This->Parser.filter.csFilter);
323 pin->pin.pin.tStart = start;
324 pin->pin.pin.dRate = This->Parser.sourceSeeking.dRate;
325 hr = IPin_ConnectedTo(&pin->pin.pin.IPin_iface, &victim);
326 if (hr == S_OK)
327 {
328 hr = IPin_NewSegment(victim, start, This->Parser.sourceSeeking.llStop,
329 This->Parser.sourceSeeking.dRate);
330 if (hr != S_OK)
331 FIXME("NewSegment returns %08x\n", hr);
332 IPin_Release(victim);
333 }
334 LeaveCriticalSection(&This->Parser.filter.csFilter);
335 if (hr != S_OK)
336 return hr;
337 }
338 rtstart = (double)(start - pin->pin.pin.tStart) / pin->pin.pin.dRate;
339 rtstop = (double)(stop - pin->pin.pin.tStart) / pin->pin.pin.dRate;
340 IMediaSample_SetMediaTime(sample, &start, &stop);
341 IMediaSample_SetTime(sample, &rtstart, &rtstop);
342 IMediaSample_SetMediaTime(sample, &start, &stop);
343
344 hr = BaseOutputPinImpl_Deliver(&pin->pin, sample);
345
346/* Uncomment this if you want to debug the time differences between the
347 * different streams, it is useful for that
348 *
349 FIXME("stream %u, hr: %08x, Start: %u.%03u, Stop: %u.%03u\n", streamnumber, hr,
350 (DWORD)(start / 10000000), (DWORD)((start / 10000)%1000),
351 (DWORD)(stop / 10000000), (DWORD)((stop / 10000)%1000));
352*/
353 return hr;
354}
static Parser_OutputPin * unsafe_impl_Parser_OutputPin_from_IPin(IPin *iface)
Definition: parser.h:81
GLuint start
Definition: gl.h:1545
Definition: axcore.idl:92
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
HRESULT WINAPI BaseOutputPinImpl_Deliver(BaseOutputPin *This, IMediaSample *pSample)
Definition: pin.c:574
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)

Referenced by AVISplitter_thread_reader().

◆ AVISplitter_Release()

static ULONG WINAPI AVISplitter_Release ( IBaseFilter iface)
static

Definition at line 1267 of file avisplit.c.

1268{
1270 ULONG ref;
1271
1272 ref = InterlockedDecrement(&This->Parser.filter.refCount);
1273
1274 TRACE("(%p)->() Release from %d\n", This, ref + 1);
1275
1276 if (!ref)
1277 {
1279 Parser_Destroy(&This->Parser);
1280 }
1281
1282 return ref;
1283}
#define InterlockedDecrement
Definition: armddk.h:52
void Parser_Destroy(ParserImpl *This)
Definition: parser.c:176

◆ AVISplitter_Sample()

static HRESULT AVISplitter_Sample ( LPVOID  iface,
IMediaSample pSample,
DWORD_PTR  cookie 
)
static

Definition at line 394 of file avisplit.c.

395{
396 AVISplitterImpl *This = iface;
397 StreamData *stream = This->streams + cookie;
398 HRESULT hr = S_OK;
399
400 if (!IMediaSample_GetActualDataLength(pSample))
401 {
402 ERR("Received empty sample\n");
403 return S_OK;
404 }
405
406 /* Send the sample to whatever thread is appropriate
407 * That thread should also not have a sample queued at the moment
408 */
409 /* Debugging */
410 TRACE("(%p)->(%p size: %u, %lu)\n", This, pSample, IMediaSample_GetActualDataLength(pSample), cookie);
411 assert(cookie < This->Parser.cStreams);
412 assert(!stream->sample);
413 assert(WaitForSingleObject(stream->packet_queued, 0) == WAIT_TIMEOUT);
414
415 IMediaSample_AddRef(pSample);
416
417 stream->sample = pSample;
418 SetEvent(stream->packet_queued);
419
420 return hr;
421}
Definition: cookie.c:34

Referenced by AVISplitter_create(), and AVISplitter_first_request().

◆ AVISplitter_seek()

static HRESULT WINAPI AVISplitter_seek ( IMediaSeeking iface)
static

Definition at line 1285 of file avisplit.c.

1286{
1288 PullPin *pPin = This->Parser.pInputPin;
1289 LONGLONG newpos, endpos;
1290 DWORD x;
1291
1292 newpos = This->Parser.sourceSeeking.llCurrent;
1293 endpos = This->Parser.sourceSeeking.llDuration;
1294
1295 if (newpos > endpos)
1296 {
1297 WARN("Requesting position %x%08x beyond end of stream %x%08x\n", (DWORD)(newpos>>32), (DWORD)newpos, (DWORD)(endpos>>32), (DWORD)endpos);
1298 return E_INVALIDARG;
1299 }
1300
1301 FIXME("Moving position to %u.%03u s!\n", (DWORD)(newpos / 10000000), (DWORD)((newpos / 10000)%1000));
1302
1304 /* Send a flush to all output pins */
1305 IPin_BeginFlush(&pPin->pin.IPin_iface);
1306
1307 /* Make sure this is done while stopped, BeginFlush takes care of this */
1308 EnterCriticalSection(&This->Parser.filter.csFilter);
1309 for (x = 0; x < This->Parser.cStreams; ++x)
1310 {
1312 StreamData *stream = This->streams + x;
1313 LONGLONG wanted_frames;
1314 DWORD last_keyframe = 0, last_keyframeidx = 0, preroll = 0;
1315
1316 wanted_frames = newpos;
1317 wanted_frames *= stream->streamheader.dwRate;
1318 wanted_frames /= 10000000;
1319 wanted_frames /= stream->streamheader.dwScale;
1320
1321 pin->dwSamplesProcessed = 0;
1322 stream->index = 0;
1323 stream->pos = 0;
1324 stream->seek = TRUE;
1325 if (stream->stdindex)
1326 {
1327 DWORD y, z = 0;
1328
1329 for (y = 0; y < stream->entries; ++y)
1330 {
1331 for (z = 0; z < stream->stdindex[y]->nEntriesInUse; ++z)
1332 {
1333 if (stream->streamheader.dwSampleSize)
1334 {
1335 ULONG len = stream->stdindex[y]->aIndex[z].dwSize & ~(1u << 31);
1336 ULONG size = stream->streamheader.dwSampleSize;
1337
1338 pin->dwSamplesProcessed += len / size;
1339 if (len % size)
1340 ++pin->dwSamplesProcessed;
1341 }
1342 else ++pin->dwSamplesProcessed;
1343
1344 if (!(stream->stdindex[y]->aIndex[z].dwSize >> 31))
1345 {
1346 last_keyframe = z;
1347 last_keyframeidx = y;
1348 preroll = 0;
1349 }
1350 else
1351 ++preroll;
1352
1353 if (pin->dwSamplesProcessed >= wanted_frames)
1354 break;
1355 }
1356 if (pin->dwSamplesProcessed >= wanted_frames)
1357 break;
1358 }
1359 stream->index = last_keyframeidx;
1360 stream->pos = last_keyframe;
1361 }
1362 else
1363 {
1364 DWORD nMax, n;
1365 nMax = This->oldindex->cb / sizeof(This->oldindex->aIndex[0]);
1366
1367 for (n = 0; n < nMax; ++n)
1368 {
1369 DWORD streamId = StreamFromFOURCC(This->oldindex->aIndex[n].dwChunkId);
1370 if (streamId != x)
1371 continue;
1372
1373 if (stream->streamheader.dwSampleSize)
1374 {
1375 ULONG len = This->oldindex->aIndex[n].dwSize;
1376 ULONG size = stream->streamheader.dwSampleSize;
1377
1378 pin->dwSamplesProcessed += len / size;
1379 if (len % size)
1380 ++pin->dwSamplesProcessed;
1381 }
1382 else ++pin->dwSamplesProcessed;
1383
1384 if (This->oldindex->aIndex[n].dwFlags & AVIIF_KEYFRAME)
1385 {
1386 last_keyframe = n;
1387 preroll = 0;
1388 }
1389 else
1390 ++preroll;
1391
1392 if (pin->dwSamplesProcessed >= wanted_frames)
1393 break;
1394 }
1395 assert(n < nMax);
1396 stream->pos = last_keyframe;
1397 stream->index = 0;
1398 }
1399 stream->preroll = preroll;
1400 stream->seek = TRUE;
1401 }
1402 LeaveCriticalSection(&This->Parser.filter.csFilter);
1403
1404 TRACE("Done flushing\n");
1405 IPin_EndFlush(&pPin->pin.IPin_iface);
1407
1408 return S_OK;
1409}
#define AVIIF_KEYFRAME
Definition: aviriff.h:131
static AVISplitterImpl * impl_from_IMediaSeeking(IMediaSeeking *iface)
Definition: avisplit.c:103
#define WARN(fmt,...)
Definition: debug.h:112
IPin IPin_iface
Definition: strmbase.h:35
CRITICAL_SECTION thread_lock
Definition: pin.h:94
BasePin pin
Definition: pin.h:73

Referenced by AVISplitter_create().

◆ AVISplitter_SendEndOfFile()

static HRESULT AVISplitter_SendEndOfFile ( AVISplitterImpl This,
DWORD  streamnumber 
)
static

Definition at line 128 of file avisplit.c.

129{
130 IPin* ppin = NULL;
131 HRESULT hr;
132
133 TRACE("End of file reached\n");
134
135 hr = IPin_ConnectedTo(This->Parser.ppPins[streamnumber+1], &ppin);
136 if (SUCCEEDED(hr))
137 {
138 hr = IPin_EndOfStream(ppin);
139 IPin_Release(ppin);
140 }
141 TRACE("--> %x\n", hr);
142
143 /* Force the pullpin thread to stop */
144 return S_FALSE;
145}

Referenced by AVISplitter_first_request(), and AVISplitter_thread_reader().

◆ AVISplitter_thread_reader()

static DWORD WINAPI AVISplitter_thread_reader ( LPVOID  data)
static

Definition at line 356 of file avisplit.c.

357{
358 struct thread_args *args = data;
359 AVISplitterImpl *This = args->This;
360 DWORD streamnumber = args->stream;
361 HRESULT hr = S_OK;
362
363 do
364 {
365 HRESULT nexthr = S_FALSE;
366 IMediaSample *sample;
367
368 WaitForSingleObject(This->streams[streamnumber].packet_queued, INFINITE);
369 sample = This->streams[streamnumber].sample;
370 This->streams[streamnumber].sample = NULL;
371 if (!sample)
372 break;
373
374 nexthr = AVISplitter_next_request(This, streamnumber);
375
376 hr = AVISplitter_Receive(This, sample, streamnumber);
377 if (hr != S_OK)
378 FIXME("Receiving error: %08x\n", hr);
379
380 IMediaSample_Release(sample);
381 if (hr == S_OK)
382 hr = nexthr;
383 if (nexthr == S_FALSE)
384 AVISplitter_SendEndOfFile(This, streamnumber);
385 } while (hr == S_OK);
386
387 if (hr != S_FALSE)
388 FIXME("Thread %u terminated with hr %08x!\n", streamnumber, hr);
389 else
390 TRACE("Thread %u terminated properly\n", streamnumber);
391 return hr;
392}
static HRESULT AVISplitter_Receive(AVISplitterImpl *This, IMediaSample *sample, DWORD streamnumber)
Definition: avisplit.c:293
#define INFINITE
Definition: serial.h:102
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950

Referenced by AVISplitter_first_request().

◆ impl_from_IMediaSeeking()

static AVISplitterImpl * impl_from_IMediaSeeking ( IMediaSeeking iface)
inlinestatic

Definition at line 103 of file avisplit.c.

104{
105 return CONTAINING_RECORD(iface, AVISplitterImpl, Parser.sourceSeeking.IMediaSeeking_iface);
106}
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by AVISplitter_seek().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( quartz  )

Variable Documentation

◆ AVISplitterImpl_Vtbl

const IBaseFilterVtbl AVISplitterImpl_Vtbl
static
Initial value:
=
{
}
static ULONG WINAPI AVISplitter_Release(IBaseFilter *iface)
Definition: avisplit.c:1267
HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *pInfo)
Definition: parser.c:419
HRESULT WINAPI Parser_GetClassID(IBaseFilter *iface, CLSID *pClsid)
Definition: parser.c:228
HRESULT WINAPI Parser_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
Definition: parser.c:313
HRESULT WINAPI Parser_Pause(IBaseFilter *iface)
Definition: parser.c:279
HRESULT WINAPI Parser_Stop(IBaseFilter *iface)
Definition: parser.c:241
ULONG WINAPI Parser_AddRef(IBaseFilter *iface)
Definition: parser.c:171
HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter *iface, LPWSTR *pVendorInfo)
Definition: parser.c:429
HRESULT WINAPI Parser_GetState(IBaseFilter *iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
Definition: parser.c:361
HRESULT WINAPI Parser_GetSyncSource(IBaseFilter *iface, IReferenceClock **ppClock)
Definition: parser.c:397
HRESULT WINAPI Parser_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum)
Definition: parser.c:404
HRESULT WINAPI Parser_SetSyncSource(IBaseFilter *iface, IReferenceClock *pClock)
Definition: parser.c:383
HRESULT WINAPI Parser_QueryInterface(IBaseFilter *iface, REFIID riid, LPVOID *ppv)
Definition: parser.c:142
HRESULT WINAPI Parser_FindPin(IBaseFilter *iface, LPCWSTR Id, IPin **ppPin)
Definition: parser.c:409
HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *pGraph, LPCWSTR pName)
Definition: parser.c:424

Definition at line 1411 of file avisplit.c.

Referenced by AVISplitter_create().