\begin{DoxyParagraph}{Contents}

\begin{DoxyItemize}
\item \mbox{\hyperlink{index_intro_sec}{Introduction}}
\item \mbox{\hyperlink{index_features}{Features}}
\item \mbox{\hyperlink{index_concepts}{A\+PI concepts}}
\item \mbox{\hyperlink{index_comp}{Components}}
\item \mbox{\hyperlink{index_create}{Component Creation}}
\item \mbox{\hyperlink{index_port}{Component Ports}}
\item \mbox{\hyperlink{index_buf}{Buffer Headers}}
\item \mbox{\hyperlink{index_queue}{Queues of Buffer Headers}}
\item \mbox{\hyperlink{index_pool}{Pools of Buffer Headers}}
\item \mbox{\hyperlink{index_param}{Port Parameters}}
\item \mbox{\hyperlink{index_events}{Port Events}}
\item \mbox{\hyperlink{index_version}{Versioning}}
\item \mbox{\hyperlink{index_example}{Example Code}}
\end{DoxyItemize}
\end{DoxyParagraph}
\hypertarget{index_intro_sec}{}\section{Introduction}\label{index_intro_sec}
M\+M\+AL (Multi-\/\+Media Abstraction Layer) is a framework which is used to provide a host-\/side, simple and relatively low-\/level interface to multimedia components running on Video\+Core. It also provides a component interface so that new components can be easily created and integrated into the framework.

There is no requirement that all the components be running on Video\+Core as M\+M\+AL doesn\textquotesingle{}t put any restriction on where components live. The current implementation for instance provides some components which can be run on both host-\/side or Video\+Core (e.\+g. the splitter component).\hypertarget{index_features}{}\section{Features}\label{index_features}
The M\+M\+AL A\+PI has been designed to support all the following features\+:
\begin{DoxyItemize}
\item Sufficiently generic to support different kinds of multimedia component.
\item Simple to use from client side (mostly synchronous except where it matters).
\item Straightforward A\+PI for designing components (e.\+g. avoids multiple data paths, as found in R\+IL).
\item Allows for fully-\/optimised implementation of components (e.\+g. zero-\/copy buffer passing).
\item Portability (A\+PI is self-\/contained).
\item Supports multiple instances (e.\+g. of Video\+Core).
\item Extensible without breaking source or binary backward compatibility.
\end{DoxyItemize}\hypertarget{index_concepts}{}\section{A\+P\+I concepts}\label{index_concepts}
The M\+M\+AL A\+PI is based on the concept of components, ports and buffer headers. Clients create M\+M\+AL components which expose ports for each individual elementary stream of data they support (e.\+g. audio/video). Components expose input ports to receive data from the client, and expose output ports to return data to the client.

Data sent to or received from the component needs to be attached to a buffer header. Buffer headers are necessary because they contain buffer specific ancillary data which is necessary for the component and client to do their processing (e.\+g timestamps).\hypertarget{index_comp}{}\section{Components}\label{index_comp}
M\+M\+AL lets clients create multi-\/media components (video encoders, video decoders, camera, and so-\/on) using a common A\+PI. Clients exchange data with components using buffer headers. A buffer header has a pointer to the payload data. Buffer headers are sent to and received from ports that are provided by components.

A typical decoder component would have a single input port and a single output port, but the same architecture could also be used for components with different layouts (e.\+g. a camera with a capture and preview port, or a debugging component with just an input port).\hypertarget{index_create}{}\subsection{Component Creation}\label{index_create}
Each component is identified by a unique name. To create a specific component the client needs to call \mbox{\hyperlink{group___mmal_component_ga402fecd9fa4f1d1b76e724eec5fe93b9}{mmal\+\_\+component\+\_\+create}} with the desired component\textquotesingle{}s name as an argument. This call will return a context (\mbox{\hyperlink{struct_m_m_a_l___c_o_m_p_o_n_e_n_t___t}{M\+M\+A\+L\+\_\+\+C\+O\+M\+P\+O\+N\+E\+N\+T\+\_\+T}}) to the component. This context will expose the input and output ports (\mbox{\hyperlink{struct_m_m_a_l___p_o_r_t___t}{M\+M\+A\+L\+\_\+\+P\+O\+R\+T\+\_\+T}}) supported by this specific component.

