Back to project page spydroid-ipcamera.
The source code is released under:
GNU General Public License
If you think the Android project spydroid-ipcamera listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2011-2014 GUIGUI Simon, fyhertz@gmail.com * /* ww w . j a va2s .c o m*/ * This file is part of libstreaming (https://github.com/fyhertz/libstreaming) * * Spydroid is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this source code; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package net.majorkernelpanic.streaming; import java.io.IOException; import java.net.InetAddress; import java.util.Random; import net.majorkernelpanic.streaming.audio.AudioStream; import net.majorkernelpanic.streaming.rtp.AbstractPacketizer; import net.majorkernelpanic.streaming.video.VideoStream; import android.annotation.SuppressLint; import android.media.MediaCodec; import android.media.MediaRecorder; import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.util.Log; /** * A MediaRecorder that streams what it records using a packetizer from the rtp package. * You can't use this class directly ! */ public abstract class MediaStream implements Stream { protected static final String TAG = "MediaStream"; /** Raw audio/video will be encoded using the MediaRecorder API. */ public static final byte MODE_MEDIARECORDER_API = 0x01; /** Raw audio/video will be encoded using the MediaCodec API with buffers. */ public static final byte MODE_MEDIACODEC_API = 0x02; /** Raw audio/video will be encoded using the MediaCode API with a surface. */ public static final byte MODE_MEDIACODEC_API_2 = 0x05; /** Prefix that will be used for all shared preferences saved by libstreaming */ protected static final String PREF_PREFIX = "libstreaming-"; /** The packetizer that will read the output of the camera and send RTP packets over the networkd. */ protected AbstractPacketizer mPacketizer = null; protected static byte sSuggestedMode = MODE_MEDIARECORDER_API; protected byte mMode, mRequestedMode; protected boolean mStreaming = false, mConfigured = false; protected int mRtpPort = 0, mRtcpPort = 0; protected InetAddress mDestination; protected LocalSocket mReceiver, mSender = null; private LocalServerSocket mLss = null; private int mSocketId, mTTL = 64; protected MediaRecorder mMediaRecorder; protected MediaCodec mMediaCodec; static { // We determine wether or not the MediaCodec API should be used try { Class.forName("android.media.MediaCodec"); // Will be set to MODE_MEDIACODEC_API at some point... sSuggestedMode = MODE_MEDIACODEC_API; Log.i(TAG,"Phone supports the MediaCoded API"); } catch (ClassNotFoundException e) { sSuggestedMode = MODE_MEDIARECORDER_API; Log.i(TAG,"Phone does not support the MediaCodec API"); } } public MediaStream() { mRequestedMode = sSuggestedMode; mMode = sSuggestedMode; } /** * Sets the destination ip address of the stream. * @param dest The destination address of the stream */ public void setDestinationAddress(InetAddress dest) { mDestination = dest; } /** * Sets the destination ports of the stream. * If an odd number is supplied for the destination port then the next * lower even number will be used for RTP and it will be used for RTCP. * If an even number is supplied, it will be used for RTP and the next odd * number will be used for RTCP. * @param dport The destination port */ public void setDestinationPorts(int dport) { if (dport % 2 == 1) { mRtpPort = dport-1; mRtcpPort = dport; } else { mRtpPort = dport; mRtcpPort = dport+1; } } /** * Sets the destination ports of the stream. * @param rtpPort Destination port that will be used for RTP * @param rtcpPort Destination port that will be used for RTCP */ public void setDestinationPorts(int rtpPort, int rtcpPort) { mRtpPort = rtpPort; mRtcpPort = rtcpPort; } /** * Sets the Time To Live of packets sent over the network. * @param ttl The time to live * @throws IOException */ public void setTimeToLive(int ttl) throws IOException { mTTL = ttl; } /** * Returns a pair of destination ports, the first one is the * one used for RTP and the second one is used for RTCP. **/ public int[] getDestinationPorts() { return new int[] { mRtpPort, mRtcpPort }; } /** * Returns a pair of source ports, the first one is the * one used for RTP and the second one is used for RTCP. **/ public int[] getLocalPorts() { return new int[] { this.mPacketizer.getRtpSocket().getLocalPort(), this.mPacketizer.getRtcpSocket().getLocalPort() }; } /** * Sets the streaming method that will be used. * * If the mode is set to {@link #MODE_MEDIARECORDER_API}, raw audio/video will be encoded * using the MediaRecorder API. <br /> * * If the mode is set to {@link #MODE_MEDIACODEC_API} or to {@link #MODE_MEDIACODEC_API_2}, * audio/video will be encoded with using the MediaCodec. <br /> * * The {@link #MODE_MEDIACODEC_API_2} mode only concerns {@link VideoStream}, it makes * use of the createInputSurface() method of the MediaCodec API (Android 4.3 is needed there). <br /> * * @param mode Can be {@link #MODE_MEDIARECORDER_API}, {@link #MODE_MEDIACODEC_API} or {@link #MODE_MEDIACODEC_API_2} */ public void setStreamingMethod(byte mode) { mRequestedMode = mode; } /** * Returns the packetizer associated with the {@link MediaStream}. * @return The packetizer */ public AbstractPacketizer getPacketizer() { return mPacketizer; } /** * Returns an approximation of the bit rate consumed by the stream in bit per seconde. */ public long getBitrate() { return !mStreaming ? 0 : mPacketizer.getRtpSocket().getBitrate(); } /** * Indicates if the {@link MediaStream} is streaming. * @return A boolean indicating if the {@link MediaStream} is streaming */ public boolean isStreaming() { return mStreaming; } /** * Configures the stream with the settings supplied with * {@link VideoStream#setVideoQuality(net.majorkernelpanic.streaming.video.VideoQuality)} * for a {@link VideoStream} and {@link AudioStream#setAudioQuality(net.majorkernelpanic.streaming.audio.AudioQuality)} * for a {@link AudioStream}. */ public synchronized void configure() throws IllegalStateException, IOException { if (mStreaming) throw new IllegalStateException("Can't be called while streaming."); mMode = mRequestedMode; mConfigured = true; } /** Starts the stream. */ public synchronized void start() throws IllegalStateException, IOException { if (mDestination==null) throw new IllegalStateException("No destination ip address set for the stream !"); if (mRtpPort<=0 || mRtcpPort<=0) throw new IllegalStateException("No destination ports set for the stream !"); mPacketizer.setTimeToLive(mTTL); if (mMode != MODE_MEDIARECORDER_API) { encodeWithMediaCodec(); } else { encodeWithMediaRecorder(); } } /** Stops the stream. */ @SuppressLint("NewApi") public synchronized void stop() { if (mStreaming) { try { if (mMode==MODE_MEDIARECORDER_API) { mMediaRecorder.stop(); mMediaRecorder.release(); mMediaRecorder = null; closeSockets(); mPacketizer.stop(); } else { mPacketizer.stop(); mMediaCodec.stop(); mMediaCodec.release(); mMediaCodec = null; } } catch (Exception e) { e.printStackTrace(); } mStreaming = false; } } protected abstract void encodeWithMediaRecorder() throws IOException; protected abstract void encodeWithMediaCodec() throws IOException; /** * Returns a description of the stream using SDP. * This method can only be called after {@link Stream#configure()}. * @throws IllegalStateException Thrown when {@link Stream#configure()} wa not called. */ public abstract String getSessionDescription(); /** * Returns the SSRC of the underlying {@link net.majorkernelpanic.streaming.rtp.RtpSocket}. * @return the SSRC of the stream */ public int getSSRC() { return getPacketizer().getSSRC(); } protected void createSockets() throws IOException { final String LOCAL_ADDR = "net.majorkernelpanic.streaming-"; for (int i=0;i<10;i++) { try { mSocketId = new Random().nextInt(); mLss = new LocalServerSocket(LOCAL_ADDR+mSocketId); break; } catch (IOException e1) {} } mReceiver = new LocalSocket(); mReceiver.connect( new LocalSocketAddress(LOCAL_ADDR+mSocketId)); mReceiver.setReceiveBufferSize(500000); mReceiver.setSoTimeout(3000); mSender = mLss.accept(); mSender.setSendBufferSize(500000); } protected void closeSockets() { try { mReceiver.close(); } catch (Exception e) { e.printStackTrace(); } try { mSender.close(); } catch (Exception e) { e.printStackTrace(); } try { mLss.close(); } catch (Exception e) { e.printStackTrace(); } mLss = null; mSender = null; mReceiver = null; } }