├── .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 |
14 | 56 |
57 | 58 | 59 | -------------------------------------------------------------------------------- /doc/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deprecated List 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Deprecated API

73 |

Contents

74 |
75 | 76 |
77 | 78 | 79 |
Skip navigation links
80 | 81 | 82 | 83 | 92 |
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 | <noscript> 69 | <div>JavaScript is disabled on your browser.</div> 70 | </noscript> 71 | <h2>Frame Alert</h2> 72 | <p>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 <a href="overview-summary.html">Non-frame version</a>.</p> 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 |

net.majorkernelpanic.streaming.audio

13 |
14 |

Classes

15 | 21 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package net.majorkernelpanic.streaming.audio

73 |
74 |
75 | 112 |
113 | 114 |
115 | 116 | 117 |
Skip navigation links
118 | 119 | 120 | 121 | 130 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming.audio

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 97 |
98 | 99 |
100 | 101 | 102 |
Skip navigation links
103 | 104 | 105 | 106 | 115 |
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 |

net.majorkernelpanic.streaming.exceptions

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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package net.majorkernelpanic.streaming.exceptions

73 |
74 |
75 | 104 |
105 | 106 |
107 | 108 | 109 |
Skip navigation links
110 | 111 | 112 | 113 | 122 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming.exceptions

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 106 |
107 | 108 |
109 | 110 | 111 |
Skip navigation links
112 | 113 | 114 | 115 | 124 |
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 |

net.majorkernelpanic.streaming.gl

13 |
14 |

Classes

15 | 20 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package net.majorkernelpanic.streaming.gl

73 |
74 |
75 | 104 |
105 | 106 |
107 | 108 | 109 |
Skip navigation links
110 | 111 | 112 | 113 | 122 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming.gl

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 94 |
95 | 96 |
97 | 98 | 99 |
Skip navigation links
100 | 101 | 102 | 103 | 112 |
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 |

net.majorkernelpanic.streaming.hw

13 |
14 |

Classes

15 | 20 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package net.majorkernelpanic.streaming.hw

73 |
74 |
75 | 105 |
106 | 107 |
108 | 109 | 110 |
Skip navigation links
111 | 112 | 113 | 114 | 123 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming.hw

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 89 |
90 | 91 |
92 | 93 | 94 |
Skip navigation links
95 | 96 | 97 | 98 | 107 |
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 |

net.majorkernelpanic.streaming.mp4

13 |
14 |

Classes

15 | 19 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package net.majorkernelpanic.streaming.mp4

73 |
74 |
75 | 100 |
101 | 102 |
103 | 104 | 105 |
Skip navigation links
106 | 107 | 108 | 109 | 118 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming.mp4

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 88 |
89 | 90 |
91 | 92 | 93 |
Skip navigation links
94 | 95 | 96 | 97 | 106 |
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 |

net.majorkernelpanic.streaming

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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 89 |

Interface Hierarchy

90 | 94 |
95 | 96 |
97 | 98 | 99 |
Skip navigation links
100 | 101 | 102 | 103 | 112 |
113 | 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 |

net.majorkernelpanic.streaming.rtcp

13 |
14 |

Classes

15 | 18 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package net.majorkernelpanic.streaming.rtcp

73 |
74 |
75 | 94 |
95 | 96 |
97 | 98 | 99 |
Skip navigation links
100 | 101 | 102 | 103 | 112 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming.rtcp

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 87 |
88 | 89 |
90 | 91 | 92 |
Skip navigation links
93 | 94 | 95 | 96 | 105 |
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 |

net.majorkernelpanic.streaming.rtp

13 |
14 |

Classes

15 | 25 |
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 |

net.majorkernelpanic.streaming.rtsp

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 |

net.majorkernelpanic.streaming.video

13 |
14 |

Classes

15 | 22 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package net.majorkernelpanic.streaming.video

73 |
74 |
75 | 116 |
117 | 118 |
119 | 120 | 121 |
Skip navigation links
122 | 123 | 124 | 125 | 134 |
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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package net.majorkernelpanic.streaming.video

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 98 |
99 | 100 |
101 | 102 | 103 |
Skip navigation links
104 | 105 | 106 | 107 | 116 |
117 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /doc/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview List 7 | 8 | 9 | 10 | 11 | 12 |
All Classes
13 |
14 |

Packages

15 | 27 |
28 |

 

29 | 30 | 31 | -------------------------------------------------------------------------------- /doc/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |
Packages 
PackageDescription
net.majorkernelpanic.streaming 
net.majorkernelpanic.streaming.audio 
net.majorkernelpanic.streaming.exceptions 
net.majorkernelpanic.streaming.gl 
net.majorkernelpanic.streaming.hw 
net.majorkernelpanic.streaming.mp4 
net.majorkernelpanic.streaming.rtcp 
net.majorkernelpanic.streaming.rtp 
net.majorkernelpanic.streaming.rtsp 
net.majorkernelpanic.streaming.video 
121 |
122 | 123 |
124 | 125 | 126 |
Skip navigation links
127 | 128 | 129 | 130 | 139 |
140 | 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 | 25 | 26 |
27 | 28 | 29 |
Skip navigation links
30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Serialized Form

73 |
74 |
75 | 118 |
119 | 120 |
121 | 122 | 123 |
Skip navigation links
124 | 125 | 126 | 127 | 136 |
137 | 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 | --------------------------------------------------------------------------------