\begin{DoxyNote}{Note}
All Video\+Core components have a name starting with the \char`\"{}vc.\char`\"{} prefix (this prefix is used to distinguish when a creation request needs to be forwarded to Video\+Core).
\end{DoxyNote}
\hypertarget{index_port}{}\section{Component Ports}\label{index_port}
A port (\mbox{\hyperlink{struct_m_m_a_l___p_o_r_t___t}{M\+M\+A\+L\+\_\+\+P\+O\+R\+T\+\_\+T}}) is the entity which exposes an elementary stream (\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t}{M\+M\+A\+L\+\_\+\+E\+S\+\_\+\+F\+O\+R\+M\+A\+T\+\_\+T}}) on a component. It is also the entity to which buffer headers (\mbox{\hyperlink{struct_m_m_a_l___b_u_f_f_e_r___h_e_a_d_e_r___t}{M\+M\+A\+L\+\_\+\+B\+U\+F\+F\+E\+R\+\_\+\+H\+E\+A\+D\+E\+R\+\_\+T}}) are sent or from which they are received.

Clients do not need to create ports. They are created automatically by the component when this one is created but the format of a port might need to be set by the client depending on the type of component the client is using.

For example, for a video decoding component, one input port and one output port will be available. The format of the input port must be set by the client (using \mbox{\hyperlink{group___mmal_port_gae118f5d30974f414fd2ead7891ad9ee9}{mmal\+\_\+port\+\_\+format\+\_\+commit}}) while the format of the output port will be automatically set by the component once the component has enough information to find out what its format should be.

If the input port format contains enough information for the component to determine the format of the output port straight away, then the output port will be set to the proper format when \mbox{\hyperlink{group___mmal_port_gae118f5d30974f414fd2ead7891ad9ee9}{mmal\+\_\+port\+\_\+format\+\_\+commit}} returns. Otherwise the output format will be set to M\+M\+A\+L\+\_\+\+E\+N\+C\+O\+D\+I\+N\+G\+\_\+\+U\+N\+K\+N\+O\+WN until the component is fed enough data to determine the format of the output port. When this happens, the client will receive an event on the output port, signalling that its format has changed.\hypertarget{index_buf}{}\section{Buffer Headers}\label{index_buf}
Buffer headers (\mbox{\hyperlink{struct_m_m_a_l___b_u_f_f_e_r___h_e_a_d_e_r___t}{M\+M\+A\+L\+\_\+\+B\+U\+F\+F\+E\+R\+\_\+\+H\+E\+A\+D\+E\+R\+\_\+T}}) are used to exchange data with components. They do not contain the data directly but instead contain a pointer to the data being transferred.

Separating the buffer headers from the payload means that the memory for the data can be allocated outside of M\+M\+AL (e.\+g. if it is supplied by an external library) while still providing a consistent way to exchange data between clients and components.

Buffer headers are allocated from pools and are reference counted. The refcount will drop when \mbox{\hyperlink{group___mmal_buffer_header_ga69dfbc6faf317c320c4abbeb750a556e}{mmal\+\_\+buffer\+\_\+header\+\_\+release}} is called and the buffer header will be recycled to its pool when it reaches zero. The client can be notified when the buffer header is recycled so that it can recycle the associated payload memory as well.

A pool of buffer headers should be created after committing the format of the port. When the format is changed, the minimum and recommended size and number of buffers may change.

