In this post I want to talk about some of the pitfalls that can be encountered when working with streaming video in 
Android applications. Specifically, it will be about video conversion and video delivery / playback protocols.
Immediately, I’ll make a reservation that I am not an expert in this field, but just want to share my recently gained experience.
Imagine that you are faced with the task of implementing an 
Android application capable of playing many files uploaded by users to your server. Write your youtube, with blackjack and codecs. To do this, you will have to solve at least two tasks: video conversion to a format supported on 
Android , video playback from a remote source. Consider both of these tasks in more detail.
Video conversion
And so, before you play some video on our 
Android device, you need to transcode this video into a supported format. The Android documentation clearly identifies a 
list of these formats.
')
In order to transcode files uploaded by users to your service, or to record stream from a TV tuner, you will need the help of a special utility 
ffmpeg , which is the de facto standard in the industry. Detailed instructions for its installation can be found on the 
site of the same name project .
The most common (in my opinion) video storage method is the 
MP4 container using the 
H.264 AVC codec . We will, in fact, consider them.
First of all, note that 
Android does not support all the features of the 
H.264 codec, but only a specific set — a profile called 
Baseline Profile (BP). For example, 
BP does not include such useful 
H.264 features as 
CABAC or 
B-Frames .
For us, this means that if we use these features when encoding a video, then 
Android will not have to lose this video. Although it may, if your phone is powerful enough and the vendor has taken care of installing and supporting additional codecs. For example, the video in the 
Main Profile is played without any problems on the 
Samsung Galaxy SII . On the phones of the usual class (for example, 
Samsung Galaxy Ace ) we will receive a message about the impossibility of playing the video and an error with the codec of the wrong codec in 
logcat .
But let's move from theory to practice. In order to compress the video, you must run the following command:
ffmpeg -i in.3gp -f mp4
-vcodec libx264 -vprofile baseline -b: v 1500K
-acodec libfaac -b: a 128k -ar 44100 -ac 2
-y out.mp4
Let us consider in more detail each of the parameters:
- -i src input (recoded) file;
 - -f mp4 video container used;
 - -vcodec libx264 video codec used;
 - -vprofile baseline profile used;
 - -b: v 1500K bitrate;
 - -acodec libfaac used audio codec;
 - -b: a 128k audio bitrate;
 - -ar 44100 sound frequency;
 - -ac 2 number of audio streams;
 - -y flag for overwriting the output file;
 
It is also worth noting that you can do without specifying the profile, and explicitly enable / disable the necessary options for the 
H.264 codec through the 
-x264opts parameter, so that they would satisfy the conditions of 
BP . But this is a lesson for lovers.
Video distribution
The easiest way to play video from a remote server is to download it to temporary storage and play it locally. However, I think everyone understands that in view of the size of modern video recordings - this is not an option.
How to be? The Android platform offers us native support for the following technologies / protocols:
- HTTP / HTTPS progressive streaming;
 - HTTP / HTTPS live streaming;
 - RTSP (RTP, SDP);
 
