I have just decided to post a link to the talk I made on last November hoping maybe to boost the number of views which is currently below 100 (most of them are family and friends 🙂 ) to maybe 101 or 102. I am also including the slides which are not linked in the original video.
Category: Technical
Relating C++ move semantics to python objects
I have been learning lately about C++11 move semantics, originally being a C programmer who is concerned with the performance it was very interesting to explore such an important optimization feature. I had to go through many articles explaining rvalues, lvalues and the && operator. I believe you still need to learn these topics to develop a firm understanding of the topic but in my point of view the move semantics can be explained intuitively by drawing the similarity between it and python’s object execution model.
The goal of move semantics is to avoid copying large objects unnecessarily when they are passed from one function to another.
How are objects passed in python?
Interestingly enough, python was created with that particular optimization in mind.
Firstly, It’s important to understand the subtle difference between the interpretation of the following statement in python and C++
str = 'medium' |
In C++ the variable str is created in memory, this location in memory contains the data medium and str refers to this memory location.
However in python the story is different. Although this statement also creates an object with the same content, but str isn’t the object reference. str is a merely a name and the statement binds it to the object. This subtle deviation may not look crucial but it makes all the difference when passing arguments to a function.
Consider the following 2 code snippets
def modify(arg): | |
arg = 'hard' | |
str = 'medium' | |
modify(str) | |
print(str) # >> medium |
In the first snippet, an immutable object is created containing the data ‘medium’ and str is bound to this object. When the method modify is called a new name arg is also bound to ‘medium’, but as soon as line 2 is executed the binding of arg is relocated to another new object with the data ‘hard’ because there is no way to change an immutable. The resulting behavior appears as a conventional pass by value call.
def modify(arg): | |
arg += [1] | |
l = [2] | |
modify(l) | |
print(l) # >> [2, 1] |
On the other hand, the behavior depicted in the second snippet resembles a pass by reference call as modify here doesn’t rebind arg to a new object because this object is mutable. arg and l are two names bound to the same object. When line 2 is executed this object is modified.
In python object references are passed by value, in other words objects are moved.
C++ move semantics in layman terms
Before the move semantics there were a couple of ways to avoid unnecessary large copies by passing pointers around which is somehow considered an unsafe practice compared to use an instantiated object which auto destructs.
Move semantics are based on rvalue references. An rvalue appears on the right hand side of the assignment statement. Example of an rvalue could be “medium” here:
string str = "medium"; |
Also the function getName() can return an rvalue because it appears on the right side of the statement.
string getName() { | |
string str = "medium"; | |
return s; | |
} | |
// getName() returns an rvalue | |
string&& name = getName(); |
name is an rvalue reference.
I like to think of an rvalue as a python object and the rvalue reference as the name bound to this object. The difference being that an rvalue can’t exist on its own while python relies on garbage collection to clean up objects which are no longer bound to any scope.
class Obj { | |
//default constructor | |
Obj(int size){ | |
.. | |
} | |
//copy constructor | |
Obj(const Obj& other){ | |
.. | |
} | |
//assignment operator | |
Obj& operator= (const Obj& other){ | |
.. | |
} | |
} | |
Obj B; | |
B = Obj(1000); |
Without a move constructor the last line assignment will
- allocate memory for the temporary object (and destruct it later)
- allocate memory again at the destination
Adding a move constructor to the object definition will optimize out the second allocation and reuse the previous allocation for the destination.
class Obj { | |
… | |
//move constructor | |
Obj(const Obj&& other){ | |
.. | |
} | |
//move assignment operator | |
Obj& operator= (const Obj&& other){ | |
.. | |
} | |
} |
Conclusion
Having this analogy in head, comprehending the power of move semantics was no more complicated. When a move constructor is defined for an object, it will be possible to rebind it to different name while avoiding expensive copies.
Resources
https://medium.com/@meghamohan/mutable-and-immutable-side-of-python-c2145cf72747
https://www.internalpointers.com/post/c-rvalue-references-and-move-semantics-beginners
https://mbevin.wordpress.com/2012/11/20/move-semantics/
https://stackoverflow.com/questions/3106110/what-is-move-semantics
Serial Communication with FTDI D2xx API on Windows
I was performing some testing on the FTDI throughput and I wrote this simple program that measures the throughput of FTDI chip if you connect its Rx pin to the Tx pin.
You are free to use it for any application with FTDI, it proved to be actually faster than using Windows VCP API but remember you need to install D2xx driver and make sure that your FTDI is actually using this driver and not the default ًWindows VCP driver
Note that the D2xx API uses a different method than conventional
hSerial = CreateFile("COM9",GENERIC_READ | GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
, it uses a string name instead that you can get from
device manager >> Right click on COM >> Details >> From the scroll list choose Device instance id >> you will find it after VID and PID
Code on github
Fast DES C++ code
I found an old undergraduate project in a Security course, I and some friends implemented DES encryption algorithm. I don’t remember much but what I do remember is :
– We were Group Number 4 😀
– We tried to optimize it as much as possible to be fast , degrading the code readability and actually our algorithm was the fastest among the class.
– Compile it in Release mode
Code on github
OCRA : OCR for Arabic Cursive Text is now open source !
Hi,
I was working on a MATLAB implementation for Arabic OCR on graduate course project and I decided to release it as as open source software under GPL license.
Disclaimer
This implementation was a part of a graduate course project and actually it achieves very poor results, you can’t rely on it for any real OCR but it will be useful as a starting point to learn from and build on.
Details
You can learn all about it here : My github repo
al-haitham is open source
I have benefited a lot from the open source community and it’s time to give back, I uploaded the source code of my graduation project which proposes a real time computer vision system implemented on FPGA to translate human gestures into computer commands
First I would like to thank my graduation project team members:
Ahmed Hafez Khalil
Asmaa Omar
Amani Mohamed Sedek
Mohamed Ismail Khalil
Mohamed Kamal Ali
Mohamed Maged Abdel Majed
and here are the links to my grad project github repos:
Hardware repo : https://github.com/aabdelfattah/alhaitham-hardware
Software repo : https://github.com/aabdelfattah/alhaitham-software
Have a look at thd brochure I designed for the EED competition 2012 which we won its 1st place 🙂
Cross-compiling a Pie ! The Raspberry Pi Ultimate Guide
Hi,
During the last few weeks I was interested in cross-compiling for the RPi. I have gone through many tutorials and blog posts to get the task done , so I tried to compile as many information as I can in this guide as a future reference and to help everybody else [The post is long, use CTRL+F for navigation].
Topics:
- Getting started , setting up the cross-compilation toolchain.
- Hello World! Building an RPi C application using shell.
- Hello World 2! Building an RPi C application using eclipse.
- Remote debugging the RPi with gdb on eclipse + RSE plugin.
- Updating your kernel. RPi Kernel cross-compilation.
- Extra: How does the bootloader work ??
Let’s get started with cross-compiling a Pie , there are usually 2 configurations :
- either to build the tool chain yourself on your host machine;
- or to get a pre-compiled toolchain (the Canadian cross).
[images from free-electrons embedded training slides]
For this guide I will be using pre-built linaro toolchain(the second way),still I encourage you to try to build the toolchain yourself for the sake of knowledge using one of those excellent tutorials : A and B
Now, let’s download the Linaro gcc toolchain [source]
$ sudo apt-get install git rsync cmake ia32-libs
$ mkdir raspberrypi
$ cd raspberrypi
$ git clone git://github.com/raspberrypi/tools.git
Add the cross-compile to your $PATH
$ export PATH=$PATH:$HOME/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin
And finally append the very same line to the end of your ~/.bashrc
file to make the change permnant
That’s it, now try
$ arm-linux-gnueabihf-gcc -v
should give you something like this
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/home/ahmed/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../libexec/gcc/arm-linux-gnueabihf/4.8.3/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/src/gcc-linaro-4.8-2014.01/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-linux-gnueabihf --prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/install --with-sysroot=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/install/arm-linux-gnueabihf/libc --enable-languages=c,c++,fortran --disable-multilib --enable-multiarch --with-arch=armv6 --with-tune=arm1176jz-s --with-fpu=vfp --with-float=hard --with-pkgversion='crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11' --with-bugurl=https://bugs.launchpad.net/gcc-linaro --enable-__cxa_atexit --enable-libmudflap --enable-libgomp --enable-libssp --with-gmp=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-mpfr=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-mpc=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-isl=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-cloog=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-libelf=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --enable-threads=posix --disable-libstdcxx-pch --enable-linker-build-id --enable-plugin --enable-gold --with-local-prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/install/arm-linux-gnueabihf/libc --enable-c99 --enable-long-long --with-float=hard
Thread model: posix
gcc version 4.8.3 20140106 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11)
Now let’s build a simple application , use your favorite editor to write helloworld.c
#include <stdio.h> int main() { printf("Hello world \n"); return 0; }
and compile it using the usual gcc way
$ arm-linux-gnueabihf-gcc -o helloworld helloworld.c
Copy this to your Pi with a USB flash memory or on the sd card or whatever suits you, launch it and it should work !
pi@raspberrypi:~$ ./helloworld
Hello world
pi@raspberrypi:~$
Now, Let’s add our toolchain to eclipse :
- install C/C++ cross-compiler support plugin;
- from the menu
File >> New Project >> C-Project >> Cross-Compile project
, input the name of your project and hit next; - enter
arm-linux-gnueabihf-
as Tool command prefix and~/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin
as the tool command path , hit next and finish;
- Congratulations 🙂 !!
It’s important to be able to debug your code online on the RPi, so we are going to use a nice plugin called RSE to do this [source]:
You may use this source code HelloDebug.c if you wish:
#include <stdio.h> int main() { int i = 0; printf("Hello world \n"); while (i < 1000) { printf("%d \n",i); i++; } return 0; }
- install the RSE plugin;
- create a new project with the above source, build it in debug mode (not release);
- add a new connection to your RPi from the Remote Systems window (if you can’t see it , add it from W
indow >> Show View >> Others >> Remote Systems
) , then hit the tiny button to add an ssh connection to your pi;
- copy the elf executable to the pi using RSE (right click to copy it and paste it on the dir you wish from the stfp menu);
- make sure to
chmod+x
the execultable; - now we will add a new debug configuration , right click on the project and select
Debug as >> Debug Configurations
and add a new C/C++ Remote Application configuration; - ensure that in
Debugger >> Main
tab the debugger isarm-linux-gnueabihf-gdb
- login to your pi using ssh to launch the gdbserver $
sudo gdbserver your-linux-pc-ip:any-free-port HelloDebug
- back to eclipse , ensure that you have the right connection parameters in
Debugger >> Connection
tab where you should pick the RPi IP and the port number you previously picked. - That’s it !! click Debug and enjoy debugging 🙂
Now , there is an excellent tutorial for compiling the kernel [this is not my work, I am just copying it here for future reference because it’s short and to the point ]also elinux wiki has a good compilation:
Create our working directory:
$ mkdir -p raspberrypi/kernel
$ cd raspberrypi/kernel
Before starting our work, install the necessary tools and source code of Raspberry Pi linux:
$ git clone https://github.com/raspberrypi/tools.git
$ git clone https://github.com/raspberrypi/linux.git
Prepare the .config file from pre-packaged config, bcmrpi_cutdown_defconfig:
$ cd linux
$ make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- bcmrpi_cutdown_defconfig
Build kernel:
$ make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi-
$ mkdir ../modules
$ make modules_install ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- INSTALL_MOD_PATH=../modules/
$ cd ../tools/mkimage/
$ ./imagetool-uncompressed.py ../../linux/arch/arm/boot/Image
Now insert a Raspbian installed SD Card, and run the command:
$ sudo rm /media/<boot-partition>/kernel.img
$ sudo mv kernel.img /media/<boot-partition>/
$ sudo rm -rf /media/<rootfs-partition>/lib/modules/
$ sudo rm -rf /media/<rootfs-partition>/lib/firmware/
$ cd ../../modules/
$ sudo cp -a lib/modules/ /media/<rootfs-partition>/lib/
$ sudo cp -a lib/firmware/ /media/<rootfs-partition>/lib/
$ sync
Now you can remove the SD Card and use it to boot Raspberry Pi with the new kernel.
Finally , here is a nice answer on stackexchange about How the Pi boots and another nice reference :
- When the Raspberry Pi is first turned on, the ARM core is off, and the GPU core is on. At this point the SDRAM is disabled.
- The GPU starts executing the first stage bootloader, which is stored in ROM on the SoC. The first stage bootloader reads the SD card, and loads the second stage bootloader (
bootcode.bin
) into the L2 cache, and runs it. bootcode.bin
enables SDRAM, and reads the third stage bootloader (loader.bin) from the SD card into RAM, and runs it.loader.bin
reads the GPU firmware (start.elf
).start.elf
readsconfig.txt
,cmdline.txt
andkernel.img
loader.bin
doesn’t do much. It can handle .elf
files, and so is needed to load start.elf
at the top of memory (ARM uses SDRAM from address zero). There is a plan to add elf loading support to bootcode.bin
, which would make loader.bin
unnecessary, but it’s a low priority (I guess it might save you 100ms on boot).
How did I turn my old crappy Pentium 4 PC into a nice home network data cloud ?
Do you have an old PC lying somewhere with a lot of dust all over it ? Do you want a local data cloud to sync all your files across your laptop, tablet, PCs ?
Then, I guess this tutorial will come in handy.
– First step is to dust your machine off , when I first plugged in my machine it didn’t even boot except when I really cleaned it well but sadly one RAM stick died because of dust . Now I am stuck with only 256 MB of RAM on my P4 2.8 GHZ machine but that didn’t set me back !
– Download, burn and install your favorite Linux distro as ownclowd supports many distros, but note that this tutorial is debian-based, I am using debian wheezy 7.4 standard(no desktop)
– Remember that we are dealing with a server now:
- It’s important that when the machine restarts because of a power cut for example; it should always boot to your server OS without any external intervention because we will only use ssh and won’t connect any IO devices to the server machine (keyboard,mouse,monitor…etc.) , also make sure to configure your BIOS settings (boot device, order..etc.) .
- To save power disconnect any unneeded peripherals(for ex: I disconnected my Nvidia VGA card and DVD ROM ) , not sure if it will do much saving for this old machine but better than nothing.
– Set a static IP to your local server , for a Debian server you can follow the following instructions from elinux which were originally written for the raspberry pi but the will work perfectly here:
You only need to modify the file /etc/network/interfaces
Before you do, backup the current version of the interfaces file, if there is already one present:
pi@raspberry:sudo cp /etc/network/interfaces /etc/network/interfaces.sav
You can edit the file with any text editor such as vi or vim.
We need root privileges, so we use sudo:
pi@raspberry:sudo vi /etc/network/interfaces
In the interfaces file look for a line such as:
iface eth0 inet dhcp
This is to enable the DHCP client. You do not want this to work any more.
Put a hash at the beginning of the line to disable it or delete it:
#iface eth0 inet dhcp
In the file you must insert the following lines:
# The loopback interface auto lo iface lo inet loopback auto eth0 iface eth0 inet static #your static IP address 192.168.1.118 #your gateway IP gateway 192.168.1.1 netmask 255.255.255.0 #your network address "family" network 192.168.1.0 broadcast 192.168.1.255
Only the address and netmask data are strictly required.
If for example your LAN is configured to have IP adresses in the range x.x.x.1 to x.x.x.255, you will put x.x.x.0 in the network line.
“address” is the IP you want the RPi will assume (in the proper range, as described above). pay attention not to use an IP already used by another device in your LAN or that can be assigned to a device by your router by DHCP (set the DHCP range of the router wisely in order to avoid potential overlaps).
“netmask” will “always” be 255.255.255.0
gateway is usually x.x.x.1 (your router IP or the one given by your ISP)
You now need to restart the network:
pi@raspberry:sudo /etc/init.d/networking restart
– Install ownclowd using the following techcint great tutorial , I recommend you to fully read it to understand what you are doing but here is a cheat sheet of the commands
# apt-get install apache2 apache2-doc apache2-utils mysql-server mysql-client php5 php5-mysql php5-gd # mysql -u root -p mysql> create database cloud ; Query OK, 1 row affected (0.00 sec) mysql> grant all on cloud.* to yourname@localhost identified by 'my_password'; Query OK, 0 rows affected (0.00 sec) # wget http://download.owncloud.org/community/owncloud-6.0.0a.tar.bz2 # cp owncloud-6.0.0a.tar.bz2 /var/www/ # tar -jxvf owncloud-6.0.0a.tar.bz2 # rm -rf owncloud-6.0.0a.tar.bz2 # chmod -R 777 owncloud/ # a2enmod rewrite # a2enmod headers # nano /etc/apache2/sites-available/default
Find
AllowOverride None
Change this to:
AllowOverride All # service apache2 restart
VOILA ! You should be up and running now using : http://your-ip-address/owncloud
Now , you should create the admin user and remember to enter the mysql user and database to get it ready .
– Don’t go yet as there is a last step, php is set to have a max upload of 2 MBs which is useless so you have to configure it a bit :
Note: The order of the following steps is important! If you swap steps described below, the settings may fail.
Go to the admin section in the ownCloud-WebUI and do the following:
- Under “File handling” set the Maximum upload size to the desired value (e.g. 16GB)
- Click the “save”-Button
Open the php.ini – file
- Under Debian or SUSE and their derivatives this file lies at /etc/php5/apache2/php.ini
- On Windows, you can find this file within C:/Program Files (x86)/PHP/PHP.ini
Do the following:
- Set the following three parameters inside th php.ini to the same value as chosen inside the admin-section one step before:
- upload_max_filesize = 16G (e.g., to stay consistent with the example value above)
- post_max_size = 16G (e.g., to stay consistent with the example value above)
- output_buffering = 16384 (e.g., to stay consistent with the example value above)
whereas the “output_buffering” has to be given in MegaBytes but as a plain figure (without size-units as ‘M’ or ‘G’)
These client configurations have been proven by testing maximum file sizes of 16 GB:
- Linux 32 Bit: Ubuntu, Firefox => 16GB
- Windows 8 64 Bit: Google Chrome => 8GB
Here are some screenshots of my local cloud !
A Linux bash script to download all pdf files from a page
Are you trying to download multiple files from a webpage and bored from clicking and clicking ??
I needed to download like a 100 PDF from a single web page , so I started to look for a bash script that automates the process and found this interesting article by Guillermo Garron that combines several useful programs into a nice script to download all links from a page using lynx command line web browser and wget downloader.
First , install the the browser
$ sudo apt-get install lynx
Lynx has a nice feature that allows you to grab all links from a page
$ lynx --dump http://mlg.eng.cam.ac.uk/pub/ >> ~/links.txt
The output will be like this
So we need to filter out the first numbering column and all non pdf links for the output to be nice and readable by wget
$ lynx --dump //http://mlg.eng.cam.ac.uk/pub/ | awk '/http/{print $2}' | grep pdf >> ~/links.txt
Resulting in a clean input to wget
and the last step is to pass this file into wget to download all the pdfs
$ for i in $( cat ~/links.txt ); do wget $i; done
voilà ! you get all the files downloaded
Quick notes about SRTP (Secure Real-time protocol)
Here are some quick notes that I took while studying the SRTP from the standard document , they are not meant to be complete but rather a quick overview of the protocol.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<+ |V=2|P|X| CC |M| PT | sequence number | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | timestamp | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | synchronization source (SSRC) identifier | | +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | contributing source (CSRC) identifiers | | | .... | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | RTP extension (OPTIONAL) | | +>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | payload ... | | | | +-------------------------------+ | | | | RTP padding | RTP pad count | | +>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<+ | ~ SRTP MKI (OPTIONAL) ~ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | : authentication tag (RECOMMENDED) : | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | +- Encrypted Portion* Authenticated Portion ---+
The encryption transforms defined in SRTP map the SRTP packet index
and secret key into a pseudo-random keystream segment. Each
keystream segment encrypts a single RTP packet. The process of
encrypting a packet consists of generating the keystream segment
corresponding to the packet, and then bitwise exclusive-oring that
keystream segment onto the payload of the RTP packet to produce the
Encrypted Portion of the SRTP packet. In case the payload size is
not an integer multiple of n_b bits, the excess (least significant)
bits of the keystream are simply discarded. Decryption is done the
same way, but swapping the roles of the plaintext and ciphertext.
We describe the process of computing authentication tags as follows.
The sender computes the tag of M and appends it to the packet. The
SRTP receiver verifies a message/authentication tag pair by computing
a new authentication tag over M using the selected algorithm and key,
and then compares it to the tag associated with the received message.
If the two tags are equal, then the message/tag pair is valid;
otherwise, it is invalid and the error audit message "AUTHENTICATION
FAILURE" MUST be returned.
Mainly, the encryption process is as simple as XORing the payload with a keystream segment . The keystream segment SHALL be the concatenation of the 128-bit output blocks of the AES cipher in the encrypt direction, using key k = k_e, in which the block indices are in increasing order. Symbolically, each keystream segment looks like E(k, IV) || E(k, IV + 1 mod 2^128) || E(k, IV + 2 mod 2^128) ... where the 128-bit integer value IV SHALL be defined by the SSRC, the SRTP packet index i, and the SRTP session salting key k_s, as below. IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)