001: /*
002: * Copyright (c) 2000 Silvere Martin-Michiellot All Rights Reserved.
003: *
004: * Silvere Martin-Michiellot grants you ("Licensee") a non-exclusive,
005: * royalty free, license to use, modify and redistribute this
006: * software in source and binary code form,
007: * provided that i) this copyright notice and license appear on all copies of
008: * the software; and ii) Licensee does not utilize the software in a manner
009: * which is disparaging to Silvere Martin-Michiellot.
010: *
011: * This software is provided "AS IS," without a warranty of any kind. ALL
012: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
013: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
014: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. Silvere Martin-Michiellot
015: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
016: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
017: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
018: * Silvere Martin-Michiellot OR ITS LICENSORS BE LIABLE
019: * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
020: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
021: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
022: * OR INABILITY TO USE SOFTWARE, EVEN IF Silvere Martin-Michiellot HAS BEEN
023: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
024: *
025: * This software is not designed or intended for use in on-line control of
026: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
027: * the design, construction, operation or maintenance of any nuclear
028: * facility. Licensee represents and warrants that it will not use or
029: * redistribute the Software for such purposes.
030: *
031: */
032:
033: package com.db.layers.underlay;
034:
035: import java.awt.Dimension;
036: import javax.media.*;
037: import javax.media.format.*;
038: import javax.media.protocol.*;
039: import javax.media.protocol.DataSource;
040: import java.io.IOException;
041:
042: public class LiveStream implements PushBufferStream, Runnable {
043:
044: private ContentDescriptor cd = new ContentDescriptor(
045: ContentDescriptor.RAW);
046: private int maxDataLength;
047: private byte[] data;
048: private Dimension size;
049: private RGBFormat rgbFormat;
050: private AudioFormat audioFormat;
051: private boolean started;
052: private Thread thread;
053:
054: private final static float DEFAULT_FRAME_RATE = 25;
055: private float frameRate = DEFAULT_FRAME_RATE;
056:
057: private BufferTransferHandler transferHandler;
058: private Control[] controls = new Control[0];
059:
060: private boolean videoData = true;
061:
062: public LiveStream() {
063:
064: if (videoData) {
065: int x, y, pos, revpos;
066:
067: size = new Dimension(320, 240);
068: maxDataLength = size.width * size.height * 3;
069: rgbFormat = new RGBFormat(size, maxDataLength,
070: Format.byteArray, frameRate, 24, 3, 2, 1, 3,
071: size.width * 3, VideoFormat.FALSE,
072: Format.NOT_SPECIFIED);
073:
074: // generate the data
075: data = new byte[maxDataLength];
076: pos = 0;
077: revpos = (size.height - 1) * size.width * 3;
078: for (y = 0; y < size.height / 2; y++) {
079: for (x = 0; x < size.width; x++) {
080: byte value = (byte) ((y * 2) & 0xFF);
081: data[pos++] = value;
082: data[pos++] = 0;
083: data[pos++] = 0;
084: data[revpos++] = value;
085: data[revpos++] = 0;
086: data[revpos++] = 0;
087: }
088: revpos -= size.width * 6;
089: }
090: } else { // audio data
091: audioFormat = new AudioFormat(AudioFormat.LINEAR, 8000.0,
092: 8, 1, Format.NOT_SPECIFIED, AudioFormat.SIGNED, 8,
093: Format.NOT_SPECIFIED, Format.byteArray);
094: maxDataLength = 1000;
095: }
096:
097: thread = new Thread(this );
098:
099: }
100:
101: public ContentDescriptor getContentDescriptor() {
102:
103: return cd;
104:
105: }
106:
107: public long getContentLength() {
108:
109: return LENGTH_UNKNOWN;
110:
111: }
112:
113: public boolean endOfStream() {
114:
115: return false;
116:
117: }
118:
119: int seqNo = 0;
120: double freq = 2.0;
121:
122: public Format getFormat() {
123:
124: if (videoData)
125: return rgbFormat;
126: else
127: return audioFormat;
128:
129: }
130:
131: public void read(Buffer buffer) throws IOException {
132:
133: synchronized (this ) {
134: Object outdata = buffer.getData();
135: if (outdata == null
136: || !(outdata.getClass() == Format.byteArray)
137: || ((byte[]) outdata).length < maxDataLength) {
138: outdata = new byte[maxDataLength];
139: buffer.setData(outdata);
140: }
141: if (videoData) {
142: buffer.setFormat(rgbFormat);
143: buffer
144: .setTimeStamp((long) (seqNo
145: * (1000 / frameRate) * 1000000));
146: int lineNo = (seqNo * 2) % size.height;
147: int chunkStart = lineNo * size.width * 3;
148: System.arraycopy(data, chunkStart, outdata, 0,
149: maxDataLength - (chunkStart));
150: if (chunkStart != 0) {
151: System.arraycopy(data, 0, outdata, maxDataLength
152: - chunkStart, chunkStart);
153: }
154: } else {
155: buffer.setFormat(audioFormat);
156: buffer.setTimeStamp(1000000000 / 8);
157: for (int i = 0; i < 1000; i++) {
158: ((byte[]) outdata)[i] = (byte) (Math.sin(i / freq) * 32);
159: freq = (freq + 0.01);
160: if (freq > 10.0)
161: freq = 2.0;
162: }
163: }
164: buffer.setSequenceNumber(seqNo);
165: buffer.setLength(maxDataLength);
166: buffer.setFlags(0);
167: buffer.setHeader(null);
168: seqNo++;
169: }
170:
171: }
172:
173: public void setTransferHandler(BufferTransferHandler transferHandler) {
174:
175: synchronized (this ) {
176: this .transferHandler = transferHandler;
177: notifyAll();
178: }
179:
180: }
181:
182: void start(boolean started) {
183:
184: synchronized (this ) {
185: this .started = started;
186: if (started && !thread.isAlive()) {
187: thread = new Thread(this );
188: thread.start();
189: }
190: notifyAll();
191: }
192:
193: }
194:
195: public void run() {
196:
197: while (started) {
198: synchronized (this ) {
199: while (transferHandler == null && started) {
200: try {
201: wait(1000);
202: } catch (InterruptedException ie) {
203: }
204: } // while
205: }
206:
207: if (started && transferHandler != null) {
208: transferHandler.transferData(this );
209: try {
210: Thread.currentThread().sleep(10);
211: } catch (InterruptedException ise) {
212: }
213: }
214: } // while (started)
215:
216: } // run
217:
218: public Object[] getControls() {
219:
220: return controls;
221:
222: }
223:
224: public Object getControl(String controlType) {
225:
226: try {
227: Class cls = Class.forName(controlType);
228: Object cs[] = getControls();
229: for (int i = 0; i < cs.length; i++) {
230: if (cls.isInstance(cs[i]))
231: return cs[i];
232: }
233: return null;
234:
235: } catch (Exception e) { // no such controlType or such control
236: return null;
237: }
238:
239: }
240:
241: }
|