\begin{DoxyNote}{Note}
The current number of buffers and their size (\mbox{\hyperlink{struct_m_m_a_l___p_o_r_t___t_afedb224ac236134e0802c630ca7edadd}{M\+M\+A\+L\+\_\+\+P\+O\+R\+T\+\_\+\+T\+::buffer\+\_\+num}} and \mbox{\hyperlink{struct_m_m_a_l___p_o_r_t___t_ac4a6ecc45ef42a4609e5a3a5a706eade}{M\+M\+A\+L\+\_\+\+P\+O\+R\+T\+\_\+\+T\+::buffer\+\_\+size}}) are not modified by M\+M\+AL, and must be updated by the client as required after changes to a port\textquotesingle{}s format.
\end{DoxyNote}
\hypertarget{index_queue}{}\subsection{Queues of Buffer Headers}\label{index_queue}
Queues (M\+M\+A\+L\+\_\+\+Q\+U\+E\+U\+E\+\_\+T) are a facility that allows thread-\/safe processing of buffer headers from the client. Callbacks triggered by a M\+M\+AL component when it sends a buffer header to the client can simply put the buffer in a queue and let the main processing thread of the client get its data from the queue.\hypertarget{index_pool}{}\subsection{Pools of Buffer Headers}\label{index_pool}
Pools (\mbox{\hyperlink{struct_m_m_a_l___p_o_o_l___t}{M\+M\+A\+L\+\_\+\+P\+O\+O\+L\+\_\+T}}) let clients allocate a fixed number of buffer headers, and a queue (M\+M\+A\+L\+\_\+\+Q\+U\+E\+U\+E\+\_\+T). They are used for buffer header allocation. Optionally a pool can also allocate the payload memory for the client.

Pools can also be resized after creation, for example, if the port format is changed leading to a new number or size of buffers being required.\hypertarget{index_param}{}\section{Port Parameters}\label{index_param}
Components support setting and getting component specific parameters using \mbox{\hyperlink{group___mmal_port_ga7feccb996f0bab5c798b3465747bb0a3}{mmal\+\_\+port\+\_\+parameter\+\_\+set}} and \mbox{\hyperlink{group___mmal_port_ga58f2b79985132199992a99790264541a}{mmal\+\_\+port\+\_\+parameter\+\_\+get}}. Parameters are identified using an integer index; parameter data is binary. See the \mbox{\hyperlink{group___m_m_a_l___p_a_r_a_m_e_t_e_r___i_d_s}{Pre-\/defined M\+M\+AL parameter I\+Ds}} page for more information on the pre-\/defined parameters.\hypertarget{index_events}{}\section{Port Events}\label{index_events}
Components can generate events on their ports. Events are sent to clients as buffer headers and thus when the client receives a buffer header on one of the component\textquotesingle{}s port it should check if the buffer header is an event and in which case process it and then release it (\mbox{\hyperlink{group___mmal_buffer_header_ga69dfbc6faf317c320c4abbeb750a556e}{mmal\+\_\+buffer\+\_\+header\+\_\+release}}). The reason for transmitting events in-\/band with the actual data is that it is often very valuable to know exactly when the event happens relative to the the actual data (e.\+g. with a focus event, from which video frame are we in focus).~\newline
Buffer headers used to transmit events are allocated internally by the framework so it is important to release the buffer headers with \mbox{\hyperlink{group___mmal_buffer_header_ga69dfbc6faf317c320c4abbeb750a556e}{mmal\+\_\+buffer\+\_\+header\+\_\+release}} so the buffer headers make it back to their actual owner.

Event buffer headers are allocated when the component is created, based on the minimum number and size of control port buffers set by the component. Component wide events (not port specific) are sent to the control port callback when that port is enabled. Port events are sent to the port callback, the same as data buffers, but the \textquotesingle{}cmd\textquotesingle{} field is non-\/zero.\hypertarget{index_version}{}\section{Versioning}\label{index_version}
The A\+PI requires that the M\+M\+AL core be the same or more recent version as the components and clients. Clients and components can be older and the A\+PI will still work both at compile-\/time and run-\/time.\hypertarget{index_example}{}\section{Example Code}\label{index_example}
The following code is a simple example on how to do video decoding using M\+M\+AL. Note that the code is intended to be clear and illustrate how to use M\+M\+AL at its most fundamental level, not necessarily the most efficient way to achieve the same result. Use of opaque images, tunneling and zero-\/copy inter-\/processor buffers can all improve the performance or reduce the load.

The \mbox{\hyperlink{group___mmal_connection_utility}{Port Connection Utility}} functions can also be used to replace much of the common \char`\"{}boilerplate\char`\"{} code, especially when a pipeline of several components needs to be processed.


