MediaProcessors
DOCUMENTATION

Processor concept

The basic idea is to define a generic structure to wrap any multimedia processor type. By "multimedia processor" we mean any encoder, decoder, multiplexer or demultiplexer. Namely, any "codec" or "muxer" will be implemented as a particularization of this generic processor interface, and in consequence, they all will offer the same generic interface/API (despite each particularization may extend the common interface as desired).

A processor defined in this library has two basic forms of interfacing:
1.- Control (CTRL) interface;
2.- Input/output (I/O) interface.

The latter is used to send or receive processed data, and may suppose a bit-rate as high as desired. This is important to remark, as the I/O interface should carefully take into account fast-fetching and efficient data transfers without interruptions.
The former suppose insignificant bit-rate, but should be unlinked -as possible- to the I/O interface; in other words, control commands should not interfere with I/O operations performance.
The processor generic implementation provides not only these characteristics, but also:

In view of the above, the processor API has the following fundamental operations:

  1. Control (CTRL) interface
    • POST
    • DELETE
    • GET
    • PUT
  2. Input/output (I/O) interface
    • send
    • recieve

Figure 1: The processor structure

The CTRL operations, as implemented in this library, use textual information formatted in the JavaScript Object Notation (JSON).
The CTR interface interoperability philosophy is based on the Representational State Transfer (REST): the processor resources are accessible as textual representations through the GET operation, and may be manipulable using the PUT operation.

To analyze the processor API, it is interesting to have a picture of how a processor fits in a typical application.
In the next section we have a brief insight on How to use a Processor.

How to use a Processor: the API

A typical application would use a generic processor as follows (refer to the figure 2):

Figure 2: Typical processing flow

The representational state

Considering that any external application can implement and register a private processor type, doing a formal documentation of all the available processor types representational states may be an impossible task. Despite the library defines some common data and settings for video and audio codecs, the easiest -and recommendable- way to fetch any processor's REST is to actually "ask" this information to the processor (request through the API).
The only thing you need to know is the general form of the REST all the processors should comply, which is represented in the following JSON string:

1 {
2  "settings":
3  {
4  ... here you will find the settings ...
5  },
6  ... anything outside object 'settings' is state-information data -informative, cannot be modified-
7 }

The following sample code shows how to GET a processor's instance REST (see 'procs_opt()' function):

1 char *rest_str= NULL;
2 ...
3 ret_code= procs_opt(procs_ctx, "PROCS_ID_GET", proc_id, &rest_str);

Let's suppose the answer is the following JSON string (e.g. given by a video encoder):

1 {
2  ... any data ....
3  "settings": {
4  "bit_rate_output":1024000,
5  "frame_rate_output":25,
6  "width_output":720,
7  "height_output":576,
8  "gop_size":25,
9  "conf_preset":"ultrafast"
10  }
11 }

Then, all the parameters that can be manipulated in the processor are specified within the "settings" object. If we want to change the output width and height, for example, we can perform a PUT operation passing the corresponding parameters either as a query string

1 ret_code= procs_opt(procs_ctx, "PROCS_ID_PUT", proc_id, "width_output=352&height_output=288");

or as a JSON string (both are accepted)

1 ret_code= procs_opt(procs_ctx, "PROCS_ID_PUT", proc_id,
2  "{\"width_output\":352,\"height_output\":288}");

