Check-in [0caee6df12]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:improvements in tclwmf extension code
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0caee6df1282d470058e48fd87404d541f5cb495
User & Date: chw 2016-07-15 13:51:37
Context
2016-07-15
15:37
add selected SDL2 upstream changes check-in: b9140dc5ec user: chw tags: trunk
13:51
improvements in tclwmf extension code check-in: 0caee6df12 user: chw tags: trunk
09:59
add tcl upstream changes check-in: d5f759979a user: chw tags: trunk
Changes

jni/tcl/library/tzdata/America/Resolute became executable.

Changes to undroid/tclwmf/tclwmf.c.

111
112
113
114
115
116
117

118
119
120
121
122
123
124
...
154
155
156
157
158
159
160

161
162
163
164
165
166
167
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
501
502
503
504
505
506
507



508
509
510
511
512
513
514
...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
...
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
...
636
637
638
639
640
641
642
643

644

645
646
647
648
649
650
651
...
931
932
933
934
935
936
937

938
939
940
941
942
943
944
...
963
964
965
966
967
968
969

970
971
972
973
974
975
976
....
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046

1047
1048


1049
1050
1051
1052












1053
1054
1055
1056
1057
1058
1059
....
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
....
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
....
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
....
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
 * IMFSourceReaderCallback implementation.
 */

typedef struct {
    interface IMFSourceReaderCallback isrcb;	/* Interface, methods. */
    CRITICAL_SECTION lock;			/* Mutex. */
    int refCount;				/* Reference count. */

    struct WMFC *wmfc;				/* Pointer to WMF struct. */
} SourceReaderCB;

/*
 * Frame buffer.
 */

................................................................................
    IMFMediaSource *mediaSrc;	/* Handle for device. */
    IMFSourceReader *srcReader;	/* Handle for capture. */
    Tcl_Interp *interp;		/* Interpreter for this object. */
    char devId[32];		/* Device id. */
    Tcl_DString devName;	/* Device name. */
    int cbCmdLen;               /* Initial length of callback command. */
    Tcl_DString cbCmd;          /* Callback command prefix. */

    int fourcc;			/* Media format code. */
    int stride, width, height;	/* Image dimensions. */
    int mirror;			/* Image mirror flags. */
    int rotate;			/* Image rotation in degrees. */
    Tcl_WideInt counters[4];	/* Statistic counters. */
    int useFmt;			/* MediaFmt index to use. */
    int numFmts;		/* Number formats in fmts. */
................................................................................
 */

#ifdef USE_ASYNC_HANDLER
static int SignalBuffer(ClientData clientData, Tcl_Interp *interp, int code);
#else
static int SignalBuffer(Tcl_Event *evPtr, int flags);
#endif
static int StopCapture(WMFC *wmfc);

 
/*
 *-------------------------------------------------------------------------
 *
 * EnumDevices --
 *
................................................................................
    LeaveCriticalSection(&srcb->lock);
    return hr;
}

static HRESULT STDMETHODCALLTYPE
SR_OnFlush(IMFSourceReaderCallback *This, DWORD streamIndex)
{



    return S_OK;
}

static HRESULT STDMETHODCALLTYPE
SR_OnEvent(IMFSourceReaderCallback *This, DWORD streamIndex,
	   IMFMediaEvent *pEvent)
{
................................................................................
};
 
/*
 *-------------------------------------------------------------------------
 *
 * ImageCallback --
 *
 *	Called as do-when-idle handler from the (async) event handler
 *	when a new image is available or image capture was stopped
 *	due to an error.
 *
 *-------------------------------------------------------------------------
 */

static void
................................................................................
    int ret;
#ifdef USE_ASYNC_HANDLER
    int capture = (wmfc->async != NULL);
#else
    int capture = (wmfc->tid != NULL);
#endif


    Tcl_DStringSetLength(&wmfc->cbCmd, wmfc->cbCmdLen);
    Tcl_DStringAppendElement(&wmfc->cbCmd, wmfc->devId);
    if (wmfc->streamEnd) {
	Tcl_DStringAppendElement(&wmfc->cbCmd, (wmfc->streamEnd < 0) ?
				 "error" : "eof");
    } else {
	Tcl_DStringAppendElement(&wmfc->cbCmd, capture ? "capture" : "stop");
    }
    Tcl_Preserve((ClientData) interp);
    ret = Tcl_EvalEx(interp, Tcl_DStringValue(&wmfc->cbCmd),
		     Tcl_DStringLength(&wmfc->cbCmd), TCL_EVAL_GLOBAL);
    if (ret != TCL_OK) {
	StopCapture(wmfc);
	Tcl_AddErrorInfo(interp, "\n    (wmf event handler)");
 	Tcl_BackgroundError(interp);
    }
    Tcl_Release((ClientData) interp);
}
 
