1/*
2 * libjingle
3 * Copyright 2013 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28package org.webrtc;
29
30import java.util.LinkedList;
31
32/** Java wrapper for a C++ MediaStreamInterface. */
33public class MediaStream {
34  public final LinkedList<AudioTrack> audioTracks;
35  public final LinkedList<VideoTrack> videoTracks;
36  public final LinkedList<VideoTrack> preservedVideoTracks;
37  // Package-protected for PeerConnection.
38  final long nativeStream;
39
40  public MediaStream(long nativeStream) {
41    audioTracks = new LinkedList<AudioTrack>();
42    videoTracks = new LinkedList<VideoTrack>();
43    preservedVideoTracks = new LinkedList<VideoTrack>();
44    this.nativeStream = nativeStream;
45  }
46
47  public boolean addTrack(AudioTrack track) {
48    if (nativeAddAudioTrack(nativeStream, track.nativeTrack)) {
49      audioTracks.add(track);
50      return true;
51    }
52    return false;
53  }
54
55  public boolean addTrack(VideoTrack track) {
56    if (nativeAddVideoTrack(nativeStream, track.nativeTrack)) {
57      videoTracks.add(track);
58      return true;
59    }
60    return false;
61  }
62
63  // Tracks added in addTrack() call will be auto released once MediaStream.dispose()
64  // is called. If video track need to be preserved after MediaStream is destroyed it
65  // should be added to MediaStream using addPreservedTrack() call.
66  public boolean addPreservedTrack(VideoTrack track) {
67    if (nativeAddVideoTrack(nativeStream, track.nativeTrack)) {
68      preservedVideoTracks.add(track);
69      return true;
70    }
71    return false;
72  }
73
74  public boolean removeTrack(AudioTrack track) {
75    if (nativeRemoveAudioTrack(nativeStream, track.nativeTrack)) {
76      audioTracks.remove(track);
77      return true;
78    }
79    return false;
80  }
81
82  public boolean removeTrack(VideoTrack track) {
83    if (nativeRemoveVideoTrack(nativeStream, track.nativeTrack)) {
84      videoTracks.remove(track);
85      preservedVideoTracks.remove(track);
86      return true;
87    }
88    return false;
89  }
90
91  public void dispose() {
92    // Remove and release previously added audio and video tracks.
93    while (!audioTracks.isEmpty()) {
94      AudioTrack track = audioTracks.getFirst();
95      removeTrack(track);
96      track.dispose();
97    }
98    while (!videoTracks.isEmpty()) {
99      VideoTrack track = videoTracks.getFirst();
100      removeTrack(track);
101      track.dispose();
102    }
103    // Remove, but do not release preserved video tracks.
104    while (!preservedVideoTracks.isEmpty()) {
105      removeTrack(preservedVideoTracks.getFirst());
106    }
107    free(nativeStream);
108  }
109
110  public String label() {
111    return nativeLabel(nativeStream);
112  }
113
114  public String toString() {
115    return "[" + label() + ":A=" + audioTracks.size() +
116        ":V=" + videoTracks.size() + "]";
117  }
118
119  private static native boolean nativeAddAudioTrack(
120      long nativeStream, long nativeAudioTrack);
121
122  private static native boolean nativeAddVideoTrack(
123      long nativeStream, long nativeVideoTrack);
124
125  private static native boolean nativeRemoveAudioTrack(
126      long nativeStream, long nativeAudioTrack);
127
128  private static native boolean nativeRemoveVideoTrack(
129      long nativeStream, long nativeVideoTrack);
130
131  private static native String nativeLabel(long nativeStream);
132
133  private static native void free(long nativeStream);
134}
135