Requesting the settings REST to the processor is effective but may be not always self-explanatory (parameters are not documented in a REST response). To get formal documentation of each specific processor (any codec or muxer) you will have to go to the processor's code and analyze corresponding settings structure and the associated doxygen specifications.
To do that, consider the following example.
The video settings which are common to all video codec types ("generic" video codec settings) are defined at the structures video_settings_enc_ctx_s and video_settings_dec_ctx_s (encoding and decoding respectively) at the 'codecs' library. Similarly, common audio settings are defined at audio_settings_enc_ctx_s and audio_settings_dec_ctx_s.
Any video codec is supposed to use this common settings and extend them as desired. As a concrete example, the H.264 encoder implemented at ffmpeg_x264.c (MediaProcessors's wrapper of the FFmpeg x.264 codec facility) extends the video common settings in the structure defined as ffmpeg_x264_enc_settings_ctx_s. Then, all the settings for this specific codec are documented at ffmpeg_x264_enc_settings_ctx_s and the extended common structure video_settings_enc_ctx_s.
The rest of the codecs implemented in the 'codecs' library use analogue structure extensions as the above mentioned, so you can generalize this rule to see the settings parameters of any codec type implementation.

The RESTful HTTP/web-services adapter

REST philosophy of the API enables straightforward implementation of an HTTP web service exposing the CTRL API. Figure 3 depicts the basic scheme:

Translation of an HTTP request to a CTRL API request is immediate, and is implemented for reference, and for your application, at procs_api_http.h / procs_api_http.c.
The function 'procs_api_http_req_handler()' is in charge of translating the HTTP request and returning the corresponding response.

Figure 3: A RESTful HTTP/web-services adapter

RESTful wrapped responses

The function 'procs_api_http_req_handler()' adds a JSON wrapper object to the response given by the CTRL API. This wrapper is a proper adaptation to the HTTP environment.
Because in many web-services frameworks (e.g. JavaScript) the HTTP status response codes can not be easily reached by end-developers, a wrapped response is included in the message body with the following properties:

Schematically, the RESTful adapter response has then the following form:

1 {
2  "code":number,
3  "status":string,
4  "message":string,
5  "data": {...} // object returned by PROCS CTR API if any or null.
6 }

Returning and requesting representation extensions

For this project RESTful specification, services use the file extension '.json' (e.g. all the request will have the form: 'http://server_url:port/my/url/path.json').

Pluralization

For this project RESTful specification, the use of pluralizations in name nodes is mandatory and generalized.
Example:
For referencing a specific processor with identifier '0' , we always use (note the plural 'procs' at the URL path):

1 http://server_url:port/procs/:processor_id.json

rather than:

1 http://server_url:port/proc/:processor_id.json

RESTful minimal hyper-linking practices

The RESTful API is navigable via its links to the various components of the representation.
Example:
Consider we are running our MediaProcessor based application with a 3rd party HTTP server with address 127.0.0.1 ('localhost') listening to port 8088. By default, the URL base the RESTful adapter (procs_api_http.h / procs_api_http.c) use is '/procs'; thus, any remote HTTP request to our application would have an URL of the form '127.0.0.1:8088/procs[...].json'.
The 'entrance point' of the API is given by the base URL ('/procs'); thus, if we perform from a remote HTTP client the following request:

1 GET 127.0.0.1:8088/procs.json

We will have a response similar to the following:

1 {
2  "code":200,
3  "status":"OK",
4  "message":null,
5  "data":{
6  "procs":[
7  {
8  "proc_id":0,
9  "type_name":"my_codec_type",
10  "links":[
11  {
12  "rel":"self",
13  "href":"/procs/0.json"
14  }
15  ]
16  },
17  {
18  "proc_id":1,
19  "type_name":"other_codec_type",
20  "links":[
21  {
22  "rel":"self",
23  "href":"/procs/1.json"
24  }
25  ]
26  }, ...
27  ]
28  }
29 }

For navigating through the rest of the resources representations we just need to follow the links; e.g. for requesting the state of processor with identifier '0':

1 GET 127.0.0.1:8088/procs/0.json

A sample response:

1 {
2  "code":200,
3  "status":"OK",
4  "message":null,
5  "data":{
6  "settings":{
7  "bit_rate_output":307200,
8  "frame_rate_output":15,
9  "width_output":352,
10  "height_output":288,
11  "gop_size":15,
12  "conf_preset":null
13  }
14  }
15 }

Processor with Id. '0' has settings; we can manipulate them using the PUT method:

1 PUT 127.0.0.1:8088/procs/0.json?width_output=720&height_output=480

If we request again proessor's state:

1 {
2  "code":200,
3  "status":"OK",
4  "message":null,
5  "data":{
6  "settings":{
7  ...
8  "width_output":720,
9  "height_output":480,
10  ...
11  }
12  }
13 }

How to use a Processor: hands-on

Please continue with the examples documentation.