/*
 *-------------------------------------------------------------------------
 *
 * SignalBuffer --
 *
 *	(Async) event handler called when an image became ready.
 *	Requests next frame and schedules do-when-idle handler
 *	for performing the Tcl callback established on open.
 *
 *-------------------------------------------------------------------------
 */

static int
#ifdef USE_ASYNC_HANDLER
................................................................................
	Tcl_AsyncDelete(wmfc->async);
	wmfc->async = NULL;
#else
	wmfc->tid = NULL;
#endif
    }
    if (bufok || dostop) {
	Tcl_CancelIdleCall(ImageCallback, (ClientData) wmfc);

	Tcl_DoWhenIdle(ImageCallback, (ClientData) wmfc);

    }
    return code;
}
 
/*
 *-------------------------------------------------------------------------
 *
................................................................................
	wmfc->counters[0] = wmfc->counters[1] = 0;
	wmfc->counters[2] = wmfc->counters[3] = 0;
	wmfc->frame[0].ready = wmfc->frame[1].ready = 0;
	wmfc->streamEnd = 0;
	wmfc->frameReady = wmfc->frameQueued = -1;
	wmfc->srcb.isrcb.lpVtbl = &SourceReaderVtbl;
	wmfc->srcb.refCount = 1;

	wmfc->srcb.wmfc = wmfc;
	hr = attr->lpVtbl->SetUnknown(attr,
				      &MF_SOURCE_READER_ASYNC_CALLBACK,
				      (struct IUnknown *) &wmfc->srcb);
	hr = MFCreateSourceReaderFromMediaSource(wmfc->mediaSrc, attr,
						 &wmfc->srcReader);
	if (attr != NULL) {
................................................................................
	    return TCL_ERROR;
	}
	if (GetFormat(wmfc) != TCL_OK) {
 	    wmfc->srcReader->lpVtbl->Release(wmfc->srcReader);
	    wmfc->srcReader = NULL;
	    return TCL_ERROR;
	}

    }
    EnterCriticalSection(&wmfc->srcb.lock);
#ifdef USE_ASYNC_HANDLER
    if (wmfc->async == NULL) {
	wmfc->async = Tcl_AsyncCreate(SignalBuffer, (ClientData) wmfc);
	doread = 1;
    }
................................................................................
 
/*
 *-------------------------------------------------------------------------
 *
 * StopCapture --
 *
 *      Stop capture if running. The (async) event handler is removed and
 *	a pending idle call to ImageCallback is cancelled, too.
 *
 *-------------------------------------------------------------------------
 */

static int
StopCapture(WMFC *wmfc)
{
#ifdef USE_ASYNC_HANDLER
    EnterCriticalSection(&wmfc->srcb.lock);

    if (wmfc->async != NULL) {
        Tcl_AsyncDelete(wmfc->async);
        wmfc->async = NULL;
    }
    wmfc->frameQueued = -1;
    if (wmfc->srcReader != NULL) {
	wmfc->srcReader->lpVtbl->Flush(wmfc->srcReader,
				       MF_SOURCE_READER_ALL_STREAMS);
    }
    LeaveCriticalSection(&wmfc->srcb.lock);
#else
    EnterCriticalSection(&wmfc->srcb.lock);
    wmfc->tid = NULL;

    if (wmfc->streamEnd < 0) {
	wmfc->streamEnd = 0;
    }
    wmfc->frameQueued = -1;
    if (wmfc->srcReader != NULL) {

	wmfc->srcReader->lpVtbl->Flush(wmfc->srcReader,
				       MF_SOURCE_READER_ALL_STREAMS);


    }
    LeaveCriticalSection(&wmfc->srcb.lock);
#endif
    Tcl_CancelIdleCall(ImageCallback, (ClientData) wmfc);












    return TCL_OK;
}
 
