1 /**************************************************************************
3 * Copyright 2013 Advanced Micro Devices, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Christian König <christian.koenig@amd.com>
37 #include <OMX_Video.h>
39 /* bellagio defines a DEBUG macro that we don't want */
41 #include <bellagio/omxcore.h>
44 #include <bellagio/omxcore.h>
47 #include "pipe/p_screen.h"
48 #include "pipe/p_video_codec.h"
49 #include "util/u_memory.h"
50 #include "util/u_surface.h"
51 #include "vl/vl_video_buffer.h"
52 #include "vl/vl_vlc.h"
54 #include "entrypoint.h"
57 static OMX_ERRORTYPE
vid_dec_Constructor(OMX_COMPONENTTYPE
*comp
, OMX_STRING name
);
58 static OMX_ERRORTYPE
vid_dec_Destructor(OMX_COMPONENTTYPE
*comp
);
59 static OMX_ERRORTYPE
vid_dec_SetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
);
60 static OMX_ERRORTYPE
vid_dec_GetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
);
61 static OMX_ERRORTYPE
vid_dec_MessageHandler(OMX_COMPONENTTYPE
*comp
, internalRequestMessageType
*msg
);
62 static OMX_ERRORTYPE
vid_dec_DecodeBuffer(omx_base_PortType
*port
, OMX_BUFFERHEADERTYPE
*buf
);
63 static OMX_ERRORTYPE
vid_dec_FreeDecBuffer(omx_base_PortType
*port
, OMX_U32 idx
, OMX_BUFFERHEADERTYPE
*buf
);
64 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE
*comp
, OMX_BUFFERHEADERTYPE
* input
, OMX_BUFFERHEADERTYPE
* output
);
66 OMX_ERRORTYPE
vid_dec_LoaderComponent(stLoaderComponentType
*comp
)
68 comp
->componentVersion
.s
.nVersionMajor
= 0;
69 comp
->componentVersion
.s
.nVersionMinor
= 0;
70 comp
->componentVersion
.s
.nRevision
= 0;
71 comp
->componentVersion
.s
.nStep
= 1;
72 comp
->name_specific_length
= 2;
74 comp
->name
= CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
75 if (comp
->name
== NULL
)
78 comp
->name_specific
= CALLOC(comp
->name_specific_length
, sizeof(char *));
79 if (comp
->name_specific
== NULL
)
82 comp
->role_specific
= CALLOC(comp
->name_specific_length
, sizeof(char *));
83 if (comp
->role_specific
== NULL
)
86 comp
->name_specific
[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
87 if (comp
->name_specific
[0] == NULL
)
90 comp
->name_specific
[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
91 if (comp
->name_specific
[1] == NULL
)
94 comp
->role_specific
[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
95 if (comp
->role_specific
[0] == NULL
)
98 comp
->role_specific
[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
99 if (comp
->role_specific
[1] == NULL
)
102 strcpy(comp
->name
, OMX_VID_DEC_BASE_NAME
);
103 strcpy(comp
->name_specific
[0], OMX_VID_DEC_MPEG2_NAME
);
104 strcpy(comp
->name_specific
[1], OMX_VID_DEC_AVC_NAME
);
106 strcpy(comp
->role_specific
[0], OMX_VID_DEC_MPEG2_ROLE
);
107 strcpy(comp
->role_specific
[1], OMX_VID_DEC_AVC_ROLE
);
109 comp
->constructor
= vid_dec_Constructor
;
111 return OMX_ErrorNone
;
114 FREE(comp
->role_specific
[1]);
115 FREE(comp
->role_specific
[0]);
116 FREE(comp
->name_specific
[1]);
117 FREE(comp
->name_specific
[0]);
120 FREE(comp
->role_specific
);
121 FREE(comp
->name_specific
);
125 return OMX_ErrorInsufficientResources
;
128 static OMX_ERRORTYPE
vid_dec_Constructor(OMX_COMPONENTTYPE
*comp
, OMX_STRING name
)
130 vid_dec_PrivateType
*priv
;
131 omx_base_video_PortType
*port
;
132 struct pipe_screen
*screen
;
136 assert(!comp
->pComponentPrivate
);
138 priv
= comp
->pComponentPrivate
= CALLOC(1, sizeof(vid_dec_PrivateType
));
140 return OMX_ErrorInsufficientResources
;
142 r
= omx_base_filter_Constructor(comp
, name
);
146 priv
->profile
= PIPE_VIDEO_PROFILE_UNKNOWN
;
148 if (!strcmp(name
, OMX_VID_DEC_MPEG2_NAME
))
149 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
151 if (!strcmp(name
, OMX_VID_DEC_AVC_NAME
))
152 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
;
154 priv
->BufferMgmtCallback
= vid_dec_FrameDecoded
;
155 priv
->messageHandler
= vid_dec_MessageHandler
;
156 priv
->destructor
= vid_dec_Destructor
;
158 comp
->SetParameter
= vid_dec_SetParameter
;
159 comp
->GetParameter
= vid_dec_GetParameter
;
161 priv
->screen
= omx_get_screen();
163 return OMX_ErrorInsufficientResources
;
165 screen
= priv
->screen
->pscreen
;
166 priv
->pipe
= screen
->context_create(screen
, priv
->screen
, 0);
168 return OMX_ErrorInsufficientResources
;
170 if (!vl_compositor_init(&priv
->compositor
, priv
->pipe
)) {
171 priv
->pipe
->destroy(priv
->pipe
);
173 return OMX_ErrorInsufficientResources
;
176 if (!vl_compositor_init_state(&priv
->cstate
, priv
->pipe
)) {
177 vl_compositor_cleanup(&priv
->compositor
);
178 priv
->pipe
->destroy(priv
->pipe
);
180 return OMX_ErrorInsufficientResources
;
183 priv
->sPortTypesParam
[OMX_PortDomainVideo
].nStartPortNumber
= 0;
184 priv
->sPortTypesParam
[OMX_PortDomainVideo
].nPorts
= 2;
185 priv
->ports
= CALLOC(2, sizeof(omx_base_PortType
*));
187 return OMX_ErrorInsufficientResources
;
189 for (i
= 0; i
< 2; ++i
) {
190 priv
->ports
[i
] = CALLOC(1, sizeof(omx_base_video_PortType
));
192 return OMX_ErrorInsufficientResources
;
194 base_video_port_Constructor(comp
, &priv
->ports
[i
], i
, i
== 0);
197 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
198 strcpy(port
->sPortParam
.format
.video
.cMIMEType
,"video/MPEG2");
199 port
->sPortParam
.nBufferCountMin
= 8;
200 port
->sPortParam
.nBufferCountActual
= 8;
201 port
->sPortParam
.nBufferSize
= DEFAULT_OUT_BUFFER_SIZE
;
202 port
->sPortParam
.format
.video
.nFrameWidth
= 176;
203 port
->sPortParam
.format
.video
.nFrameHeight
= 144;
204 port
->sPortParam
.format
.video
.eCompressionFormat
= OMX_VIDEO_CodingMPEG2
;
205 port
->sVideoParam
.eCompressionFormat
= OMX_VIDEO_CodingMPEG2
;
206 port
->Port_SendBufferFunction
= vid_dec_DecodeBuffer
;
207 port
->Port_FreeBuffer
= vid_dec_FreeDecBuffer
;
209 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
210 port
->sPortParam
.nBufferCountActual
= 8;
211 port
->sPortParam
.nBufferCountMin
= 4;
212 port
->sPortParam
.format
.video
.nFrameWidth
= 176;
213 port
->sPortParam
.format
.video
.nFrameHeight
= 144;
214 port
->sPortParam
.format
.video
.eColorFormat
= OMX_COLOR_FormatYUV420SemiPlanar
;
215 port
->sVideoParam
.eColorFormat
= OMX_COLOR_FormatYUV420SemiPlanar
;
217 return OMX_ErrorNone
;
220 static OMX_ERRORTYPE
vid_dec_Destructor(OMX_COMPONENTTYPE
*comp
)
222 vid_dec_PrivateType
* priv
= comp
->pComponentPrivate
;
226 for (i
= 0; i
< priv
->sPortTypesParam
[OMX_PortDomainVideo
].nPorts
; ++i
) {
228 priv
->ports
[i
]->PortDestructor(priv
->ports
[i
]);
235 vl_compositor_cleanup_state(&priv
->cstate
);
236 vl_compositor_cleanup(&priv
->compositor
);
237 priv
->pipe
->destroy(priv
->pipe
);
243 return omx_workaround_Destructor(comp
);
246 static OMX_ERRORTYPE
vid_dec_SetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
)
248 OMX_COMPONENTTYPE
*comp
= handle
;
249 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
253 return OMX_ErrorBadParameter
;
256 case OMX_IndexParamPortDefinition
: {
257 OMX_PARAM_PORTDEFINITIONTYPE
*def
= param
;
259 r
= omx_base_component_SetParameter(handle
, idx
, param
);
263 if (def
->nPortIndex
== OMX_BASE_FILTER_INPUTPORT_INDEX
) {
264 omx_base_video_PortType
*port
;
265 unsigned framesize
= def
->format
.video
.nFrameWidth
* def
->format
.video
.nFrameHeight
;
267 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
268 port
->sPortParam
.nBufferSize
= framesize
* 512 / (16*16);
270 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
271 port
->sPortParam
.format
.video
.nFrameWidth
= def
->format
.video
.nFrameWidth
;
272 port
->sPortParam
.format
.video
.nFrameHeight
= def
->format
.video
.nFrameHeight
;
273 port
->sPortParam
.format
.video
.nStride
= def
->format
.video
.nFrameWidth
;
274 port
->sPortParam
.format
.video
.nSliceHeight
= def
->format
.video
.nFrameHeight
;
275 port
->sPortParam
.nBufferSize
= framesize
*3/2;
277 priv
->callbacks
->EventHandler(comp
, priv
->callbackData
, OMX_EventPortSettingsChanged
,
278 OMX_BASE_FILTER_OUTPUTPORT_INDEX
, 0, NULL
);
282 case OMX_IndexParamStandardComponentRole
: {
283 OMX_PARAM_COMPONENTROLETYPE
*role
= param
;
285 r
= checkHeader(param
, sizeof(OMX_PARAM_COMPONENTROLETYPE
));
289 if (!strcmp((char *)role
->cRole
, OMX_VID_DEC_MPEG2_ROLE
)) {
290 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
291 } else if (!strcmp((char *)role
->cRole
, OMX_VID_DEC_AVC_ROLE
)) {
292 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
;
294 return OMX_ErrorBadParameter
;
299 case OMX_IndexParamVideoPortFormat
: {
300 OMX_VIDEO_PARAM_PORTFORMATTYPE
*format
= param
;
301 omx_base_video_PortType
*port
;
303 r
= checkHeader(param
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
307 if (format
->nPortIndex
> 1)
308 return OMX_ErrorBadPortIndex
;
310 port
= (omx_base_video_PortType
*)priv
->ports
[format
->nPortIndex
];
311 memcpy(&port
->sVideoParam
, format
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
315 return omx_base_component_SetParameter(handle
, idx
, param
);
317 return OMX_ErrorNone
;
320 static OMX_ERRORTYPE
vid_dec_GetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
)
322 OMX_COMPONENTTYPE
*comp
= handle
;
323 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
327 return OMX_ErrorBadParameter
;
330 case OMX_IndexParamStandardComponentRole
: {
331 OMX_PARAM_COMPONENTROLETYPE
*role
= param
;
333 r
= checkHeader(param
, sizeof(OMX_PARAM_COMPONENTROLETYPE
));
337 if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG2_MAIN
)
338 strcpy((char *)role
->cRole
, OMX_VID_DEC_MPEG2_ROLE
);
339 else if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
)
340 strcpy((char *)role
->cRole
, OMX_VID_DEC_AVC_ROLE
);
345 case OMX_IndexParamVideoInit
:
346 r
= checkHeader(param
, sizeof(OMX_PORT_PARAM_TYPE
));
350 memcpy(param
, &priv
->sPortTypesParam
[OMX_PortDomainVideo
], sizeof(OMX_PORT_PARAM_TYPE
));
353 case OMX_IndexParamVideoPortFormat
: {
354 OMX_VIDEO_PARAM_PORTFORMATTYPE
*format
= param
;
355 omx_base_video_PortType
*port
;
357 r
= checkHeader(param
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
361 if (format
->nPortIndex
> 1)
362 return OMX_ErrorBadPortIndex
;
364 port
= (omx_base_video_PortType
*)priv
->ports
[format
->nPortIndex
];
365 memcpy(format
, &port
->sVideoParam
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
370 return omx_base_component_GetParameter(handle
, idx
, param
);
373 return OMX_ErrorNone
;
376 static OMX_ERRORTYPE
vid_dec_MessageHandler(OMX_COMPONENTTYPE
* comp
, internalRequestMessageType
*msg
)
378 vid_dec_PrivateType
* priv
= comp
->pComponentPrivate
;
380 if (msg
->messageType
== OMX_CommandStateSet
) {
381 if ((msg
->messageParam
== OMX_StateIdle
) && (priv
->state
== OMX_StateLoaded
)) {
382 if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG2_MAIN
)
383 vid_dec_mpeg12_Init(priv
);
384 else if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
)
385 vid_dec_h264_Init(priv
);
387 } else if ((msg
->messageParam
== OMX_StateLoaded
) && (priv
->state
== OMX_StateIdle
)) {
389 priv
->shadow
->destroy(priv
->shadow
);
393 priv
->codec
->destroy(priv
->codec
);
399 return omx_base_component_MessageHandler(comp
, msg
);
402 void vid_dec_NeedTarget(vid_dec_PrivateType
*priv
)
404 struct pipe_video_buffer templat
= {};
405 struct vl_screen
*omx_screen
;
406 struct pipe_screen
*pscreen
;
407 omx_base_video_PortType
*port
;
409 omx_screen
= priv
->screen
;
410 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
415 pscreen
= omx_screen
->pscreen
;
420 memset(&templat
, 0, sizeof(templat
));
422 templat
.chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
423 templat
.width
= port
->sPortParam
.format
.video
.nFrameWidth
;
424 templat
.height
= port
->sPortParam
.format
.video
.nFrameHeight
;
425 templat
.buffer_format
= pscreen
->get_video_param(
427 PIPE_VIDEO_PROFILE_UNKNOWN
,
428 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
429 PIPE_VIDEO_CAP_PREFERED_FORMAT
431 templat
.interlaced
= pscreen
->get_video_param(
433 PIPE_VIDEO_PROFILE_UNKNOWN
,
434 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
435 PIPE_VIDEO_CAP_PREFERS_INTERLACED
437 priv
->target
= priv
->pipe
->create_video_buffer(priv
->pipe
, &templat
);
441 static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE
*buf
)
443 struct pipe_video_buffer
*vbuf
= buf
->pInputPortPrivate
;
448 buf
->pInputPortPrivate
= NULL
;
451 static OMX_ERRORTYPE
vid_dec_DecodeBuffer(omx_base_PortType
*port
, OMX_BUFFERHEADERTYPE
*buf
)
453 OMX_COMPONENTTYPE
* comp
= port
->standCompContainer
;
454 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
455 unsigned i
= priv
->num_in_buffers
++;
458 priv
->in_buffers
[i
] = buf
;
459 priv
->sizes
[i
] = buf
->nFilledLen
;
460 priv
->inputs
[i
] = buf
->pBuffer
;
461 priv
->timestamps
[i
] = buf
->nTimeStamp
;
463 while (priv
->num_in_buffers
> (!!(buf
->nFlags
& OMX_BUFFERFLAG_EOS
) ? 0 : 1)) {
464 bool eos
= !!(priv
->in_buffers
[0]->nFlags
& OMX_BUFFERFLAG_EOS
);
465 unsigned min_bits_left
= eos
? 32 : MAX2(buf
->nFilledLen
* 8, 32);
468 vl_vlc_init(&vlc
, priv
->num_in_buffers
, priv
->inputs
, priv
->sizes
);
471 priv
->bytes_left
= vl_vlc_bits_left(&vlc
) / 8;
473 while (vl_vlc_bits_left(&vlc
) > min_bits_left
) {
474 priv
->Decode(priv
, &vlc
, min_bits_left
);
475 vl_vlc_fillbits(&vlc
);
479 unsigned bytes
= priv
->bytes_left
- vl_vlc_bits_left(&vlc
) / 8;
481 priv
->codec
->decode_bitstream(priv
->codec
, priv
->target
, &priv
->picture
.base
,
482 1, &priv
->slice
, &bytes
);
484 if (priv
->num_in_buffers
)
485 priv
->slice
= priv
->inputs
[1];
490 if (eos
&& priv
->frame_started
)
491 priv
->EndFrame(priv
);
493 if (priv
->frame_finished
) {
494 priv
->frame_finished
= false;
495 priv
->in_buffers
[0]->nFilledLen
= priv
->in_buffers
[0]->nAllocLen
;
496 r
= base_port_SendBufferFunction(port
, priv
->in_buffers
[0]);
498 vid_dec_FreeInputPortPrivate(priv
->in_buffers
[0]);
499 priv
->in_buffers
[0]->nFilledLen
= priv
->in_buffers
[0]->nAllocLen
;
500 r
= base_port_SendBufferFunction(port
, priv
->in_buffers
[0]);
502 priv
->in_buffers
[0]->nFilledLen
= 0;
503 r
= port
->ReturnBufferFunction(port
, priv
->in_buffers
[0]);
506 if (--priv
->num_in_buffers
) {
507 unsigned delta
= MIN2((min_bits_left
- vl_vlc_bits_left(&vlc
)) / 8, priv
->sizes
[1]);
509 priv
->in_buffers
[0] = priv
->in_buffers
[1];
510 priv
->sizes
[0] = priv
->sizes
[1] - delta
;
511 priv
->inputs
[0] = priv
->inputs
[1] + delta
;
512 priv
->timestamps
[0] = priv
->timestamps
[1];
519 return OMX_ErrorNone
;
522 static OMX_ERRORTYPE
vid_dec_FreeDecBuffer(omx_base_PortType
*port
, OMX_U32 idx
, OMX_BUFFERHEADERTYPE
*buf
)
524 vid_dec_FreeInputPortPrivate(buf
);
525 return base_port_FreeBuffer(port
, idx
, buf
);
528 static void vid_dec_FillOutput(vid_dec_PrivateType
*priv
, struct pipe_video_buffer
*buf
,
529 OMX_BUFFERHEADERTYPE
* output
)
531 omx_base_PortType
*port
= priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
532 OMX_VIDEO_PORTDEFINITIONTYPE
*def
= &port
->sPortParam
.format
.video
;
534 struct pipe_sampler_view
**views
;
536 unsigned width
, height
;
538 views
= buf
->get_sampler_view_planes(buf
);
540 for (i
= 0; i
< 2 /* NV12 */; i
++) {
541 if (!views
[i
]) continue;
542 width
= def
->nFrameWidth
;
543 height
= def
->nFrameHeight
;
544 vl_video_buffer_adjust_size(&width
, &height
, i
, buf
->chroma_format
, buf
->interlaced
);
545 for (j
= 0; j
< views
[i
]->texture
->array_size
; ++j
) {
546 struct pipe_box box
= {0, 0, j
, width
, height
, 1};
547 struct pipe_transfer
*transfer
;
549 map
= priv
->pipe
->transfer_map(priv
->pipe
, views
[i
]->texture
, 0,
550 PIPE_TRANSFER_READ
, &box
, &transfer
);
554 dst
= ((uint8_t*)output
->pBuffer
+ output
->nOffset
) + j
* def
->nStride
+
555 i
* def
->nFrameWidth
* def
->nFrameHeight
;
557 views
[i
]->texture
->format
,
558 def
->nStride
* views
[i
]->texture
->array_size
, 0, 0,
559 box
.width
, box
.height
, map
, transfer
->stride
, 0, 0);
561 pipe_transfer_unmap(priv
->pipe
, transfer
);
566 static void vid_dec_deint(vid_dec_PrivateType
*priv
, struct pipe_video_buffer
*src_buf
,
567 struct pipe_video_buffer
*dst_buf
)
569 struct vl_compositor
*compositor
= &priv
->compositor
;
570 struct vl_compositor_state
*s
= &priv
->cstate
;
571 struct pipe_surface
**dst_surface
;
572 struct u_rect dst_rect
;
574 dst_surface
= dst_buf
->get_surfaces(dst_buf
);
575 vl_compositor_clear_layers(s
);
578 dst_rect
.x1
= src_buf
->width
;
580 dst_rect
.y1
= src_buf
->height
;
582 vl_compositor_set_yuv_layer(s
, compositor
, 0, src_buf
, NULL
, NULL
, true);
583 vl_compositor_set_layer_dst_area(s
, 0, &dst_rect
);
584 vl_compositor_render(s
, compositor
, dst_surface
[0], NULL
, false);
589 vl_compositor_set_yuv_layer(s
, compositor
, 0, src_buf
, NULL
, NULL
, false);
590 vl_compositor_set_layer_dst_area(s
, 0, &dst_rect
);
591 vl_compositor_render(s
, compositor
, dst_surface
[1], NULL
, false);
594 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE
*comp
, OMX_BUFFERHEADERTYPE
* input
,
595 OMX_BUFFERHEADERTYPE
* output
)
597 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
598 bool eos
= !!(input
->nFlags
& OMX_BUFFERFLAG_EOS
);
601 if (!input
->pInputPortPrivate
) {
602 input
->pInputPortPrivate
= priv
->Flush(priv
, ×tamp
);
603 if (timestamp
!= OMX_VID_DEC_TIMESTAMP_INVALID
)
604 input
->nTimeStamp
= timestamp
;
607 if (input
->pInputPortPrivate
) {
608 if (output
->pInputPortPrivate
) {
609 struct pipe_video_buffer
*tmp
, *vbuf
, *new_vbuf
;
611 tmp
= output
->pOutputPortPrivate
;
612 vbuf
= input
->pInputPortPrivate
;
613 if (vbuf
->interlaced
) {
614 /* re-allocate the progressive buffer */
615 omx_base_video_PortType
*port
;
616 struct pipe_video_buffer templat
= {};
618 port
= (omx_base_video_PortType
*)
619 priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
620 memset(&templat
, 0, sizeof(templat
));
621 templat
.chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
622 templat
.width
= port
->sPortParam
.format
.video
.nFrameWidth
;
623 templat
.height
= port
->sPortParam
.format
.video
.nFrameHeight
;
624 templat
.buffer_format
= PIPE_FORMAT_NV12
;
625 templat
.interlaced
= false;
626 new_vbuf
= priv
->pipe
->create_video_buffer(priv
->pipe
, &templat
);
628 /* convert the interlaced to the progressive */
629 vid_dec_deint(priv
, input
->pInputPortPrivate
, new_vbuf
);
630 priv
->pipe
->flush(priv
->pipe
, NULL
, 0);
632 /* set the progrssive buffer for next round */
634 input
->pInputPortPrivate
= new_vbuf
;
636 output
->pOutputPortPrivate
= input
->pInputPortPrivate
;
637 input
->pInputPortPrivate
= tmp
;
639 vid_dec_FillOutput(priv
, input
->pInputPortPrivate
, output
);
641 output
->nFilledLen
= output
->nAllocLen
;
642 output
->nTimeStamp
= input
->nTimeStamp
;
645 if (eos
&& input
->pInputPortPrivate
)
646 vid_dec_FreeInputPortPrivate(input
);
648 input
->nFilledLen
= 0;