DTU 
 

 

02162: Course on Software Engineering 2 (e14)

In this tutorial, you will learn how to record and play vidoes on Android phones. Moreover, you will learn how to "stream" the videos to other phones via an intermediate server. Note that both tasks are discussed in tutorial 6 on Friday, October 10, since I probably need to cancle one of the later tutorials. But, the second task should be done by the students responsible for tutorial 7, and it can be done after the holidays. Anyway, you have all the information on the technologies and techniques that you might need for the submission of your technology experiment available already now.

 

For the recording and playing, you will can the the Android MediaRecorder and the VideoView. For playing a video, you could also use the Android MediaPlayer, which however is not discussed in this tutorial. You will find some more information on the Android MediaPlayer at http://developer.android.com/guide/topics/media/mediaplayer.html. On the side, you will learn how to access Androids internal storage too, which we use for saving the vidoe files locally in the App.

 

Actually, Android's standard API is not really made for realtime streaming of videos. There would be some libraries for streaming, such as the libstreaming library (you can find an exmaple of its use here). Since this requires also a fully fledge streaming server (such as the Wowza Engine), which is more than we can stomach right now, we go for a very simple ad hoc solution for now. A very simple VideoServer will be made available to you as part of this assignment.

 

Tasks

Below, the steps for the tasks of the sixth assignment (the second one is actually assignment 7) are explained:
  1. In the first part of this assignment, you will implement a simple App that records short video snippets and replays them right away (in a different part of the screen). So, you will see the camera preview and the replayed video on the same screen (activity), where the replayed video will be slightly delayed. The actual delay can be defined in your App by some constant. This should happen until the App is stopped.

     

    Note that you need to take some extra care that the recording and playing is properly stopped, when the user turnes the phone from portrait to landscape mode or vice versa — and properly clean up the resources you are using.

     

    1. To start with, create a new Android project (see tutorial 3). In this new project, change the layout of the activity (actually, the fragment) so that you have a SurfaceView and a VideoView in it. The SurfaceView is used for showing the camera preview; the VideoView is used for replaying the recorded video.

       

    2. Since you will need to access the camera, you need to add the respective permission to the AndroidManifest.xml file. In the XML file, this permission entry will look as follows:

       

        <uses-permission android:name="android.permission.CAMERA" android:required="true" />

       

    3. The actual recording and replaying should be started from a separte RecordingThread, which you should implement in this task. In order to install this thread at the right time, you should make the Fragement implement the SurfaceHolder.Callback and OnPreparedListener interfaces (and use the Eclipse IDE, to implement the required methods). In the Frament's onViewCreated() method, add the Fragment itself as the "Callback" to the respective SurfaceView, which you can obtain from the view as discussed in tutorial 3.

       

      Note that you also need to take this RecordingThread down, when the surface is destroyed (in method surfaceDestroyed()).

       

    4. The RecordingThread should cyclically record a video to some file and replay it (the video snippets could have one or two seconds so that the delay between the two videos is not too large). In order not to mix up playing and recording, you would need to use at least two different files. While the App records to one file, it can replay the video from the other.

       

      The code for recording to a file could roughly (e.g. the necessary exceptions are omitted) look as in the example snippet. But, you need to experiment a bit with some addional parameters, and find the proper size for the video (which can be obtained from the camera).

       

      Moreover, the code for starting and stopping the recording needs to be properly intertwined with the code for starting the playback (note that the actual recording and playback does not block your thread).

       

      You also need to properly release the camera, when the RecordingThread stops; otherwise, other apps or your own app later might not be able to access the camera anymore.

       

      The context for accessing the internal storage of an App, can be obtained from the activity by the getApplicationContext() method, and can be passed to the RecordingThread when this thread is created by the activity (or its fragment).

       

    5. The code for starting and stopping the replay of the video in the VideoView could roughly look like the following code snippets.

       

      Note that issuing the start() of the replay on a VideoView widget from another thread requires this to be issued with the post() method of the widget.

       

    6. Make sure that the thread can be properly terminated (when the surface is destroyed) in the end; in particular, make sure that the camera is properly released when the thread terminates.

       

    7. Test your application and check whether the replay of the video runs halfway smoothly (on older phones this might not be possible, but on the Galaxy S5 it should not be a problem). But, of course there will be some unavoidable glitches, since this is not real streaming.

       

    8. There are many options on how to configure recording and replaying videos. For the recorder, you can for example set a limit for the time for which it is recording; and the recording can also be limited by a given file size. Moreover, there are many options concerning the format, size, aspect-ratio, and orientation of the recording. Try to get an overview of that and experiment a bit with these options. You will find them at http://developer.android.com/reference/android/media/MediaRecorder.html and http://developer.android.com/reference/android/widget/VideoView.html.

       

  2. In the second part, you can reuse some of the code from the first part (but copy it to a new Android project) so that the video is not replayed on the phone where it is recorded, but shown on an other phone. To this end, you can use an extremely simple (quick and dirty) implementation of a "VideoServer". The Eclipse project can be obtained from videoserver.zip and an executable jar-file is available at videoserver.jar. This server will receive MP4 transmissions from some App at port 8800 and serve HTTP GET requests at port 8801, where it delivers the latest transmitted MP4 file. Morevoer, port 8802 can be used to to stop the server.

     

    You can either start the VideoServer from the Eclipse workbench, where the MP4 files will be stored in the "tmp" folder (unless you provide another folder as a parameter). You can also start it as a jar file from some folder, where the parameter defines the folder to which the MP4 files should be saved. If you do not provide a parameter, it will be the "tmp" folder in the folder from where you start the jar file.

     

    1. Now create a new Android project. Instead of playing the recorded video in the App itself, add some code to the RecordingThread that transmits the record file to the port 8800 of the VideoServer. Note that this port does not run any protocol; it just receives all the bytes that are sent; this should make it easy to transmit the data via a socket (you could look at the source code in the VideoServer itself for inspiration).

       

      You could either hardcode the IP_ADDRESS of the VideoServer or allow the user to enter it before you start "streaming" the videos.

       

      Note that you need to add the permission for using the internet to this new App, so that you are allowed to connect to the external sockets of the VideoServer.

       

    2. Next create yet another App, which connects to the VideoServer and shows the the latest video snippet; and when this snippet is finished shows the next one. Basically you can use the URL of the VideoServer on port 8801 using the http protocol (this could look like "http://10.16.164.111:8801/") as URI for the VideoView. Since the VideoServer implements a very simple form of the HTTP protocol, the code snippets from the first example should work fine for showing the MP4 files from the server.

       

      There are some speciallities that you need to take care of, though:

       

      First of all, there might not be a video available intitially. In this case, the server just closes the socket (a bit nasty). If you do not do anything about that, the App would show a user dialog that there was an error. This can be prevented by adding a own OnErrorListener to the VideoView; in this OnErrorListener you can implement in the onError() method what should be done in the case of an error. And if this method returns true, the user dialog will be suppressed. Moreover, you can re-schedule another attempt for loading and playing the vidoe again after some delay. You can use the postDelayed() method of the VideoView for that purpose.

       

      When the video was played completely, the VideoView normally just stops at the last frame of the video. In your App you do not want that. The VideoView should start loading the next video from the server. To achive this, you can install an OnCompletionListener on the VideoView, which will be notified when playing the vidoe is finished. Then, you can issue the loading and playing of the next video snippet (using the post() method.

       

    3. Test your two applications together with the VideoView and check whether it is running properly.

       

    4. In your project, you would probably not want to use the very ad-hoc VideoServer. Therefore, you should think of possibilities to obtain a similar solution with the GlassFish server. This will give you much more control over the videostreaming, and the server could influence the length of the recorded videos with respect to current demands (when recording offline, i.e. when no users are watching, the videos could be longer; only when users are watching online, the length of the transmittion could be reduced in order to give a realtime feeling).

       

    Useful links

    Here are some links that might be helpful:

     

 

Ekkart Kindler (), October 9, 2014