├── .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 |

All Classes

12 |
13 | 55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /doc/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deprecated List 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Deprecated API

66 |

Contents

67 |
68 | 69 |
70 | 71 | 72 | 73 | 74 | 83 |
84 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Generated Documentation (Untitled) 7 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <noscript> 68 | <div>JavaScript is disabled on your browser.</div> 69 | </noscript> 70 | <h2>Frame Alert</h2> 71 | <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> 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/audio/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.audio 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.audio

12 |
13 |

Classes

14 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/audio/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.audio 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package net.majorkernelpanic.streaming.audio

66 |
67 |
68 | 105 |
106 | 107 |
108 | 109 | 110 | 111 | 112 | 121 |
122 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /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 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.audio

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 90 |
91 | 92 |
93 | 94 | 95 | 96 | 97 | 106 |
107 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/exceptions/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.exceptions 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.exceptions

12 |
13 |

Exceptions

14 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/exceptions/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.exceptions 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package net.majorkernelpanic.streaming.exceptions

66 |
67 |
68 | 97 |
98 | 99 |
100 | 101 | 102 | 103 | 104 | 113 |
114 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /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 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.exceptions

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 99 |
100 | 101 |
102 | 103 | 104 | 105 | 106 | 115 |
116 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/gl/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.gl 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.gl

12 |
13 |

Classes

14 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/gl/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.gl 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package net.majorkernelpanic.streaming.gl

66 |
67 |
68 | 97 |
98 | 99 |
100 | 101 | 102 | 103 | 104 | 113 |
114 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /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 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.gl

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 91 |
92 | 93 |
94 | 95 | 96 | 97 | 98 | 107 |
108 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/hw/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.hw 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.hw

12 |
13 |

Classes

14 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/hw/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.hw 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package net.majorkernelpanic.streaming.hw

66 |
67 |
68 | 98 |
99 | 100 |
101 | 102 | 103 | 104 | 105 | 114 |
115 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /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 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.hw

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 82 |
83 | 84 |
85 | 86 | 87 | 88 | 89 | 98 |
99 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/mp4/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.mp4 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.mp4

12 |
13 |

Classes

14 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/mp4/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.mp4 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package net.majorkernelpanic.streaming.mp4

66 |
67 |
68 | 93 |
94 | 95 |
96 | 97 | 98 | 99 | 100 | 109 |
110 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /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 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.mp4

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 81 |
82 | 83 |
84 | 85 | 86 | 87 | 88 | 97 |
98 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming

12 |
13 |

Interfaces

14 | 18 |

Classes

19 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 82 |

Interface Hierarchy

83 | 87 |
88 | 89 |
90 | 91 | 92 | 93 | 94 | 103 |
104 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/rtcp/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.rtcp 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.rtcp

12 |
13 |

Classes

14 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/rtcp/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.rtcp 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package net.majorkernelpanic.streaming.rtcp

66 |
67 |
68 | 87 |
88 | 89 |
90 | 91 | 92 | 93 | 94 | 103 |
104 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /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 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.rtcp

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 80 |
81 | 82 |
83 | 84 | 85 | 86 | 87 | 96 |
97 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/rtp/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.rtp 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.rtp

12 |
13 |

Classes

14 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/rtsp/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.rtsp 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.rtsp

12 |
13 |

Interfaces

14 | 18 |

Classes

19 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/rtsp/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.rtsp Class Hierarchy 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.rtsp

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 99 |

Interface Hierarchy

100 | 104 |
105 | 106 |
107 | 108 | 109 | 110 | 111 | 120 |
121 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/video/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.video 7 | 8 | 9 | 10 | 11 |

net.majorkernelpanic.streaming.video

12 |
13 |

Classes

14 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /doc/net/majorkernelpanic/streaming/video/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net.majorkernelpanic.streaming.video 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Package net.majorkernelpanic.streaming.video

66 |
67 |
68 | 109 |
110 | 111 |
112 | 113 | 114 | 115 | 116 | 125 |
126 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /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 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Hierarchy For Package net.majorkernelpanic.streaming.video

66 | Package Hierarchies: 67 | 70 |
71 |
72 |

Class Hierarchy

73 | 91 |
92 | 93 |
94 | 95 | 96 | 97 | 98 | 107 |
108 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /doc/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview List 7 | 8 | 9 | 10 | 11 |
All Classes
12 |
13 |

Packages

14 | 26 |
27 |

 

28 | 29 | 30 | -------------------------------------------------------------------------------- /doc/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 | 66 | 67 | 68 | 69 | 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 |
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 
114 |
115 | 116 |
117 | 118 | 119 | 120 | 121 | 130 |
131 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /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/Ziggeo/android-libstreaming/17e3499f3aa8182c713198d2d8d0ebf6be4d8893/doc/resources/background.gif -------------------------------------------------------------------------------- /doc/resources/tab.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ziggeo/android-libstreaming/17e3499f3aa8182c713198d2d8d0ebf6be4d8893/doc/resources/tab.gif -------------------------------------------------------------------------------- /doc/resources/titlebar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ziggeo/android-libstreaming/17e3499f3aa8182c713198d2d8d0ebf6be4d8893/doc/resources/titlebar.gif -------------------------------------------------------------------------------- /doc/resources/titlebar_end.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ziggeo/android-libstreaming/17e3499f3aa8182c713198d2d8d0ebf6be4d8893/doc/resources/titlebar_end.gif -------------------------------------------------------------------------------- /doc/serialized-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Serialized Form 7 | 8 | 9 | 10 | 11 | 17 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 35 |
36 | 63 | 64 |
65 |

Serialized Form