Consider them in order.
Progressive streaming
The easiest way to distribute video using a conventional web server, which essentially amounts to downloading a previously prepared file using the 
HTTP (S) protocol. The whole point in this case is that the file does not start playing at the end of the download, but as soon as enough data is downloaded (some buffer is filled).
Here it is worth clarifying that when using the 
MP4 container, it is necessary to form a file so that metadata about the video stream ( 
moov atoms ) is located at the beginning of the file (after the 
ftyp atom), before the video data ( 
mdat atoms ). This can be done by processing the file with the 
qt-faststart utility:
qt-faststart output.mp4 result.mp4
The main problem of 
progressive streaming is the impossibility of rewinding video to a non-downloaded moment, the presence of a sufficient amount of free space on the device and the need to support a large number of "fat" clients downloading videos on a web server.
Reproduction using this technology is supported by the Android platform natively. You can easily play a remote file using the standard 
MediaPlayer class (apart from the communication channel, power of the device and availability of free space).
Pseudo streaming
This technology is a logical extension of 
progressive streaming 'a and allows you to solve one of its main problems - rewinding to a fragment that has not yet been downloaded. Applicable for 
MP4 / 
FLV containers with 
H.264 / 
AAC codec.
The only difference from 
progressive streaming 'a in this case is the fact that you need a special web server that, given the timestamp in the GET request, will give you the fragment of the video file you need. An example of such a web server can naturally serve as an Orthodox 
NGINX with its 
ngx_http_mp4_module .
I could not find any official information regarding the support of this standard in 
Android . However, empirically, it was found that it is present on at least 
HTC Desire and 
Samsung Galaxy SII devices. However, I want to note that even if there is no native support on your device, you can always use third-party players like 
MX Player , who independently implement the logic of downloading and playing video fragments with the required timestamp, which allows you to organize rewind.
Live streaming
Quite a non-standard 
data transfer protocol from 
Apple . Its essence boils down to the fact that the file being distributed is “sawn” into many small parts, joined by a special M3U8 format 
playlist . Data transfer occurs via the 
HTTP (S) protocol.
There are no problems with rewind and free space on the device in this case. Moreover, under certain conditions, you have the opportunity to choose the quality of the video being played.
However, there are problems. To “cut” a file and create a playlist will require processor resources, time and space on the server. To broadcast a file to the network, as in the previous examples, you will need an HTTP server (without any additional modules).
You can use 
VLC to cut a video file:
vlc -I dummy /path/to/pornofilm.mpg vlc: // quit --sout '#transcode {width = 320, height = 240, fps = 25, vcodec = h264, vb = 256, venc = x264 {aud, profile = baseline, level = 30, keyint = 30, ref = 1}, acodec = mp3, ab = 96}: std {access = livehttp {seglen = 10, delsegs = false, numsegs = 0, index = / path / to /web/server/root/pornofilm.m3u8,index-url=http://localhost/pornofilm/stream-########.ts }mmux{useuse- /path/to/web/server/root/pornofilm/stream-#######.ts} '
You can play this file at the URL 
localhost / pornofilm.m3u8 .
Support for 
HTTP Live Streaming at the native level in Android has been present since version 3.0. With the help of third-party players ( 
DicePlayer , 
MX Player ), judging by the wiki, you can achieve support from version 2.2.
Real Time Streaming Protocol (RTSP)
A state-level application 
protocol designed specifically for video transmission. The command format is very similar to 
HTTP . The teams themselves resemble buttons on a conventional cassette recorder: PLAY, PAUSE, RECORD, etc.
Unlike 
HTTP Live Streaming, RTSP does not require splitting files into smaller parts and creating playlists. The necessary parts of the file will be generated and given to the client on the fly. 
VLC can be used as an 
RTSP server.
It is worth noting that the 
RTSP protocol itself does not determine the method of data transmission, but delegates this to other protocols. For example, 
RTP . To stream a file using the 
RTP protocol, you will need to run 
VLC with the following parameters:
vlc -vvv /path/to/pornofilm.mp4 --sout '#rtp {dst = localhost, port = 1234, sdp = rtsp: // localhost: 8080 / pornofilm.sdp}'
However, it would be foolish to raise for each file its own process with a separate port, regardless of the presence of users who want to view it.
So back to the 
RTSP protocol and video playback on demand (Vidoe On Demand). In order to use 
VLC as an 
RTSP server to play VOD, you must first run 
VLC , specifying the attributes of the 
RTSP server and the 
Telnet interface:
vlc -vvv -I telnet --telnet-password 123 --rtsp-host 127.0.0.1 --rtsp-port 5554
After that, as the server is started, you need to configure it. It is most convenient to do this with the help of 
telnet 'a, since such an approach makes it possible to adjust on the fly:
new porno vod enabled
setup porno input /path/to/pornofilm.mpg
To play a video (including on the Android platform), you need to request it at the URL 
rtsp: // localhost: 5554 / pornofilm .
Among the shortcomings, we can note the fact that 
HTTP is often open on all firewalls and proxies ... with 
RTSP in the case of Deny, Allow policies, everything is different.
In addition, when using the 
RTSP server, to add / delete files on the server, you will have to update its configuration (list of vods). Yes, there is 
telnet for this, but it is still more difficult than just uploading or deleting files from web server directories.
Reproduction using this technology is supported by the Android platform natively. For example, using the same standard class 
MediaPlayer .
Multicast
Many people believe that 
multicast does not work in Android. This is not quite true.
Firstly, in most cases it is simply disabled by default so as not to load the device resources with unnecessary work. You can simply 
turn it 
on .
Secondly, yes - on a rather impressive number of devices it is disabled in everything or it does not work correctly. On the Internet, so you can 
find a lot of tears and even some solutions.
However, as practice shows, everything can be played on 
multicast video on 
Android . In my case, the recently released 
VLC Beta for 
Android successfully coped with this task.
In addition, using 
VLC server you can always reduce the playback of 
multicast 'a to 
HLS :
vlc -I dummy udp: //@192.168.20.1: 1234 vlc: // quit --sout '#transcode {width = 320, height = 240, fps = 25, vcodec = h264, vb = 256, venc = x264 { aud, profile = baseline, level = 30, keyint = 30, ref = 1}, acodec = mp3, ab = 96}: std {access = livehttp {seglen = 10, delsegs = false, numsegs = 0, index = / path /to/web/server/root/multicast-porno.m3u8,index-url=http://localhost/multicast-porno/stream-#######.ts (mu) -frames}, dst = / path / to / web / server / root / multicast-porno / stream - ########. ts} '
or rtsp:
new multicast-porno vod enabled
setup multicast-porno input udp: //@192.168.20.1: 1234
You can try your luck with playing multicast on your device by giving the player a URL like 
udp: //@192.168.20.1: 1234 .
What to choose
If everything is clear with the video format ( 
H.264 BP / 
MP4 ), then the question is open with the distribution method. Each of them has its advantages and disadvantages.
First of all, I would remove the usual 
progressive streaming from consideration. Yes, it works always and everywhere, but the lack of rewinding and downloading the entire file is too much.
The next candidate for crash is 
live streaming . Its main disadvantage is native support in 
Android since version 3.0. And ignoring more than 
80% of users with version 2.x is not an option. Although here you can look at a third-party player, or do your own implementation (I, alas, did not find any free practices to support 
HLS ).
And the last one I would have struck off the RTSP. Yes, this is a protocol designed specifically for video. Yes, its use is ideologically correct. But there are two points. Firstly - you need to constantly update the server configuration. Secondly, 
HTTP is open always and everywhere, which is not the case with 
RTSP / 
RTP .
Personally, I would stop at 
pseudo streaming . It allows you to rewind and not download the entire file completely. All we have to do is tweak the web server a bit.