This repository was archived by the owner on Jun 15, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtee.c
More file actions
156 lines (127 loc) · 4.32 KB
/
tee.c
File metadata and controls
156 lines (127 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* Splits stream two ways. Copies each frame of the incoming stream into
* the outgoing stream. A function (such as targetoverlay) can then
* modify the outgoing stream without harming the incoming stream. tee
* uses the callback functionality of the incoming nstream to notify it
* when to copy frames, and call the optional callback function.
*
* BUGS: Does not implement double buffering as it should, but instead
* just locks the mutex on the outgoing stream while it copies
* the frame and executes the callback function.
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "nstream.h"
#include "tee.h"
/*
* Starts the tee.
*
* stream: The incoming stream to be copied.
* optarg: An optional argument to the imagemodify function.
* imagemodify: An optional callback to be called (while the
* buffer mutex is locked) usually used to
* modify the outgoing stream. Takes two
* arguments, the nstream_t * of the outgoing
* stream, and the void * of the optarg passed to
* tee_start on initialization.
*/
struct tee_hand_t *tee_start(struct nstream_t *stream, void *optarg,
void (*imagemodify) (struct nstream_t *, void *))
{
struct tee_hand_t *out;
/* initialize stuff */
out = malloc(sizeof(struct tee_hand_t));
assert(out);
out->imagemodify = imagemodify;
assert(out->imagemodify);
out->optarg = optarg;
out->stream = stream;
out->out_stream =
nstream_init(stream->imgwidth, stream->imgheight, stream->imgdepth,
tee_callstartstream, tee_callstopstream, out);
assert(out->out_stream);
/* set the callback */
out->stream->callbackarg = out;
out->stream->newframe = tee_newframe_handle;
out->stream->streamstarting = tee_streamstarting_handle;
out->stream->streamstopping = tee_streamstopping_handle;
return out;
}
void tee_stop(struct tee_hand_t *handle)
{
/* unset the callback */
handle->stream->newframe = NULL;
/* clean up */
nstream_destroy(handle->out_stream);
free(handle->out_stream->buf);
free(handle);
return;
}
/*
* Callbacks registered in the incoming and outgoing streams, providing a
* passthrough. Also, callbacks that implement copying the incoming stream
* buffers into the outgoing stream.
*/
/*
* Callback passthrough (called by outgoing stream recieving end)
*/
int tee_callstartstream(struct nstream_t *nstm)
{
return nstm->startstream(nstm);
}
/*
* Callback passthrough (called by outgoing stream recieving end)
*/
int tee_callstopstream(struct nstream_t *nstm)
{
return nstm->stopstream(nstm);
}
/*
* Copies buffers from the incoming stream into the outgoing stream.
*
* stream: The incoming stream.
* optarg: Pointer to tee_hand_t, which contains a pointer to the
* outgoing stream.
*/
void tee_newframe_handle(struct nstream_t *stream, void *optarg)
{
struct tee_hand_t *handle = optarg;
pthread_mutex_lock(&handle->stream->mutex);
pthread_mutex_lock(&handle->out_stream->mutex);
memcpy(handle->out_stream->buf, handle->stream->buf,
handle->stream->bufsize);
handle->imagemodify(handle->out_stream, handle->optarg);
/* handle->out_stream->buf = stream->buf; */
pthread_mutex_unlock(&handle->out_stream->mutex);
pthread_mutex_unlock(&handle->stream->mutex);
if (handle->out_stream->newframe) {
handle->out_stream->newframe(handle->out_stream,
handle->out_stream->callbackarg);
}
return;
}
/*
* Callback passthrough (called by incoming stream sending end)
*/
void tee_streamstarting_handle(struct nstream_t *stream, void *optarg)
{
struct tee_hand_t *handle = optarg;
if (handle->out_stream->streamstarting) {
handle->out_stream->streamstarting(handle->out_stream,
handle->out_stream->callbackarg);
}
return;
}
/*
* Callback passthrough (called by incoming stream sending end)
*/
void tee_streamstopping_handle(struct nstream_t *stream, void *optarg)
{
struct tee_hand_t *handle = optarg;
if (handle->out_stream->streamstopping) {
handle->out_stream->streamstopping(handle->out_stream,
handle->out_stream->callbackarg);
}
return;
}