Thursday, March 5, 2015

Stream movies to Android devices



    After battling for some time with how to best stream movie content through Ethernet and Wifi from a media server (the Minix Neo Z64 running Linux in this case) where my USB hard disks are plugged, to Android devices connected to my TVs, I've found that the very best method for smooth streaming is to serve the files with a web server.


      That way, on any Android in the house (phone, tablet, TV box, MiniPC, or even an x86 PC) I can use a Web Browser to connect to the Z64 (with its static IP), then navigate my movie folder and click on the link of the movie I want to watch.
Android will prompt with what movie player (I use MX Player, and BSPlayer when MX has trouble) and playing will start, without installing any other app at all!

       I have even been able to have XBMC (now Kodi) on an Android device to read and manage this web-served movie collection just by adding it as an http server (however very long filenames are cut, making it harder for XBMC to link it to the Internet movie database).

For the basics of a NAS on Linux, you can read this article, which was for my original setup with the RK3188.


To serve the files just install on the Minix Neo Z64 a nice light web server, such as nginx. Then it's just a matter of editing the file /etc/nginx/sites-enabled/default to add a section for your file-web-server, like this:

server {
    charset utf-8;
   
    root /mnt;
    index index.html index.htm;

    server_name 192.168.1.4;

    location / {
        root /mnt/;
        try_files $uri $uri/ /index.html;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime off;
    }
}

You'll just have to change the IP for the static one of your Z64, and the two lines that start with "root" which should point to the root folder that you want to share (subfolders will be shared too).

The "charset" line is very important for all of us with accented languages. The "autoindex" lines do the magic of creating a link for each file in a folder.

It is also a good idea to edit /etc/nginx/nginx.conf and set keepalive_timeout and send_timeout both to a large number of seconds, like:

keepalive_timeout 1200;
send_timeout 1200;

