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
= 3;
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
->name_specific
[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
95 if (comp
->name_specific
[2] == NULL
)
98 comp
->role_specific
[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
99 if (comp
->role_specific
[0] == NULL
)
102 comp
->role_specific
[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
103 if (comp
->role_specific
[1] == NULL
)
106 comp
->role_specific
[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
107 if (comp
->role_specific
[2] == NULL
)
110 strcpy(comp
->name
, OMX_VID_DEC_BASE_NAME
);
111 strcpy(comp
->name_specific
[0], OMX_VID_DEC_MPEG2_NAME
);
112 strcpy(comp
->name_specific
[1], OMX_VID_DEC_AVC_NAME
);
113 strcpy(comp
->name_specific
[2], OMX_VID_DEC_HEVC_NAME
);
115 strcpy(comp
->role_specific
[0], OMX_VID_DEC_MPEG2_ROLE
);
116 strcpy(comp
->role_specific
[1], OMX_VID_DEC_AVC_ROLE
);
117 strcpy(comp
->role_specific
[2], OMX_VID_DEC_HEVC_ROLE
);
119 comp
->constructor
= vid_dec_Constructor
;
121 return OMX_ErrorNone
;
124 FREE(comp
->role_specific
[2]);
125 FREE(comp
->role_specific
[1]);
126 FREE(comp
->role_specific
[0]);
127 FREE(comp
->name_specific
[2]);
128 FREE(comp
->name_specific
[1]);
129 FREE(comp
->name_specific
[0]);
132 FREE(comp
->role_specific
);
133 FREE(comp
->name_specific
);
137 return OMX_ErrorInsufficientResources
;
140 static OMX_ERRORTYPE
vid_dec_Constructor(OMX_COMPONENTTYPE
*comp
, OMX_STRING name
)
142 vid_dec_PrivateType
*priv
;
143 omx_base_video_PortType
*port
;
144 struct pipe_screen
*screen
;
148 assert(!comp
->pComponentPrivate
);
150 priv
= comp
->pComponentPrivate
= CALLOC(1, sizeof(vid_dec_PrivateType
));
152 return OMX_ErrorInsufficientResources
;
154 r
= omx_base_filter_Constructor(comp
, name
);
158 priv
->profile
= PIPE_VIDEO_PROFILE_UNKNOWN
;
160 if (!strcmp(name
, OMX_VID_DEC_MPEG2_NAME
))
161 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
163 if (!strcmp(name
, OMX_VID_DEC_AVC_NAME
))
164 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
;
166 if (!strcmp(name
, OMX_VID_DEC_HEVC_NAME
))
167 priv
->profile
= PIPE_VIDEO_PROFILE_HEVC_MAIN
;
169 priv
->BufferMgmtCallback
= vid_dec_FrameDecoded
;
170 priv
->messageHandler
= vid_dec_MessageHandler
;
171 priv
->destructor
= vid_dec_Destructor
;
173 comp
->SetParameter
= vid_dec_SetParameter
;
174 comp
->GetParameter
= vid_dec_GetParameter
;
176 priv
->screen
= omx_get_screen();
178 return OMX_ErrorInsufficientResources
;
180 screen
= priv
->screen
->pscreen
;
181 priv
->pipe
= screen
->context_create(screen
, priv
->screen
, 0);
183 return OMX_ErrorInsufficientResources
;
185 if (!vl_compositor_init(&priv
->compositor
, priv
->pipe
)) {
186 priv
->pipe
->destroy(priv
->pipe
);
188 return OMX_ErrorInsufficientResources
;
191 if (!vl_compositor_init_state(&priv
->cstate
, priv
->pipe
)) {
192 vl_compositor_cleanup(&priv
->compositor
);
193 priv
->pipe
->destroy(priv
->pipe
);
195 return OMX_ErrorInsufficientResources
;
198 priv
->sPortTypesParam
[OMX_PortDomainVideo
].nStartPortNumber
= 0;
199 priv
->sPortTypesParam
[OMX_PortDomainVideo
].nPorts
= 2;
200 priv
->ports
= CALLOC(2, sizeof(omx_base_PortType
*));
202 return OMX_ErrorInsufficientResources
;
204 for (i
= 0; i
< 2; ++i
) {
205 priv
->ports
[i
] = CALLOC(1, sizeof(omx_base_video_PortType
));
207 return OMX_ErrorInsufficientResources
;
209 base_video_port_Constructor(comp
, &priv
->ports
[i
], i
, i
== 0);
212 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
213 strcpy(port
->sPortParam
.format
.video
.cMIMEType
,"video/MPEG2");
214 port
->sPortParam
.nBufferCountMin
= 8;
215 port
->sPortParam
.nBufferCountActual
= 8;
216 port
->sPortParam
.nBufferSize
= DEFAULT_OUT_BUFFER_SIZE
;
217 port
->sPortParam
.format
.video
.nFrameWidth
= 176;
218 port
->sPortParam
.format
.video
.nFrameHeight
= 144;
219 port
->sPortParam
.format
.video
.eCompressionFormat
= OMX_VIDEO_CodingMPEG2
;
220 port
->sVideoParam
.eCompressionFormat
= OMX_VIDEO_CodingMPEG2
;
221 port
->Port_SendBufferFunction
= vid_dec_DecodeBuffer
;
222 port
->Port_FreeBuffer
= vid_dec_FreeDecBuffer
;
224 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
225 port
->sPortParam
.nBufferCountActual
= 8;
226 port
->sPortParam
.nBufferCountMin
= 4;
227 port
->sPortParam
.format
.video
.nFrameWidth
= 176;
228 port
->sPortParam
.format
.video
.nFrameHeight
= 144;
229 port
->sPortParam
.format
.video
.eColorFormat
= OMX_COLOR_FormatYUV420SemiPlanar
;
230 port
->sVideoParam
.eColorFormat
= OMX_COLOR_FormatYUV420SemiPlanar
;
232 return OMX_ErrorNone
;
235 static OMX_ERRORTYPE
vid_dec_Destructor(OMX_COMPONENTTYPE
*comp
)
237 vid_dec_PrivateType
* priv
= comp
->pComponentPrivate
;
241 for (i
= 0; i
< priv
->sPortTypesParam
[OMX_PortDomainVideo
].nPorts
; ++i
) {
243 priv
->ports
[i
]->PortDestructor(priv
->ports
[i
]);
250 vl_compositor_cleanup_state(&priv
->cstate
);
251 vl_compositor_cleanup(&priv
->compositor
);
252 priv
->pipe
->destroy(priv
->pipe
);
258 return omx_workaround_Destructor(comp
);
261 static OMX_ERRORTYPE
vid_dec_SetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
)
263 OMX_COMPONENTTYPE
*comp
= handle
;
264 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
268 return OMX_ErrorBadParameter
;
271 case OMX_IndexParamPortDefinition
: {
272 OMX_PARAM_PORTDEFINITIONTYPE
*def
= param
;
274 r
= omx_base_component_SetParameter(handle
, idx
, param
);
278 if (def
->nPortIndex
== OMX_BASE_FILTER_INPUTPORT_INDEX
) {
279 omx_base_video_PortType
*port
;
280 unsigned framesize
= def
->format
.video
.nFrameWidth
* def
->format
.video
.nFrameHeight
;
282 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
283 port
->sPortParam
.nBufferSize
= framesize
* 512 / (16*16);
285 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
286 port
->sPortParam
.format
.video
.nFrameWidth
= def
->format
.video
.nFrameWidth
;
287 port
->sPortParam
.format
.video
.nFrameHeight
= def
->format
.video
.nFrameHeight
;
288 port
->sPortParam
.format
.video
.nStride
= def
->format
.video
.nFrameWidth
;
289 port
->sPortParam
.format
.video
.nSliceHeight
= def
->format
.video
.nFrameHeight
;
290 port
->sPortParam
.nBufferSize
= framesize
*3/2;
292 priv
->callbacks
->EventHandler(comp
, priv
->callbackData
, OMX_EventPortSettingsChanged
,
293 OMX_BASE_FILTER_OUTPUTPORT_INDEX
, 0, NULL
);
297 case OMX_IndexParamStandardComponentRole
: {
298 OMX_PARAM_COMPONENTROLETYPE
*role
= param
;
300 r
= checkHeader(param
, sizeof(OMX_PARAM_COMPONENTROLETYPE
));
304 if (!strcmp((char *)role
->cRole
, OMX_VID_DEC_MPEG2_ROLE
)) {
305 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
306 } else if (!strcmp((char *)role
->cRole
, OMX_VID_DEC_AVC_ROLE
)) {
307 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
;
308 } else if (!strcmp((char *)role
->cRole
, OMX_VID_DEC_HEVC_ROLE
)) {
309 priv
->profile
= PIPE_VIDEO_PROFILE_HEVC_MAIN
;
311 return OMX_ErrorBadParameter
;
316 case OMX_IndexParamVideoPortFormat
: {
317 OMX_VIDEO_PARAM_PORTFORMATTYPE
*format
= param
;
318 omx_base_video_PortType
*port
;
320 r
= checkHeader(param
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
324 if (format
->nPortIndex
> 1)
325 return OMX_ErrorBadPortIndex
;
327 port
= (omx_base_video_PortType
*)priv
->ports
[format
->nPortIndex
];
328 memcpy(&port
->sVideoParam
, format
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
332 return omx_base_component_SetParameter(handle
, idx
, param
);
334 return OMX_ErrorNone
;
337 static OMX_ERRORTYPE
vid_dec_GetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
)
339 OMX_COMPONENTTYPE
*comp
= handle
;
340 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
344 return OMX_ErrorBadParameter
;
347 case OMX_IndexParamStandardComponentRole
: {
348 OMX_PARAM_COMPONENTROLETYPE
*role
= param
;
350 r
= checkHeader(param
, sizeof(OMX_PARAM_COMPONENTROLETYPE
));
354 if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG2_MAIN
)
355 strcpy((char *)role
->cRole
, OMX_VID_DEC_MPEG2_ROLE
);
356 else if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
)
357 strcpy((char *)role
->cRole
, OMX_VID_DEC_AVC_ROLE
);
358 else if (priv
->profile
== PIPE_VIDEO_PROFILE_HEVC_MAIN
)
359 strcpy((char *)role
->cRole
, OMX_VID_DEC_HEVC_ROLE
);
364 case OMX_IndexParamVideoInit
:
365 r
= checkHeader(param
, sizeof(OMX_PORT_PARAM_TYPE
));
369 memcpy(param
, &priv
->sPortTypesParam
[OMX_PortDomainVideo
], sizeof(OMX_PORT_PARAM_TYPE
));
372 case OMX_IndexParamVideoPortFormat
: {
373 OMX_VIDEO_PARAM_PORTFORMATTYPE
*format
= param
;
374 omx_base_video_PortType
*port
;
376 r
= checkHeader(param
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
380 if (format
->nPortIndex
> 1)
381 return OMX_ErrorBadPortIndex
;
383 port
= (omx_base_video_PortType
*)priv
->ports
[format
->nPortIndex
];
384 memcpy(format
, &port
->sVideoParam
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
389 return omx_base_component_GetParameter(handle
, idx
, param
);
392 return OMX_ErrorNone
;
395 static OMX_ERRORTYPE
vid_dec_MessageHandler(OMX_COMPONENTTYPE
* comp
, internalRequestMessageType
*msg
)
397 vid_dec_PrivateType
* priv
= comp
->pComponentPrivate
;
399 if (msg
->messageType
== OMX_CommandStateSet
) {
400 if ((msg
->messageParam
== OMX_StateIdle
) && (priv
->state
== OMX_StateLoaded
)) {
401 if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG2_MAIN
)
402 vid_dec_mpeg12_Init(priv
);
403 else if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
)
404 vid_dec_h264_Init(priv
);
405 else if (priv
->profile
== PIPE_VIDEO_PROFILE_HEVC_MAIN
)
406 vid_dec_h265_Init(priv
);
408 } else if ((msg
->messageParam
== OMX_StateLoaded
) && (priv
->state
== OMX_StateIdle
)) {
410 priv
->shadow
->destroy(priv
->shadow
);
414 priv
->codec
->destroy(priv
->codec
);
420 return omx_base_component_MessageHandler(comp
, msg
);
423 void vid_dec_NeedTarget(vid_dec_PrivateType
*priv
)
425 struct pipe_video_buffer templat
= {};
426 struct vl_screen
*omx_screen
;
427 struct pipe_screen
*pscreen
;
429 omx_screen
= priv
->screen
;
432 pscreen
= omx_screen
->pscreen
;
436 memset(&templat
, 0, sizeof(templat
));
438 templat
.chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
439 templat
.width
= priv
->codec
->width
;
440 templat
.height
= priv
->codec
->height
;
441 templat
.buffer_format
= pscreen
->get_video_param(
443 PIPE_VIDEO_PROFILE_UNKNOWN
,
444 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
445 PIPE_VIDEO_CAP_PREFERED_FORMAT
447 templat
.interlaced
= pscreen
->get_video_param(
449 PIPE_VIDEO_PROFILE_UNKNOWN
,
450 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
451 PIPE_VIDEO_CAP_PREFERS_INTERLACED
453 priv
->target
= priv
->pipe
->create_video_buffer(priv
->pipe
, &templat
);
457 static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE
*buf
)
459 struct pipe_video_buffer
*vbuf
= buf
->pInputPortPrivate
;
464 buf
->pInputPortPrivate
= NULL
;
467 static OMX_ERRORTYPE
vid_dec_DecodeBuffer(omx_base_PortType
*port
, OMX_BUFFERHEADERTYPE
*buf
)
469 OMX_COMPONENTTYPE
* comp
= port
->standCompContainer
;
470 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
471 unsigned i
= priv
->num_in_buffers
++;
474 priv
->in_buffers
[i
] = buf
;
475 priv
->sizes
[i
] = buf
->nFilledLen
;
476 priv
->inputs
[i
] = buf
->pBuffer
;
477 priv
->timestamps
[i
] = buf
->nTimeStamp
;
479 while (priv
->num_in_buffers
> (!!(buf
->nFlags
& OMX_BUFFERFLAG_EOS
) ? 0 : 1)) {
480 bool eos
= !!(priv
->in_buffers
[0]->nFlags
& OMX_BUFFERFLAG_EOS
);
481 unsigned min_bits_left
= eos
? 32 : MAX2(buf
->nFilledLen
* 8, 32);
484 vl_vlc_init(&vlc
, priv
->num_in_buffers
, priv
->inputs
, priv
->sizes
);
487 priv
->bytes_left
= vl_vlc_bits_left(&vlc
) / 8;
489 while (vl_vlc_bits_left(&vlc
) > min_bits_left
) {
490 priv
->Decode(priv
, &vlc
, min_bits_left
);
491 vl_vlc_fillbits(&vlc
);
495 unsigned bytes
= priv
->bytes_left
- vl_vlc_bits_left(&vlc
) / 8;
497 priv
->codec
->decode_bitstream(priv
->codec
, priv
->target
, &priv
->picture
.base
,
498 1, &priv
->slice
, &bytes
);
500 if (priv
->num_in_buffers
)
501 priv
->slice
= priv
->inputs
[1];
506 if (eos
&& priv
->frame_started
)
507 priv
->EndFrame(priv
);
509 if (priv
->frame_finished
) {
510 priv
->frame_finished
= false;
511 priv
->in_buffers
[0]->nFilledLen
= priv
->in_buffers
[0]->nAllocLen
;
512 r
= base_port_SendBufferFunction(port
, priv
->in_buffers
[0]);
514 vid_dec_FreeInputPortPrivate(priv
->in_buffers
[0]);
515 priv
->in_buffers
[0]->nFilledLen
= priv
->in_buffers
[0]->nAllocLen
;
516 r
= base_port_SendBufferFunction(port
, priv
->in_buffers
[0]);
518 priv
->in_buffers
[0]->nFilledLen
= 0;
519 r
= port
->ReturnBufferFunction(port
, priv
->in_buffers
[0]);
522 if (--priv
->num_in_buffers
) {
523 unsigned delta
= MIN2((min_bits_left
- vl_vlc_bits_left(&vlc
)) / 8, priv
->sizes
[1]);
525 priv
->in_buffers
[0] = priv
->in_buffers
[1];
526 priv
->sizes
[0] = priv
->sizes
[1] - delta
;
527 priv
->inputs
[0] = priv
->inputs
[1] + delta
;
528 priv
->timestamps
[0] = priv
->timestamps
[1];
535 return OMX_ErrorNone
;
538 static OMX_ERRORTYPE
vid_dec_FreeDecBuffer(omx_base_PortType
*port
, OMX_U32 idx
, OMX_BUFFERHEADERTYPE
*buf
)
540 vid_dec_FreeInputPortPrivate(buf
);
541 return base_port_FreeBuffer(port
, idx
, buf
);
544 static void vid_dec_FillOutput(vid_dec_PrivateType
*priv
, struct pipe_video_buffer
*buf
,
545 OMX_BUFFERHEADERTYPE
* output
)
547 omx_base_PortType
*port
= priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
548 OMX_VIDEO_PORTDEFINITIONTYPE
*def
= &port
->sPortParam
.format
.video
;
550 struct pipe_sampler_view
**views
;
552 unsigned width
, height
;
554 views
= buf
->get_sampler_view_planes(buf
);
556 for (i
= 0; i
< 2 /* NV12 */; i
++) {
557 if (!views
[i
]) continue;
558 width
= def
->nFrameWidth
;
559 height
= def
->nFrameHeight
;
560 vl_video_buffer_adjust_size(&width
, &height
, i
, buf
->chroma_format
, buf
->interlaced
);
561 for (j
= 0; j
< views
[i
]->texture
->array_size
; ++j
) {
562 struct pipe_box box
= {0, 0, j
, width
, height
, 1};
563 struct pipe_transfer
*transfer
;
565 map
= priv
->pipe
->transfer_map(priv
->pipe
, views
[i
]->texture
, 0,
566 PIPE_TRANSFER_READ
, &box
, &transfer
);
570 dst
= ((uint8_t*)output
->pBuffer
+ output
->nOffset
) + j
* def
->nStride
+
571 i
* def
->nFrameWidth
* def
->nFrameHeight
;
573 views
[i
]->texture
->format
,
574 def
->nStride
* views
[i
]->texture
->array_size
, 0, 0,
575 box
.width
, box
.height
, map
, transfer
->stride
, 0, 0);
577 pipe_transfer_unmap(priv
->pipe
, transfer
);
582 static void vid_dec_deint(vid_dec_PrivateType
*priv
, struct pipe_video_buffer
*src_buf
,
583 struct pipe_video_buffer
*dst_buf
)
585 struct vl_compositor
*compositor
= &priv
->compositor
;
586 struct vl_compositor_state
*s
= &priv
->cstate
;
587 struct pipe_surface
**dst_surface
;
588 struct u_rect dst_rect
;
590 dst_surface
= dst_buf
->get_surfaces(dst_buf
);
591 vl_compositor_clear_layers(s
);
594 dst_rect
.x1
= src_buf
->width
;
596 dst_rect
.y1
= src_buf
->height
;
598 vl_compositor_set_yuv_layer(s
, compositor
, 0, src_buf
, NULL
, NULL
, true);
599 vl_compositor_set_layer_dst_area(s
, 0, &dst_rect
);
600 vl_compositor_render(s
, compositor
, dst_surface
[0], NULL
, false);
605 vl_compositor_set_yuv_layer(s
, compositor
, 0, src_buf
, NULL
, NULL
, false);
606 vl_compositor_set_layer_dst_area(s
, 0, &dst_rect
);
607 vl_compositor_render(s
, compositor
, dst_surface
[1], NULL
, false);
610 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE
*comp
, OMX_BUFFERHEADERTYPE
* input
,
611 OMX_BUFFERHEADERTYPE
* output
)
613 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
614 bool eos
= !!(input
->nFlags
& OMX_BUFFERFLAG_EOS
);
617 if (!input
->pInputPortPrivate
) {
618 input
->pInputPortPrivate
= priv
->Flush(priv
, ×tamp
);
619 if (timestamp
!= OMX_VID_DEC_TIMESTAMP_INVALID
)
620 input
->nTimeStamp
= timestamp
;
623 if (input
->pInputPortPrivate
) {
624 if (output
->pInputPortPrivate
&& !priv
->disable_tunnel
) {
625 struct pipe_video_buffer
*tmp
, *vbuf
, *new_vbuf
;
627 tmp
= output
->pOutputPortPrivate
;
628 vbuf
= input
->pInputPortPrivate
;
629 if (vbuf
->interlaced
) {
630 /* re-allocate the progressive buffer */
631 omx_base_video_PortType
*port
;
632 struct pipe_video_buffer templat
= {};
634 port
= (omx_base_video_PortType
*)
635 priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
636 memset(&templat
, 0, sizeof(templat
));
637 templat
.chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
638 templat
.width
= port
->sPortParam
.format
.video
.nFrameWidth
;
639 templat
.height
= port
->sPortParam
.format
.video
.nFrameHeight
;
640 templat
.buffer_format
= PIPE_FORMAT_NV12
;
641 templat
.interlaced
= false;
642 new_vbuf
= priv
->pipe
->create_video_buffer(priv
->pipe
, &templat
);
644 /* convert the interlaced to the progressive */
645 vid_dec_deint(priv
, input
->pInputPortPrivate
, new_vbuf
);
646 priv
->pipe
->flush(priv
->pipe
, NULL
, 0);
648 /* set the progrssive buffer for next round */
650 input
->pInputPortPrivate
= new_vbuf
;
652 output
->pOutputPortPrivate
= input
->pInputPortPrivate
;
653 input
->pInputPortPrivate
= tmp
;
655 vid_dec_FillOutput(priv
, input
->pInputPortPrivate
, output
);
657 output
->nFilledLen
= output
->nAllocLen
;
658 output
->nTimeStamp
= input
->nTimeStamp
;
661 if (eos
&& input
->pInputPortPrivate
)
662 vid_dec_FreeInputPortPrivate(input
);
664 input
->nFilledLen
= 0;