2 Copyright (c) 2012, Broadcom Europe Ltd
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "mmalomx_buffer.h"
30 #include "mmalomx_commands.h"
31 #include "mmalomx_marks.h"
32 #include "mmalomx_logging.h"
34 #include <util/mmal_util.h>
36 /*****************************************************************************/
37 OMX_ERRORTYPE mmalomx_buffer_send(
38 MMALOMX_COMPONENT_T *component,
39 OMX_BUFFERHEADERTYPE *omx_buffer,
40 OMX_DIRTYPE direction)
42 OMX_ERRORTYPE status = OMX_ErrorNone;
43 MMAL_BUFFER_HEADER_T *mmal_buffer;
44 MMAL_STATUS_T mmal_status;
50 return OMX_ErrorInvalidComponent;
51 if (component->state == OMX_StateInvalid)
52 return OMX_ErrorInvalidState;
54 if (!omx_buffer || omx_buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE) ||
55 omx_buffer->nOffset + omx_buffer->nFilledLen > omx_buffer->nAllocLen)
56 return OMX_ErrorBadParameter;
58 index = direction == OMX_DirInput ? omx_buffer->nInputPortIndex : omx_buffer->nOutputPortIndex;
59 if (index >= component->ports_num)
60 return OMX_ErrorBadPortIndex;
62 port = &component->ports[index];
63 if (port->direction != direction)
64 return OMX_ErrorBadPortIndex;
66 MMALOMX_LOCK_PORT(component, port);
68 if (component->state != OMX_StatePause && component->state != OMX_StateExecuting)
69 status = OMX_ErrorIncorrectStateOperation;
70 if (!port->enabled /* FIXME: || flushing || pending idle */)
71 status = OMX_ErrorIncorrectStateOperation;
72 if (status != OMX_ErrorNone)
75 mmal_buffer = mmal_queue_get( port->pool->queue );
76 if (!vcos_verify(mmal_buffer)) /* Should never happen */
78 status = OMX_ErrorUndefined;
82 mmalomx_mark_process_incoming(component, port, omx_buffer);
84 mmal_buffer->user_data = (void *)omx_buffer;
85 mmalil_buffer_header_to_mmal(mmal_buffer, omx_buffer);
87 mmal_status = mmal_port_send_buffer(port->mmal, mmal_buffer);
88 if (!vcos_verify(mmal_status == MMAL_SUCCESS))
90 LOG_ERROR("failed to send buffer on %s", port->mmal->name);
91 mmal_queue_put_back( port->pool->queue, mmal_buffer );
92 status = mmalil_error_to_omx(mmal_status);
96 port->buffers_in_transit++;
100 MMALOMX_UNLOCK_PORT(component, port);
104 /*****************************************************************************/
105 static void mmalomx_buffer_event(
106 MMALOMX_PORT_T *port,
107 MMAL_BUFFER_HEADER_T *mmal_buffer)
109 MMALOMX_COMPONENT_T *component = port->component;
110 MMAL_EVENT_FORMAT_CHANGED_T *event;
112 LOG_TRACE("hComponent %p, port %i, event %4.4s", component, port->index,
113 (char *)&mmal_buffer->cmd);
115 if (mmal_buffer->cmd == MMAL_EVENT_ERROR )
117 mmalomx_callback_event_handler(component, OMX_EventError,
118 mmalil_error_to_omx(*(MMAL_STATUS_T *)mmal_buffer->data), 0, NULL);
122 event = mmal_event_format_changed_get(mmal_buffer);
123 if (event && port->mmal->type == MMAL_PORT_TYPE_OUTPUT &&
124 port->mmal->format->type == MMAL_ES_TYPE_VIDEO)
126 uint32_t diff = mmal_format_compare(event->format, port->mmal->format);
127 MMAL_ES_FORMAT_T *format = port->mmal->format;
128 MMAL_VIDEO_FORMAT_T video = format->es->video;
130 /* Update the port settings with the new values */
131 mmal_format_copy(format, event->format);
132 port->mmal->buffer_num_min = event->buffer_num_min;
133 port->mmal->buffer_size_min = event->buffer_size_min;
134 port->format_changed = MMAL_TRUE;
136 if ((diff & MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_ASPECT_RATIO) &&
137 /* Do not report a change if going from unspecified to 1:1 */
138 !(format->es->video.par.num == format->es->video.par.den && !video.par.num))
140 LOG_DEBUG("aspect ratio change %ix%i->%ix%i", (int)video.par.num, (int)video.par.den,
141 (int)format->es->video.par.num, (int)format->es->video.par.den);
142 mmalomx_callback_event_handler(component, OMX_EventPortSettingsChanged,
143 port->index, OMX_IndexParamBrcmPixelAspectRatio, NULL);
146 if (diff & (MMAL_ES_FORMAT_COMPARE_FLAG_ENCODING|
147 MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_RESOLUTION|
148 MMAL_ES_FORMAT_COMPARE_FLAG_VIDEO_CROPPING))
150 LOG_DEBUG("format change %ix%i(%ix%i) -> %ix%i(%ix%i)",
151 (int)video.width, (int)video.height,
152 (int)video.crop.width, (int)video.crop.height,
153 (int)format->es->video.width, (int)format->es->video.height,
154 (int)format->es->video.crop.width, (int)format->es->video.crop.height);
155 mmalomx_callback_event_handler(component, OMX_EventPortSettingsChanged,
156 port->index, 0, NULL);
159 else if (event && port->mmal->type == MMAL_PORT_TYPE_OUTPUT &&
160 port->mmal->format->type == MMAL_ES_TYPE_AUDIO)
162 uint32_t diff = mmal_format_compare(event->format, port->mmal->format);
163 MMAL_ES_FORMAT_T *format = port->mmal->format;
164 MMAL_AUDIO_FORMAT_T audio = format->es->audio;
166 /* Update the port settings with the new values */
167 mmal_format_copy(format, event->format);
168 port->mmal->buffer_num_min = event->buffer_num_min;
169 port->mmal->buffer_size_min = event->buffer_size_min;
170 port->format_changed = MMAL_TRUE;
174 LOG_DEBUG("format change %ich, %iHz, %ibps -> %ich, %iHz, %ibps",
175 (int)audio.channels, (int)audio.sample_rate,
176 (int)audio.bits_per_sample,
177 (int)format->es->audio.channels,
178 (int)format->es->audio.sample_rate,
179 (int)format->es->audio.bits_per_sample);
180 mmalomx_callback_event_handler(component, OMX_EventPortSettingsChanged,
181 port->index, 0, NULL);
186 /*****************************************************************************/
187 OMX_ERRORTYPE mmalomx_buffer_return(
188 MMALOMX_PORT_T *port,
189 MMAL_BUFFER_HEADER_T *mmal_buffer)
191 MMALOMX_COMPONENT_T *component = port->component;
192 OMX_BUFFERHEADERTYPE *omx_buffer = (OMX_BUFFERHEADERTYPE *)mmal_buffer->user_data;
195 if (mmal_buffer->cmd)
197 mmalomx_buffer_event(port, mmal_buffer);
198 mmal_buffer_header_release(mmal_buffer);
199 return OMX_ErrorNone;
202 if (ENABLE_MMAL_EXTRA_LOGGING)
203 LOG_TRACE("hComponent %p, port %i, pBuffer %p", component,
204 port->index, omx_buffer);
206 vcos_assert(omx_buffer->pBuffer == mmal_buffer->data);
207 mmalil_buffer_header_to_omx(omx_buffer, mmal_buffer);
208 mmal_buffer_header_release(mmal_buffer);
210 if ((omx_buffer->nFlags & OMX_BUFFERFLAG_EOS) && port->direction == OMX_DirOutput)
212 mmalomx_callback_event_handler(component, OMX_EventBufferFlag,
213 port->index, omx_buffer->nFlags, NULL);
216 mmalomx_mark_process_outgoing(component, port, omx_buffer);
218 if (port->direction == OMX_DirInput)
219 component->callbacks.EmptyBufferDone((OMX_HANDLETYPE)&component->omx,
220 component->callbacks_data, omx_buffer );
222 component->callbacks.FillBufferDone((OMX_HANDLETYPE)&component->omx,
223 component->callbacks_data, omx_buffer );
225 MMALOMX_LOCK_PORT(component, port);
226 signal = port->actions & MMALOMX_ACTION_CHECK_FLUSHED;
227 port->buffers_in_transit--;
228 MMALOMX_UNLOCK_PORT(component, port);
231 mmalomx_commands_actions_signal(component);
233 return OMX_ErrorNone;