1 /*
2 * combiner.cc --
3 *
4 * FIXME: This file needs a description here.
5 *
6 * Copyright (c) 2001-2002 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * A. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * B. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * C. Neither the names of the copyright holders nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
22 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "combiner.h"
35
36 // this file has the code for combining two (or more hypothetically) RTP
37 // streams into one stream whose frames are the glued images of both the
38 // incoming streams. Then it gives the output to a Real encoding engine
39
40 // Constructor for our list node...
41 CombinerSourceNode::CombinerSourceNode(char* s, int p): pos(p),width(0),height(0),next(0) {
42 strcpy(source,s);
43 }
44
45 // =======================
46
47 // Wrapper for the OTcl object...
48 static class CombinerSourceClass : public TclClass {
49 public:
50 CombinerSourceClass() : TclClass ("CombinerSource") {};
51 TclObject* create(int argc, const char*const* argv) {
52 return (new CombinerSource((Combiner*)TclObject::lookup(argv[4]),argv[5],atoi(argv[6])));
53 };
54 } combiner_source;
55
56 CombinerSource::CombinerSource(Combiner* destination, const char* s, int c): dest(destination),colorModel(c) {
57 strcpy(src, s);
58 }
59
60 // this is the whole reason we need this class, so that it can tell the
61 // combiner which source the image came from.
62 void CombinerSource::recv(Buffer* b) {
63 dest->recv(b, src, colorModel);
64 }
65
66 // ==========================
67
68 // Wrapper for the OTcl object...
69 static class CombinerClass : public TclClass {
70 public:
71 CombinerClass() : TclClass ("Combiner") {};
72 TclObject* create(int argc, const char*const* argv) {
73 return (new Combiner());
74 };
75 } combiner;
76
77
78 Combiner::Combiner(): destination(0),width(0),height(0),sources(0),frame_(0),frame_data_(0) {
79 }
80
81 Combiner::~Combiner() {
82 };
83
84 // this does all the work of gluing the two images together and handing it off.
85 void Combiner::recv(Buffer* b, char* source, int colorModel) {
86 YuvFrame* in_frame_ = (YuvFrame*)b;
87 u_int8_t* dest;
88 u_int8_t* src;
89 int rownum;
90 CombinerSourceNode* temp;
91
92 if (frame_ == 0) {
93 // search the list to see if dimensions were entered yet...
94 for (temp=sources; temp != 0; temp=temp->next) {
95 if (strcmp(temp->source, source) == 0) {
96 temp->width = in_frame_->width_;
97 temp->height = in_frame_->height_;
98 break;
99 }
100 }
101 // wait until we have at least two sources...
102 if (sources !=0 && sources->next != 0) {
103 // sort them so that they are in the right left to right order (currently only works for 2 sources)
104 if (sources->pos == 2) {
105 temp = sources;
106 sources = sources->next;
107 temp->next = 0;
108 sources->next = temp;
109 }
110
111 if ((sources->width != 0) && (sources->next->width != 0)) {
112 // gather the total size of the output frame
113 for(temp=sources; temp != 0; temp=temp->next) {
114 width += temp->width;
115 if (height < temp->height)
116 height = temp->height;
117 }
118 // FIXME -- should check to make sure the size is a multiple of 8.
119 // allocate the data structure to store the frame data...
120 frame_data_ = new u_int8_t[(width*height*3)/2];
121 frame_ = new YuvFrame(0,frame_data_,0,width,height, 0);
122 } else
123 return;
124 } else
125 return;
126 }
127
128 // check to see if it is a frame we are going to use...
129 if ((strcmp(sources->source,source) != 0) && (strcmp(sources->next->source,source) != 0))
130 return;
131
132 dest = frame_data_;
133 src = in_frame_->bp_;
134 // determine if this is the second source and then put the
135 // dest (destination) pointer to the appropriate offset in the frame.
136 if (strcmp(source,sources->source) != 0)
137 dest = &(dest[sources->width]);
138
139 // copy the Luninescence
140 for(rownum=0;rownum<in_frame_->height_;rownum++)
141 memcpy(&(dest[(rownum*width)]),&(src[rownum*(in_frame_->width_)]),in_frame_->width_);
142
143 dest = &(frame_data_[width*height]);
144 src = &((in_frame_->bp_)[in_frame_->width_*in_frame_->height_]);
145 // once again, determine the proper destination in the frame (like above)
146 if (strcmp(source,sources->source) != 0)
147 dest = &(dest[(sources->width)/2]);
148
149 // copy the chrominence (the U component)
150 if (colorModel == 422) {
151 for(rownum=0;rownum<((in_frame_->height_)/2);rownum++)
152 memcpy(&(dest[(rownum*width)/2]),&(src[rownum*in_frame_->width_]),(in_frame_->width_)/2);
153 } else {
154 for(rownum=0;rownum<((in_frame_->height_)/2);rownum++)
155 memcpy(&(dest[(rownum*width)/2]),&(src[(rownum*(in_frame_->width_))/2]),(in_frame_->width_)/2);
156 }
157
158 dest = &(frame_data_[(width*height*5)/4]);
159 if (colorModel == 422)
160 src = &((in_frame_->bp_)[(in_frame_->width_*in_frame_->height_*3)/2]);
161 else
162 src = &((in_frame_->bp_)[(in_frame_->width_*in_frame_->height_*5)/4]);
163 // once again, determine the proper destination in the frame (like above)
164 if (strcmp(source,sources->source) != 0)
165 dest = &(dest[(sources->width)/2]);
166
167 // copy the chrominence (the V component)
168 if (colorModel == 422) {
169 for(rownum=0;rownum<((in_frame_->height_)/2);rownum++)
170 memcpy(&(dest[(rownum*width)/2]),&(src[rownum*in_frame_->width_]),(in_frame_->width_)/2);
171 } else {
172 for(rownum=0;rownum<((in_frame_->height_)/2);rownum++)
173 memcpy(&(dest[(rownum*width)/2]),&(src[(rownum*(in_frame_->width_))/2]),(in_frame_->width_)/2);
174 }
175
176 // hand it off to the Real Encoder.
177 if (destination != 0)
178 destination->recv(frame_, 0, 0);
179 }
180
181 // For Tcl commands to call from Tcl space...
182 int Combiner::command(int argc, const char*const* argv) {
183 Tcl& tcl = Tcl::instance();
184 if (argc == 2) {
185 if (strcmp(argv[1], "unlinkEncoder") == 0) {
186 destination = 0;
187 return (TCL_OK);
188 } else if (strcmp(argv[1], "ready") == 0) {
189 if ((sources != 0) && (sources->next != 0))
190 tcl.resultf("yes");
191 else
192 tcl.resultf("no");
193 return (TCL_OK);
194 }
195 } else if (argc == 3) {
196 if (strcmp(argv[1], "linkEncoder") == 0) {
197 destination = (Renderer*)TclObject::lookup(argv[2]);
198 return (TCL_OK);
199 }
200 } else if (argc == 4) {
201 if (strcmp(argv[1], "setSide") == 0) {
202 // check to see if the source is already there...
203 for (CombinerSourceNode* temp=sources; temp != 0; temp=temp->next) {
204 if (strcmp(temp->source, argv[3]) == 0) {
205 temp->pos = atoi(argv[2]);
206 return (TCL_OK);
207 }
208 }
209 CombinerSourceNode* head = sources;
210 sources = new CombinerSourceNode((char*)(argv[3]),atoi(argv[2]));
211 sources->next = head;
212 return (TCL_OK);
213 }
214 }
215
216 return (TclObject::command(argc, argv));
217 }
218
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.