#include "pipe/p_video_codec.h"
#include "util/u_memory.h"
#include "util/u_surface.h"
+#include "vl/vl_video_buffer.h"
#include "vl/vl_vlc.h"
#include "entrypoint.h"
r = omx_base_filter_Constructor(comp, name);
if (r)
- return r;
+ return r;
priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN;
return OMX_ErrorInsufficientResources;
screen = priv->screen->pscreen;
- priv->pipe = screen->context_create(screen, priv->screen);
+ priv->pipe = screen->context_create(screen, priv->screen, 0);
if (!priv->pipe)
return OMX_ErrorInsufficientResources;
+ if (!vl_compositor_init(&priv->compositor, priv->pipe)) {
+ priv->pipe->destroy(priv->pipe);
+ priv->pipe = NULL;
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) {
+ vl_compositor_cleanup(&priv->compositor);
+ priv->pipe->destroy(priv->pipe);
+ priv->pipe = NULL;
+ return OMX_ErrorInsufficientResources;
+ }
+
priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0;
priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2;
priv->ports = CALLOC(2, sizeof(omx_base_PortType *));
priv->ports=NULL;
}
- if (priv->pipe)
+ if (priv->pipe) {
+ vl_compositor_cleanup_state(&priv->cstate);
+ vl_compositor_cleanup(&priv->compositor);
priv->pipe->destroy(priv->pipe);
+ }
if (priv->screen)
omx_put_screen();
r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE));
if (r)
return r;
-
+
if (!strcmp((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE)) {
priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN;
} else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AVC_ROLE)) {
strcpy((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE);
else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH)
strcpy((char *)role->cRole, OMX_VID_DEC_AVC_ROLE);
-
+
break;
}
void vid_dec_NeedTarget(vid_dec_PrivateType *priv)
{
struct pipe_video_buffer templat = {};
+ struct vl_screen *omx_screen;
+ struct pipe_screen *pscreen;
omx_base_video_PortType *port;
+ omx_screen = priv->screen;
port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
+ assert(omx_screen);
+ assert(port);
+
+ pscreen = omx_screen->pscreen;
+
+ assert(pscreen);
+
if (!priv->target) {
- templat.buffer_format = PIPE_FORMAT_NV12;
+ memset(&templat, 0, sizeof(templat));
+
templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
templat.width = port->sPortParam.format.video.nFrameWidth;
templat.height = port->sPortParam.format.video.nFrameHeight;
- templat.interlaced = false;
+ templat.buffer_format = pscreen->get_video_param(
+ pscreen,
+ PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+ PIPE_VIDEO_CAP_PREFERED_FORMAT
+ );
+ templat.interlaced = pscreen->get_video_param(
+ pscreen,
+ PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+ PIPE_VIDEO_CAP_PREFERS_INTERLACED
+ );
priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat);
}
}
priv->in_buffers[i] = buf;
priv->sizes[i] = buf->nFilledLen;
priv->inputs[i] = buf->pBuffer;
+ priv->timestamps[i] = buf->nTimeStamp;
while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) {
bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS);
priv->in_buffers[0] = priv->in_buffers[1];
priv->sizes[0] = priv->sizes[1] - delta;
priv->inputs[0] = priv->inputs[1] + delta;
+ priv->timestamps[0] = priv->timestamps[1];
}
if (r)
return r;
}
-
+
return OMX_ErrorNone;
}
OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video;
struct pipe_sampler_view **views;
- struct pipe_transfer *transfer;
- struct pipe_box box = { };
- uint8_t *src, *dst;
+ unsigned i, j;
+ unsigned width, height;
views = buf->get_sampler_view_planes(buf);
- dst = output->pBuffer;
+ for (i = 0; i < 2 /* NV12 */; i++) {
+ if (!views[i]) continue;
+ width = def->nFrameWidth;
+ height = def->nFrameHeight;
+ vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced);
+ for (j = 0; j < views[i]->texture->array_size; ++j) {
+ struct pipe_box box = {0, 0, j, width, height, 1};
+ struct pipe_transfer *transfer;
+ uint8_t *map, *dst;
+ map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0,
+ PIPE_TRANSFER_READ, &box, &transfer);
+ if (!map)
+ return;
+
+ dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride +
+ i * def->nFrameWidth * def->nFrameHeight;
+ util_copy_rect(dst,
+ views[i]->texture->format,
+ def->nStride * views[i]->texture->array_size, 0, 0,
+ box.width, box.height, map, transfer->stride, 0, 0);
+
+ pipe_transfer_unmap(priv->pipe, transfer);
+ }
+ }
+}
+
+static void vid_dec_deint(vid_dec_PrivateType *priv, struct pipe_video_buffer *src_buf,
+ struct pipe_video_buffer *dst_buf)
+{
+ struct vl_compositor *compositor = &priv->compositor;
+ struct vl_compositor_state *s = &priv->cstate;
+ struct pipe_surface **dst_surface;
+ struct u_rect dst_rect;
+
+ dst_surface = dst_buf->get_surfaces(dst_buf);
+ vl_compositor_clear_layers(s);
- box.width = def->nFrameWidth;
- box.height = def->nFrameHeight;
- box.depth = 1;
+ dst_rect.x0 = 0;
+ dst_rect.x1 = src_buf->width;
+ dst_rect.y0 = 0;
+ dst_rect.y1 = src_buf->height;
- src = priv->pipe->transfer_map(priv->pipe, views[0]->texture, 0,
- PIPE_TRANSFER_READ, &box, &transfer);
- util_copy_rect(dst, views[0]->texture->format, def->nStride, 0, 0,
- box.width, box.height, src, transfer->stride, 0, 0);
- pipe_transfer_unmap(priv->pipe, transfer);
+ vl_compositor_set_yuv_layer(s, compositor, 0, src_buf, NULL, NULL, true);
+ vl_compositor_set_layer_dst_area(s, 0, &dst_rect);
+ vl_compositor_render(s, compositor, dst_surface[0], NULL, false);
- dst = ((uint8_t*)output->pBuffer) + (def->nStride * box.height);
+ dst_rect.x1 /= 2;
+ dst_rect.y1 /= 2;
- box.width = def->nFrameWidth / 2;
- box.height = def->nFrameHeight / 2;
-
- src = priv->pipe->transfer_map(priv->pipe, views[1]->texture, 0,
- PIPE_TRANSFER_READ, &box, &transfer);
- util_copy_rect(dst, views[1]->texture->format, def->nStride, 0, 0,
- box.width, box.height, src, transfer->stride, 0, 0);
- pipe_transfer_unmap(priv->pipe, transfer);
+ vl_compositor_set_yuv_layer(s, compositor, 0, src_buf, NULL, NULL, false);
+ vl_compositor_set_layer_dst_area(s, 0, &dst_rect);
+ vl_compositor_render(s, compositor, dst_surface[1], NULL, false);
}
static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input,
{
vid_dec_PrivateType *priv = comp->pComponentPrivate;
bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS);
+ OMX_TICKS timestamp;
- if (!input->pInputPortPrivate)
- input->pInputPortPrivate = priv->Flush(priv);
+ if (!input->pInputPortPrivate) {
+ input->pInputPortPrivate = priv->Flush(priv, ×tamp);
+ if (timestamp != OMX_VID_DEC_TIMESTAMP_INVALID)
+ input->nTimeStamp = timestamp;
+ }
if (input->pInputPortPrivate) {
if (output->pInputPortPrivate) {
- struct pipe_video_buffer *tmp = output->pOutputPortPrivate;
+ struct pipe_video_buffer *tmp, *vbuf, *new_vbuf;
+
+ tmp = output->pOutputPortPrivate;
+ vbuf = input->pInputPortPrivate;
+ if (vbuf->interlaced) {
+ /* re-allocate the progressive buffer */
+ omx_base_video_PortType *port;
+ struct pipe_video_buffer templat = {};
+
+ port = (omx_base_video_PortType *)
+ priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
+ memset(&templat, 0, sizeof(templat));
+ templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
+ templat.width = port->sPortParam.format.video.nFrameWidth;
+ templat.height = port->sPortParam.format.video.nFrameHeight;
+ templat.buffer_format = PIPE_FORMAT_NV12;
+ templat.interlaced = false;
+ new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat);
+
+ /* convert the interlaced to the progressive */
+ vid_dec_deint(priv, input->pInputPortPrivate, new_vbuf);
+ priv->pipe->flush(priv->pipe, NULL, 0);
+
+ /* set the progrssive buffer for next round */
+ vbuf->destroy(vbuf);
+ input->pInputPortPrivate = new_vbuf;
+ }
output->pOutputPortPrivate = input->pInputPortPrivate;
input->pInputPortPrivate = tmp;
} else {
vid_dec_FillOutput(priv, input->pInputPortPrivate, output);
}
output->nFilledLen = output->nAllocLen;
+ output->nTimeStamp = input->nTimeStamp;
}
if (eos && input->pInputPortPrivate)