diff --git a/src/net/majorkernelpanic/streaming/Session.java b/src/net/majorkernelpanic/streaming/Session.java index a904fd4f..0d3590a1 100644 --- a/src/net/majorkernelpanic/streaming/Session.java +++ b/src/net/majorkernelpanic/streaming/Session.java @@ -39,6 +39,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; +import android.util.Log; /** * You should instantiate this class with the {@link SessionBuilder}.
@@ -129,7 +130,7 @@ public Session() { mOrigin = "127.0.0.1"; } - /** + /** * The callback interface you need to implement to get some feedback * Those will be called from the UI thread. */ @@ -369,7 +370,9 @@ public void configure() { public void run() { try { syncConfigure(); - } catch (Exception e) {}; + } catch (Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); + }; } }); } @@ -622,11 +625,14 @@ public int getCamera() { } + /** * Toggles the LED of the phone if it has one. * You can get the current state of the flash with * {@link Session#getVideoTrack()} and {@link VideoStream#getFlashState()}. **/ + + /* public void toggleFlash() { mHandler.post(new Runnable() { @Override @@ -642,6 +648,51 @@ public void run() { }); } + + + +public void setSize(final int w, final int h) { + + sHandler.post(new Runnable() { + + @Override + public void run() { + if (mVideoStream != null) { + try { + + mVideoStream.setCameraPreviewSize(w,h); + } catch (RuntimeException e) { + + } + } + } + }); + + } + + + // + public List getAvailableSizes() { + + sHandler.post(new Runnable() { + + @Override + public void run() { + if (mVideoStream != null) { + try { + size = mVideoStream.getSizes(); + } catch (RuntimeException e) { + + } + } + } + }); + return size; + } + +*/ + + /** Deletes all existing tracks & release associated resources. */ public void release() { removeAudioTrack(); diff --git a/src/net/majorkernelpanic/streaming/SessionBuilder.java b/src/net/majorkernelpanic/streaming/SessionBuilder.java index 1ba39c41..0fd3b4ef 100644 --- a/src/net/majorkernelpanic/streaming/SessionBuilder.java +++ b/src/net/majorkernelpanic/streaming/SessionBuilder.java @@ -74,6 +74,7 @@ public class SessionBuilder { private SurfaceView mSurfaceView = null; private String mOrigin = null; private String mDestination = null; + private int mDestinationVideoPort = 5006; private Session.Callback mCallback = null; // Removes the default public constructor @@ -141,7 +142,7 @@ public Session build() { video.setVideoQuality(mVideoQuality); video.setSurfaceView(mSurfaceView); video.setPreviewOrientation(mOrientation); - video.setDestinationPorts(5006); + video.setDestinationPorts(mDestinationVideoPort); } if (session.getAudioTrack()!=null) { @@ -169,6 +170,13 @@ public SessionBuilder setDestination(String destination) { return this; } + /** Sets the destination IP & video port for the session. */ + public SessionBuilder setDestination(String destination, int videoPort) { + mDestination = destination; + mDestinationVideoPort = videoPort; + return this; + } + /** Sets the origin of the session. It appears in the SDP of the session. */ public SessionBuilder setOrigin(String origin) { mOrigin = origin; diff --git a/src/net/majorkernelpanic/streaming/exceptions/InvalidSurfaceException.java b/src/net/majorkernelpanic/streaming/exceptions/InvalidSurfaceException.java index 45cd5b16..f7423b44 100644 --- a/src/net/majorkernelpanic/streaming/exceptions/InvalidSurfaceException.java +++ b/src/net/majorkernelpanic/streaming/exceptions/InvalidSurfaceException.java @@ -27,5 +27,8 @@ public class InvalidSurfaceException extends RuntimeException { public InvalidSurfaceException(String message) { super(message); } + public InvalidSurfaceException(String message, Throwable t) { + super(message, t); + } } diff --git a/src/net/majorkernelpanic/streaming/gl/SurfaceView.java b/src/net/majorkernelpanic/streaming/gl/SurfaceView.java index d78b1721..f499f67a 100644 --- a/src/net/majorkernelpanic/streaming/gl/SurfaceView.java +++ b/src/net/majorkernelpanic/streaming/gl/SurfaceView.java @@ -90,9 +90,15 @@ public SurfaceView(Context context, AttributeSet attrs) { super(context, attrs); mHandler = new Handler(); getHolder().addCallback(this); - } + } + + public SurfaceView(Context context) { + super(context); + mHandler = new Handler(); + getHolder().addCallback(this); + } - public void setAspectRatioMode(int mode) { + public void setAspectRatioMode(int mode) { mAspectRatioMode = mode; } diff --git a/src/net/majorkernelpanic/streaming/video/H264Stream.java b/src/net/majorkernelpanic/streaming/video/H264Stream.java index a45034e1..a67661b6 100644 --- a/src/net/majorkernelpanic/streaming/video/H264Stream.java +++ b/src/net/majorkernelpanic/streaming/video/H264Stream.java @@ -125,7 +125,7 @@ private MP4Config testMediaCodecAPI() throws RuntimeException, IOException { createCamera(); updateCamera(); try { - if (mQuality.resX>=640) { + if (mQuality.resX>=640 && mMode == MODE_MEDIACODEC_API) { // Using the MediaCodec API with the buffer method for high resolutions is too slow mMode = MODE_MEDIARECORDER_API; } diff --git a/src/net/majorkernelpanic/streaming/video/VideoQuality.java b/src/net/majorkernelpanic/streaming/video/VideoQuality.java index 8c857f86..a4f558f2 100644 --- a/src/net/majorkernelpanic/streaming/video/VideoQuality.java +++ b/src/net/majorkernelpanic/streaming/video/VideoQuality.java @@ -79,7 +79,7 @@ public boolean equals(VideoQuality quality) { } public VideoQuality clone() { - return new VideoQuality(resX,resY,framerate,bitrate); + return new VideoQuality(resX,resY,framerate, bitrate); } public static VideoQuality parseQuality(String str) { @@ -113,7 +113,7 @@ public static VideoQuality determineClosestSupportedResolution(Camera.Parameters for (Iterator it = supportedSizes.iterator(); it.hasNext();) { Size size = it.next(); supportedSizesStr += size.width+"x"+size.height+(it.hasNext()?", ":""); - int dist = Math.abs(quality.resX - size.width); + int dist = Math.abs(quality.resX - size.width) + Math.abs(quality.resY - size.height); if (dist size = getSizes(); + Camera.Size size_to_use = getOptimalSize(size, w, h); + + System.out.println("Setting preview to: "+ w + h); + + if (mCamera != null) { + + if (mStreaming && mMode == MODE_MEDIARECORDER_API) { + lockCamera(); + } + + Parameters parameters = mCamera.getParameters(); + + parameters.setPreviewSize(size_to_use.width, size_to_use.height); + //parameters.setPreviewSize(176, 144); + try { + mCamera.setParameters(parameters); + System.out.println("Setting preview to: "+ size_to_use.width + size_to_use.height + " DONE!!"); + Camera.Size z = parameters.getPreviewSize(); + int w_temp = z.width; + int h_temp = z.height; + System.out.println("Saved preview is: "+ w_temp + h_temp); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + else { + System.out.println("Setting preview to: "+ w + h + " FAILED!!"); + } + + + + } + + + public synchronized List getSizes() { + + List size = null; + + if (mCamera != null) { + + if (mStreaming && mMode == MODE_MEDIARECORDER_API) { + lockCamera(); + } + + + try { + + Parameters parameters = mCamera.getParameters(); + size = parameters.getSupportedPreviewSizes(); + + System.out.println("Some of the supported preview is " + size.get(0).width + "x" + size.get(0).height); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + + + + } + + else { + System.out.println("Failed to get preview sizes"); + } + + return size; + } + + + + private Camera.Size getOptimalSize(List sizes, int w, int h) { + + final double ASPECT_TOLERANCE = 0.2; + double targetRatio = (double) w / h; + if (sizes == null) + return null; + Camera.Size optimalSize = null; + double minDiff = Double.MAX_VALUE; + int targetHeight = h; + // Try to find an size match aspect ratio and size + for (Camera.Size size : sizes) + { + + double ratio = (double) size.width / size.height; + if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) + continue; + if (Math.abs(size.height - targetHeight) < minDiff) + { + optimalSize = size; + minDiff = Math.abs(size.height - targetHeight); + } + } + // Cannot find the one match the aspect ratio, ignore the requirement + + if (optimalSize == null) + { + minDiff = Double.MAX_VALUE; + for (Camera.Size size : sizes) { + if (Math.abs(size.height - targetHeight) < minDiff) + { + optimalSize = size; + minDiff = Math.abs(size.height - targetHeight); + } + } + } + + + + return optimalSize; + } + + + + + + + /** * Computes the average frame rate at which the preview callback is called. * We will then use this average framerate with the MediaCodec.