#include "omxil.h"
#include "omxil_core.h"
+#include "OMX_Broadcom.h"
#ifndef NDEBUG
# define OMXIL_EXTRA_DEBUG
#define SENTINEL_FLAG 0x10000
+/* Defined in the broadcom version of OMX_Index.h */
+#define OMX_IndexConfigRequestCallback 0x7f000063
+#define OMX_IndexParamBrcmPixelAspectRatio 0x7f00004d
+
+/* Defined in the broadcom version of OMX_Core.h */
+#define OMX_EventParamOrConfigChanged 0x7F000001
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
}
}
#endif
+#ifdef RPI_OMX
+ else if (!strcmp(p_sys->psz_component, "OMX.broadcom.video_decode"))
+ {
+ /* Clear these fields before setting parameters, to allow the codec
+ * fill in what it wants (instead of rejecting whatever happened to
+ * be there. */
+ def->format.video.nStride = def->format.video.nSliceHeight = 0;
+ }
+#endif
return OMX_ErrorNone;
}
return omx_error;
}
+
+/*****************************************************************************
+ * UpdatePixelAspect: Update vlc pixel aspect based on the aspect reported on
+ * the omx port - NOTE: Broadcom specific
+ *****************************************************************************/
+static OMX_ERRORTYPE UpdatePixelAspect(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ OMX_CONFIG_POINTTYPE pixel_aspect;
+ OMX_INIT_STRUCTURE(pixel_aspect);
+ OMX_ERRORTYPE omx_err;
+
+ if (strncmp(p_sys->psz_component, "OMX.broadcom.", 13))
+ return OMX_ErrorNotImplemented;
+
+ pixel_aspect.nPortIndex = p_sys->out.i_port_index;
+ omx_err = OMX_GetParameter(p_sys->omx_handle,
+ OMX_IndexParamBrcmPixelAspectRatio, &pixel_aspect);
+ if (omx_err != OMX_ErrorNone) {
+ msg_Warn(p_dec, "Failed to retrieve aspect ratio");
+ } else {
+ p_dec->fmt_out.video.i_sar_num = pixel_aspect.nX;
+ p_dec->fmt_out.video.i_sar_den = pixel_aspect.nY;
+ }
+
+ return omx_err;
+}
+
/*****************************************************************************
* GetPortDefinition: set vlc format based on the definition of the omx port
*****************************************************************************/
def->format.video.nStride = p_port->i_frame_stride;
#endif
p_port->i_frame_stride = def->format.video.nStride;
+ UpdatePixelAspect(p_dec);
break;
case AUDIO_ES:
CHECK_ERROR(omx_error, "OMX_CommandStateSet Idle failed (%x)", omx_error );
while (1) {
OMX_U32 cmd, state;
- omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, &cmd, &state, 0);
+ omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, &cmd, &state, 0);
CHECK_ERROR(omx_error, "Wait for Idle failed (%x)", omx_error );
// The event queue can contain other OMX_EventCmdComplete items,
// such as for OMX_CommandFlush
}
}
- omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
+ omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
CHECK_ERROR(omx_error, "Wait for Loaded failed (%x)", omx_error );
}
}
}
+ if(!strncmp(p_sys->psz_component, "OMX.broadcom.", 13))
+ {
+ OMX_CONFIG_REQUESTCALLBACKTYPE notifications;
+ OMX_INIT_STRUCTURE(notifications);
+
+ notifications.nPortIndex = p_sys->out.i_port_index;
+ notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio;
+ notifications.bEnable = OMX_TRUE;
+
+ omx_error = OMX_SetParameter(omx_handle,
+ OMX_IndexConfigRequestCallback, ¬ifications);
+ if (omx_error == OMX_ErrorNone)
+ msg_Dbg(p_dec, "Enabled aspect ratio notifications");
+ else
+ msg_Dbg(p_dec, "Could not enable aspect ratio notifications");
+ }
+
/* Set port definitions */
for(i = 0; i < p_sys->ports; i++)
{
p_port->i_port_index, NULL);
CHECK_ERROR(omx_error, "OMX_CommandPortEnable on %i failed (%x)",
(int)p_port->i_port_index, omx_error );
- omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
+ omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
CHECK_ERROR(omx_error, "Wait for PortEnable on %i failed (%x)",
(int)p_port->i_port_index, omx_error );
}
p_dec->fmt_out.video = p_dec->fmt_in.video;
p_dec->fmt_out.audio = p_dec->fmt_in.audio;
p_dec->fmt_out.i_codec = 0;
+
+ /* set default aspect of 1, if parser did not set it */
+ if (p_dec->fmt_out.video.i_sar_num == 0)
+ p_dec->fmt_out.video.i_sar_num = 1;
+ if (p_dec->fmt_out.video.i_sar_den == 0)
+ p_dec->fmt_out.video.i_sar_den = 1;
}
p_sys->b_enc = b_encode;
- p_sys->pp_last_event = &p_sys->p_events;
- vlc_mutex_init (&p_sys->mutex);
- vlc_cond_init (&p_sys->cond);
+ InitOmxEventQueue(&p_sys->event_queue);
vlc_mutex_init (&p_sys->in.fifo.lock);
vlc_cond_init (&p_sys->in.fifo.wait);
p_sys->in.fifo.offset = offsetof(OMX_BUFFERHEADERTYPE, pOutputPortPrivate) / sizeof(void *);
p_sys->out.p_fmt = &p_dec->fmt_out;
p_sys->ports = 2;
p_sys->p_ports = &p_sys->in;
- p_sys->b_use_pts = 0;
+ p_sys->b_use_pts = 1;
msg_Dbg(p_dec, "fmt in:%4.4s, out: %4.4s", (char *)&p_dec->fmt_in.i_codec,
(char *)&p_dec->fmt_out.i_codec);
omx_error, (int)p_port->i_port_index, j );
}
- omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
+ omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
CHECK_ERROR(omx_error, "Wait for Idle failed (%x)", omx_error );
omx_error = OMX_SendCommand( p_sys->omx_handle, OMX_CommandStateSet,
OMX_StateExecuting, 0);
CHECK_ERROR(omx_error, "OMX_CommandStateSet Executing failed (%x)", omx_error );
- omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
+ omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
CHECK_ERROR(omx_error, "Wait for Executing failed (%x)", omx_error );
/* Send codec configuration data */
if(p_sys->b_error) goto error;
p_dec->b_need_packetized = true;
- if (!strcmp(p_sys->psz_component, "OMX.TI.DUCATI1.VIDEO.DECODER"))
- p_sys->b_use_pts = 1;
-
- if (!strcmp(p_sys->psz_component, "OMX.STM.Video.Decoder"))
- p_sys->b_use_pts = 1;
- if (p_sys->b_use_pts)
- msg_Dbg( p_dec, "using pts timestamp mode for %s", p_sys->psz_component);
+ if (!p_sys->b_use_pts)
+ msg_Dbg( p_dec, "using dts timestamp mode for %s", p_sys->psz_component);
return VLC_SUCCESS;
for(i = 0; i < p_port->i_buffers; i++)
{
OMX_FIFO_GET(&p_port->fifo, p_buffer);
+ if (p_buffer->pAppPrivate != NULL)
+ decoder_DeletePicture( p_dec, p_buffer->pAppPrivate );
if (p_buffer->nFlags & SENTINEL_FLAG) {
free(p_buffer);
i--;
CHECK_ERROR(omx_error, "OMX_FreeBuffer failed (%x, %i, %i)",
omx_error, (int)p_port->i_port_index, i );
- omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
+ omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
CHECK_ERROR(omx_error, "Wait for PortDisable failed (%x)", omx_error );
/* Get the new port definition */
CHECK_ERROR(omx_error, "OMX_UseBuffer failed (%x, %i, %i)",
omx_error, (int)p_port->i_port_index, i );
- omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
+ omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
CHECK_ERROR(omx_error, "Wait for PortEnable failed (%x)", omx_error );
PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->in.i_port_index);
OMX_BUFFERHEADERTYPE *p_header;
block_t *p_block;
+ int i_input_used = 0;
+ struct H264ConvertState convert_state = { 0, 0 };
if( !pp_block || !*pp_block )
return NULL;
OMX_FillThisBuffer(p_sys->omx_handle, p_header);
}
+more_input:
/* Send the input buffer to the component */
OMX_FIFO_GET_TIMEOUT(&p_sys->in.fifo, p_header, 200000);
if(p_header)
{
- p_header->nFilledLen = p_block->i_buffer;
+ bool decode_more = false;
+ p_header->nFilledLen = p_block->i_buffer - i_input_used;
p_header->nOffset = 0;
p_header->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
if (p_sys->b_use_pts && p_block->i_pts)
p_header->pOutputPortPrivate = p_header->pBuffer;
p_header->pBuffer = p_block->p_buffer;
p_header->pAppPrivate = p_block;
+ i_input_used = p_header->nFilledLen;
}
else
{
if(p_header->nFilledLen > p_header->nAllocLen)
{
- msg_Dbg(p_dec, "buffer too small (%i,%i)",
- (int)p_header->nFilledLen, (int)p_header->nAllocLen);
p_header->nFilledLen = p_header->nAllocLen;
}
- memcpy(p_header->pBuffer, p_block->p_buffer, p_header->nFilledLen );
- block_Release(p_block);
+ memcpy(p_header->pBuffer, p_block->p_buffer + i_input_used, p_header->nFilledLen);
+ i_input_used += p_header->nFilledLen;
+ if (i_input_used == p_block->i_buffer)
+ {
+ block_Release(p_block);
+ }
+ else
+ {
+ decode_more = true;
+ p_header->nFlags &= ~OMX_BUFFERFLAG_ENDOFFRAME;
+ }
}
/* Convert H.264 NAL format to annex b. Doesn't do anything if
* i_nal_size_length == 0, which is the case for codecs other
* than H.264 */
convert_h264_to_annexb( p_header->pBuffer, p_header->nFilledLen,
- p_sys->i_nal_size_length );
+ p_sys->i_nal_size_length, &convert_state );
#ifdef OMXIL_EXTRA_DEBUG
- msg_Dbg( p_dec, "EmptyThisBuffer %p, %p, %i", p_header, p_header->pBuffer,
- (int)p_header->nFilledLen );
+ msg_Dbg( p_dec, "EmptyThisBuffer %p, %p, %i, %"PRId64, p_header, p_header->pBuffer,
+ (int)p_header->nFilledLen, FromOmxTicks(p_header->nTimeStamp) );
#endif
OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
p_sys->in.b_flushed = false;
- *pp_block = NULL; /* Avoid being fed the same packet again */
+ if (decode_more)
+ goto more_input;
+ else
+ *pp_block = NULL; /* Avoid being fed the same packet again */
}
reconfig:
DeinitOmxCore();
- vlc_mutex_destroy (&p_sys->mutex);
- vlc_cond_destroy (&p_sys->cond);
+ DeinitOmxEventQueue(&p_sys->event_queue);
vlc_mutex_destroy (&p_sys->in.fifo.lock);
vlc_cond_destroy (&p_sys->in.fifo.wait);
vlc_mutex_destroy (&p_sys->out.fifo.lock);
unsigned int i;
(void)omx_handle;
+ PrintOmxEvent((vlc_object_t *) p_dec, event, data_1, data_2, event_data);
switch (event)
{
- case OMX_EventCmdComplete:
- switch ((OMX_STATETYPE)data_1)
- {
- case OMX_CommandStateSet:
- msg_Dbg( p_dec, "OmxEventHandler (%s, %s, %s)", EventToString(event),
- CommandToString(data_1), StateToString(data_2) );
- break;
-
- default:
- msg_Dbg( p_dec, "OmxEventHandler (%s, %s, %u)", EventToString(event),
- CommandToString(data_1), (unsigned int)data_2 );
- break;
- }
- break;
-
case OMX_EventError:
- msg_Dbg( p_dec, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event),
- ErrorToString((OMX_ERRORTYPE)data_1), (unsigned int)data_2,
- (const char *)event_data);
//p_sys->b_error = true;
break;
case OMX_EventPortSettingsChanged:
- msg_Dbg( p_dec, "OmxEventHandler (%s, %u, %u)", EventToString(event),
- (unsigned int)data_1, (unsigned int)data_2 );
- if( data_2 == 0 || data_2 == OMX_IndexParamPortDefinition )
+ if( data_2 == 0 || data_2 == OMX_IndexParamPortDefinition ||
+ data_2 == OMX_IndexParamAudioPcm )
{
OMX_BUFFERHEADERTYPE *sentinel;
for(i = 0; i < p_sys->ports; i++)
msg_Dbg( p_dec, "Unhandled setting change %x", (unsigned int)data_2 );
}
break;
+ case OMX_EventParamOrConfigChanged:
+ UpdatePixelAspect(p_dec);
+ break;
default:
- msg_Dbg( p_dec, "OmxEventHandler (%s, %u, %u)", EventToString(event),
- (unsigned int)data_1, (unsigned int)data_2 );
break;
}
- PostOmxEvent(p_dec, event, data_1, data_2, event_data);
+ PostOmxEvent(&p_sys->event_queue, event, data_1, data_2, event_data);
return OMX_ErrorNone;
}
(void)omx_handle;
#ifdef OMXIL_EXTRA_DEBUG
- msg_Dbg( p_dec, "OmxFillBufferDone %p, %p, %i", omx_header, omx_header->pBuffer,
- (int)omx_header->nFilledLen );
+ msg_Dbg( p_dec, "OmxFillBufferDone %p, %p, %i, %"PRId64, omx_header, omx_header->pBuffer,
+ (int)omx_header->nFilledLen, FromOmxTicks(omx_header->nTimeStamp) );
#endif
if(omx_header->pInputPortPrivate)