/*
 *-------------------------------------------------------------------------
 *
 * GetImage --
................................................................................
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    WMFC *wmfc;

    hPtr = Tcl_FirstHashEntry(&wmfi->wmfc, &search);
    while (hPtr != NULL) {
	wmfc = (WMFC *) Tcl_GetHashValue(hPtr);
	StopCapture(wmfc);
	if (wmfc->srcReader != NULL) {
	    wmfc->srcReader->lpVtbl->Release(wmfc->srcReader);
	}
	if (wmfc->mediaSrc != NULL) {
	    wmfc->mediaSrc->lpVtbl->Release(wmfc->mediaSrc);
	}
	if (wmfc->frame[0].data != NULL) {
................................................................................
devNotFound:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("device \"%s\" not found",
			Tcl_GetString(objv[2])));
	    ret = TCL_ERROR;
	}
	wmfc = (WMFC *) Tcl_GetHashValue(hPtr);
	Tcl_DeleteHashEntry(hPtr);
	StopCapture(wmfc);
	if (wmfc->srcReader != NULL) {
	    wmfc->srcReader->lpVtbl->Release(wmfc->srcReader);
	}
	if (wmfc->mediaSrc != NULL) {
	    wmfc->mediaSrc->lpVtbl->Release(wmfc->mediaSrc);
	}
	if (wmfc->frame[0].data != NULL) {
................................................................................
	wmfc->mediaSrc = mediaSrc;
	wmfc->srcReader = NULL;
	wmfc->streamEnd = 0;
	wmfc->frameReady = wmfc->frameQueued = -1;
        wmfc->mirror = 0;
        wmfc->rotate = 0;
        wmfc->interp = interp;

	InitializeCriticalSection(&wmfc->srcb.lock);
 	Tcl_DStringInit(&wmfc->devName);
	Tcl_DStringAppend(&wmfc->devName, devName, -1);
	Tcl_DStringInit(&wmfc->cbCmd);
	Tcl_DStringAppend(&wmfc->cbCmd, Tcl_GetString(objv[3]), -1);
	wmfc->useFmt = -1;
	wmfc->numFmts = numFmts;
................................................................................
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(&wmfi->wmfc, Tcl_GetString(objv[2]));
	if (hPtr == NULL) {
	    goto devNotFound;
	}
	wmfc = (WMFC *) Tcl_GetHashValue(hPtr);
	StopCapture(wmfc);
	break;
    }

    }

    return ret;
}







>







 







>







 







|







 







>
>
>







 







|







 







>












|












|







 







|
>
|
>







 







>







 







>







 







|





|

<

>




<
<
<
<
<
<

<

>





>


>
>


<
<
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







>







 







|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
...
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
...
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
....
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042






1043

1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057


1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
....
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
....
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
....
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
....
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
 * IMFSourceReaderCallback implementation.
 */

typedef struct {
    interface IMFSourceReaderCallback isrcb;	/* Interface, methods. */
    CRITICAL_SECTION lock;			/* Mutex. */
    int refCount;				/* Reference count. */
    int closing;				/* True during close. */
    struct WMFC *wmfc;				/* Pointer to WMF struct. */
} SourceReaderCB;

/*
 * Frame buffer.
 */

................................................................................
    IMFMediaSource *mediaSrc;	/* Handle for device. */
    IMFSourceReader *srcReader;	/* Handle for capture. */
    Tcl_Interp *interp;		/* Interpreter for this object. */
    char devId[32];		/* Device id. */
    Tcl_DString devName;	/* Device name. */
    int cbCmdLen;               /* Initial length of callback command. */
    Tcl_DString cbCmd;          /* Callback command prefix. */
    Tcl_TimerToken cbPending;	/* Set when callback dispatched. */
    int fourcc;			/* Media format code. */
    int stride, width, height;	/* Image dimensions. */
    int mirror;			/* Image mirror flags. */
    int rotate;			/* Image rotation in degrees. */
    Tcl_WideInt counters[4];	/* Statistic counters. */
    int useFmt;			/* MediaFmt index to use. */
    int numFmts;		/* Number formats in fmts. */
................................................................................
 */