\begin{DoxyCode}
\textcolor{preprocessor}{#include <\mbox{\hyperlink{mmal_8h}{mmal.h}}>}
...
static \textcolor{keywordtype}{void} input\_callback(\mbox{\hyperlink{struct_m_m_a_l___p_o_r_t___t}{MMAL\_PORT\_T}} *\mbox{\hyperlink{struct_m_m_a_l___c_o_m_p_o_n_e_n_t___t_adc07b7d97724f787f177bd11f610a047}{port}}, 
      \mbox{\hyperlink{struct_m_m_a_l___b_u_f_f_e_r___h_e_a_d_e_r___t}{MMAL\_BUFFER\_HEADER\_T}} *buffer)
\{
   \textcolor{comment}{// The decoder is done with the data, just recycle the buffer header into its pool}
   \mbox{\hyperlink{group___mmal_buffer_header_ga69dfbc6faf317c320c4abbeb750a556e}{mmal\_buffer\_header\_release}}(buffer);
\}
\textcolor{keyword}{static} \textcolor{keywordtype}{void} output\_callback(\mbox{\hyperlink{struct_m_m_a_l___p_o_r_t___t}{MMAL\_PORT\_T}} *\mbox{\hyperlink{struct_m_m_a_l___c_o_m_p_o_n_e_n_t___t_adc07b7d97724f787f177bd11f610a047}{port}}, 
      \mbox{\hyperlink{struct_m_m_a_l___b_u_f_f_e_r___h_e_a_d_e_r___t}{MMAL\_BUFFER\_HEADER\_T}} *buffer)
\{
   MMAL\_QUEUE\_T *queue = (MMAL\_QUEUE\_T *)\mbox{\hyperlink{struct_m_m_a_l___c_o_m_p_o_n_e_n_t___t_adc07b7d97724f787f177bd11f610a047}{port}}->\mbox{\hyperlink{struct_m_m_a_l___p_o_r_t___t_ac48ce60dae764525880438aabb058faa}{userdata}};
   \mbox{\hyperlink{group___mmal_queue_gaf31ecd6f4922699de7dad98e79e69a2b}{mmal\_queue\_put}}(queue, buffer); \textcolor{comment}{// Queue the decoded video frame}
\}
...

MMAL\_COMPONENT\_T *decoder = 0;
\mbox{\hyperlink{group___mmal_types_ga5ac87230bd615d2b154a9d5899bc37fd}{MMAL\_STATUS\_T}} status;

\textcolor{comment}{// Create the video decoder component on VideoCore}
status = \mbox{\hyperlink{group___mmal_component_ga402fecd9fa4f1d1b76e724eec5fe93b9}{mmal\_component\_create}}(\textcolor{stringliteral}{"vc.ril.video\_decoder"}, &decoder);
ABORT\_IF\_ERROR(status);

\textcolor{comment}{// Set format of video decoder input port}
\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t}{MMAL\_ES\_FORMAT\_T}} *format\_in = decoder->input[0]->format;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a475baf41567d062e52f63fcb4c8c3f86}{type}} = \mbox{\hyperlink{group___mmal_format_gga838de933ae805a000d9986dc569897d4a79d1b43ce9a21bb468bc8a466e102dcf}{MMAL\_ES\_TYPE\_VIDEO}};
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a89bd63daf2f62de5c79c854ef719d088}{encoding}} = MMAL\_ENCODING\_H264;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a2e38651f00f1040aed8e1fee2d658098}{es}}->\mbox{\hyperlink{union_m_m_a_l___e_s___s_p_e_c_i_f_i_c___f_o_r_m_a_t___t_ac120a2696adc364346687b6efd05225d}{video}}.\mbox{\hyperlink{struct_m_m_a_l___v_i_d_e_o___f_o_r_m_a_t___t_aec6d3aa7405e3da250798dab50e2e9c4}{width}} = 1280;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a2e38651f00f1040aed8e1fee2d658098}{es}}->\mbox{\hyperlink{union_m_m_a_l___e_s___s_p_e_c_i_f_i_c___f_o_r_m_a_t___t_ac120a2696adc364346687b6efd05225d}{video}}.\mbox{\hyperlink{struct_m_m_a_l___v_i_d_e_o___f_o_r_m_a_t___t_a1d77b2bc4d27bd2e4fefedf00488dd62}{height}} = 720;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a2e38651f00f1040aed8e1fee2d658098}{es}}->\mbox{\hyperlink{union_m_m_a_l___e_s___s_p_e_c_i_f_i_c___f_o_r_m_a_t___t_ac120a2696adc364346687b6efd05225d}{video}}.\mbox{\hyperlink{struct_m_m_a_l___v_i_d_e_o___f_o_r_m_a_t___t_a06830b7e861c9940089f1acd65a8cbee}{frame\_rate}}.\mbox{\hyperlink{struct_m_m_a_l___r_a_t_i_o_n_a_l___t_a3efe4fa2706826ddbbe3d34aaedc5b0d}{num}} = 30;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a2e38651f00f1040aed8e1fee2d658098}{es}}->\mbox{\hyperlink{union_m_m_a_l___e_s___s_p_e_c_i_f_i_c___f_o_r_m_a_t___t_ac120a2696adc364346687b6efd05225d}{video}}.\mbox{\hyperlink{struct_m_m_a_l___v_i_d_e_o___f_o_r_m_a_t___t_a06830b7e861c9940089f1acd65a8cbee}{frame\_rate}}.\mbox{\hyperlink{struct_m_m_a_l___r_a_t_i_o_n_a_l___t_a0aa0892b87af1365f224d40205f1104e}{den}} = 1;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a2e38651f00f1040aed8e1fee2d658098}{es}}->\mbox{\hyperlink{union_m_m_a_l___e_s___s_p_e_c_i_f_i_c___f_o_r_m_a_t___t_ac120a2696adc364346687b6efd05225d}{video}}.\mbox{\hyperlink{struct_m_m_a_l___v_i_d_e_o___f_o_r_m_a_t___t_a2f8ad8c0eec9c5ff9835fbf4a5060a9d}{par}}.\mbox{\hyperlink{struct_m_m_a_l___r_a_t_i_o_n_a_l___t_a3efe4fa2706826ddbbe3d34aaedc5b0d}{num}} = 1;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a2e38651f00f1040aed8e1fee2d658098}{es}}->\mbox{\hyperlink{union_m_m_a_l___e_s___s_p_e_c_i_f_i_c___f_o_r_m_a_t___t_ac120a2696adc364346687b6efd05225d}{video}}.\mbox{\hyperlink{struct_m_m_a_l___v_i_d_e_o___f_o_r_m_a_t___t_a2f8ad8c0eec9c5ff9835fbf4a5060a9d}{par}}.\mbox{\hyperlink{struct_m_m_a_l___r_a_t_i_o_n_a_l___t_a0aa0892b87af1365f224d40205f1104e}{den}} = 1;
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_a9a841ae6988fcd9eae62c45d0aacad08}{flags}} = \mbox{\hyperlink{group___mmal_format_ga26178f5c56486c3e5db7f5f7c90598a0}{MMAL\_ES\_FORMAT\_FLAG\_FRAMED}};
status = \mbox{\hyperlink{group___mmal_format_ga23bf07631a1ee50f34bef31bf1b0c935}{mmal\_format\_extradata\_alloc}}(format\_in, 
      YOUR\_H264\_CODEC\_HEADER\_BYTES\_SIZE);
