├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── LICENSE
├── README.md
├── build.xml
├── doc
├── allclasses-frame.html
├── allclasses-noframe.html
├── constant-values.html
├── deprecated-list.html
├── help-doc.html
├── index-all.html
├── index.html
├── net
│ └── majorkernelpanic
│ │ └── streaming
│ │ ├── MediaStream.html
│ │ ├── Session.Callback.html
│ │ ├── Session.html
│ │ ├── SessionBuilder.html
│ │ ├── Stream.html
│ │ ├── audio
│ │ ├── AACStream.html
│ │ ├── AMRNBStream.html
│ │ ├── AudioQuality.html
│ │ ├── AudioStream.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ ├── exceptions
│ │ ├── CameraInUseException.html
│ │ ├── ConfNotSupportedException.html
│ │ ├── InvalidSurfaceException.html
│ │ ├── StorageUnavailableException.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ ├── gl
│ │ ├── SurfaceManager.html
│ │ ├── SurfaceView.ViewAspectRatioMeasurer.html
│ │ ├── SurfaceView.html
│ │ ├── TextureManager.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ ├── hw
│ │ ├── CodecManager.html
│ │ ├── EncoderDebugger.html
│ │ ├── NV21Convertor.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ ├── mp4
│ │ ├── MP4Config.html
│ │ ├── MP4Parser.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ ├── package-tree.html
│ │ ├── rtcp
│ │ ├── SenderReport.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ ├── rtp
│ │ ├── AACADTSPacketizer.html
│ │ ├── AACLATMPacketizer.html
│ │ ├── AMRNBPacketizer.html
│ │ ├── AbstractPacketizer.html
│ │ ├── H263Packetizer.html
│ │ ├── H264Packetizer.html
│ │ ├── MediaCodecInputStream.html
│ │ ├── RtpSocket.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ ├── rtsp
│ │ ├── RtspClient.Callback.html
│ │ ├── RtspClient.html
│ │ ├── RtspServer.CallbackListener.html
│ │ ├── RtspServer.LocalBinder.html
│ │ ├── RtspServer.html
│ │ ├── UriParser.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
│ │ └── video
│ │ ├── CodecManager.html
│ │ ├── H263Stream.html
│ │ ├── H264Stream.html
│ │ ├── VideoQuality.html
│ │ ├── VideoStream.html
│ │ ├── package-frame.html
│ │ ├── package-summary.html
│ │ └── package-tree.html
├── overview-frame.html
├── overview-summary.html
├── overview-tree.html
├── package-list
├── resources
│ ├── background.gif
│ ├── tab.gif
│ ├── titlebar.gif
│ └── titlebar_end.gif
├── serialized-form.html
└── stylesheet.css
├── pom.xml
├── proguard-project.txt
├── project.properties
├── res
└── .gitkeep
└── src
└── net
└── majorkernelpanic
└── streaming
├── MediaStream.java
├── Session.java
├── SessionBuilder.java
├── Stream.java
├── audio
├── AACStream.java
├── AMRNBStream.java
├── AudioQuality.java
└── AudioStream.java
├── exceptions
├── CameraInUseException.java
├── ConfNotSupportedException.java
├── InvalidSurfaceException.java
└── StorageUnavailableException.java
├── gl
├── SurfaceManager.java
├── SurfaceView.java
└── TextureManager.java
├── hw
├── CodecManager.java
├── EncoderDebugger.java
└── NV21Convertor.java
├── mp4
├── MP4Config.java
└── MP4Parser.java
├── rtcp
└── SenderReport.java
├── rtp
├── AACADTSPacketizer.java
├── AACLATMPacketizer.java
├── AMRNBPacketizer.java
├── AbstractPacketizer.java
├── H263Packetizer.java
├── H264Packetizer.java
├── MediaCodecInputStream.java
└── RtpSocket.java
├── rtsp
├── RtcpDeinterleaver.java
├── RtspClient.java
├── RtspServer.java
└── UriParser.java
└── video
├── CodecManager.java
├── H263Stream.java
├── H264Stream.java
├── VideoQuality.java
└── VideoStream.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 | *.dex
5 | *.class
6 | bin/
7 | gen/
8 | *.class
9 | *.o
10 | *.so
11 | *.sh
12 | local.properties
13 | custom_rules.xml
14 | ant.properties
15 | *~
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | libstreaming
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
56 |
57 |
69 |
70 |
71 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/doc/allclasses-noframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | All Classes
7 |
8 |
9 |
10 |
11 |
12 | All Classes
13 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/doc/deprecated-list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Deprecated List
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
75 |
76 |
93 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/doc/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Generated Documentation (Untitled)
7 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | JavaScript is disabled on your browser.
70 |
71 | Frame Alert
72 | This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to Non-frame version .
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/audio/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.audio
7 |
8 |
9 |
10 |
11 |
12 |
13 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/audio/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.audio
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
75 |
76 |
77 |
78 | Class Summary
79 |
80 | Class
81 | Description
82 |
83 |
84 |
85 | AACStream
86 |
87 | A class for streaming AAC from the camera of an android device using RTP.
88 |
89 |
90 |
91 | AMRNBStream
92 |
93 | A class for streaming AAC from the camera of an android device using RTP.
94 |
95 |
96 |
97 | AudioQuality
98 |
99 | A class that represents the quality of an audio stream.
100 |
101 |
102 |
103 | AudioStream
104 |
105 | Don't use this class directly.
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
131 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/audio/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.audio Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
83 | net.majorkernelpanic.streaming.audio.AudioQuality
84 | net.majorkernelpanic.streaming.MediaStream (implements net.majorkernelpanic.streaming.Stream )
85 |
86 | net.majorkernelpanic.streaming.audio.AudioStream
87 |
88 | net.majorkernelpanic.streaming.audio.AACStream
89 | net.majorkernelpanic.streaming.audio.AMRNBStream
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
116 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/exceptions/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.exceptions
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Exceptions
15 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/exceptions/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.exceptions
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
105 |
106 |
123 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/exceptions/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.exceptions Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
83 | java.lang.Throwable (implements java.io.Serializable)
84 |
85 | java.lang.Exception
86 |
87 | java.io.IOException
88 |
91 |
92 | java.lang.RuntimeException
93 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
125 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/gl/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.gl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/gl/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.gl
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
75 |
76 |
77 |
78 | Class Summary
79 |
80 | Class
81 | Description
82 |
83 |
84 |
85 | SurfaceManager
86 |
87 |
88 |
89 | SurfaceView
90 |
91 | An enhanced SurfaceView in which the camera preview will be rendered.
92 |
93 |
94 |
95 | TextureManager
96 |
97 | Code for rendering a texture onto a surface using OpenGL ES 2.0.
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
123 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/gl/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.gl Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
92 |
93 |
94 |
95 |
96 |
113 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/hw/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.hw
7 |
8 |
9 |
10 |
11 |
12 |
13 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/hw/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.hw
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
75 |
76 |
77 |
78 | Class Summary
79 |
80 | Class
81 | Description
82 |
83 |
84 |
85 | CodecManager
86 |
87 |
88 |
89 | EncoderDebugger
90 |
91 | The purpose of this class is to detect and by-pass some bugs (or underspecified configuration) that
92 | encoders available through the MediaCodec API may have.
93 |
94 |
95 |
96 | NV21Convertor
97 |
98 | Converts from NV21 to YUV420 semi planar or planar.
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
124 |
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/hw/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.hw Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
87 |
88 |
89 |
90 |
91 |
108 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/mp4/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.mp4
7 |
8 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/mp4/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.mp4
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
75 |
76 |
77 |
78 | Class Summary
79 |
80 | Class
81 | Description
82 |
83 |
84 |
85 | MP4Config
86 |
87 | Finds SPS & PPS parameters in mp4 file.
88 |
89 |
90 |
91 | MP4Parser
92 |
93 | Parse an mp4 file.
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
119 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/mp4/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.mp4 Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
83 | net.majorkernelpanic.streaming.mp4.MP4Config
84 | net.majorkernelpanic.streaming.mp4.MP4Parser
85 |
86 |
87 |
88 |
89 |
90 |
107 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Interfaces
15 |
19 |
Classes
20 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
83 | net.majorkernelpanic.streaming.MediaStream (implements net.majorkernelpanic.streaming.Stream )
84 | net.majorkernelpanic.streaming.Session
85 | net.majorkernelpanic.streaming.SessionBuilder
86 |
87 |
88 |
89 |
Interface Hierarchy
90 |
94 |
95 |
96 |
113 |
114 |
115 | Prev
116 | Next
117 |
118 |
122 |
125 |
126 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/rtcp/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.rtcp
7 |
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/rtcp/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.rtcp
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
75 |
76 |
77 |
78 | Class Summary
79 |
80 | Class
81 | Description
82 |
83 |
84 |
85 | SenderReport
86 |
87 | Implementation of Sender Report RTCP packets.
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
113 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/rtcp/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.rtcp Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
85 |
86 |
87 |
88 |
89 |
106 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/rtp/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.rtp
7 |
8 |
9 |
10 |
11 |
12 |
13 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/rtsp/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.rtsp
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Interfaces
15 |
19 |
Classes
20 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/video/package-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.video
7 |
8 |
9 |
10 |
11 |
12 |
13 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/video/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.video
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
75 |
76 |
77 |
78 | Class Summary
79 |
80 | Class
81 | Description
82 |
83 |
84 |
85 | CodecManager
86 |
87 |
88 |
89 | H263Stream
90 |
91 | A class for streaming H.263 from the camera of an android device using RTP.
92 |
93 |
94 |
95 | H264Stream
96 |
97 | A class for streaming H.264 from the camera of an android device using RTP.
98 |
99 |
100 |
101 | VideoQuality
102 |
103 | A class that represents the quality of a video stream.
104 |
105 |
106 |
107 | VideoStream
108 |
109 | Don't use this class directly.
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
135 |
162 |
163 |
164 |
165 |
--------------------------------------------------------------------------------
/doc/net/majorkernelpanic/streaming/video/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net.majorkernelpanic.streaming.video Class Hierarchy
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
78 |
79 |
Class Hierarchy
80 |
81 | java.lang.Object
82 |
83 | net.majorkernelpanic.streaming.video.CodecManager
84 | net.majorkernelpanic.streaming.MediaStream (implements net.majorkernelpanic.streaming.Stream )
85 |
86 | net.majorkernelpanic.streaming.video.VideoStream
87 |
88 | net.majorkernelpanic.streaming.video.H263Stream
89 | net.majorkernelpanic.streaming.video.H264Stream
90 |
91 |
92 |
93 |
94 | net.majorkernelpanic.streaming.video.VideoQuality
95 |
96 |
97 |
98 |
99 |
100 |
117 |
118 |
119 | Prev
120 | Next
121 |
122 |
126 |
129 |
130 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/doc/overview-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Overview List
7 |
8 |
9 |
10 |
11 |
12 |
13 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/doc/overview-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Overview
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
122 |
123 |
140 |
141 |
142 | Prev
143 | Next
144 |
145 |
149 |
152 |
153 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/doc/package-list:
--------------------------------------------------------------------------------
1 | net.majorkernelpanic.streaming
2 | net.majorkernelpanic.streaming.audio
3 | net.majorkernelpanic.streaming.exceptions
4 | net.majorkernelpanic.streaming.gl
5 | net.majorkernelpanic.streaming.hw
6 | net.majorkernelpanic.streaming.mp4
7 | net.majorkernelpanic.streaming.rtcp
8 | net.majorkernelpanic.streaming.rtp
9 | net.majorkernelpanic.streaming.rtsp
10 | net.majorkernelpanic.streaming.video
11 |
--------------------------------------------------------------------------------
/doc/resources/background.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fyhertz/libstreaming/3a78d2219a4cf5bc972cdc59a8f84349fda277c6/doc/resources/background.gif
--------------------------------------------------------------------------------
/doc/resources/tab.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fyhertz/libstreaming/3a78d2219a4cf5bc972cdc59a8f84349fda277c6/doc/resources/tab.gif
--------------------------------------------------------------------------------
/doc/resources/titlebar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fyhertz/libstreaming/3a78d2219a4cf5bc972cdc59a8f84349fda277c6/doc/resources/titlebar.gif
--------------------------------------------------------------------------------
/doc/resources/titlebar_end.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fyhertz/libstreaming/3a78d2219a4cf5bc972cdc59a8f84349fda277c6/doc/resources/titlebar_end.gif
--------------------------------------------------------------------------------
/doc/serialized-form.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Serialized Form
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 | JavaScript is disabled on your browser.
24 |
25 |
26 |
43 |
70 |
71 |
74 |
119 |
120 |
137 |
138 |
139 | Prev
140 | Next
141 |
142 |
146 |
149 |
150 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 | net.majorkernelpanic
7 | libstreaming
8 | libstreaming
9 | 3.0
10 | apklib
11 | libstreaming is an API that allows you, with only a few lines of code, to stream the camera and/or microphone of an android powered device using RTP over UDP.
12 | https://github.com/fyhertz/libstreaming
13 | 2013
14 |
15 |
16 | https://github.com/fyhertz/libstreaming
17 | scm:git:git://github.com/fyhertz/libstreaming
18 |
19 |
20 |
21 |
22 | fyhertz
23 | fyhertz@gmail.com
24 | fyhertz
25 |
26 | developer
27 |
28 |
29 |
30 |
31 |
32 |
33 | GNU General Public License Version 3
34 | http://www.gnu.org/licenses/gpl.html
35 | repo
36 |
37 |
38 |
39 |
40 | GitHub Issues
41 | https://github.com/fyhertz/libstreaming/issues
42 |
43 |
44 |
45 |
46 | com.google.android
47 | android
48 | 4.3_r2
49 | provided
50 |
51 |
52 |
53 |
54 | src
55 | test
56 |
57 |
58 |
59 | com.jayway.maven.plugins.android.generation2
60 | android-maven-plugin
61 |
62 |
63 | 18
64 |
65 |
66 | true
67 |
68 |
69 |
70 | org.apache.maven.plugins
71 | maven-javadoc-plugin
72 |
73 | true
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-24
12 | android.library=true
13 |
--------------------------------------------------------------------------------
/res/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fyhertz/libstreaming/3a78d2219a4cf5bc972cdc59a8f84349fda277c6/res/.gitkeep
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/Stream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming;
20 |
21 | import java.io.IOException;
22 | import java.io.OutputStream;
23 | import java.net.InetAddress;
24 |
25 | /**
26 | * An interface that represents a Stream.
27 | */
28 | public interface Stream {
29 |
30 | /**
31 | * Configures the stream. You need to call this before calling {@link #getSessionDescription()}
32 | * to apply your configuration of the stream.
33 | */
34 | public void configure() throws IllegalStateException, IOException;
35 |
36 | /**
37 | * Starts the stream.
38 | * This method can only be called after {@link Stream#configure()}.
39 | */
40 | public void start() throws IllegalStateException, IOException;
41 |
42 | /**
43 | * Stops the stream.
44 | */
45 | public void stop();
46 |
47 | /**
48 | * Sets the Time To Live of packets sent over the network.
49 | * @param ttl The time to live
50 | * @throws IOException
51 | */
52 | public void setTimeToLive(int ttl) throws IOException;
53 |
54 | /**
55 | * Sets the destination ip address of the stream.
56 | * @param dest The destination address of the stream
57 | */
58 | public void setDestinationAddress(InetAddress dest);
59 |
60 | /**
61 | * Sets the destination ports of the stream.
62 | * If an odd number is supplied for the destination port then the next
63 | * lower even number will be used for RTP and it will be used for RTCP.
64 | * If an even number is supplied, it will be used for RTP and the next odd
65 | * number will be used for RTCP.
66 | * @param dport The destination port
67 | */
68 | public void setDestinationPorts(int dport);
69 |
70 | /**
71 | * Sets the destination ports of the stream.
72 | * @param rtpPort Destination port that will be used for RTP
73 | * @param rtcpPort Destination port that will be used for RTCP
74 | */
75 | public void setDestinationPorts(int rtpPort, int rtcpPort);
76 |
77 | /**
78 | * If a TCP is used as the transport protocol for the RTP session,
79 | * the output stream to which RTP packets will be written to must
80 | * be specified with this method.
81 | */
82 | public void setOutputStream(OutputStream stream, byte channelIdentifier);
83 |
84 | /**
85 | * Returns a pair of source ports, the first one is the
86 | * one used for RTP and the second one is used for RTCP.
87 | **/
88 | public int[] getLocalPorts();
89 |
90 | /**
91 | * Returns a pair of destination ports, the first one is the
92 | * one used for RTP and the second one is used for RTCP.
93 | **/
94 | public int[] getDestinationPorts();
95 |
96 |
97 | /**
98 | * Returns the SSRC of the underlying {@link net.majorkernelpanic.streaming.rtp.RtpSocket}.
99 | * @return the SSRC of the stream.
100 | */
101 | public int getSSRC();
102 |
103 | /**
104 | * Returns an approximation of the bit rate consumed by the stream in bit per seconde.
105 | */
106 | public long getBitrate();
107 |
108 | /**
109 | * Returns a description of the stream using SDP.
110 | * This method can only be called after {@link Stream#configure()}.
111 | * @throws IllegalStateException Thrown when {@link Stream#configure()} wa not called.
112 | */
113 | public String getSessionDescription() throws IllegalStateException;
114 |
115 | public boolean isStreaming();
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/audio/AMRNBStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.audio;
20 |
21 | import java.io.IOException;
22 | import java.lang.reflect.Field;
23 | import net.majorkernelpanic.streaming.SessionBuilder;
24 | import net.majorkernelpanic.streaming.rtp.AMRNBPacketizer;
25 | import android.media.MediaRecorder;
26 | import android.service.textservice.SpellCheckerService.Session;
27 |
28 | /**
29 | * A class for streaming AAC from the camera of an android device using RTP.
30 | * You should use a {@link Session} instantiated with {@link SessionBuilder} instead of using this class directly.
31 | * Call {@link #setDestinationAddress(InetAddress)}, {@link #setDestinationPorts(int)} and {@link #setAudioQuality(AudioQuality)}
32 | * to configure the stream. You can then call {@link #start()} to start the RTP stream.
33 | * Call {@link #stop()} to stop the stream.
34 | */
35 | public class AMRNBStream extends AudioStream {
36 |
37 | public AMRNBStream() {
38 | super();
39 |
40 | mPacketizer = new AMRNBPacketizer();
41 |
42 | setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
43 |
44 | try {
45 | // RAW_AMR was deprecated in API level 16.
46 | Field deprecatedName = MediaRecorder.OutputFormat.class.getField("RAW_AMR");
47 | setOutputFormat(deprecatedName.getInt(null));
48 | } catch (Exception e) {
49 | setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
50 | }
51 |
52 | setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
53 |
54 | }
55 |
56 | /**
57 | * Starts the stream.
58 | */
59 | public synchronized void start() throws IllegalStateException, IOException {
60 | if (!mStreaming) {
61 | configure();
62 | super.start();
63 | }
64 | }
65 |
66 | public synchronized void configure() throws IllegalStateException, IOException {
67 | super.configure();
68 | mMode = MODE_MEDIARECORDER_API;
69 | mQuality = mRequestedQuality.clone();
70 | }
71 |
72 | /**
73 | * Returns a description of the stream using SDP. It can then be included in an SDP file.
74 | */
75 | public String getSessionDescription() {
76 | return "m=audio "+String.valueOf(getDestinationPorts()[0])+" RTP/AVP 96\r\n" +
77 | "a=rtpmap:96 AMR/8000\r\n" +
78 | "a=fmtp:96 octet-align=1;\r\n";
79 | }
80 |
81 | @Override
82 | protected void encodeWithMediaCodec() throws IOException {
83 | super.encodeWithMediaRecorder();
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/audio/AudioQuality.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.audio;
20 |
21 | /**
22 | * A class that represents the quality of an audio stream.
23 | */
24 | public class AudioQuality {
25 |
26 | /** Default audio stream quality. */
27 | public final static AudioQuality DEFAULT_AUDIO_QUALITY = new AudioQuality(8000,32000);
28 |
29 | /** Represents a quality for a video stream. */
30 | public AudioQuality() {}
31 |
32 | /**
33 | * Represents a quality for an audio stream.
34 | * @param samplingRate The sampling rate
35 | * @param bitRate The bitrate in bit per seconds
36 | */
37 | public AudioQuality(int samplingRate, int bitRate) {
38 | this.samplingRate = samplingRate;
39 | this.bitRate = bitRate;
40 | }
41 |
42 | public int samplingRate = 0;
43 | public int bitRate = 0;
44 |
45 | public boolean equals(AudioQuality quality) {
46 | if (quality==null) return false;
47 | return (quality.samplingRate == this.samplingRate &&
48 | quality.bitRate == this.bitRate);
49 | }
50 |
51 | public AudioQuality clone() {
52 | return new AudioQuality(samplingRate, bitRate);
53 | }
54 |
55 | public static AudioQuality parseQuality(String str) {
56 | AudioQuality quality = DEFAULT_AUDIO_QUALITY.clone();
57 | if (str != null) {
58 | String[] config = str.split("-");
59 | try {
60 | quality.bitRate = Integer.parseInt(config[0])*1000; // conversion to bit/s
61 | quality.samplingRate = Integer.parseInt(config[1]);
62 | }
63 | catch (IndexOutOfBoundsException ignore) {}
64 | }
65 | return quality;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/audio/AudioStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.audio;
20 |
21 | import java.io.FileDescriptor;
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 |
25 | import net.majorkernelpanic.streaming.MediaStream;
26 | import android.media.MediaRecorder;
27 | import android.os.ParcelFileDescriptor;
28 | import android.util.Log;
29 |
30 | /**
31 | * Don't use this class directly.
32 | */
33 | public abstract class AudioStream extends MediaStream {
34 |
35 | protected int mAudioSource;
36 | protected int mOutputFormat;
37 | protected int mAudioEncoder;
38 | protected AudioQuality mRequestedQuality = AudioQuality.DEFAULT_AUDIO_QUALITY.clone();
39 | protected AudioQuality mQuality = mRequestedQuality.clone();
40 |
41 | public AudioStream() {
42 | setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
43 | }
44 |
45 | public void setAudioSource(int audioSource) {
46 | mAudioSource = audioSource;
47 | }
48 |
49 | public void setAudioQuality(AudioQuality quality) {
50 | mRequestedQuality = quality;
51 | }
52 |
53 | /**
54 | * Returns the quality of the stream.
55 | */
56 | public AudioQuality getAudioQuality() {
57 | return mQuality;
58 | }
59 |
60 | protected void setAudioEncoder(int audioEncoder) {
61 | mAudioEncoder = audioEncoder;
62 | }
63 |
64 | protected void setOutputFormat(int outputFormat) {
65 | mOutputFormat = outputFormat;
66 | }
67 |
68 | @Override
69 | protected void encodeWithMediaRecorder() throws IOException {
70 |
71 | // We need a local socket to forward data output by the camera to the packetizer
72 | createSockets();
73 |
74 | Log.v(TAG,"Requested audio with "+mQuality.bitRate/1000+"kbps"+" at "+mQuality.samplingRate/1000+"kHz");
75 |
76 | mMediaRecorder = new MediaRecorder();
77 | mMediaRecorder.setAudioSource(mAudioSource);
78 | mMediaRecorder.setOutputFormat(mOutputFormat);
79 | mMediaRecorder.setAudioEncoder(mAudioEncoder);
80 | mMediaRecorder.setAudioChannels(1);
81 | mMediaRecorder.setAudioSamplingRate(mQuality.samplingRate);
82 | mMediaRecorder.setAudioEncodingBitRate(mQuality.bitRate);
83 |
84 | // We write the output of the camera in a local socket instead of a file !
85 | // This one little trick makes streaming feasible quiet simply: data from the camera
86 | // can then be manipulated at the other end of the socket
87 | FileDescriptor fd = null;
88 | if (sPipeApi == PIPE_API_PFD) {
89 | fd = mParcelWrite.getFileDescriptor();
90 | } else {
91 | fd = mSender.getFileDescriptor();
92 | }
93 | mMediaRecorder.setOutputFile(fd);
94 | mMediaRecorder.setOutputFile(fd);
95 |
96 | mMediaRecorder.prepare();
97 | mMediaRecorder.start();
98 |
99 | InputStream is = null;
100 |
101 | if (sPipeApi == PIPE_API_PFD) {
102 | is = new ParcelFileDescriptor.AutoCloseInputStream(mParcelRead);
103 | } else {
104 | try {
105 | // mReceiver.getInputStream contains the data from the camera
106 | is = mReceiver.getInputStream();
107 | } catch (IOException e) {
108 | stop();
109 | throw new IOException("Something happened with the local sockets :/ Start failed !");
110 | }
111 | }
112 |
113 | // the mPacketizer encapsulates this stream in an RTP stream and send it over the network
114 | mPacketizer.setInputStream(is);
115 | mPacketizer.start();
116 | mStreaming = true;
117 |
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/exceptions/CameraInUseException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.exceptions;
20 |
21 | public class CameraInUseException extends RuntimeException {
22 |
23 | public CameraInUseException(String message) {
24 | super(message);
25 | }
26 |
27 | private static final long serialVersionUID = -1866132102949435675L;
28 | }
29 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/exceptions/ConfNotSupportedException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.exceptions;
20 |
21 | public class ConfNotSupportedException extends RuntimeException {
22 |
23 | public ConfNotSupportedException(String message) {
24 | super(message);
25 | }
26 |
27 | private static final long serialVersionUID = 5876298277802827615L;
28 | }
29 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/exceptions/InvalidSurfaceException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.exceptions;
20 |
21 | public class InvalidSurfaceException extends RuntimeException {
22 |
23 | private static final long serialVersionUID = -7238661340093544496L;
24 |
25 | public InvalidSurfaceException(String message) {
26 | super(message);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/exceptions/StorageUnavailableException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.exceptions;
20 |
21 | import java.io.IOException;
22 |
23 | public class StorageUnavailableException extends IOException {
24 |
25 | public StorageUnavailableException(String message) {
26 | super(message);
27 | }
28 |
29 | private static final long serialVersionUID = -7537890350373995089L;
30 | }
31 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/gl/SurfaceManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Based on the work of fadden
3 | *
4 | * Copyright 2012 Google Inc. All Rights Reserved.
5 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
6 | *
7 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
8 | *
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with the License.
11 | * You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | */
21 |
22 | package net.majorkernelpanic.streaming.gl;
23 |
24 | import android.annotation.SuppressLint;
25 | import android.opengl.EGL14;
26 | import android.opengl.EGLConfig;
27 | import android.opengl.EGLContext;
28 | import android.opengl.EGLDisplay;
29 | import android.opengl.EGLExt;
30 | import android.opengl.EGLSurface;
31 | import android.opengl.GLES20;
32 | import android.view.Surface;
33 |
34 | @SuppressLint("NewApi")
35 | public class SurfaceManager {
36 |
37 | public final static String TAG = "TextureManager";
38 |
39 | private static final int EGL_RECORDABLE_ANDROID = 0x3142;
40 |
41 | private EGLContext mEGLContext = null;
42 | private EGLContext mEGLSharedContext = null;
43 | private EGLSurface mEGLSurface = null;
44 | private EGLDisplay mEGLDisplay = null;
45 |
46 | private Surface mSurface;
47 |
48 | /**
49 | * Creates an EGL context and an EGL surface.
50 | */
51 | public SurfaceManager(Surface surface, SurfaceManager manager) {
52 | mSurface = surface;
53 | mEGLSharedContext = manager.mEGLContext;
54 | eglSetup();
55 | }
56 |
57 | /**
58 | * Creates an EGL context and an EGL surface.
59 | */
60 | public SurfaceManager(Surface surface) {
61 | mSurface = surface;
62 | eglSetup();
63 | }
64 |
65 | public void makeCurrent() {
66 | if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext))
67 | throw new RuntimeException("eglMakeCurrent failed");
68 | }
69 |
70 | public void swapBuffer() {
71 | EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
72 | }
73 |
74 | /**
75 | * Sends the presentation time stamp to EGL. Time is expressed in nanoseconds.
76 | */
77 | public void setPresentationTime(long nsecs) {
78 | EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
79 | checkEglError("eglPresentationTimeANDROID");
80 | }
81 |
82 | /**
83 | * Prepares EGL. We want a GLES 2.0 context and a surface that supports recording.
84 | */
85 | private void eglSetup() {
86 | mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
87 | if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
88 | throw new RuntimeException("unable to get EGL14 display");
89 | }
90 | int[] version = new int[2];
91 | if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
92 | throw new RuntimeException("unable to initialize EGL14");
93 | }
94 |
95 | // Configure EGL for recording and OpenGL ES 2.0.
96 | int[] attribList;
97 | if (mEGLSharedContext == null) {
98 | attribList = new int[] {
99 | EGL14.EGL_RED_SIZE, 8,
100 | EGL14.EGL_GREEN_SIZE, 8,
101 | EGL14.EGL_BLUE_SIZE, 8,
102 | EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
103 | EGL14.EGL_NONE
104 | };
105 | } else {
106 | attribList = new int[] {
107 | EGL14.EGL_RED_SIZE, 8,
108 | EGL14.EGL_GREEN_SIZE, 8,
109 | EGL14.EGL_BLUE_SIZE, 8,
110 | EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
111 | EGL_RECORDABLE_ANDROID, 1,
112 | EGL14.EGL_NONE
113 | };
114 | }
115 | EGLConfig[] configs = new EGLConfig[1];
116 | int[] numConfigs = new int[1];
117 | EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
118 | numConfigs, 0);
119 | checkEglError("eglCreateContext RGB888+recordable ES2");
120 |
121 | // Configure context for OpenGL ES 2.0.
122 | int[] attrib_list = {
123 | EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
124 | EGL14.EGL_NONE
125 | };
126 |
127 | if (mEGLSharedContext == null) {
128 | mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT, attrib_list, 0);
129 | } else {
130 | mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], mEGLSharedContext, attrib_list, 0);
131 | }
132 | checkEglError("eglCreateContext");
133 |
134 | // Create a window surface, and attach it to the Surface we received.
135 | int[] surfaceAttribs = {
136 | EGL14.EGL_NONE
137 | };
138 | mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
139 | surfaceAttribs, 0);
140 | checkEglError("eglCreateWindowSurface");
141 |
142 | GLES20.glDisable(GLES20.GL_DEPTH_TEST);
143 | GLES20.glDisable(GLES20.GL_CULL_FACE);
144 |
145 | }
146 |
147 | /**
148 | * Discards all resources held by this class, notably the EGL context. Also releases the
149 | * Surface that was passed to our constructor.
150 | */
151 | public void release() {
152 | if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
153 | EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
154 | EGL14.EGL_NO_CONTEXT);
155 | EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
156 | EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
157 | EGL14.eglReleaseThread();
158 | EGL14.eglTerminate(mEGLDisplay);
159 | }
160 | mEGLDisplay = EGL14.EGL_NO_DISPLAY;
161 | mEGLContext = EGL14.EGL_NO_CONTEXT;
162 | mEGLSurface = EGL14.EGL_NO_SURFACE;
163 | mSurface.release();
164 | }
165 |
166 | /**
167 | * Checks for EGL errors. Throws an exception if one is found.
168 | */
169 | private void checkEglError(String msg) {
170 | int error;
171 | if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
172 | throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
173 | }
174 | }
175 |
176 |
177 |
178 |
179 | }
180 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/hw/CodecManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.hw;
20 |
21 | import java.util.ArrayList;
22 | import java.util.HashSet;
23 | import java.util.Set;
24 | import android.annotation.SuppressLint;
25 | import android.media.MediaCodecInfo;
26 | import android.media.MediaCodecList;
27 | import android.util.Log;
28 |
29 | @SuppressLint("InlinedApi")
30 | public class CodecManager {
31 |
32 | public final static String TAG = "CodecManager";
33 |
34 | public static final int[] SUPPORTED_COLOR_FORMATS = {
35 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
36 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar,
37 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar,
38 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar,
39 | MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar
40 | };
41 |
42 | private static Codec[] sEncoders = null;
43 | private static Codec[] sDecoders = null;
44 |
45 | static class Codec {
46 | public Codec(String name, Integer[] formats) {
47 | this.name = name;
48 | this.formats = formats;
49 | }
50 | public String name;
51 | public Integer[] formats;
52 | }
53 |
54 | /**
55 | * Lists all encoders that claim to support a color format that we know how to use.
56 | * @return A list of those encoders
57 | */
58 | @SuppressLint("NewApi")
59 | public synchronized static Codec[] findEncodersForMimeType(String mimeType) {
60 | if (sEncoders != null) return sEncoders;
61 |
62 | ArrayList encoders = new ArrayList<>();
63 |
64 | // We loop through the encoders, apparently this can take up to a sec (testes on a GS3)
65 | for(int j = MediaCodecList.getCodecCount() - 1; j >= 0; j--){
66 | MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(j);
67 | if (!codecInfo.isEncoder()) continue;
68 |
69 | String[] types = codecInfo.getSupportedTypes();
70 | for (int i = 0; i < types.length; i++) {
71 | if (types[i].equalsIgnoreCase(mimeType)) {
72 | try {
73 | MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
74 | Set formats = new HashSet<>();
75 |
76 | // And through the color formats supported
77 | for (int k = 0; k < capabilities.colorFormats.length; k++) {
78 | int format = capabilities.colorFormats[k];
79 |
80 | for (int l=0;l decoders = new ArrayList<>();
109 |
110 | // We loop through the decoders, apparently this can take up to a sec (testes on a GS3)
111 | for(int j = MediaCodecList.getCodecCount() - 1; j >= 0; j--){
112 | MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(j);
113 | if (codecInfo.isEncoder()) continue;
114 |
115 | String[] types = codecInfo.getSupportedTypes();
116 | for (int i = 0; i < types.length; i++) {
117 | if (types[i].equalsIgnoreCase(mimeType)) {
118 | try {
119 | MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
120 | Set formats = new HashSet<>();
121 |
122 | // And through the color formats supported
123 | for (int k = 0; k < capabilities.colorFormats.length; k++) {
124 | int format = capabilities.colorFormats[k];
125 |
126 | for (int l=0;l0) {
129 | System.arraycopy(data, 0, mBuffer, 0, mSize);
130 | System.arraycopy(data, mSize, mBuffer, mSize+mYPadding, mSize/2);
131 | return mBuffer;
132 | }
133 | return data;
134 | }
135 | } else {
136 | if (mSliceHeight==mHeight && mStride==mWidth) {
137 | // De-interleave U and V
138 | if (!mPanesReversed) {
139 | for (int i = 0; i < mSize/4; i+=1) {
140 | mBuffer[i] = data[mSize+2*i+1];
141 | mBuffer[mSize/4+i] = data[mSize+2*i];
142 | }
143 | } else {
144 | for (int i = 0; i < mSize/4; i+=1) {
145 | mBuffer[i] = data[mSize+2*i];
146 | mBuffer[mSize/4+i] = data[mSize+2*i+1];
147 | }
148 | }
149 | if (mYPadding == 0) {
150 | System.arraycopy(mBuffer, 0, data, mSize, mSize/2);
151 | } else {
152 | System.arraycopy(data, 0, mBuffer, 0, mSize);
153 | System.arraycopy(mBuffer, 0, mBuffer, mSize+mYPadding, mSize/2);
154 | return mBuffer;
155 | }
156 | return data;
157 | }
158 | }
159 |
160 | return data;
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/mp4/MP4Config.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.mp4;
20 |
21 | import java.io.FileNotFoundException;
22 | import java.io.IOException;
23 | import android.util.Base64;
24 | import android.util.Log;
25 |
26 | /**
27 | * Finds SPS & PPS parameters in mp4 file.
28 | */
29 | public class MP4Config {
30 |
31 | public final static String TAG = "MP4Config";
32 |
33 | private MP4Parser mp4Parser;
34 | private String mProfilLevel, mPPS, mSPS;
35 |
36 | public MP4Config(String profil, String sps, String pps) {
37 | mProfilLevel = profil;
38 | mPPS = pps;
39 | mSPS = sps;
40 | }
41 |
42 | public MP4Config(String sps, String pps) {
43 | mPPS = pps;
44 | mSPS = sps;
45 | mProfilLevel = MP4Parser.toHexString(Base64.decode(sps, Base64.NO_WRAP),1,3);
46 | }
47 |
48 | public MP4Config(byte[] sps, byte[] pps) {
49 | mPPS = Base64.encodeToString(pps, 0, pps.length, Base64.NO_WRAP);
50 | mSPS = Base64.encodeToString(sps, 0, sps.length, Base64.NO_WRAP);
51 | mProfilLevel = MP4Parser.toHexString(sps,1,3);
52 | }
53 |
54 | /**
55 | * Finds SPS & PPS parameters inside a .mp4.
56 | * @param path Path to the file to analyze
57 | * @throws IOException
58 | * @throws FileNotFoundException
59 | */
60 | public MP4Config (String path) throws IOException, FileNotFoundException {
61 |
62 | StsdBox stsdBox;
63 |
64 | // We open the mp4 file and parse it
65 | try {
66 | mp4Parser = MP4Parser.parse(path);
67 | } catch (IOException ignore) {
68 | // Maybe enough of the file has been parsed and we can get the stsd box
69 | }
70 |
71 | // We find the stsdBox
72 | stsdBox = mp4Parser.getStsdBox();
73 | mPPS = stsdBox.getB64PPS();
74 | mSPS = stsdBox.getB64SPS();
75 | mProfilLevel = stsdBox.getProfileLevel();
76 |
77 | mp4Parser.close();
78 |
79 | }
80 |
81 | public String getProfileLevel() {
82 | return mProfilLevel;
83 | }
84 |
85 | public String getB64PPS() {
86 | Log.d(TAG, "PPS: "+mPPS);
87 | return mPPS;
88 | }
89 |
90 | public String getB64SPS() {
91 | Log.d(TAG, "SPS: "+mSPS);
92 | return mSPS;
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/rtp/AACADTSPacketizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.rtp;
20 |
21 | import java.io.IOException;
22 | import net.majorkernelpanic.streaming.audio.AACStream;
23 | import android.os.SystemClock;
24 | import android.util.Log;
25 |
26 | /**
27 | *
28 | * RFC 3640.
29 | *
30 | * This packetizer must be fed with an InputStream containing ADTS AAC.
31 | * AAC will basically be rewrapped in an RTP stream and sent over the network.
32 | * This packetizer only implements the aac-hbr mode (High Bit-rate AAC) and
33 | * each packet only carry a single and complete AAC access unit.
34 | *
35 | */
36 | public class AACADTSPacketizer extends AbstractPacketizer implements Runnable {
37 |
38 | private final static String TAG = "AACADTSPacketizer";
39 |
40 | private Thread t;
41 | private int samplingRate = 8000;
42 |
43 | public AACADTSPacketizer() {
44 | super();
45 | }
46 |
47 | public void start() {
48 | if (t==null) {
49 | t = new Thread(this);
50 | t.start();
51 | }
52 | }
53 |
54 | public void stop() {
55 | if (t != null) {
56 | try {
57 | is.close();
58 | } catch (IOException ignore) {}
59 | t.interrupt();
60 | try {
61 | t.join();
62 | } catch (InterruptedException e) {}
63 | t = null;
64 | }
65 | }
66 |
67 | public void setSamplingRate(int samplingRate) {
68 | this.samplingRate = samplingRate;
69 | socket.setClockFrequency(samplingRate);
70 | }
71 |
72 | public void run() {
73 |
74 | Log.d(TAG,"AAC ADTS packetizer started !");
75 |
76 | // "A packet SHALL carry either one or more complete Access Units, or a
77 | // single fragment of an Access Unit. Fragments of the same Access Unit
78 | // have the same time stamp but different RTP sequence numbers. The
79 | // marker bit in the RTP header is 1 on the last fragment of an Access
80 | // Unit, and 0 on all other fragments." RFC 3640
81 |
82 | // ADTS header fields that we need to parse
83 | boolean protection;
84 | int frameLength, sum, length, nbau, nbpk, samplingRateIndex, profile;
85 | long oldtime = SystemClock.elapsedRealtime(), now = oldtime;
86 | byte[] header = new byte[8];
87 |
88 | try {
89 | while (!Thread.interrupted()) {
90 |
91 | // Synchronisation: ADTS packet starts with 12bits set to 1
92 | while (true) {
93 | if ( (is.read()&0xFF) == 0xFF ) {
94 | header[1] = (byte) is.read();
95 | if ( (header[1]&0xF0) == 0xF0) break;
96 | }
97 | }
98 |
99 | // Parse adts header (ADTS packets start with a 7 or 9 byte long header)
100 | fill(header, 2, 5);
101 |
102 | // The protection bit indicates whether or not the header contains the two extra bytes
103 | protection = (header[1]&0x01)>0 ? true : false;
104 | frameLength = (header[3]&0x03) << 11 |
105 | (header[4]&0xFF) << 3 |
106 | (header[5]&0xFF) >> 5 ;
107 | frameLength -= (protection ? 7 : 9);
108 |
109 | // Number of AAC frames in the ADTS frame
110 | nbau = (header[6]&0x03) + 1;
111 |
112 | // The number of RTP packets that will be sent for this ADTS frame
113 | nbpk = frameLength/MAXPACKETSIZE + 1;
114 |
115 | // Read CRS if any
116 | if (!protection) is.read(header,0,2);
117 |
118 | samplingRate = AACStream.AUDIO_SAMPLING_RATES[(header[2]&0x3C) >> 2];
119 | profile = ( (header[2]&0xC0) >> 6 ) + 1 ;
120 |
121 | // We update the RTP timestamp
122 | ts += 1024L*1000000000L/samplingRate; //stats.average();
123 |
124 | //Log.d(TAG,"frameLength: "+frameLength+" protection: "+protection+" p: "+profile+" sr: "+samplingRate);
125 |
126 | sum = 0;
127 | while (sum MAXPACKETSIZE-rtphl-4) {
134 | length = MAXPACKETSIZE-rtphl-4;
135 | }
136 | else {
137 | length = frameLength-sum;
138 | socket.markNextPacket();
139 | }
140 | sum += length;
141 | fill(buffer, rtphl+4, length);
142 |
143 | // AU-headers-length field: contains the size in bits of a AU-header
144 | // 13+3 = 16 bits -> 13bits for AU-size and 3bits for AU-Index / AU-Index-delta
145 | // 13 bits will be enough because ADTS uses 13 bits for frame length
146 | buffer[rtphl] = 0;
147 | buffer[rtphl+1] = 0x10;
148 |
149 | // AU-size
150 | buffer[rtphl+2] = (byte) (frameLength>>5);
151 | buffer[rtphl+3] = (byte) (frameLength<<3);
152 |
153 | // AU-Index
154 | buffer[rtphl+3] &= 0xF8;
155 | buffer[rtphl+3] |= 0x00;
156 |
157 | send(rtphl+4+length);
158 |
159 | }
160 |
161 | }
162 | } catch (IOException e) {
163 | // Ignore
164 | } catch (ArrayIndexOutOfBoundsException e) {
165 | Log.e(TAG,"ArrayIndexOutOfBoundsException: "+(e.getMessage()!=null?e.getMessage():"unknown error"));
166 | e.printStackTrace();
167 | } catch (InterruptedException ignore) {}
168 |
169 | Log.d(TAG,"AAC ADTS packetizer stopped !");
170 |
171 | }
172 |
173 | private int fill(byte[] buffer, int offset,int length) throws IOException {
174 | int sum = 0, len;
175 | while (sum0) {
86 |
87 | bufferInfo = ((MediaCodecInputStream)is).getLastBufferInfo();
88 | //Log.d(TAG,"length: "+length+" ts: "+bufferInfo.presentationTimeUs);
89 | oldts = ts;
90 | ts = bufferInfo.presentationTimeUs*1000;
91 |
92 | // Seems to happen sometimes
93 | if (oldts>ts) {
94 | socket.commitBuffer();
95 | continue;
96 | }
97 |
98 | socket.markNextPacket();
99 | socket.updateTimestamp(ts);
100 |
101 | // AU-headers-length field: contains the size in bits of a AU-header
102 | // 13+3 = 16 bits -> 13bits for AU-size and 3bits for AU-Index / AU-Index-delta
103 | // 13 bits will be enough because ADTS uses 13 bits for frame length
104 | buffer[rtphl] = 0;
105 | buffer[rtphl+1] = 0x10;
106 |
107 | // AU-size
108 | buffer[rtphl+2] = (byte) (length>>5);
109 | buffer[rtphl+3] = (byte) (length<<3);
110 |
111 | // AU-Index
112 | buffer[rtphl+3] &= 0xF8;
113 | buffer[rtphl+3] |= 0x00;
114 |
115 | send(rtphl+length+4);
116 |
117 | } else {
118 | socket.commitBuffer();
119 | }
120 |
121 | }
122 | } catch (IOException e) {
123 | } catch (ArrayIndexOutOfBoundsException e) {
124 | Log.e(TAG,"ArrayIndexOutOfBoundsException: "+(e.getMessage()!=null?e.getMessage():"unknown error"));
125 | e.printStackTrace();
126 | } catch (InterruptedException ignore) {}
127 |
128 | Log.d(TAG,"AAC LATM packetizer stopped !");
129 |
130 | }
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/rtp/AMRNBPacketizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.rtp;
20 |
21 | import java.io.IOException;
22 | import android.util.Log;
23 |
24 | /**
25 | *
26 | * RFC 3267.
27 | *
28 | * AMR Streaming over RTP.
29 | *
30 | * Must be fed with an InputStream containing raw AMR NB
31 | * Stream must begin with a 6 bytes long header: "#!AMR\n", it will be skipped
32 | *
33 | */
34 | public class AMRNBPacketizer extends AbstractPacketizer implements Runnable {
35 |
36 | public final static String TAG = "AMRNBPacketizer";
37 |
38 | private final int AMR_HEADER_LENGTH = 6; // "#!AMR\n"
39 | private static final int AMR_FRAME_HEADER_LENGTH = 1; // Each frame has a short header
40 | private static final int[] sFrameBits = {95, 103, 118, 134, 148, 159, 204, 244};
41 | private int samplingRate = 8000;
42 |
43 | private Thread t;
44 |
45 | public AMRNBPacketizer() {
46 | super();
47 | socket.setClockFrequency(samplingRate);
48 | }
49 |
50 | public void start() {
51 | if (t==null) {
52 | t = new Thread(this);
53 | t.start();
54 | }
55 | }
56 |
57 | public void stop() {
58 | if (t != null) {
59 | try {
60 | is.close();
61 | } catch (IOException ignore) {}
62 | t.interrupt();
63 | try {
64 | t.join();
65 | } catch (InterruptedException e) {}
66 | t = null;
67 | }
68 | }
69 |
70 | public void run() {
71 |
72 | int frameLength, frameType;
73 | long now = System.nanoTime(), oldtime = now;
74 | byte[] header = new byte[AMR_HEADER_LENGTH];
75 |
76 | try {
77 |
78 | // Skip raw AMR header
79 | fill(header,0,AMR_HEADER_LENGTH);
80 |
81 | if (header[5] != '\n') {
82 | Log.e(TAG,"Bad header ! AMR not correcty supported by the phone !");
83 | return;
84 | }
85 |
86 | while (!Thread.interrupted()) {
87 |
88 | buffer = socket.requestBuffer();
89 | buffer[rtphl] = (byte) 0xF0;
90 |
91 | // First we read the frame header
92 | fill(buffer, rtphl+1,AMR_FRAME_HEADER_LENGTH);
93 |
94 | // Then we calculate the frame payload length
95 | frameType = (Math.abs(buffer[rtphl + 1]) >> 3) & 0x0f;
96 | frameLength = (sFrameBits[frameType]+7)/8;
97 |
98 | // And we read the payload
99 | fill(buffer, rtphl+2,frameLength);
100 |
101 | //Log.d(TAG,"Frame length: "+frameLength+" frameType: "+frameType);
102 |
103 | // RFC 3267 Page 14: "For AMR, the sampling frequency is 8 kHz"
104 | // FIXME: Is this really always the case ??
105 | ts += 160L*1000000000L/samplingRate; //stats.average();
106 | socket.updateTimestamp(ts);
107 | socket.markNextPacket();
108 |
109 | //Log.d(TAG,"expected: "+ expected + " measured: "+measured);
110 |
111 | send(rtphl+1+AMR_FRAME_HEADER_LENGTH+frameLength);
112 |
113 | }
114 |
115 | } catch (IOException e) {
116 | } catch (InterruptedException e) {}
117 |
118 | Log.d(TAG,"AMR packetizer stopped !");
119 |
120 | }
121 |
122 | private int fill(byte[] buffer, int offset,int length) throws IOException {
123 | int sum = 0, len;
124 | while (sumperiod) {
132 | elapsed = 0;
133 | long now = System.nanoTime();
134 | if (!initoffset || (now - start < 0)) {
135 | start = now;
136 | duration = 0;
137 | initoffset = true;
138 | }
139 | // Prevents drifting issues by comparing the real duration of the
140 | // stream with the sum of all temporal lengths of RTP packets.
141 | value += (now - start) - duration;
142 | //Log.d(TAG, "sum1: "+duration/1000000+" sum2: "+(now-start)/1000000+" drift: "+((now-start)-duration)/1000000+" v: "+value/1000000);
143 | }
144 | if (c<5) {
145 | // We ignore the first 20 measured values because they may not be accurate
146 | c++;
147 | m = value;
148 | } else {
149 | m = (m*q+value)/(q+1);
150 | if (q>2;
96 | //Log.d(TAG,"j: "+j+" buffer: "+printBuffer(rtphl, rtphl+5)+" tr: "+tr);
97 | if (firstFragment) {
98 | // This is the first fragment of the frame -> header is set to 0x0400
99 | buffer[rtphl] = 4;
100 | firstFragment = false;
101 | } else {
102 | buffer[rtphl] = 0;
103 | }
104 | if (j>0) {
105 | // We have found the end of the frame
106 | stats.push(duration);
107 | ts+= stats.average(); duration = 0;
108 | //Log.d(TAG,"End of frame ! duration: "+stats.average());
109 | // The last fragment of a frame has to be marked
110 | socket.markNextPacket();
111 | send(j);
112 | nextBuffer = socket.requestBuffer();
113 | System.arraycopy(buffer,j+2,nextBuffer,rtphl+2,MAXPACKETSIZE-j-2);
114 | buffer = nextBuffer;
115 | j = MAXPACKETSIZE-j-2;
116 | firstFragment = true;
117 | } else {
118 | // We have not found the beginning of another frame
119 | // The whole packet is a fragment of a frame
120 | send(MAXPACKETSIZE);
121 | }
122 | }
123 | } catch (IOException e) {
124 | } catch (InterruptedException e) {}
125 |
126 | Log.d(TAG,"H263 Packetizer stopped !");
127 |
128 | }
129 |
130 | private int fill(int offset,int length) throws IOException {
131 |
132 | int sum = 0, len;
133 |
134 | while (sum=0 ){
73 | //Log.d(TAG,"Index: "+mIndex+" Time: "+mBufferInfo.presentationTimeUs+" size: "+mBufferInfo.size);
74 | mBuffer = mBuffers[mIndex];
75 | mBuffer.position(0);
76 | break;
77 | } else if (mIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
78 | mBuffers = mMediaCodec.getOutputBuffers();
79 | } else if (mIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
80 | mMediaFormat = mMediaCodec.getOutputFormat();
81 | Log.i(TAG,mMediaFormat.toString());
82 | } else if (mIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
83 | Log.v(TAG,"No buffer available...");
84 | //return 0;
85 | } else {
86 | Log.e(TAG,"Message: "+mIndex);
87 | //return 0;
88 | }
89 | }
90 | }
91 |
92 | if (mClosed) throw new IOException("This InputStream was closed");
93 |
94 | min = length < mBufferInfo.size - mBuffer.position() ? length : mBufferInfo.size - mBuffer.position();
95 | mBuffer.get(buffer, offset, min);
96 | if (mBuffer.position()>=mBufferInfo.size) {
97 | mMediaCodec.releaseOutputBuffer(mIndex, false);
98 | mBuffer = null;
99 | }
100 |
101 | } catch (RuntimeException e) {
102 | e.printStackTrace();
103 | }
104 |
105 | return min;
106 | }
107 |
108 | public int available() {
109 | if (mBuffer != null)
110 | return mBufferInfo.size - mBuffer.position();
111 | else
112 | return 0;
113 | }
114 |
115 | public BufferInfo getLastBufferInfo() {
116 | return mBufferInfo;
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/rtsp/RtcpDeinterleaver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.rtsp;
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 | import java.io.PipedInputStream;
24 | import java.io.PipedOutputStream;
25 |
26 | class RtcpDeinterleaver extends InputStream implements Runnable {
27 |
28 | public final static String TAG = "RtcpDeinterleaver";
29 |
30 | private IOException mIOException;
31 | private InputStream mInputStream;
32 | private PipedInputStream mPipedInputStream;
33 | private PipedOutputStream mPipedOutputStream;
34 | private byte[] mBuffer;
35 |
36 | public RtcpDeinterleaver(InputStream inputStream) {
37 | mInputStream = inputStream;
38 | mPipedInputStream = new PipedInputStream(4096);
39 | try {
40 | mPipedOutputStream = new PipedOutputStream(mPipedInputStream);
41 | } catch (IOException e) {}
42 | mBuffer = new byte[1024];
43 | new Thread(this).start();
44 | }
45 |
46 | @Override
47 | public void run() {
48 | try {
49 | while (true) {
50 | int len = mInputStream.read(mBuffer, 0, 1024);
51 | mPipedOutputStream.write(mBuffer, 0, len);
52 | }
53 | } catch (IOException e) {
54 | try {
55 | mPipedInputStream.close();
56 | } catch (IOException ignore) {}
57 | mIOException = e;
58 | }
59 | }
60 |
61 | @Override
62 | public int read(byte[] buffer) throws IOException {
63 | if (mIOException != null) {
64 | throw mIOException;
65 | }
66 | return mPipedInputStream.read(buffer);
67 | }
68 |
69 | @Override
70 | public int read(byte[] buffer, int offset, int length) throws IOException {
71 | if (mIOException != null) {
72 | throw mIOException;
73 | }
74 | return mPipedInputStream.read(buffer, offset, length);
75 | }
76 |
77 | @Override
78 | public int read() throws IOException {
79 | if (mIOException != null) {
80 | throw mIOException;
81 | }
82 | return mPipedInputStream.read();
83 | }
84 |
85 | @Override
86 | public void close() throws IOException {
87 | mInputStream.close();
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/video/H263Stream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.video;
20 |
21 | import java.io.IOException;
22 | import net.majorkernelpanic.streaming.SessionBuilder;
23 | import net.majorkernelpanic.streaming.rtp.H263Packetizer;
24 | import android.graphics.ImageFormat;
25 | import android.hardware.Camera.CameraInfo;
26 | import android.media.MediaRecorder;
27 | import android.service.textservice.SpellCheckerService.Session;
28 |
29 | /**
30 | * A class for streaming H.263 from the camera of an android device using RTP.
31 | * You should use a {@link Session} instantiated with {@link SessionBuilder} instead of using this class directly.
32 | * Call {@link #setDestinationAddress(InetAddress)}, {@link #setDestinationPorts(int)} and {@link #setVideoQuality(VideoQuality)}
33 | * to configure the stream. You can then call {@link #start()} to start the RTP stream.
34 | * Call {@link #stop()} to stop the stream.
35 | */
36 | public class H263Stream extends VideoStream {
37 |
38 | /**
39 | * Constructs the H.263 stream.
40 | * Uses CAMERA_FACING_BACK by default.
41 | * @throws IOException
42 | */
43 | public H263Stream() throws IOException {
44 | this(CameraInfo.CAMERA_FACING_BACK);
45 | }
46 |
47 | /**
48 | * Constructs the H.263 stream.
49 | * @param cameraId Can be either CameraInfo.CAMERA_FACING_BACK or CameraInfo.CAMERA_FACING_FRONT
50 | * @throws IOException
51 | */
52 | public H263Stream(int cameraId) {
53 | super(cameraId);
54 | mCameraImageFormat = ImageFormat.NV21;
55 | mVideoEncoder = MediaRecorder.VideoEncoder.H263;
56 | mPacketizer = new H263Packetizer();
57 | }
58 |
59 | /**
60 | * Starts the stream.
61 | */
62 | public synchronized void start() throws IllegalStateException, IOException {
63 | if (!mStreaming) {
64 | configure();
65 | super.start();
66 | }
67 | }
68 |
69 | public synchronized void configure() throws IllegalStateException, IOException {
70 | super.configure();
71 | mMode = MODE_MEDIARECORDER_API;
72 | mQuality = mRequestedQuality.clone();
73 | }
74 |
75 | /**
76 | * Returns a description of the stream using SDP. It can then be included in an SDP file.
77 | */
78 | public String getSessionDescription() {
79 | return "m=video "+String.valueOf(getDestinationPorts()[0])+" RTP/AVP 96\r\n" +
80 | "a=rtpmap:96 H263-1998/90000\r\n";
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/net/majorkernelpanic/streaming/video/VideoQuality.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011-2015 GUIGUI Simon, fyhertz@gmail.com
3 | *
4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming)
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package net.majorkernelpanic.streaming.video;
20 |
21 | import java.util.Iterator;
22 | import java.util.List;
23 | import android.hardware.Camera;
24 | import android.hardware.Camera.Size;
25 | import android.util.Log;
26 |
27 | /**
28 | * A class that represents the quality of a video stream.
29 | * It contains the resolution, the framerate (in fps) and the bitrate (in bps) of the stream.
30 | */
31 | public class VideoQuality {
32 |
33 | public final static String TAG = "VideoQuality";
34 |
35 | /** Default video stream quality. */
36 | public final static VideoQuality DEFAULT_VIDEO_QUALITY = new VideoQuality(176,144,20,500000);
37 |
38 | /** Represents a quality for a video stream. */
39 | public VideoQuality() {}
40 |
41 | /**
42 | * Represents a quality for a video stream.
43 | * @param resX The horizontal resolution
44 | * @param resY The vertical resolution
45 | */
46 | public VideoQuality(int resX, int resY) {
47 | this.resX = resX;
48 | this.resY = resY;
49 | }
50 |
51 | /**
52 | * Represents a quality for a video stream.
53 | * @param resX The horizontal resolution
54 | * @param resY The vertical resolution
55 | * @param framerate The framerate in frame per seconds
56 | * @param bitrate The bitrate in bit per seconds
57 | */
58 | public VideoQuality(int resX, int resY, int framerate, int bitrate) {
59 | this.framerate = framerate;
60 | this.bitrate = bitrate;
61 | this.resX = resX;
62 | this.resY = resY;
63 | }
64 |
65 | public int framerate = 0;
66 | public int bitrate = 0;
67 | public int resX = 0;
68 | public int resY = 0;
69 |
70 | public boolean equals(VideoQuality quality) {
71 | if (quality==null) return false;
72 | return (quality.resX == this.resX &&
73 | quality.resY == this.resY &&
74 | quality.framerate == this.framerate &&
75 | quality.bitrate == this.bitrate);
76 | }
77 |
78 | public VideoQuality clone() {
79 | return new VideoQuality(resX,resY,framerate,bitrate);
80 | }
81 |
82 | public static VideoQuality parseQuality(String str) {
83 | VideoQuality quality = DEFAULT_VIDEO_QUALITY.clone();
84 | if (str != null) {
85 | String[] config = str.split("-");
86 | try {
87 | quality.bitrate = Integer.parseInt(config[0])*1000; // conversion to bit/s
88 | quality.framerate = Integer.parseInt(config[1]);
89 | quality.resX = Integer.parseInt(config[2]);
90 | quality.resY = Integer.parseInt(config[3]);
91 | }
92 | catch (IndexOutOfBoundsException ignore) {}
93 | }
94 | return quality;
95 | }
96 |
97 | public String toString() {
98 | return resX+"x"+resY+" px, "+framerate+" fps, "+bitrate/1000+" kbps";
99 | }
100 |
101 | /**
102 | * Checks if the requested resolution is supported by the camera.
103 | * If not, it modifies it by supported parameters.
104 | **/
105 | public static VideoQuality determineClosestSupportedResolution(Camera.Parameters parameters, VideoQuality quality) {
106 | VideoQuality v = quality.clone();
107 | int minDist = Integer.MAX_VALUE;
108 | String supportedSizesStr = "Supported resolutions: ";
109 | List supportedSizes = parameters.getSupportedPreviewSizes();
110 | for (Iterator it = supportedSizes.iterator(); it.hasNext();) {
111 | Size size = it.next();
112 | supportedSizesStr += size.width+"x"+size.height+(it.hasNext()?", ":"");
113 | int dist = Math.abs(quality.resX - size.width);
114 | if (dist"+v.resX+"x"+v.resY);
123 | }
124 |
125 | return v;
126 | }
127 |
128 | public static int[] determineMaximumSupportedFramerate(Camera.Parameters parameters) {
129 | int[] maxFps = new int[]{0,0};
130 | String supportedFpsRangesStr = "Supported frame rates: ";
131 | List supportedFpsRanges = parameters.getSupportedPreviewFpsRange();
132 | for (Iterator it = supportedFpsRanges.iterator(); it.hasNext();) {
133 | int[] interval = it.next();
134 | // Intervals are returned as integers, for example "29970" means "29.970" FPS.
135 | supportedFpsRangesStr += interval[0]/1000+"-"+interval[1]/1000+"fps"+(it.hasNext()?", ":"");
136 | if (interval[1]>maxFps[1] || (interval[0]>maxFps[0] && interval[1]==maxFps[1])) {
137 | maxFps = interval;
138 | }
139 | }
140 | Log.v(TAG,supportedFpsRangesStr);
141 | return maxFps;
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------