#ifdef USE_ASYNC_HANDLER
static int SignalBuffer(ClientData clientData, Tcl_Interp *interp, int code);
#else
static int SignalBuffer(Tcl_Event *evPtr, int flags);
#endif
static int StopCapture(WMFC *wmfc, int closing);

 
/*
 *-------------------------------------------------------------------------
 *
 * EnumDevices --
 *
................................................................................
    LeaveCriticalSection(&srcb->lock);
    return hr;
}

static HRESULT STDMETHODCALLTYPE
SR_OnFlush(IMFSourceReaderCallback *This, DWORD streamIndex)
{
    SourceReaderCB *srcb = (SourceReaderCB *) This;

    srcb->closing = 0;
    return S_OK;
}

static HRESULT STDMETHODCALLTYPE
SR_OnEvent(IMFSourceReaderCallback *This, DWORD streamIndex,
	   IMFMediaEvent *pEvent)
{
................................................................................
};
 
/*
 *-------------------------------------------------------------------------
 *
 * ImageCallback --
 *
 *	Called as timer handler from the (async) event handler
 *	when a new image is available or image capture was stopped
 *	due to an error.
 *
 *-------------------------------------------------------------------------
 */

static void
................................................................................
    int ret;
#ifdef USE_ASYNC_HANDLER
    int capture = (wmfc->async != NULL);
#else
    int capture = (wmfc->tid != NULL);
#endif

    wmfc->cbPending = NULL;
    Tcl_DStringSetLength(&wmfc->cbCmd, wmfc->cbCmdLen);
    Tcl_DStringAppendElement(&wmfc->cbCmd, wmfc->devId);
    if (wmfc->streamEnd) {
	Tcl_DStringAppendElement(&wmfc->cbCmd, (wmfc->streamEnd < 0) ?
				 "error" : "eof");
    } else {
	Tcl_DStringAppendElement(&wmfc->cbCmd, capture ? "capture" : "stop");
    }
    Tcl_Preserve((ClientData) interp);
    ret = Tcl_EvalEx(interp, Tcl_DStringValue(&wmfc->cbCmd),
		     Tcl_DStringLength(&wmfc->cbCmd), TCL_EVAL_GLOBAL);
    if (ret != TCL_OK) {
	StopCapture(wmfc, 0);
	Tcl_AddErrorInfo(interp, "\n    (wmf event handler)");
 	Tcl_BackgroundError(interp);
    }
    Tcl_Release((ClientData) interp);
}
 
/*
 *-------------------------------------------------------------------------
 *
 * SignalBuffer --
 *
 *	(Async) event handler called when an image became ready.
 *	Requests next frame and schedules timer handler
 *	for performing the Tcl callback established on open.
 *
 *-------------------------------------------------------------------------
 */

static int
#ifdef USE_ASYNC_HANDLER
................................................................................
	Tcl_AsyncDelete(wmfc->async);
	wmfc->async = NULL;
#else
	wmfc->tid = NULL;
#endif
    }
    if (bufok || dostop) {
	if (wmfc->cbPending == NULL) {
	    wmfc->cbPending =
		Tcl_CreateTimerHandler(0, ImageCallback, (ClientData) wmfc);
	}
    }
    return code;
}
 
/*
 *-------------------------------------------------------------------------
 *
................................................................................
	wmfc->counters[0] = wmfc->counters[1] = 0;
	wmfc->counters[2] = wmfc->counters[3] = 0;
	wmfc->frame[0].ready = wmfc->frame[1].ready = 0;
	wmfc->streamEnd = 0;
	wmfc->frameReady = wmfc->frameQueued = -1;
	wmfc->srcb.isrcb.lpVtbl = &SourceReaderVtbl;
	wmfc->srcb.refCount = 1;
	wmfc->srcb.closing = 0;
	wmfc->srcb.wmfc = wmfc;
	hr = attr->lpVtbl->SetUnknown(attr,
				      &MF_SOURCE_READER_ASYNC_CALLBACK,
				      (struct IUnknown *) &wmfc->srcb);
	hr = MFCreateSourceReaderFromMediaSource(wmfc->mediaSrc, attr,
						 &wmfc->srcReader);
	if (attr != NULL) {
................................................................................
	    return TCL_ERROR;
	}
	if (GetFormat(wmfc) != TCL_OK) {
 	    wmfc->srcReader->lpVtbl->Release(wmfc->srcReader);
	    wmfc->srcReader = NULL;
	    return TCL_ERROR;
	}
	wmfc->cbPending = NULL;
    }
    EnterCriticalSection(&wmfc->srcb.lock);
#ifdef USE_ASYNC_HANDLER
    if (wmfc->async == NULL) {
	wmfc->async = Tcl_AsyncCreate(SignalBuffer, (ClientData) wmfc);
	doread = 1;
    }
................................................................................
 
/*
 *-------------------------------------------------------------------------
 *
 * StopCapture --
 *
 *      Stop capture if running. The (async) event handler is removed and
 *	a pending call to ImageCallback is cancelled, too.
 *
 *-------------------------------------------------------------------------
 */

