From f8437002353b3267bc8f8bf3ea9f5fee37b3e6b2 Mon Sep 17 00:00:00 2001 From: Miguel Astor Date: Tue, 7 Jan 2014 18:12:47 -0430 Subject: [PATCH] Started fixing the video streaming code. --- AndroidManifest.xml | 15 +- .../VideoFrameDataMessage.java} | 6 +- .../VideoStreamingControlMessage.java} | 6 +- src/ve/ucv/ciens/ccg/nxtcam/CamActivity.java | 6 +- ...rThread.java => VideoStreamingThread.java} | 145 ++++++++++++------ ...tocol.java => VideoStreamingProtocol.java} | 2 +- 6 files changed, 116 insertions(+), 64 deletions(-) rename src/ve/ucv/ciens/ccg/{nxtcam/network/protocols/ImageDataMessage.java => networkdata/VideoFrameDataMessage.java} (86%) rename src/ve/ucv/ciens/ccg/{nxtcam/network/protocols/ImageTransferProtocolMessage.java => networkdata/VideoStreamingControlMessage.java} (83%) rename src/ve/ucv/ciens/ccg/nxtcam/network/{ImageTransferThread.java => VideoStreamingThread.java} (66%) rename src/ve/ucv/ciens/ccg/nxtcam/network/protocols/{ImageTransferProtocol.java => VideoStreamingProtocol.java} (96%) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index cb91dd7..bce1ee6 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -24,16 +24,15 @@ android:minSdkVersion="11" android:targetSdkVersion="19" /> + + + + - - - @@ -43,8 +42,8 @@ android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" - android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" - android:screenOrientation="landscape" > + android:screenOrientation="landscape" + android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" > @@ -64,4 +63,4 @@ - + \ No newline at end of file diff --git a/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageDataMessage.java b/src/ve/ucv/ciens/ccg/networkdata/VideoFrameDataMessage.java similarity index 86% rename from src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageDataMessage.java rename to src/ve/ucv/ciens/ccg/networkdata/VideoFrameDataMessage.java index adf546c..bfff587 100644 --- a/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageDataMessage.java +++ b/src/ve/ucv/ciens/ccg/networkdata/VideoFrameDataMessage.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package ve.ucv.ciens.ccg.nxtcam.network.protocols; +package ve.ucv.ciens.ccg.networkdata; import java.io.Serializable; -public final class ImageDataMessage implements Serializable{ +public final class VideoFrameDataMessage implements Serializable{ private static final long serialVersionUID = 9989L; public static final int magicNumber = 0x10; @@ -25,7 +25,7 @@ public final class ImageDataMessage implements Serializable{ public int imageHeight; public byte[] data; - public ImageDataMessage(){ + public VideoFrameDataMessage(){ imageWidth = -1; imageHeight = -1; data = null; diff --git a/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageTransferProtocolMessage.java b/src/ve/ucv/ciens/ccg/networkdata/VideoStreamingControlMessage.java similarity index 83% rename from src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageTransferProtocolMessage.java rename to src/ve/ucv/ciens/ccg/networkdata/VideoStreamingControlMessage.java index 3cca499..6f32081 100644 --- a/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageTransferProtocolMessage.java +++ b/src/ve/ucv/ciens/ccg/networkdata/VideoStreamingControlMessage.java @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package ve.ucv.ciens.ccg.nxtcam.network.protocols; +package ve.ucv.ciens.ccg.networkdata; import java.io.Serializable; -public final class ImageTransferProtocolMessage implements Serializable{ +public final class VideoStreamingControlMessage implements Serializable{ private static final long serialVersionUID = 8898L; public static final int magicNumber = 0x20; public byte message; - public ImageTransferProtocolMessage(){ + public VideoStreamingControlMessage(){ message = -1; } } \ No newline at end of file diff --git a/src/ve/ucv/ciens/ccg/nxtcam/CamActivity.java b/src/ve/ucv/ciens/ccg/nxtcam/CamActivity.java index c1b6e54..e02b331 100644 --- a/src/ve/ucv/ciens/ccg/nxtcam/CamActivity.java +++ b/src/ve/ucv/ciens/ccg/nxtcam/CamActivity.java @@ -16,7 +16,7 @@ package ve.ucv.ciens.ccg.nxtcam; import ve.ucv.ciens.ccg.nxtcam.camera.CameraPreview; -import ve.ucv.ciens.ccg.nxtcam.network.ImageTransferThread; +import ve.ucv.ciens.ccg.nxtcam.network.VideoStreamingThread; import ve.ucv.ciens.ccg.nxtcam.network.LCPThread; import ve.ucv.ciens.ccg.nxtcam.utils.Logger; import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants; @@ -39,7 +39,7 @@ public class CamActivity extends Activity{ private Camera hwCamera; private CameraPreview cPreview; private CameraSetupTask camSetupTask; - private ImageTransferThread imThread; + private VideoStreamingThread imThread; private LCPThread botThread; private String serverIp; @@ -54,7 +54,7 @@ public class CamActivity extends Activity{ Intent intent = getIntent(); serverIp = intent.getStringExtra("address"); - imThread = new ImageTransferThread(serverIp); + imThread = new VideoStreamingThread(serverIp); imThread.start(); } diff --git a/src/ve/ucv/ciens/ccg/nxtcam/network/ImageTransferThread.java b/src/ve/ucv/ciens/ccg/nxtcam/network/VideoStreamingThread.java similarity index 66% rename from src/ve/ucv/ciens/ccg/nxtcam/network/ImageTransferThread.java rename to src/ve/ucv/ciens/ccg/nxtcam/network/VideoStreamingThread.java index 4114df9..93dd089 100644 --- a/src/ve/ucv/ciens/ccg/nxtcam/network/ImageTransferThread.java +++ b/src/ve/ucv/ciens/ccg/nxtcam/network/VideoStreamingThread.java @@ -22,31 +22,33 @@ import java.io.ObjectOutputStream; import java.net.InetAddress; import java.net.Socket; +import ve.ucv.ciens.ccg.networkdata.VideoFrameDataMessage; +import ve.ucv.ciens.ccg.networkdata.VideoStreamingControlMessage; import ve.ucv.ciens.ccg.nxtcam.camera.CameraImageMonitor; -import ve.ucv.ciens.ccg.nxtcam.network.protocols.ImageDataMessage; -import ve.ucv.ciens.ccg.nxtcam.network.protocols.ImageTransferProtocol; -import ve.ucv.ciens.ccg.nxtcam.network.protocols.ImageTransferProtocolMessage; +import ve.ucv.ciens.ccg.nxtcam.network.protocols.VideoStreamingProtocol; import ve.ucv.ciens.ccg.nxtcam.utils.Logger; import ve.ucv.ciens.ccg.nxtcam.utils.ProjectConstants; import android.graphics.ImageFormat; import android.graphics.Rect; import android.graphics.YuvImage; -public class ImageTransferThread extends Thread{ +public class VideoStreamingThread extends Thread{ private final String TAG = "IM_THREAD"; - private final String CLASS_NAME = ImageTransferThread.class.getSimpleName(); + private final String CLASS_NAME = VideoStreamingThread.class.getSimpleName(); - private enum thread_state_t {WAIT_FOR_ACK, WAIT_FOR_READY, CAN_SEND, END_STREAM}; + private enum ProtocolState_t {WAIT_FOR_ACK, WAIT_FOR_READY, CAN_SEND, END_STREAM}; private boolean pause, done; private Object threadPauseMonitor; private CameraImageMonitor camMonitor; private Socket socket; private ObjectOutputStream writer; - private ObjectInputStream reader; private String serverIp; - private thread_state_t threadState; + private ObjectInputStream reader; + private String serverIp; + private ProtocolState_t protocolState; + private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - public ImageTransferThread(String serverIp){ + public VideoStreamingThread(String serverIp){ this.serverIp = serverIp; pause = false; done = false; @@ -55,14 +57,14 @@ public class ImageTransferThread extends Thread{ writer = null; reader = null; camMonitor = CameraImageMonitor.getInstance(); - threadState = thread_state_t.WAIT_FOR_READY; + protocolState = ProtocolState_t.WAIT_FOR_READY; } - public void run(){ + /*public void run(){ byte[] image; - Object auxiliary; - ImageTransferProtocolMessage simpleMessage; - ImageDataMessage imageMessage; + Object tmpMessage; + VideoStreamingControlMessage controlMessage; + VideoFrameDataMessage dataMessage; final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); connectToServer(); @@ -73,12 +75,12 @@ public class ImageTransferThread extends Thread{ }else{ while(!done){ // checkPause(); - switch(threadState){ + switch(protocolState){ case WAIT_FOR_READY: Logger.log_d(TAG, CLASS_NAME + ".run() :: Reading message from server. State is WAIT_FOR_READY."); - auxiliary = readMessage(); + tmpMessage = readMessage(); - if(!validateImageTransferProtocolMessage(auxiliary)){ + if(!validateImageTransferProtocolMessage(tmpMessage)){ // If the message received is not valid then send an UNRECOGNIZED message to the server. Logger.log_d(TAG, CLASS_NAME + ".run() :: Received an unrecognized protocol message. State WAIT_FOR_READY."); Logger.log_d(TAG, CLASS_NAME + ".run() :: Sending UNRECOGNIZED message to server."); @@ -86,24 +88,24 @@ public class ImageTransferThread extends Thread{ }else{ // Else if the message passed the validity check then proceed to the next protocol state. - simpleMessage = (ImageTransferProtocolMessage)auxiliary; - if(simpleMessage.message == ImageTransferProtocol.FLOW_CONTROL_CONTINUE){ + controlMessage = (VideoStreamingControlMessage)tmpMessage; + if(controlMessage.message == VideoStreamingProtocol.FLOW_CONTROL_CONTINUE){ Logger.log_d(TAG, CLASS_NAME + ".run() :: Received FLOW_CONTROL_CONTINUE from the server."); Logger.log_d(TAG, CLASS_NAME + ".run() :: Transitioning from WAIT_FOR_READY to CAN_SEND."); - threadState = thread_state_t.CAN_SEND; - }else if(simpleMessage.message == ImageTransferProtocol.STREAM_CONTROL_END){ + protocolState = ProtocolState_t.CAN_SEND; + }else if(controlMessage.message == VideoStreamingProtocol.STREAM_CONTROL_END){ Logger.log_d(TAG, CLASS_NAME + ".run() :: Received STREAM_CONTROL_END from the server."); Logger.log_d(TAG, CLASS_NAME + ".run() :: Transitioning from WAIT_FOR_READY to END_STREAM."); - threadState = thread_state_t.END_STREAM; + protocolState = ProtocolState_t.END_STREAM; } } break; case WAIT_FOR_ACK: Logger.log_d(TAG, CLASS_NAME + ".run() :: Reading message from server. State is WAIT_FOR_ACK."); - auxiliary = readMessage(); + tmpMessage = readMessage(); - if(!validateImageTransferProtocolMessage(auxiliary)){ + if(!validateImageTransferProtocolMessage(tmpMessage)){ // If the message received is not valid then send an UNRECOGNIZED message to the server. Logger.log_d(TAG, CLASS_NAME + ".run() :: Received an unrecognized protocol message. State WAIT_FOR_ACK."); Logger.log_d(TAG, CLASS_NAME + ".run() :: Sending UNRECOGNIZED message to server."); @@ -111,17 +113,17 @@ public class ImageTransferThread extends Thread{ }else{ // Else if the message passed the validity check then proceed to the next protocol state. - simpleMessage = (ImageTransferProtocolMessage)auxiliary; - if(simpleMessage.message == ImageTransferProtocol.ACK_SEND_NEXT){ + controlMessage = (VideoStreamingControlMessage)tmpMessage; + if(controlMessage.message == VideoStreamingProtocol.ACK_SEND_NEXT){ Logger.log_d(TAG, CLASS_NAME + ".run() :: Received ACK_SEND_NEXT from the server."); Logger.log_d(TAG, CLASS_NAME + ".run() :: Transitioning from WAIT_FOR_ACK to CAN_SEND."); - threadState = thread_state_t.CAN_SEND; - }else if(simpleMessage.message == ImageTransferProtocol.ACK_WAIT){ + protocolState = ProtocolState_t.CAN_SEND; + }else if(controlMessage.message == VideoStreamingProtocol.ACK_WAIT){ Logger.log_d(TAG, CLASS_NAME + ".run() :: Received ACK_WAIT from the server."); Logger.log_d(TAG, CLASS_NAME + ".run() :: Transitioning from WAIT_FOR_ACK to WAIT_FOR_READY."); - threadState = thread_state_t.WAIT_FOR_READY; - }else if(simpleMessage.message == ImageTransferProtocol.STREAM_CONTROL_END){ - threadState = thread_state_t.END_STREAM; + protocolState = ProtocolState_t.WAIT_FOR_READY; + }else if(controlMessage.message == VideoStreamingProtocol.STREAM_CONTROL_END){ + protocolState = ProtocolState_t.END_STREAM; } } break; @@ -139,15 +141,15 @@ public class ImageTransferThread extends Thread{ // Prepare the message for sending. Logger.log_d(TAG, CLASS_NAME + ".run() :: Building message."); - imageMessage = new ImageDataMessage(); - imageMessage.imageWidth = imageSize.width(); - imageMessage.imageHeight = imageSize.height(); - imageMessage.data = outputStream.toByteArray(); + dataMessage = new VideoFrameDataMessage(); + dataMessage.imageWidth = imageSize.width(); + dataMessage.imageHeight = imageSize.height(); + dataMessage.data = outputStream.toByteArray(); // Send the message. try{ Logger.log_d(TAG, CLASS_NAME + ".run() :: Sending message."); - writer.writeObject(imageMessage); + writer.writeObject(dataMessage); }catch(IOException io){ Logger.log_e(TAG, CLASS_NAME + ".run() :: Error sending image to the server: " + io.getMessage()); } @@ -157,12 +159,12 @@ public class ImageTransferThread extends Thread{ yuvImage = null; image = null; outputStream.reset(); - imageMessage = null; + dataMessage = null; imageSize = null; Logger.log_d(TAG, CLASS_NAME + ".run() :: Image data successfuly sent."); Logger.log_d(TAG, CLASS_NAME + ".run() :: Transitioning from CAN_SEND to WAIT_FOR_ACK."); - threadState = thread_state_t.WAIT_FOR_ACK; + protocolState = ProtocolState_t.WAIT_FOR_ACK; break; case END_STREAM: @@ -175,6 +177,57 @@ public class ImageTransferThread extends Thread{ } } Logger.log_d(TAG, CLASS_NAME + ".run() :: Thread finish reached."); + }*/ + + public void run(){ + connectToServer(); + + if(!socket.isConnected()){ + Logger.log_e(TAG, CLASS_NAME + ".run() :: Not connected to a server. Finishing thread."); + return; + + }else{ + while(!done){ + sendImage(); + } + } + + Logger.log_d(TAG, CLASS_NAME + ".run() :: Thread finish reached."); + } + + private void sendImage(){ + byte[] image; + YuvImage yuvImage; + VideoFrameDataMessage message; + Rect imageSize; + + image = camMonitor.getImageData(); + imageSize = camMonitor.getImageParameters(); + + // Compress the image as Jpeg. + Logger.log_d(TAG, CLASS_NAME + ".sendImage() :: Compressing image."); + yuvImage = new YuvImage(image, ImageFormat.NV21, imageSize.width(), imageSize.height(), null); + yuvImage.compressToJpeg(imageSize, 90, outputStream); + + Logger.log_d(TAG, CLASS_NAME + ".sendImage() :: Building message."); + message = new VideoFrameDataMessage(); + message.data = outputStream.toByteArray(); + message.imageWidth = imageSize.width(); + message.imageHeight = imageSize.height(); + + try{ + Logger.log_d(TAG, CLASS_NAME + ".sendImage() :: Sending message."); + writer.writeObject(message); + writer.flush(); + Logger.log_e(TAG, CLASS_NAME + ".sendImage() :: Message sent successfully: "); + + }catch(IOException io){ + Logger.log_e(TAG, CLASS_NAME + ".sendImage() :: Error sending image to the server: " + io.getMessage()); + + }finally{ + Logger.log_d(TAG, CLASS_NAME + ".sendImage() :: Cleaning."); + outputStream.reset(); + } } private void connectToServer(){ @@ -215,35 +268,35 @@ public class ImageTransferThread extends Thread{ } private Object readMessage(){ - Object auxiliary; + Object tmpMessage; // Read a message from the server stream. try{ - auxiliary = reader.readObject(); + tmpMessage = reader.readObject(); }catch(IOException io){ Logger.log_e(TAG, CLASS_NAME + ".run() :: IOException when reading in WAIT_FOR_READY state."); - auxiliary = null; + tmpMessage = null; return null; }catch(ClassNotFoundException cn){ Logger.log_e(TAG, CLASS_NAME + ".run() :: ClassNotFoundException when reading in WAIT_FOR_READY state."); - auxiliary = null; + tmpMessage = null; return null; } - return auxiliary; + return tmpMessage; } private boolean validateImageTransferProtocolMessage(Object message){ - if(message != null && message instanceof ImageTransferProtocolMessage) + if(message != null && message instanceof VideoStreamingControlMessage) return true; else return false; } private void sendUnrecognizedMessage(){ - ImageTransferProtocolMessage message = new ImageTransferProtocolMessage(); - message.message = ImageTransferProtocol.UNRECOGNIZED; + VideoStreamingControlMessage message = new VideoStreamingControlMessage(); + message.message = VideoStreamingProtocol.UNRECOGNIZED; try{ writer.writeObject(message); diff --git a/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageTransferProtocol.java b/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/VideoStreamingProtocol.java similarity index 96% rename from src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageTransferProtocol.java rename to src/ve/ucv/ciens/ccg/nxtcam/network/protocols/VideoStreamingProtocol.java index 6273078..2a0e8fe 100644 --- a/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/ImageTransferProtocol.java +++ b/src/ve/ucv/ciens/ccg/nxtcam/network/protocols/VideoStreamingProtocol.java @@ -15,7 +15,7 @@ */ package ve.ucv.ciens.ccg.nxtcam.network.protocols; -public final class ImageTransferProtocol{ +public final class VideoStreamingProtocol{ public static final byte STREAM_CONTROL_END = 0x10; public static final byte ACK_SEND_NEXT = 0x20; public static final byte ACK_WAIT = 0x30;