ABORT\_IF\_ERROR(status);
format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_aacd642a60a08c3b2aa0211e29990f1ab}{extradata\_size}} = YOUR\_H264\_CODEC\_HEADER\_BYTES\_SIZE;
memcpy(format\_in->\mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_ae832c72b3ed803108442244ef90e314a}{extradata}}, YOUR\_H264\_CODEC\_HEADER\_BYTES, format\_in->
      \mbox{\hyperlink{struct_m_m_a_l___e_s___f_o_r_m_a_t___t_aacd642a60a08c3b2aa0211e29990f1ab}{extradata\_size}});

status = \mbox{\hyperlink{group___mmal_port_gae118f5d30974f414fd2ead7891ad9ee9}{mmal\_port\_format\_commit}}(decoder->input[0]);
ABORT\_IF\_ERROR(status);

\textcolor{comment}{// Once the call to mmal\_port\_format\_commit() on the input port returns, the decoder will}
\textcolor{comment}{// have set the format of the output port.}
\textcolor{comment}{// If the decoder still doesn t have enough information to determine the format of the}
\textcolor{comment}{// output port, the encoding will be set to unknown. As soon as the decoder receives}
\textcolor{comment}{// enough stream data to determine the format of the output port it will send an event}
\textcolor{comment}{// to the client to signal that the format of the port has changed.}
\textcolor{comment}{// However, for the sake of simplicity this example assumes that the decoder was given}
\textcolor{comment}{// all the necessary information right at the start (i.e. video format and codec header bytes)}
MMAL\_FORMAT\_T *format\_out = decoder->output[0]->format;
\textcolor{keywordflow}{if} (format\_out->encoding == MMAL\_ENCODING\_UNKNOWN)
   ABORT();

\textcolor{comment}{// Now we know the format of both ports and the requirements of the decoder, we can create}
\textcolor{comment}{// our buffer headers and their associated memory buffers. We use the buffer pool API for this.}
decoder->input[0]->buffer\_num = decoder->input[0]->buffer\_num\_min;
decoder->input[0]->buffer\_size = decoder->input[0]->buffer\_size\_min;
\mbox{\hyperlink{struct_m_m_a_l___p_o_o_l___t}{MMAL\_POOL\_T}} *pool\_in = \mbox{\hyperlink{group___mmal_pool_ga88abb9b58d7c2509640231b9fb905d58}{mmal\_pool\_create}}(decoder->input[0]->buffer\_num,
                                        decoder->input[0]->buffer\_size);
decoder->output[0]->buffer\_num = decoder->output[0]->buffer\_num\_min;
decoder->output[0]->buffer\_size = decoder->output[0]->buffer\_size\_min;
\mbox{\hyperlink{struct_m_m_a_l___p_o_o_l___t}{MMAL\_POOL\_T}} *pool\_out = \mbox{\hyperlink{group___mmal_pool_ga88abb9b58d7c2509640231b9fb905d58}{mmal\_pool\_create}}(decoder->output[0]->buffer\_num,
                                         decoder->output[0]->buffer\_size);

\textcolor{comment}{// Create a queue to store our decoded video frames. The callback we will get when}
\textcolor{comment}{// a frame has been decoded will put the frame into this queue.}
MMAL\_QUEUE\_T *queue\_decoded\_frames = \mbox{\hyperlink{group___mmal_queue_gacafb60bc36fdb1de9b802335cb1488bc}{mmal\_queue\_create}}();
decoder->output[0]->userdata = (void)queue\_decoded\_frames;

\textcolor{comment}{// Enable all the input port and the output port.}
\textcolor{comment}{// The callback specified here is the function which will be called when the buffer header}
\textcolor{comment}{// we sent to the component has been processed.}
status = \mbox{\hyperlink{group___mmal_port_gaa723c325260a53f553c6ab7ee8038b70}{mmal\_port\_enable}}(decoder->input[0], input\_callback);
ABORT\_IF\_ERROR(status);
status = \mbox{\hyperlink{group___mmal_port_gaa723c325260a53f553c6ab7ee8038b70}{mmal\_port\_enable}}(decoder->output[0], output\_callback);
ABORT\_IF\_ERROR(status);

\textcolor{comment}{// Enable the component. Components will only process data when they are enabled.}
status = \mbox{\hyperlink{group___mmal_component_ga8f3de5407c032faa0af3c0c3aaba235a}{mmal\_component\_enable}}(decoder);
ABORT\_IF\_ERROR(status);

\textcolor{comment}{// Data processing loop}
\textcolor{keywordflow}{while} (1)
\{
   \mbox{\hyperlink{struct_m_m_a_l___b_u_f_f_e_r___h_e_a_d_e_r___t}{MMAL\_BUFFER\_HEADER\_T}} *buffer;

   \textcolor{comment}{// The client needs to implement its own blocking code.}
   \textcolor{comment}{// (e.g. a semaphore which is posted when a buffer header is put in one of the queues)}
   WAIT\_FOR\_QUEUES\_TO\_HAVE\_BUFFERS();

   \textcolor{comment}{// Send empty buffers to the output port of the decoder to allow the decoder to start}
   \textcolor{comment}{// producing frames as soon as it gets input data}
   \textcolor{keywordflow}{while} ((buffer = \mbox{\hyperlink{group___mmal_queue_gae03a53a1cba809a9c42fefe1af835932}{mmal\_queue\_get}}(pool\_out->\mbox{\hyperlink{struct_m_m_a_l___p_o_o_l___t_ae4175dd1f85f1adbe6be2dc4207fb064}{queue}})) != NULL)
   \{
      status = \mbox{\hyperlink{group___mmal_port_ga098a7b91bb6fc596aed0e5585aee3253}{mmal\_port\_send\_buffer}}(decoder->output[0], buffer);
      ABORT\_IF\_ERROR(status);
   \}

   \textcolor{comment}{// Send data to decode to the input port of the video decoder}
   \textcolor{keywordflow}{if} ((buffer = \mbox{\hyperlink{group___mmal_queue_gae03a53a1cba809a9c42fefe1af835932}{mmal\_queue\_get}}(pool\_in->\mbox{\hyperlink{struct_m_m_a_l___p_o_o_l___t_ae4175dd1f85f1adbe6be2dc4207fb064}{queue}})) != NULL)
   \{
      READ\_DATA\_INTO\_BUFFER(buffer);

      status = \mbox{\hyperlink{group___mmal_port_ga098a7b91bb6fc596aed0e5585aee3253}{mmal\_port\_send\_buffer}}(decoder->input[0], buffer);
      ABORT\_IF\_ERROR(status);
   \}

   \textcolor{comment}{// Get our decoded frames. We also need to cope with events}
   \textcolor{comment}{// generated from the component here.}
   \textcolor{keywordflow}{while} ((buffer = \mbox{\hyperlink{group___mmal_queue_gae03a53a1cba809a9c42fefe1af835932}{mmal\_queue\_get}}(queue\_decoded\_frames)) != NULL)
   \{
      \textcolor{keywordflow}{if} (buffer->\mbox{\hyperlink{struct_m_m_a_l___b_u_f_f_e_r___h_e_a_d_e_r___t_aafab0a567a9ba1bc56e79903ce404a7c}{cmd}})
      \{
         \textcolor{comment}{// This is an event. Do something with it and release the buffer.}
         \mbox{\hyperlink{group___mmal_buffer_header_ga69dfbc6faf317c320c4abbeb750a556e}{mmal\_buffer\_header\_release}}(buffer);
         \textcolor{keywordflow}{continue};
      \}

      \textcolor{comment}{// We have a frame, do something with it (why not display it for instance?).}
      \textcolor{comment}{// Once we're done with it, we release it. It will magically go back}
      \textcolor{comment}{// to its original pool so it can be reused for a new video frame.}
      \mbox{\hyperlink{group___mmal_buffer_header_ga69dfbc6faf317c320c4abbeb750a556e}{mmal\_buffer\_header\_release}}(buffer);
   \}
\}

\textcolor{comment}{// Cleanup everything}
\mbox{\hyperlink{group___mmal_component_ga25c289404703b6a348fe1c1880fe3f5f}{mmal\_component\_destroy}}(decoder);
\mbox{\hyperlink{group___mmal_pool_ga392efa95efde822ddec1187aa7332a3d}{mmal\_pool\_destroy}}(pool\_in);
\mbox{\hyperlink{group___mmal_pool_ga392efa95efde822ddec1187aa7332a3d}{mmal\_pool\_destroy}}(pool\_out);
\mbox{\hyperlink{group___mmal_queue_ga4caac58e82878025213b922cc6815863}{mmal\_queue\_destroy}}(queue\_decode\_frames);
\end{DoxyCode}
 