66 |
67 |
68 | 111 |
112 | 113 |
114 | 115 | 116 | 117 | 118 | 127 |
128 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /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-21 12 | android.library=true 13 | -------------------------------------------------------------------------------- /res/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ziggeo/android-libstreaming/17e3499f3aa8182c713198d2d8d0ebf6be4d8893/res/.gitkeep -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/Stream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming; 22 | 23 | import java.io.IOException; 24 | import java.io.OutputStream; 25 | import java.net.InetAddress; 26 | 27 | /** 28 | * An interface that represents a Stream. 29 | */ 30 | public interface Stream { 31 | 32 | /** 33 | * Configures the stream. You need to call this before calling {@link #getSessionDescription()} 34 | * to apply your configuration of the stream. 35 | */ 36 | public void configure() throws IllegalStateException, IOException; 37 | 38 | /** 39 | * Starts the stream. 40 | * This method can only be called after {@link Stream#configure()}. 41 | */ 42 | public void start() throws IllegalStateException, IOException; 43 | 44 | /** 45 | * Stops the stream. 46 | */ 47 | public void stop(); 48 | 49 | /** 50 | * Sets the Time To Live of packets sent over the network. 51 | * @param ttl The time to live 52 | * @throws IOException 53 | */ 54 | public void setTimeToLive(int ttl) throws IOException; 55 | 56 | /** 57 | * Sets the destination ip address of the stream. 58 | * @param dest The destination address of the stream 59 | */ 60 | public void setDestinationAddress(InetAddress dest); 61 | 62 | /** 63 | * Sets the destination ports of the stream. 64 | * If an odd number is supplied for the destination port then the next 65 | * lower even number will be used for RTP and it will be used for RTCP. 66 | * If an even number is supplied, it will be used for RTP and the next odd 67 | * number will be used for RTCP. 68 | * @param dport The destination port 69 | */ 70 | public void setDestinationPorts(int dport); 71 | 72 | /** 73 | * Sets the destination ports of the stream. 74 | * @param rtpPort Destination port that will be used for RTP 75 | * @param rtcpPort Destination port that will be used for RTCP 76 | */ 77 | public void setDestinationPorts(int rtpPort, int rtcpPort); 78 | 79 | /** 80 | * If a TCP is used as the transport protocol for the RTP session, 81 | * the output stream to which RTP packets will be written to must 82 | * be specified with this method. 83 | */ 84 | public void setOutputStream(OutputStream stream, byte channelIdentifier); 85 | 86 | /** 87 | * Returns a pair of source ports, the first one is the 88 | * one used for RTP and the second one is used for RTCP. 89 | **/ 90 | public int[] getLocalPorts(); 91 | 92 | /** 93 | * Returns a pair of destination ports, the first one is the 94 | * one used for RTP and the second one is used for RTCP. 95 | **/ 96 | public int[] getDestinationPorts(); 97 | 98 | 99 | /** 100 | * Returns the SSRC of the underlying {@link net.majorkernelpanic.streaming.rtp.RtpSocket}. 101 | * @return the SSRC of the stream. 102 | */ 103 | public int getSSRC(); 104 | 105 | /** 106 | * Returns an approximation of the bit rate consumed by the stream in bit per seconde. 107 | */ 108 | public long getBitrate(); 109 | 110 | /** 111 | * Returns a description of the stream using SDP. 112 | * This method can only be called after {@link Stream#configure()}. 113 | * @throws IllegalStateException Thrown when {@link Stream#configure()} wa not called. 114 | */ 115 | public String getSessionDescription() throws IllegalStateException; 116 | 117 | public boolean isStreaming(); 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/audio/AMRNBStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.audio; 22 | 23 | import java.io.IOException; 24 | import java.lang.reflect.Field; 25 | 26 | import net.majorkernelpanic.streaming.SessionBuilder; 27 | import net.majorkernelpanic.streaming.rtp.AMRNBPacketizer; 28 | import android.media.MediaRecorder; 29 | import android.service.textservice.SpellCheckerService.Session; 30 | 31 | /** 32 | * A class for streaming AAC from the camera of an android device using RTP. 33 | * You should use a {@link Session} instantiated with {@link SessionBuilder} instead of using this class directly. 34 | * Call {@link #setDestinationAddress(InetAddress)}, {@link #setDestinationPorts(int)} and {@link #setAudioQuality(AudioQuality)} 35 | * to configure the stream. You can then call {@link #start()} to start the RTP stream. 36 | * Call {@link #stop()} to stop the stream. 37 | */ 38 | public class AMRNBStream extends AudioStream { 39 | 40 | public AMRNBStream() { 41 | super(); 42 | 43 | mPacketizer = new AMRNBPacketizer(); 44 | 45 | setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 46 | 47 | try { 48 | // RAW_AMR was deprecated in API level 16. 49 | Field deprecatedName = MediaRecorder.OutputFormat.class.getField("RAW_AMR"); 50 | setOutputFormat(deprecatedName.getInt(null)); 51 | } catch (Exception e) { 52 | setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); 53 | } 54 | 55 | setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 56 | 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=audio "+String.valueOf(getDestinationPorts()[0])+" RTP/AVP 96\r\n" + 80 | "a=rtpmap:96 AMR/8000\r\n" + 81 | "a=fmtp:96 octet-align=1;\r\n"; 82 | } 83 | 84 | @Override 85 | protected void encodeWithMediaCodec() throws IOException { 86 | super.encodeWithMediaRecorder(); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/audio/AudioQuality.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.audio; 22 | 23 | /** 24 | * A class that represents the quality of an audio stream. 25 | */ 26 | public class AudioQuality { 27 | 28 | /** Default audio stream quality. */ 29 | public final static AudioQuality DEFAULT_AUDIO_QUALITY = new AudioQuality(8000,32000); 30 | 31 | /** Represents a quality for a video stream. */ 32 | public AudioQuality() {} 33 | 34 | /** 35 | * Represents a quality for an audio stream. 36 | * @param samplingRate The sampling rate 37 | * @param bitRate The bitrate in bit per seconds 38 | */ 39 | public AudioQuality(int samplingRate, int bitRate) { 40 | this.samplingRate = samplingRate; 41 | this.bitRate = bitRate; 42 | } 43 | 44 | public int samplingRate = 0; 45 | public int bitRate = 0; 46 | 47 | public boolean equals(AudioQuality quality) { 48 | if (quality==null) return false; 49 | return (quality.samplingRate == this.samplingRate & 50 | quality.bitRate == this.bitRate); 51 | } 52 | 53 | public AudioQuality clone() { 54 | return new AudioQuality(samplingRate, bitRate); 55 | } 56 | 57 | public static AudioQuality parseQuality(String str) { 58 | AudioQuality quality = DEFAULT_AUDIO_QUALITY.clone(); 59 | if (str != null) { 60 | String[] config = str.split("-"); 61 | try { 62 | quality.bitRate = Integer.parseInt(config[0])*1000; // conversion to bit/s 63 | quality.samplingRate = Integer.parseInt(config[1]); 64 | } 65 | catch (IndexOutOfBoundsException ignore) {} 66 | } 67 | return quality; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /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 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.audio; 22 | 23 | import java.io.FileDescriptor; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | 27 | import net.majorkernelpanic.streaming.MediaStream; 28 | import android.media.MediaRecorder; 29 | import android.os.ParcelFileDescriptor; 30 | import android.util.Log; 31 | 32 | /** 33 | * Don't use this class directly. 34 | */ 35 | public abstract class AudioStream extends MediaStream { 36 | 37 | protected int mAudioSource; 38 | protected int mOutputFormat; 39 | protected int mAudioEncoder; 40 | protected AudioQuality mRequestedQuality = AudioQuality.DEFAULT_AUDIO_QUALITY.clone(); 41 | protected AudioQuality mQuality = mRequestedQuality.clone(); 42 | 43 | public AudioStream() { 44 | setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 45 | } 46 | 47 | public void setAudioSource(int audioSource) { 48 | mAudioSource = audioSource; 49 | } 50 | 51 | public void setAudioQuality(AudioQuality quality) { 52 | mRequestedQuality = quality; 53 | } 54 | 55 | /** 56 | * Returns the quality of the stream. 57 | */ 58 | public AudioQuality getAudioQuality() { 59 | return mQuality; 60 | } 61 | 62 | protected void setAudioEncoder(int audioEncoder) { 63 | mAudioEncoder = audioEncoder; 64 | } 65 | 66 | protected void setOutputFormat(int outputFormat) { 67 | mOutputFormat = outputFormat; 68 | } 69 | 70 | @Override 71 | protected void encodeWithMediaRecorder() throws IOException { 72 | 73 | // We need a local socket to forward data output by the camera to the packetizer 74 | createSockets(); 75 | 76 | Log.v(TAG,"Requested audio with "+mQuality.bitRate/1000+"kbps"+" at "+mQuality.samplingRate/1000+"kHz"); 77 | 78 | mMediaRecorder = new MediaRecorder(); 79 | mMediaRecorder.setAudioSource(mAudioSource); 80 | mMediaRecorder.setOutputFormat(mOutputFormat); 81 | mMediaRecorder.setAudioEncoder(mAudioEncoder); 82 | mMediaRecorder.setAudioChannels(1); 83 | mMediaRecorder.setAudioSamplingRate(mQuality.samplingRate); 84 | mMediaRecorder.setAudioEncodingBitRate(mQuality.bitRate); 85 | 86 | // We write the output of the camera in a local socket instead of a file ! 87 | // This one little trick makes streaming feasible quiet simply: data from the camera 88 | // can then be manipulated at the other end of the socket 89 | FileDescriptor fd = null; 90 | if (sPipeApi == PIPE_API_PFD) { 91 | fd = mParcelWrite.getFileDescriptor(); 92 | } else { 93 | fd = mSender.getFileDescriptor(); 94 | } 95 | mMediaRecorder.setOutputFile(fd); 96 | mMediaRecorder.setOutputFile(fd); 97 | 98 | mMediaRecorder.prepare(); 99 | mMediaRecorder.start(); 100 | 101 | InputStream is = null; 102 | 103 | if (sPipeApi == PIPE_API_PFD) { 104 | is = new ParcelFileDescriptor.AutoCloseInputStream(mParcelRead); 105 | } else { 106 | try { 107 | // mReceiver.getInputStream contains the data from the camera 108 | is = mReceiver.getInputStream(); 109 | } catch (IOException e) { 110 | stop(); 111 | throw new IOException("Something happened with the local sockets :/ Start failed !"); 112 | } 113 | } 114 | 115 | // the mPacketizer encapsulates this stream in an RTP stream and send it over the network 116 | mPacketizer.setInputStream(is); 117 | mPacketizer.start(); 118 | mStreaming = true; 119 | 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/exceptions/CameraInUseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.exceptions; 22 | 23 | public class CameraInUseException extends RuntimeException { 24 | 25 | public CameraInUseException(String message) { 26 | super(message); 27 | } 28 | 29 | private static final long serialVersionUID = -1866132102949435675L; 30 | } 31 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/exceptions/ConfNotSupportedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.exceptions; 22 | 23 | public class ConfNotSupportedException extends RuntimeException { 24 | 25 | public ConfNotSupportedException(String message) { 26 | super(message); 27 | } 28 | 29 | private static final long serialVersionUID = 5876298277802827615L; 30 | } 31 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/exceptions/InvalidSurfaceException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.exceptions; 22 | 23 | public class InvalidSurfaceException extends RuntimeException { 24 | 25 | private static final long serialVersionUID = -7238661340093544496L; 26 | 27 | public InvalidSurfaceException(String message) { 28 | super(message); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/exceptions/StorageUnavailableException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.exceptions; 22 | 23 | import java.io.IOException; 24 | 25 | public class StorageUnavailableException extends IOException { 26 | 27 | public StorageUnavailableException(String message) { 28 | super(message); 29 | } 30 | 31 | private static final long serialVersionUID = -7537890350373995089L; 32 | } 33 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/hw/CodecManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of Spydroid (http://code.google.com/p/spydroid-ipcamera/) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.hw; 22 | 23 | import java.util.ArrayList; 24 | import java.util.HashSet; 25 | import java.util.Set; 26 | 27 | import android.annotation.SuppressLint; 28 | import android.media.MediaCodecInfo; 29 | import android.media.MediaCodecList; 30 | import android.util.Log; 31 | 32 | @SuppressLint("InlinedApi") 33 | public class CodecManager { 34 | 35 | public final static String TAG = "CodecManager"; 36 | 37 | public static final int[] SUPPORTED_COLOR_FORMATS = { 38 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, 39 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar, 40 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, 41 | MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar, 42 | MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar 43 | }; 44 | 45 | private static Codec[] sEncoders = null; 46 | private static Codec[] sDecoders = null; 47 | 48 | static class Codec { 49 | public Codec(String name, Integer[] formats) { 50 | this.name = name; 51 | this.formats = formats; 52 | } 53 | public String name; 54 | public Integer[] formats; 55 | } 56 | 57 | /** 58 | * Lists all encoders that claim to support a color format that we know how to use. 59 | * @return A list of those encoders 60 | */ 61 | @SuppressLint("NewApi") 62 | public synchronized static Codec[] findEncodersForMimeType(String mimeType) { 63 | if (sEncoders != null) return sEncoders; 64 | 65 | ArrayList encoders = new ArrayList(); 66 | 67 | // We loop through the encoders, apparently this can take up to a sec (testes on a GS3) 68 | for(int j = MediaCodecList.getCodecCount() - 1; j >= 0; j--){ 69 | MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(j); 70 | if (!codecInfo.isEncoder()) continue; 71 | 72 | String[] types = codecInfo.getSupportedTypes(); 73 | for (int i = 0; i < types.length; i++) { 74 | if (types[i].equalsIgnoreCase(mimeType)) { 75 | try { 76 | MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType); 77 | Set formats = new HashSet(); 78 | 79 | // And through the color formats supported 80 | for (int k = 0; k < capabilities.colorFormats.length; k++) { 81 | int format = capabilities.colorFormats[k]; 82 | 83 | for (int l=0;l decoders = new ArrayList(); 112 | 113 | // We loop through the decoders, apparently this can take up to a sec (testes on a GS3) 114 | for(int j = MediaCodecList.getCodecCount() - 1; j >= 0; j--){ 115 | MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(j); 116 | if (codecInfo.isEncoder()) continue; 117 | 118 | String[] types = codecInfo.getSupportedTypes(); 119 | for (int i = 0; i < types.length; i++) { 120 | if (types[i].equalsIgnoreCase(mimeType)) { 121 | try { 122 | MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType); 123 | Set formats = new HashSet(); 124 | 125 | // And through the color formats supported 126 | for (int k = 0; k < capabilities.colorFormats.length; k++) { 127 | int format = capabilities.colorFormats[k]; 128 | 129 | for (int l=0;l0) { 132 | System.arraycopy(data, 0, mBuffer, 0, mSize); 133 | System.arraycopy(data, mSize, mBuffer, mSize+mYPadding, mSize/2); 134 | return mBuffer; 135 | } 136 | return data; 137 | } 138 | } else { 139 | if (mSliceHeight==mHeight && mStride==mWidth) { 140 | // De-interleave U and V 141 | if (!mPanesReversed) { 142 | for (int i = 0; i < mSize/4; i+=1) { 143 | mBuffer[i] = data[mSize+2*i+1]; 144 | mBuffer[mSize/4+i] = data[mSize+2*i]; 145 | } 146 | } else { 147 | for (int i = 0; i < mSize/4; i+=1) { 148 | mBuffer[i] = data[mSize+2*i]; 149 | mBuffer[mSize/4+i] = data[mSize+2*i+1]; 150 | } 151 | } 152 | if (mYPadding == 0) { 153 | System.arraycopy(mBuffer, 0, data, mSize, mSize/2); 154 | } else { 155 | System.arraycopy(data, 0, mBuffer, 0, mSize); 156 | System.arraycopy(mBuffer, 0, mBuffer, mSize+mYPadding, mSize/2); 157 | return mBuffer; 158 | } 159 | return data; 160 | } 161 | } 162 | 163 | return data; 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/mp4/MP4Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.mp4; 22 | import java.io.FileNotFoundException; 23 | import java.io.IOException; 24 | 25 | import android.util.Base64; 26 | import android.util.Log; 27 | 28 | /** 29 | * Finds SPS & PPS parameters in mp4 file. 30 | */ 31 | public class MP4Config { 32 | 33 | public final static String TAG = "MP4Config"; 34 | 35 | private MP4Parser mp4Parser; 36 | private String mProfilLevel, mPPS, mSPS; 37 | 38 | public MP4Config(String profil, String sps, String pps) { 39 | mProfilLevel = profil; 40 | mPPS = pps; 41 | mSPS = sps; 42 | } 43 | 44 | public MP4Config(String sps, String pps) { 45 | mPPS = pps; 46 | mSPS = sps; 47 | mProfilLevel = MP4Parser.toHexString(Base64.decode(sps, Base64.NO_WRAP),1,3); 48 | } 49 | 50 | public MP4Config(byte[] sps, byte[] pps) { 51 | mPPS = Base64.encodeToString(pps, 0, pps.length, Base64.NO_WRAP); 52 | mSPS = Base64.encodeToString(sps, 0, sps.length, Base64.NO_WRAP); 53 | mProfilLevel = MP4Parser.toHexString(sps,1,3); 54 | } 55 | 56 | /** 57 | * Finds SPS & PPS parameters inside a .mp4. 58 | * @param path Path to the file to analyze 59 | * @throws IOException 60 | * @throws FileNotFoundException 61 | */ 62 | public MP4Config (String path) throws IOException, FileNotFoundException { 63 | 64 | StsdBox stsdBox; 65 | 66 | // We open the mp4 file and parse it 67 | try { 68 | mp4Parser = MP4Parser.parse(path); 69 | } catch (IOException ignore) { 70 | // Maybe enough of the file has been parsed and we can get the stsd box 71 | } 72 | 73 | // We find the stsdBox 74 | stsdBox = mp4Parser.getStsdBox(); 75 | mPPS = stsdBox.getB64PPS(); 76 | mSPS = stsdBox.getB64SPS(); 77 | mProfilLevel = stsdBox.getProfileLevel(); 78 | 79 | mp4Parser.close(); 80 | 81 | } 82 | 83 | public String getProfileLevel() { 84 | return mProfilLevel; 85 | } 86 | 87 | public String getB64PPS() { 88 | Log.d(TAG, "PPS: "+mPPS); 89 | return mPPS; 90 | } 91 | 92 | public String getB64SPS() { 93 | Log.d(TAG, "SPS: "+mSPS); 94 | return mSPS; 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/rtp/AACADTSPacketizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.rtp; 22 | 23 | import java.io.IOException; 24 | 25 | import net.majorkernelpanic.streaming.audio.AACStream; 26 | import android.os.SystemClock; 27 | import android.util.Log; 28 | 29 | /** 30 | * 31 | * RFC 3640. 32 | * 33 | * This packetizer must be fed with an InputStream containing ADTS AAC. 34 | * AAC will basically be rewrapped in an RTP stream and sent over the network. 35 | * This packetizer only implements the aac-hbr mode (High Bit-rate AAC) and 36 | * each packet only carry a single and complete AAC access unit. 37 | * 38 | */ 39 | public class AACADTSPacketizer extends AbstractPacketizer implements Runnable { 40 | 41 | private final static String TAG = "AACADTSPacketizer"; 42 | 43 | private Thread t; 44 | private int samplingRate = 8000; 45 | 46 | public AACADTSPacketizer() { 47 | super(); 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 setSamplingRate(int samplingRate) { 71 | this.samplingRate = samplingRate; 72 | socket.setClockFrequency(samplingRate); 73 | } 74 | 75 | public void run() { 76 | 77 | Log.d(TAG,"AAC ADTS packetizer started !"); 78 | 79 | // "A packet SHALL carry either one or more complete Access Units, or a 80 | // single fragment of an Access Unit. Fragments of the same Access Unit 81 | // have the same time stamp but different RTP sequence numbers. The 82 | // marker bit in the RTP header is 1 on the last fragment of an Access 83 | // Unit, and 0 on all other fragments." RFC 3640 84 | 85 | // ADTS header fields that we need to parse 86 | boolean protection; 87 | int frameLength, sum, length, nbau, nbpk, samplingRateIndex, profile; 88 | long oldtime = SystemClock.elapsedRealtime(), now = oldtime; 89 | byte[] header = new byte[8]; 90 | 91 | try { 92 | while (!Thread.interrupted()) { 93 | 94 | // Synchronisation: ADTS packet starts with 12bits set to 1 95 | while (true) { 96 | if ( (is.read()&0xFF) == 0xFF ) { 97 | header[1] = (byte) is.read(); 98 | if ( (header[1]&0xF0) == 0xF0) break; 99 | } 100 | } 101 | 102 | // Parse adts header (ADTS packets start with a 7 or 9 byte long header) 103 | fill(header, 2, 5); 104 | 105 | // The protection bit indicates whether or not the header contains the two extra bytes 106 | protection = (header[1]&0x01)>0 ? true : false; 107 | frameLength = (header[3]&0x03) << 11 | 108 | (header[4]&0xFF) << 3 | 109 | (header[5]&0xFF) >> 5 ; 110 | frameLength -= (protection ? 7 : 9); 111 | 112 | // Number of AAC frames in the ADTS frame 113 | nbau = (header[6]&0x03) + 1; 114 | 115 | // The number of RTP packets that will be sent for this ADTS frame 116 | nbpk = frameLength/MAXPACKETSIZE + 1; 117 | 118 | // Read CRS if any 119 | if (!protection) is.read(header,0,2); 120 | 121 | samplingRate = AACStream.AUDIO_SAMPLING_RATES[(header[2]&0x3C) >> 2]; 122 | profile = ( (header[2]&0xC0) >> 6 ) + 1 ; 123 | 124 | // We update the RTP timestamp 125 | ts += 1024L*1000000000L/samplingRate; //stats.average(); 126 | 127 | //Log.d(TAG,"frameLength: "+frameLength+" protection: "+protection+" p: "+profile+" sr: "+samplingRate); 128 | 129 | sum = 0; 130 | while (sum MAXPACKETSIZE-rtphl-4) { 137 | length = MAXPACKETSIZE-rtphl-4; 138 | } 139 | else { 140 | length = frameLength-sum; 141 | socket.markNextPacket(); 142 | } 143 | sum += length; 144 | fill(buffer, rtphl+4, length); 145 | 146 | // AU-headers-length field: contains the size in bits of a AU-header 147 | // 13+3 = 16 bits -> 13bits for AU-size and 3bits for AU-Index / AU-Index-delta 148 | // 13 bits will be enough because ADTS uses 13 bits for frame length 149 | buffer[rtphl] = 0; 150 | buffer[rtphl+1] = 0x10; 151 | 152 | // AU-size 153 | buffer[rtphl+2] = (byte) (frameLength>>5); 154 | buffer[rtphl+3] = (byte) (frameLength<<3); 155 | 156 | // AU-Index 157 | buffer[rtphl+3] &= 0xF8; 158 | buffer[rtphl+3] |= 0x00; 159 | 160 | send(rtphl+4+length); 161 | 162 | } 163 | 164 | } 165 | } catch (IOException e) { 166 | // Ignore 167 | } catch (ArrayIndexOutOfBoundsException e) { 168 | Log.e(TAG,"ArrayIndexOutOfBoundsException: "+(e.getMessage()!=null?e.getMessage():"unknown error")); 169 | e.printStackTrace(); 170 | } catch (InterruptedException ignore) {} 171 | 172 | Log.d(TAG,"AAC ADTS packetizer stopped !"); 173 | 174 | } 175 | 176 | private int fill(byte[] buffer, int offset,int length) throws IOException { 177 | int sum = 0, len; 178 | while (sum0) { 89 | 90 | bufferInfo = ((MediaCodecInputStream)is).getLastBufferInfo(); 91 | //Log.d(TAG,"length: "+length+" ts: "+bufferInfo.presentationTimeUs); 92 | oldts = ts; 93 | ts = bufferInfo.presentationTimeUs*1000; 94 | 95 | // Seems to happen sometimes 96 | if (oldts>ts) { 97 | socket.commitBuffer(); 98 | continue; 99 | } 100 | 101 | socket.markNextPacket(); 102 | socket.updateTimestamp(ts); 103 | 104 | // AU-headers-length field: contains the size in bits of a AU-header 105 | // 13+3 = 16 bits -> 13bits for AU-size and 3bits for AU-Index / AU-Index-delta 106 | // 13 bits will be enough because ADTS uses 13 bits for frame length 107 | buffer[rtphl] = 0; 108 | buffer[rtphl+1] = 0x10; 109 | 110 | // AU-size 111 | buffer[rtphl+2] = (byte) (length>>5); 112 | buffer[rtphl+3] = (byte) (length<<3); 113 | 114 | // AU-Index 115 | buffer[rtphl+3] &= 0xF8; 116 | buffer[rtphl+3] |= 0x00; 117 | 118 | send(rtphl+length+4); 119 | 120 | } else { 121 | socket.commitBuffer(); 122 | } 123 | 124 | } 125 | } catch (IOException e) { 126 | } catch (ArrayIndexOutOfBoundsException e) { 127 | Log.e(TAG,"ArrayIndexOutOfBoundsException: "+(e.getMessage()!=null?e.getMessage():"unknown error")); 128 | e.printStackTrace(); 129 | } catch (InterruptedException ignore) {} 130 | 131 | Log.d(TAG,"AAC LATM packetizer stopped !"); 132 | 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/rtp/AMRNBPacketizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.rtp; 22 | 23 | import java.io.IOException; 24 | 25 | import android.util.Log; 26 | 27 | /** 28 | * 29 | * RFC 3267. 30 | * 31 | * AMR Streaming over RTP. 32 | * 33 | * Must be fed with an InputStream containing raw AMR NB 34 | * Stream must begin with a 6 bytes long header: "#!AMR\n", it will be skipped 35 | * 36 | */ 37 | public class AMRNBPacketizer extends AbstractPacketizer implements Runnable { 38 | 39 | public final static String TAG = "AMRNBPacketizer"; 40 | 41 | private final int AMR_HEADER_LENGTH = 6; // "#!AMR\n" 42 | private static final int AMR_FRAME_HEADER_LENGTH = 1; // Each frame has a short header 43 | private static final int[] sFrameBits = {95, 103, 118, 134, 148, 159, 204, 244}; 44 | private int samplingRate = 8000; 45 | 46 | private Thread t; 47 | 48 | public AMRNBPacketizer() { 49 | super(); 50 | socket.setClockFrequency(samplingRate); 51 | } 52 | 53 | public void start() { 54 | if (t==null) { 55 | t = new Thread(this); 56 | t.start(); 57 | } 58 | } 59 | 60 | public void stop() { 61 | if (t != null) { 62 | try { 63 | is.close(); 64 | } catch (IOException ignore) {} 65 | t.interrupt(); 66 | try { 67 | t.join(); 68 | } catch (InterruptedException e) {} 69 | t = null; 70 | } 71 | } 72 | 73 | public void run() { 74 | 75 | int frameLength, frameType; 76 | long now = System.nanoTime(), oldtime = now; 77 | byte[] header = new byte[AMR_HEADER_LENGTH]; 78 | 79 | try { 80 | 81 | // Skip raw AMR header 82 | fill(header,0,AMR_HEADER_LENGTH); 83 | 84 | if (header[5] != '\n') { 85 | Log.e(TAG,"Bad header ! AMR not correcty supported by the phone !"); 86 | return; 87 | } 88 | 89 | while (!Thread.interrupted()) { 90 | 91 | buffer = socket.requestBuffer(); 92 | buffer[rtphl] = (byte) 0xF0; 93 | 94 | // First we read the frame header 95 | fill(buffer, rtphl+1,AMR_FRAME_HEADER_LENGTH); 96 | 97 | // Then we calculate the frame payload length 98 | frameType = (Math.abs(buffer[rtphl + 1]) >> 3) & 0x0f; 99 | frameLength = (sFrameBits[frameType]+7)/8; 100 | 101 | // And we read the payload 102 | fill(buffer, rtphl+2,frameLength); 103 | 104 | //Log.d(TAG,"Frame length: "+frameLength+" frameType: "+frameType); 105 | 106 | // RFC 3267 Page 14: "For AMR, the sampling frequency is 8 kHz" 107 | // FIXME: Is this really always the case ?? 108 | ts += 160L*1000000000L/samplingRate; //stats.average(); 109 | socket.updateTimestamp(ts); 110 | socket.markNextPacket(); 111 | 112 | //Log.d(TAG,"expected: "+ expected + " measured: "+measured); 113 | 114 | send(rtphl+1+AMR_FRAME_HEADER_LENGTH+frameLength); 115 | 116 | } 117 | 118 | } catch (IOException e) { 119 | } catch (InterruptedException e) {} 120 | 121 | Log.d(TAG,"AMR packetizer stopped !"); 122 | 123 | } 124 | 125 | private int fill(byte[] buffer, int offset,int length) throws IOException { 126 | int sum = 0, len; 127 | while (sumperiod) { 135 | elapsed = 0; 136 | long now = System.nanoTime(); 137 | if (!initoffset || (now - start < 0)) { 138 | start = now; 139 | duration = 0; 140 | initoffset = true; 141 | } 142 | // Prevents drifting issues by comparing the real duration of the 143 | // stream with the sum of all temporal lengths of RTP packets. 144 | value += (now - start) - duration; 145 | //Log.d(TAG, "sum1: "+duration/1000000+" sum2: "+(now-start)/1000000+" drift: "+((now-start)-duration)/1000000+" v: "+value/1000000); 146 | } 147 | if (c<5) { 148 | // We ignore the first 20 measured values because they may not be accurate 149 | c++; 150 | m = value; 151 | } else { 152 | m = (m*q+value)/(q+1); 153 | if (q>2; 99 | //Log.d(TAG,"j: "+j+" buffer: "+printBuffer(rtphl, rtphl+5)+" tr: "+tr); 100 | if (firstFragment) { 101 | // This is the first fragment of the frame -> header is set to 0x0400 102 | buffer[rtphl] = 4; 103 | firstFragment = false; 104 | } else { 105 | buffer[rtphl] = 0; 106 | } 107 | if (j>0) { 108 | // We have found the end of the frame 109 | stats.push(duration); 110 | ts+= stats.average(); duration = 0; 111 | //Log.d(TAG,"End of frame ! duration: "+stats.average()); 112 | // The last fragment of a frame has to be marked 113 | socket.markNextPacket(); 114 | send(j); 115 | nextBuffer = socket.requestBuffer(); 116 | System.arraycopy(buffer,j+2,nextBuffer,rtphl+2,MAXPACKETSIZE-j-2); 117 | buffer = nextBuffer; 118 | j = MAXPACKETSIZE-j-2; 119 | firstFragment = true; 120 | } else { 121 | // We have not found the beginning of another frame 122 | // The whole packet is a fragment of a frame 123 | send(MAXPACKETSIZE); 124 | } 125 | } 126 | } catch (IOException e) { 127 | } catch (InterruptedException e) {} 128 | 129 | Log.d(TAG,"H263 Packetizer stopped !"); 130 | 131 | } 132 | 133 | private int fill(int offset,int length) throws IOException { 134 | 135 | int sum = 0, len; 136 | 137 | while (sum=0 ){ 76 | //Log.d(TAG,"Index: "+mIndex+" Time: "+mBufferInfo.presentationTimeUs+" size: "+mBufferInfo.size); 77 | mBuffer = mBuffers[mIndex]; 78 | mBuffer.position(0); 79 | break; 80 | } else if (mIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 81 | mBuffers = mMediaCodec.getOutputBuffers(); 82 | } else if (mIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 83 | mMediaFormat = mMediaCodec.getOutputFormat(); 84 | Log.i(TAG,mMediaFormat.toString()); 85 | } else if (mIndex == MediaCodec.INFO_TRY_AGAIN_LATER) { 86 | Log.v(TAG,"No buffer available..."); 87 | //return 0; 88 | } else { 89 | Log.e(TAG,"Message: "+mIndex); 90 | //return 0; 91 | } 92 | } 93 | } 94 | 95 | if (mClosed) throw new IOException("This InputStream was closed"); 96 | 97 | min = length < mBufferInfo.size - mBuffer.position() ? length : mBufferInfo.size - mBuffer.position(); 98 | mBuffer.get(buffer, offset, min); 99 | if (mBuffer.position()>=mBufferInfo.size) { 100 | mMediaCodec.releaseOutputBuffer(mIndex, false); 101 | mBuffer = null; 102 | } 103 | 104 | } catch (RuntimeException e) { 105 | e.printStackTrace(); 106 | } 107 | 108 | return min; 109 | } 110 | 111 | public int available() { 112 | if (mBuffer != null) 113 | return mBufferInfo.size - mBuffer.position(); 114 | else 115 | return 0; 116 | } 117 | 118 | public BufferInfo getLastBufferInfo() { 119 | return mBufferInfo; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/rtsp/RtcpDeinterleaver.java: -------------------------------------------------------------------------------- 1 | package net.majorkernelpanic.streaming.rtsp; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.PipedInputStream; 6 | import java.io.PipedOutputStream; 7 | 8 | class RtcpDeinterleaver extends InputStream implements Runnable { 9 | 10 | public final static String TAG = "RtcpDeinterleaver"; 11 | 12 | private IOException mIOException; 13 | private InputStream mInputStream; 14 | private PipedInputStream mPipedInputStream; 15 | private PipedOutputStream mPipedOutputStream; 16 | private byte[] mBuffer; 17 | 18 | public RtcpDeinterleaver(InputStream inputStream) { 19 | mInputStream = inputStream; 20 | mPipedInputStream = new PipedInputStream(4096); 21 | try { 22 | mPipedOutputStream = new PipedOutputStream(mPipedInputStream); 23 | } catch (IOException e) {} 24 | mBuffer = new byte[1024]; 25 | new Thread(this).start(); 26 | } 27 | 28 | @Override 29 | public void run() { 30 | try { 31 | while (true) { 32 | int len = mInputStream.read(mBuffer, 0, 1024); 33 | mPipedOutputStream.write(mBuffer, 0, len); 34 | } 35 | } catch (IOException e) { 36 | try { 37 | mPipedInputStream.close(); 38 | } catch (IOException ignore) {} 39 | mIOException = e; 40 | } 41 | } 42 | 43 | @Override 44 | public int read(byte[] buffer) throws IOException { 45 | if (mIOException != null) { 46 | throw mIOException; 47 | } 48 | return mPipedInputStream.read(buffer); 49 | } 50 | 51 | @Override 52 | public int read(byte[] buffer, int offset, int length) throws IOException { 53 | if (mIOException != null) { 54 | throw mIOException; 55 | } 56 | return mPipedInputStream.read(buffer, offset, length); 57 | } 58 | 59 | @Override 60 | public int read() throws IOException { 61 | if (mIOException != null) { 62 | throw mIOException; 63 | } 64 | return mPipedInputStream.read(); 65 | } 66 | 67 | @Override 68 | public void close() throws IOException { 69 | mInputStream.close(); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/video/H263Stream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.video; 22 | 23 | import java.io.IOException; 24 | 25 | import net.majorkernelpanic.streaming.SessionBuilder; 26 | import net.majorkernelpanic.streaming.rtp.H263Packetizer; 27 | import android.graphics.ImageFormat; 28 | import android.hardware.Camera.CameraInfo; 29 | import android.media.MediaRecorder; 30 | import android.service.textservice.SpellCheckerService.Session; 31 | 32 | /** 33 | * A class for streaming H.263 from the camera of an android device using RTP. 34 | * You should use a {@link Session} instantiated with {@link SessionBuilder} instead of using this class directly. 35 | * Call {@link #setDestinationAddress(InetAddress)}, {@link #setDestinationPorts(int)} and {@link #setVideoQuality(VideoQuality)} 36 | * to configure the stream. You can then call {@link #start()} to start the RTP stream. 37 | * Call {@link #stop()} to stop the stream. 38 | */ 39 | public class H263Stream extends VideoStream { 40 | 41 | /** 42 | * Constructs the H.263 stream. 43 | * Uses CAMERA_FACING_BACK by default. 44 | * @throws IOException 45 | */ 46 | public H263Stream() throws IOException { 47 | this(CameraInfo.CAMERA_FACING_BACK); 48 | } 49 | 50 | /** 51 | * Constructs the H.263 stream. 52 | * @param cameraId Can be either CameraInfo.CAMERA_FACING_BACK or CameraInfo.CAMERA_FACING_FRONT 53 | * @throws IOException 54 | */ 55 | public H263Stream(int cameraId) { 56 | super(cameraId); 57 | mCameraImageFormat = ImageFormat.NV21; 58 | mVideoEncoder = MediaRecorder.VideoEncoder.H263; 59 | mPacketizer = new H263Packetizer(); 60 | } 61 | 62 | /** 63 | * Starts the stream. 64 | */ 65 | public synchronized void start() throws IllegalStateException, IOException { 66 | if (!mStreaming) { 67 | configure(); 68 | super.start(); 69 | } 70 | } 71 | 72 | public synchronized void configure() throws IllegalStateException, IOException { 73 | super.configure(); 74 | mMode = MODE_MEDIARECORDER_API; 75 | mQuality = mRequestedQuality.clone(); 76 | } 77 | 78 | /** 79 | * Returns a description of the stream using SDP. It can then be included in an SDP file. 80 | */ 81 | public String getSessionDescription() { 82 | return "m=video "+String.valueOf(getDestinationPorts()[0])+" RTP/AVP 96\r\n" + 83 | "a=rtpmap:96 H263-1998/90000\r\n"; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/net/majorkernelpanic/streaming/video/VideoQuality.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com 3 | * 4 | * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) 5 | * 6 | * Spydroid is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This source code is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this source code; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | package net.majorkernelpanic.streaming.video; 22 | 23 | import java.util.Iterator; 24 | import java.util.List; 25 | 26 | import android.hardware.Camera; 27 | import android.hardware.Camera.Size; 28 | import android.util.Log; 29 | 30 | /** 31 | * A class that represents the quality of a video stream. 32 | * It contains the resolution, the framerate (in fps) and the bitrate (in bps) of the stream. 33 | */ 34 | public class VideoQuality { 35 | 36 | // Tag 37 | private final static String TAG = "VideoQuality"; 38 | 39 | // Default video stream quality. 40 | public final static VideoQuality DEFAULT_VIDEO_QUALITY = new VideoQuality(176,144,20,500000); 41 | 42 | public int framerate = 0; 43 | public int bitrate = 0; 44 | public int resX = 0; 45 | public int resY = 0; 46 | 47 | 48 | /** 49 | * Represents a quality for a video stream. 50 | * @param resX The horizontal resolution 51 | * @param resY The vertical resolution 52 | */ 53 | public VideoQuality(int resX, int resY) { 54 | this.resX = resX; 55 | this.resY = resY; 56 | this.bitrate = DEFAULT_VIDEO_QUALITY.bitrate; 57 | this.framerate = DEFAULT_VIDEO_QUALITY.framerate; 58 | } 59 | 60 | /** 61 | * Represents a quality for a video stream. 62 | * @param resX The horizontal resolution 63 | * @param resY The vertical resolution 64 | * @param framerate The framerate in frame per seconds 65 | */ 66 | public VideoQuality(int resX, int resY, int framerate) { 67 | this.framerate = framerate; 68 | this.bitrate = DEFAULT_VIDEO_QUALITY.bitrate; 69 | this.resX = resX; 70 | this.resY = resY; 71 | } 72 | 73 | /** 74 | * Represents a quality for a video stream. 75 | * @param resX The horizontal resolution 76 | * @param resY The vertical resolution 77 | * @param framerate The framerate in frame per seconds 78 | * @param bitrate The bitrate in bit per seconds 79 | */ 80 | public VideoQuality(int resX, int resY, int framerate, int bitrate) { 81 | this.framerate = framerate; 82 | this.bitrate = bitrate; 83 | this.resX = resX; 84 | this.resY = resY; 85 | } 86 | 87 | public boolean equals(VideoQuality quality) { 88 | if (quality==null) return false; 89 | return (quality.resX == this.resX & 90 | quality.resY == this.resY & 91 | quality.framerate == this.framerate & 92 | quality.bitrate == this.bitrate); 93 | } 94 | 95 | public VideoQuality clone() { 96 | return new VideoQuality(resX,resY,framerate,bitrate); 97 | } 98 | 99 | public static VideoQuality parseQuality(String str) { 100 | VideoQuality quality = DEFAULT_VIDEO_QUALITY.clone(); 101 | if (str != null) { 102 | String[] config = str.split("-"); 103 | try { 104 | quality.bitrate = Integer.parseInt(config[0])*1000; // conversion to bit/s 105 | quality.framerate = Integer.parseInt(config[1]); 106 | quality.resX = Integer.parseInt(config[2]); 107 | quality.resY = Integer.parseInt(config[3]); 108 | } 109 | catch (IndexOutOfBoundsException ignore) {} 110 | } 111 | return quality; 112 | } 113 | 114 | public String toString() { 115 | return resX+"x"+resY+" px, "+framerate+" fps, "+bitrate/1000+" kbps"; 116 | } 117 | 118 | /** 119 | * Checks if the requested resolution is supported by the camera. 120 | * If not, it modifies it by supported parameters. 121 | **/ 122 | public static VideoQuality determineClosestSupportedResolution(List supportedSizes, VideoQuality quality) { 123 | VideoQuality v = quality.clone(); 124 | int minDist = Integer.MAX_VALUE; 125 | String supportedSizesStr = "Supported resolutions: "; 126 | for (Iterator it = supportedSizes.iterator(); it.hasNext();) { 127 | Size size = it.next(); 128 | supportedSizesStr += size.width+"x"+size.height+(it.hasNext()?", ":""); 129 | int dist = Math.abs(quality.resX - size.width); 130 | if (dist"+v.resX+"x"+v.resY); 139 | } 140 | 141 | return v; 142 | } 143 | 144 | public static VideoQuality getHighestQuality(Camera.Parameters parameters) { 145 | List supportedSizes = parameters.getSupportedPreviewSizes(); 146 | Size highestQuality = supportedSizes.get(0); 147 | return new VideoQuality(highestQuality.width, highestQuality.height); 148 | } 149 | 150 | public static int[] determineMaximumSupportedFramerate(Camera.Parameters parameters) { 151 | int[] maxFps = new int[]{0,0}; 152 | String supportedFpsRangesStr = "Supported frame rates: "; 153 | List supportedFpsRanges = parameters.getSupportedPreviewFpsRange(); 154 | for (Iterator it = supportedFpsRanges.iterator(); it.hasNext();) { 155 | int[] interval = it.next(); 156 | // Intervals are returned as integers, for example "29970" means "29.970" FPS. 157 | supportedFpsRangesStr += interval[0]/1000+"-"+interval[1]/1000+"fps"+(it.hasNext()?", ":""); 158 | if (interval[1]>maxFps[1] || (interval[0]>maxFps[0] && interval[1]==maxFps[1])) { 159 | maxFps = interval; 160 | } 161 | } 162 | Log.v(TAG,supportedFpsRangesStr); 163 | return maxFps; 164 | } 165 | 166 | } 167 | --------------------------------------------------------------------------------