# A Cloud-Based Distributed Architecture to Accelerate Video Encoders
## 3 Proposed Architecture
### Dynamic Distributed Execution of Encoding Tasks  
The application deployed on the top of the virtual infrastructure creates a direct exchange in RabbitMQ named _Video_, which performs load balancing among message consumers, with two queues:  
* _Jobs Queue_ that stores VideoJob messages sent by the master and consumed by a worker. A VideoJob message contains all the information and parameters needed to retrieve and encode a video chunk, and the sort of encoders that has to be used.
* _Times Queue_ that stores ProcessingTimes sent by the workers and consumed by the master.  
Firstly, the application in the master node parses the command line arguments, obtains a channel associated to RabbitMQ to create the exchange and the queues, and performs the bindings. Then, for each chunk to be encoded a VideoJob message is created and sent (serialized in JSON format) to the RabbitMQ exchange.  
Secondly, the application deployed in each worker carries out according to Algorithm 1. Initially, it obtains a RabbitMQ channel and subscribes to the Jobs queue. Thus, after a VideoJob message is received, it is deserialized. Then, a port number is selected and a netcat, nc, process is started in localhost to receive the chunks of video from the previously selected port. After that, a nc process in the media is started to extract and send the video chunk from the RAW video to the worker. Note that, as each frame has a fixed size, it is possible to extract the portion of the video using for instance the dd command from the number of chunk and the number of frames per chunk. When the chunk has been completely downloaded in the disk volume attached to the VM, _ffmpeg_ is used to encode each chunk for each value of bit rate. Each encoded chunk is uploaded to the media server. If the encoding process has terminated in the worker node and the encoded chunks have been uploaded to the media server, the message is acknowledged and a message with the time data is sent. On the contrary, when an error occurs, a message is sent informing about the error, so the master node can send the corresponding job message with higher priority.  
Finally, the new encoded videos are obtained by joining the encoded video chunks.  
Notice that, our proposal is able to work with other codecs. The required adjustments are:  
* Creating a new worker VM image with the libraries required for the new codecs and ffmpeg recompiled to support them.
* Creating a new script with the call to ffmpeg for the new encoder.
* Adapting particular parameters to the new encoder.
* Changing the call to the application running in the master node to pass the name of the new encoder as an argument.  
```
Obtain a channel from RabbitMQ in Master node;  Create exchanges, queues, and bindings; /* To receive just one message */;  Set prefetch to 1;  Subscribe to RabbitMQ Jobs queue; for(each received message) {  Deserialize VideoJob from message payload;  port - Select a port number;  Start nc in localhost and listen in selected port;  Start a nc process in media to send video chunk, using direct access, to worker;  Wait for video chunk to download; for(each bit rate) {  Start a ffmpeg process to encode the video chunk ; Wait for encoding process to finish;  Upload encoded video to media server; }  Send a message to Times exchange with processing times; ifnot errorthen  ACK the message; else  NACK the message;  end if }
```  
**Algorithm 1**Worker video encoder code