static int
StopCapture(WMFC *wmfc, int closing)
{

    EnterCriticalSection(&wmfc->srcb.lock);
#ifdef USE_ASYNC_HANDLER
    if (wmfc->async != NULL) {
        Tcl_AsyncDelete(wmfc->async);
        wmfc->async = NULL;
    }






#else

    wmfc->tid = NULL;
#endif
    if (wmfc->streamEnd < 0) {
	wmfc->streamEnd = 0;
    }
    wmfc->frameQueued = -1;
    if (wmfc->srcReader != NULL) {
	wmfc->srcb.closing = closing;
	wmfc->srcReader->lpVtbl->Flush(wmfc->srcReader,
				       MF_SOURCE_READER_ALL_STREAMS);
    } else {
	closing = 0;
    }
    LeaveCriticalSection(&wmfc->srcb.lock);


    Tcl_DeleteTimerHandler(wmfc->cbPending);
    wmfc->cbPending = NULL;
    if (closing) {
	int i;

	for (i = 0; i < 5; i++) {
	    if (!wmfc->srcb.closing) {
		break;
	    }
	    Sleep(20);
	}
    }
    return TCL_OK;
}
 
/*
 *-------------------------------------------------------------------------
 *
 * GetImage --
................................................................................
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    WMFC *wmfc;

    hPtr = Tcl_FirstHashEntry(&wmfi->wmfc, &search);
    while (hPtr != NULL) {
	wmfc = (WMFC *) Tcl_GetHashValue(hPtr);
	StopCapture(wmfc, 1);
	if (wmfc->srcReader != NULL) {
	    wmfc->srcReader->lpVtbl->Release(wmfc->srcReader);
	}
	if (wmfc->mediaSrc != NULL) {
	    wmfc->mediaSrc->lpVtbl->Release(wmfc->mediaSrc);
	}
	if (wmfc->frame[0].data != NULL) {
................................................................................
devNotFound:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("device \"%s\" not found",
			Tcl_GetString(objv[2])));
	    ret = TCL_ERROR;
	}
	wmfc = (WMFC *) Tcl_GetHashValue(hPtr);
	Tcl_DeleteHashEntry(hPtr);
	StopCapture(wmfc, 1);
	if (wmfc->srcReader != NULL) {
	    wmfc->srcReader->lpVtbl->Release(wmfc->srcReader);
	}
	if (wmfc->mediaSrc != NULL) {
	    wmfc->mediaSrc->lpVtbl->Release(wmfc->mediaSrc);
	}
	if (wmfc->frame[0].data != NULL) {
................................................................................
	wmfc->mediaSrc = mediaSrc;
	wmfc->srcReader = NULL;
	wmfc->streamEnd = 0;
	wmfc->frameReady = wmfc->frameQueued = -1;
        wmfc->mirror = 0;
        wmfc->rotate = 0;
        wmfc->interp = interp;
	wmfc->cbPending = NULL;
	InitializeCriticalSection(&wmfc->srcb.lock);
 	Tcl_DStringInit(&wmfc->devName);
	Tcl_DStringAppend(&wmfc->devName, devName, -1);
	Tcl_DStringInit(&wmfc->cbCmd);
	Tcl_DStringAppend(&wmfc->cbCmd, Tcl_GetString(objv[3]), -1);
	wmfc->useFmt = -1;
	wmfc->numFmts = numFmts;
................................................................................
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(&wmfi->wmfc, Tcl_GetString(objv[2]));
	if (hPtr == NULL) {
	    goto devNotFound;
	}
	wmfc = (WMFC *) Tcl_GetHashValue(hPtr);
	StopCapture(wmfc, 0);
	break;
    }

    }

    return ret;
}