That way you can pause a movie for 10 minutes and still be able to resume (or else, after a X minutes pause, upon resume the Android movie player will stop after soem seconds and you'll have to open the file again).

Then, on any device on your local network enter the Z64's IP on a web browser and you'll see the files and folders under /mnt in your Z64.


I usually install also the openssh-server so I can ssh into the Z64 from my PC, instead of connecting it to a TV.




BONUS: Add a script to init that executes one line like this for every hard disk (substitute the sd_) connected to the media server:
sudo hdparm -S 200 -B 100 -K 1 /dev/sd_
 This invaluable piece of advice makes sure that the hard drivers spin off when not used for some time ("-S 200" for 16 minutes). This will enhance by orders of magnitude the life of your precious hard disks, and will reduce your energy bill.

Getting Linux on the Minix Neo Z64

      I have recently received the latest Minix Neo Z64, courtesy of Minix. This TV Box is equipped with an Intel x86 processor, an Atom 3735F, which is not so far off a low-end PC desktop but at just 2.2W making it fanless. You can check its respectable specs at this Intel page, and even compare it against other Intel CPUs.



The Z64 is smaller than previous Minix TV boxes, which is nice. As always, a good quality power adapter, HDMI cable, and remote are bundled in the box. The Wifi antenna design is non-detachable, and this time I have been unable to find a way to open the box in order to take the customary PCB photo. Sorry about that :-(

Apart from that, you get 32 GB fast eMMC flash (instead of the usual slower NAND flash chip), 2 GB DDR3 RAM at 1333 MHz, two (ouch) USB 2.0 ports, Ethernet 10/100 (ouch), Wifi and Bluetooth.

I find several big reasons to prefer this TV box over ARM ones:

- the x86 architecture is completely PC SW compatible (think Adobe Flash)

- Intel has a solid background on Open Source, like its Linux GPU drivers (2D/3D) which are top of the line. You even have 3D support on the HDMI interface (see 5.4.1.3 at the CPU datasheet here).

- For HW accelerated video decoding you have a VPU supporting 1080p60 decoding for H-264,  WMV9, and MPEG-2 (see 1.4 on Type 3 SoC at the CPU datasheet here).
 
- And one important thing: the USB controller. Usually ARM CPUs have DesignWare's USB controller, which has nasty and buggy firmware/driver, leading to lots of problems with USB devices (webcams, external hard disks, 10/100 USB Ethernet and Wifi dongles). However, here we have a good and robust Intel USB controller.

The last reason alone has made me jump into switching my NAS home media server (which has several USB hard disks) to this Minix Neo Z64 with Linux.

This tiny Intel CPU even has virtualization features (VT-x), you could even install Xen on this (or even Qubes-OS, if you are serious about secure computing).

So... sorry Windows 8.1, you look nice and you run fast, but Linux and I...


Hence, find here instructions to get into the Minix Neo Z64 whatever distribution of Linux you prefer. I don't like creating distros when you can very easily install a standard one.



Live Linux USB


     First of all get a USB pendrive that can be erased, so we can start Linux on the Z64 to make a backup of Windows, before removing it.

I've developed a liking for Xubuntu (XFCE based) after Canonical decided to outsmart all of us by inventing their hateable GUI, and then Gnome followed suit with its 3.0 version.

You can use any version of Ubuntu, they'll work the very same way as described here. Just head to the corresponding official Ubuntu page and download the x86_64 version (also called amd64) of the distro.

I wish I could tell you that's it, but truth is somebody messed up somewhere and all Intel Atom boxes/MiniPCs I know happen to have a 32 bits UEFI BIOS, which complicates booting a 64 bits OS, so there is one extra step.

This consists of adding a 32 bits bootloader to the 64 bits one in the Ubuntu distro so it can boot, that's it. You can either download the bootia32.efi bootloader from this link or you can follow the instructions (from the same place) to build it yourself.

Now, about creating a LiveUSB for UEFI systems and modifying it... people around are resorting to using a tool called Rufus that requires you to use Windows... ugly.

However, there is a simple way (thanks lopaka) to do everything from your usual Linux PC (the lines preceded with "#" are just my comments, disregard them):


#first erase the USB pendrive
sgdisk --zap-all /dev/sd_
#create a new GPT partition for booting on UEFI systems
sgdisk --new=1:0:0 --typecode=1:ef00 /dev/sd_

#create a FAT32 partition, as expected by the UEFI BIOS
mkfs.vfat -F32 /dev/sd_1

#create a temporary folder

mkdir image
#mount the FAT32 partition (only root can mount)
sudo mount -t vfat /dev/sd_1 image/

#uncompress Ubuntu onto the mounted USB
sudo 7z x xubuntu-14.10-desktop-amd64.iso -oimage/

#add the 32 bits bootloader (see blog above)
sudo cp bootia32.efi image/EFI/BOOT/

#finish any pending writes
sudo sync

#unmount the USB
sudo umount image

#remove the temporary folder
rmdir image

Please note that ALL references to the USB disk above are in the form "sd_" or "sd_1", this is because you can delete your hard disk if you just copy paste this code, so don't!!! You first have to find if your USB pendrive is at sdb, sdc, sdd, sde, or whatever sd*.
Easy way is, without the USB drive inserted, type in a terminal:
ls /dev/sd*
And then again, after inserting the USB. The new sd_ (without trailing number) is your pendrive. Use that letter instead of the "_" above.



BIOS settings


   In order to boot the Live USB, connect a keyboard to the Minix and as soon as you press the power button, start pressing several times the "Del" key to enter BIOS setup (if screen remains black after 10s, then you'll need a PC monitor instead of a TV to see it).

BTW, the sensible way to forcefully power off the box, if there is nothing on screen, is to keep pressed the power button for a bit more than 5 seconds.

On the BIOS screen, go to "Advanced", then "CPU Configuration" and on the "Execute Disable Bit" hit Enter and select Disabled.


By the way, just in case you dig through the BIOS options, you may see one named "ISP PCI Device Selection", just ignore it. I say this because it mentions that it should be another value for Linux, but never mind that, leave it at Windows.

However, there is a very important change to be done, find the "Quiet boot" item. It must be disabled since there seems to be something missing in the GFX initialization that the BIOS is doing but Linux is missing. Maybe the logo that appears (when Quiet boot is enabled) instead of the usual BIOS text is pushing the GPU into an incompatible video mode, and it prevents booting Linux (black screen).

Head to the last menu page (the one on Boot options) and select the option to Save Settings (without reset or exit, just save).
 
Finally, if the above instructions for the USB preparation were followed, you should see the pendrive's name or brand listed in the "Boot Override" choices at the bottom, select it and hit Enter to boot.

On the grub2 menu that should appear select "Try Ubuntu before installing".
If you get a black screen or Windows, then you may be missing the bootia32.efi file, re-do the instructions above on USB preparation.


Backup Windows 8.1


      Since Minix bundles a fully licensed Windows 8.1 with Bing (as opposed to many other TV boxes that come with a 30 days trial version), it is a good idea to back it up to avoid losing the licensed OS, in case we wanted to switch back to it anytime.

This part of the instructions is based on this CNX-Software's page, the news site for hacking with embedded devices; though there are additional things to make Linux work on the Z64.

We will install "pv" as a convenience, to monitor the copy's progress, since the backup takes several minutes to complete.

Just open a terminal and cd into the folder of another USB pendrive (the Live USB is read only so nothing survives reboot) to execute these commands:

sudo apt-get install pv
sudo dd if=/dev/mmcblk0 bs=16M | pv | gzip -9 > Z64_Win81.gz

Most of the 32 GB flash is empty, so gzip'ing it produces a much smaller file (mine was some 4 GB, instead of 32 GB)

To restore Windows 8.1 from the backup you should follow this section up to the "pv" install, and then do:

gzip -dc Z64_Win81.gz | pv | sudo dd of=/dev/mmcblk0 bs=16M


Installing Linux in Flash


Finally! Click on the icon to Install Ubuntu and start the setup as usual.

When asked about the partitioning select the do "Something else" choice and you'll be presented with the current partitioning of the internal eMMC flash that contains Windows 8.1.

We are going to wipe Windows. But you have to leave the first two partitions untouched, they are mmcblk0p1 and mmcblk0p2. Together they amount to less than 240MB and are needed to boot EFI (at least p1, the FAT32 one).

However, you can perfectly remove the "Win" and "Images" partitions, which together are around 30 GB of space.

I used all but 2 GB for an ext4 partition to be mounted at "/" where Linux will reside, and the remaining 2 GB for swap partition (the ancient recommendation is to match your RAM size in swap).

Even if this is a Flash, it's ok to have a swap partition, it should be seldom used, only when you start filling up the RAM, but a home server should be ok even without it.

On the booloader device dropdown at the bottom of the new window, select "/dev/mmcblk0" not other, just that one (or update-grub2 later may update the wrong place and you'll end up with two "ubuntu" entries on the UEFI BIOS).


Once installation is finished (this is based on Linuxium's great work here), you'll need to boot once more with the Live USB, but when presented with its grub2 menu, press 'c' to go to its console and enter these three lines:

linux (hd1,gpt3)/boot/vmlinuz-3.16.0-31-generic root=/dev/mmcblk0p3
initrd (hd1,gpt3)/boot/initrd-3.16.0-31-generic
boot






If you used a different Linux distro, the version numbers may be different. You can use grub's auto-completion, with the Tab key, to help you find your vmlinuz and initrd files for you.

 The Ubuntu that you have installed on the internal eMMC flash will boot up, connect to the Internet with an Ethernet cable (there is no wireless out of the box) and enter these commands on a terminal:

sudo apt-get install grub-efi-ia32 grub-efi-ia32-bin
sudo cp /boot/efi/EFI/ubuntu/grubia32.efi /boot/efi/EFI/ubuntu/grubx64.efi
sudo update-grub2


Now you can power off, remove the pendrive, and boot again

You should then boot to your Linux.


If you see a Windows bluish screen stating that there is something wrong, then you'll have to enter the BIOS once more and change the Boot priority #1 to "ubuntu".


Limitations


Please note Wifi (Realtek RGN RTL8723BS) is not working out of the box, but CNX-Software's page provides info on compiling its drivers from source.

Also the sound (Realtek ALC5642) is not working, there is one person around that says to have fixed it by using Chromium's Intel firmware (see this page) but I've tried it and, even though a new output appeared in the audio mixer, nothing sounded and the "dmesg" log was full of errors related to audio.

If you google around for ALC5642 and Linux there seems to be a good place to look for the driver (see this page) whenever it appears.


That's it. Enjoy!