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_vlc.h"
53 #include "entrypoint.h"
56 static OMX_ERRORTYPE
vid_dec_Constructor(OMX_COMPONENTTYPE
*comp
, OMX_STRING name
);
57 static OMX_ERRORTYPE
vid_dec_Destructor(OMX_COMPONENTTYPE
*comp
);
58 static OMX_ERRORTYPE
vid_dec_SetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
);
59 static OMX_ERRORTYPE
vid_dec_GetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
);
60 static OMX_ERRORTYPE
vid_dec_MessageHandler(OMX_COMPONENTTYPE
*comp
, internalRequestMessageType
*msg
);
61 static OMX_ERRORTYPE
vid_dec_DecodeBuffer(omx_base_PortType
*port
, OMX_BUFFERHEADERTYPE
*buf
);
62 static OMX_ERRORTYPE
vid_dec_FreeDecBuffer(omx_base_PortType
*port
, OMX_U32 idx
, OMX_BUFFERHEADERTYPE
*buf
);
63 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE
*comp
, OMX_BUFFERHEADERTYPE
* input
, OMX_BUFFERHEADERTYPE
* output
);
65 OMX_ERRORTYPE
vid_dec_LoaderComponent(stLoaderComponentType
*comp
)
67 comp
->componentVersion
.s
.nVersionMajor
= 0;
68 comp
->componentVersion
.s
.nVersionMinor
= 0;
69 comp
->componentVersion
.s
.nRevision
= 0;
70 comp
->componentVersion
.s
.nStep
= 1;
71 comp
->name_specific_length
= 2;
73 comp
->name
= CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
74 if (comp
->name
== NULL
)
77 comp
->name_specific
= CALLOC(comp
->name_specific_length
, sizeof(char *));
78 if (comp
->name_specific
== NULL
)
81 comp
->role_specific
= CALLOC(comp
->name_specific_length
, sizeof(char *));
82 if (comp
->role_specific
== NULL
)
85 comp
->name_specific
[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
86 if (comp
->name_specific
[0] == NULL
)
89 comp
->name_specific
[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
90 if (comp
->name_specific
[1] == NULL
)
93 comp
->role_specific
[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
94 if (comp
->role_specific
[0] == NULL
)
97 comp
->role_specific
[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE
);
98 if (comp
->role_specific
[1] == NULL
)
101 strcpy(comp
->name
, OMX_VID_DEC_BASE_NAME
);
102 strcpy(comp
->name_specific
[0], OMX_VID_DEC_MPEG2_NAME
);
103 strcpy(comp
->name_specific
[1], OMX_VID_DEC_AVC_NAME
);
105 strcpy(comp
->role_specific
[0], OMX_VID_DEC_MPEG2_ROLE
);
106 strcpy(comp
->role_specific
[1], OMX_VID_DEC_AVC_ROLE
);
108 comp
->constructor
= vid_dec_Constructor
;
110 return OMX_ErrorNone
;
113 FREE(comp
->role_specific
[1]);
114 FREE(comp
->role_specific
[0]);
115 FREE(comp
->name_specific
[1]);
116 FREE(comp
->name_specific
[0]);
119 FREE(comp
->role_specific
);
120 FREE(comp
->name_specific
);
124 return OMX_ErrorInsufficientResources
;
127 static OMX_ERRORTYPE
vid_dec_Constructor(OMX_COMPONENTTYPE
*comp
, OMX_STRING name
)
129 vid_dec_PrivateType
*priv
;
130 omx_base_video_PortType
*port
;
131 struct pipe_screen
*screen
;
135 assert(!comp
->pComponentPrivate
);
137 priv
= comp
->pComponentPrivate
= CALLOC(1, sizeof(vid_dec_PrivateType
));
139 return OMX_ErrorInsufficientResources
;
141 r
= omx_base_filter_Constructor(comp
, name
);
145 priv
->profile
= PIPE_VIDEO_PROFILE_UNKNOWN
;
147 if (!strcmp(name
, OMX_VID_DEC_MPEG2_NAME
))
148 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
150 if (!strcmp(name
, OMX_VID_DEC_AVC_NAME
))
151 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
;
153 priv
->BufferMgmtCallback
= vid_dec_FrameDecoded
;
154 priv
->messageHandler
= vid_dec_MessageHandler
;
155 priv
->destructor
= vid_dec_Destructor
;
157 comp
->SetParameter
= vid_dec_SetParameter
;
158 comp
->GetParameter
= vid_dec_GetParameter
;
160 priv
->screen
= omx_get_screen();
162 return OMX_ErrorInsufficientResources
;
164 screen
= priv
->screen
->pscreen
;
165 priv
->pipe
= screen
->context_create(screen
, priv
->screen
, 0);
167 return OMX_ErrorInsufficientResources
;
169 priv
->sPortTypesParam
[OMX_PortDomainVideo
].nStartPortNumber
= 0;
170 priv
->sPortTypesParam
[OMX_PortDomainVideo
].nPorts
= 2;
171 priv
->ports
= CALLOC(2, sizeof(omx_base_PortType
*));
173 return OMX_ErrorInsufficientResources
;
175 for (i
= 0; i
< 2; ++i
) {
176 priv
->ports
[i
] = CALLOC(1, sizeof(omx_base_video_PortType
));
178 return OMX_ErrorInsufficientResources
;
180 base_video_port_Constructor(comp
, &priv
->ports
[i
], i
, i
== 0);
183 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
184 strcpy(port
->sPortParam
.format
.video
.cMIMEType
,"video/MPEG2");
185 port
->sPortParam
.nBufferCountMin
= 8;
186 port
->sPortParam
.nBufferCountActual
= 8;
187 port
->sPortParam
.nBufferSize
= DEFAULT_OUT_BUFFER_SIZE
;
188 port
->sPortParam
.format
.video
.nFrameWidth
= 176;
189 port
->sPortParam
.format
.video
.nFrameHeight
= 144;
190 port
->sPortParam
.format
.video
.eCompressionFormat
= OMX_VIDEO_CodingMPEG2
;
191 port
->sVideoParam
.eCompressionFormat
= OMX_VIDEO_CodingMPEG2
;
192 port
->Port_SendBufferFunction
= vid_dec_DecodeBuffer
;
193 port
->Port_FreeBuffer
= vid_dec_FreeDecBuffer
;
195 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
196 port
->sPortParam
.nBufferCountActual
= 8;
197 port
->sPortParam
.nBufferCountMin
= 4;
198 port
->sPortParam
.format
.video
.nFrameWidth
= 176;
199 port
->sPortParam
.format
.video
.nFrameHeight
= 144;
200 port
->sPortParam
.format
.video
.eColorFormat
= OMX_COLOR_FormatYUV420SemiPlanar
;
201 port
->sVideoParam
.eColorFormat
= OMX_COLOR_FormatYUV420SemiPlanar
;
203 return OMX_ErrorNone
;
206 static OMX_ERRORTYPE
vid_dec_Destructor(OMX_COMPONENTTYPE
*comp
)
208 vid_dec_PrivateType
* priv
= comp
->pComponentPrivate
;
212 for (i
= 0; i
< priv
->sPortTypesParam
[OMX_PortDomainVideo
].nPorts
; ++i
) {
214 priv
->ports
[i
]->PortDestructor(priv
->ports
[i
]);
221 priv
->pipe
->destroy(priv
->pipe
);
226 return omx_workaround_Destructor(comp
);
229 static OMX_ERRORTYPE
vid_dec_SetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
)
231 OMX_COMPONENTTYPE
*comp
= handle
;
232 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
236 return OMX_ErrorBadParameter
;
239 case OMX_IndexParamPortDefinition
: {
240 OMX_PARAM_PORTDEFINITIONTYPE
*def
= param
;
242 r
= omx_base_component_SetParameter(handle
, idx
, param
);
246 if (def
->nPortIndex
== OMX_BASE_FILTER_INPUTPORT_INDEX
) {
247 omx_base_video_PortType
*port
;
248 unsigned framesize
= def
->format
.video
.nFrameWidth
* def
->format
.video
.nFrameHeight
;
250 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
251 port
->sPortParam
.nBufferSize
= framesize
* 512 / (16*16);
253 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
254 port
->sPortParam
.format
.video
.nFrameWidth
= def
->format
.video
.nFrameWidth
;
255 port
->sPortParam
.format
.video
.nFrameHeight
= def
->format
.video
.nFrameHeight
;
256 port
->sPortParam
.format
.video
.nStride
= def
->format
.video
.nFrameWidth
;
257 port
->sPortParam
.format
.video
.nSliceHeight
= def
->format
.video
.nFrameHeight
;
258 port
->sPortParam
.nBufferSize
= framesize
*3/2;
260 priv
->callbacks
->EventHandler(comp
, priv
->callbackData
, OMX_EventPortSettingsChanged
,
261 OMX_BASE_FILTER_OUTPUTPORT_INDEX
, 0, NULL
);
265 case OMX_IndexParamStandardComponentRole
: {
266 OMX_PARAM_COMPONENTROLETYPE
*role
= param
;
268 r
= checkHeader(param
, sizeof(OMX_PARAM_COMPONENTROLETYPE
));
272 if (!strcmp((char *)role
->cRole
, OMX_VID_DEC_MPEG2_ROLE
)) {
273 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG2_MAIN
;
274 } else if (!strcmp((char *)role
->cRole
, OMX_VID_DEC_AVC_ROLE
)) {
275 priv
->profile
= PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
;
277 return OMX_ErrorBadParameter
;
282 case OMX_IndexParamVideoPortFormat
: {
283 OMX_VIDEO_PARAM_PORTFORMATTYPE
*format
= param
;
284 omx_base_video_PortType
*port
;
286 r
= checkHeader(param
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
290 if (format
->nPortIndex
> 1)
291 return OMX_ErrorBadPortIndex
;
293 port
= (omx_base_video_PortType
*)priv
->ports
[format
->nPortIndex
];
294 memcpy(&port
->sVideoParam
, format
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
298 return omx_base_component_SetParameter(handle
, idx
, param
);
300 return OMX_ErrorNone
;
303 static OMX_ERRORTYPE
vid_dec_GetParameter(OMX_HANDLETYPE handle
, OMX_INDEXTYPE idx
, OMX_PTR param
)
305 OMX_COMPONENTTYPE
*comp
= handle
;
306 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
310 return OMX_ErrorBadParameter
;
313 case OMX_IndexParamStandardComponentRole
: {
314 OMX_PARAM_COMPONENTROLETYPE
*role
= param
;
316 r
= checkHeader(param
, sizeof(OMX_PARAM_COMPONENTROLETYPE
));
320 if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG2_MAIN
)
321 strcpy((char *)role
->cRole
, OMX_VID_DEC_MPEG2_ROLE
);
322 else if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
)
323 strcpy((char *)role
->cRole
, OMX_VID_DEC_AVC_ROLE
);
328 case OMX_IndexParamVideoInit
:
329 r
= checkHeader(param
, sizeof(OMX_PORT_PARAM_TYPE
));
333 memcpy(param
, &priv
->sPortTypesParam
[OMX_PortDomainVideo
], sizeof(OMX_PORT_PARAM_TYPE
));
336 case OMX_IndexParamVideoPortFormat
: {
337 OMX_VIDEO_PARAM_PORTFORMATTYPE
*format
= param
;
338 omx_base_video_PortType
*port
;
340 r
= checkHeader(param
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
344 if (format
->nPortIndex
> 1)
345 return OMX_ErrorBadPortIndex
;
347 port
= (omx_base_video_PortType
*)priv
->ports
[format
->nPortIndex
];
348 memcpy(format
, &port
->sVideoParam
, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE
));
353 return omx_base_component_GetParameter(handle
, idx
, param
);
356 return OMX_ErrorNone
;
359 static OMX_ERRORTYPE
vid_dec_MessageHandler(OMX_COMPONENTTYPE
* comp
, internalRequestMessageType
*msg
)
361 vid_dec_PrivateType
* priv
= comp
->pComponentPrivate
;
363 if (msg
->messageType
== OMX_CommandStateSet
) {
364 if ((msg
->messageParam
== OMX_StateIdle
) && (priv
->state
== OMX_StateLoaded
)) {
365 if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG2_MAIN
)
366 vid_dec_mpeg12_Init(priv
);
367 else if (priv
->profile
== PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
)
368 vid_dec_h264_Init(priv
);
370 } else if ((msg
->messageParam
== OMX_StateLoaded
) && (priv
->state
== OMX_StateIdle
)) {
372 priv
->shadow
->destroy(priv
->shadow
);
376 priv
->codec
->destroy(priv
->codec
);
382 return omx_base_component_MessageHandler(comp
, msg
);
385 void vid_dec_NeedTarget(vid_dec_PrivateType
*priv
)
387 struct pipe_video_buffer templat
= {};
388 struct vl_screen
*omx_screen
;
389 struct pipe_screen
*pscreen
;
390 omx_base_video_PortType
*port
;
392 omx_screen
= priv
->screen
;
393 port
= (omx_base_video_PortType
*)priv
->ports
[OMX_BASE_FILTER_INPUTPORT_INDEX
];
398 pscreen
= omx_screen
->pscreen
;
403 memset(&templat
, 0, sizeof(templat
));
405 templat
.chroma_format
= PIPE_VIDEO_CHROMA_FORMAT_420
;
406 templat
.width
= port
->sPortParam
.format
.video
.nFrameWidth
;
407 templat
.height
= port
->sPortParam
.format
.video
.nFrameHeight
;
408 templat
.buffer_format
= pscreen
->get_video_param(
410 PIPE_VIDEO_PROFILE_UNKNOWN
,
411 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
412 PIPE_VIDEO_CAP_PREFERED_FORMAT
414 templat
.interlaced
= pscreen
->get_video_param(
416 PIPE_VIDEO_PROFILE_UNKNOWN
,
417 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
418 PIPE_VIDEO_CAP_PREFERS_INTERLACED
420 priv
->target
= priv
->pipe
->create_video_buffer(priv
->pipe
, &templat
);
424 static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE
*buf
)
426 struct pipe_video_buffer
*vbuf
= buf
->pInputPortPrivate
;
431 buf
->pInputPortPrivate
= NULL
;
434 static OMX_ERRORTYPE
vid_dec_DecodeBuffer(omx_base_PortType
*port
, OMX_BUFFERHEADERTYPE
*buf
)
436 OMX_COMPONENTTYPE
* comp
= port
->standCompContainer
;
437 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
438 unsigned i
= priv
->num_in_buffers
++;
441 priv
->in_buffers
[i
] = buf
;
442 priv
->sizes
[i
] = buf
->nFilledLen
;
443 priv
->inputs
[i
] = buf
->pBuffer
;
444 priv
->timestamps
[i
] = buf
->nTimeStamp
;
446 while (priv
->num_in_buffers
> (!!(buf
->nFlags
& OMX_BUFFERFLAG_EOS
) ? 0 : 1)) {
447 bool eos
= !!(priv
->in_buffers
[0]->nFlags
& OMX_BUFFERFLAG_EOS
);
448 unsigned min_bits_left
= eos
? 32 : MAX2(buf
->nFilledLen
* 8, 32);
451 vl_vlc_init(&vlc
, priv
->num_in_buffers
, priv
->inputs
, priv
->sizes
);
454 priv
->bytes_left
= vl_vlc_bits_left(&vlc
) / 8;
456 while (vl_vlc_bits_left(&vlc
) > min_bits_left
) {
457 priv
->Decode(priv
, &vlc
, min_bits_left
);
458 vl_vlc_fillbits(&vlc
);
462 unsigned bytes
= priv
->bytes_left
- vl_vlc_bits_left(&vlc
) / 8;
464 priv
->codec
->decode_bitstream(priv
->codec
, priv
->target
, &priv
->picture
.base
,
465 1, &priv
->slice
, &bytes
);
467 if (priv
->num_in_buffers
)
468 priv
->slice
= priv
->inputs
[1];
473 if (eos
&& priv
->frame_started
)
474 priv
->EndFrame(priv
);
476 if (priv
->frame_finished
) {
477 priv
->frame_finished
= false;
478 priv
->in_buffers
[0]->nFilledLen
= priv
->in_buffers
[0]->nAllocLen
;
479 r
= base_port_SendBufferFunction(port
, priv
->in_buffers
[0]);
481 vid_dec_FreeInputPortPrivate(priv
->in_buffers
[0]);
482 priv
->in_buffers
[0]->nFilledLen
= priv
->in_buffers
[0]->nAllocLen
;
483 r
= base_port_SendBufferFunction(port
, priv
->in_buffers
[0]);
485 priv
->in_buffers
[0]->nFilledLen
= 0;
486 r
= port
->ReturnBufferFunction(port
, priv
->in_buffers
[0]);
489 if (--priv
->num_in_buffers
) {
490 unsigned delta
= MIN2((min_bits_left
- vl_vlc_bits_left(&vlc
)) / 8, priv
->sizes
[1]);
492 priv
->in_buffers
[0] = priv
->in_buffers
[1];
493 priv
->sizes
[0] = priv
->sizes
[1] - delta
;
494 priv
->inputs
[0] = priv
->inputs
[1] + delta
;
495 priv
->timestamps
[0] = priv
->timestamps
[1];
502 return OMX_ErrorNone
;
505 static OMX_ERRORTYPE
vid_dec_FreeDecBuffer(omx_base_PortType
*port
, OMX_U32 idx
, OMX_BUFFERHEADERTYPE
*buf
)
507 vid_dec_FreeInputPortPrivate(buf
);
508 return base_port_FreeBuffer(port
, idx
, buf
);
511 static void vid_dec_FillOutput(vid_dec_PrivateType
*priv
, struct pipe_video_buffer
*buf
,
512 OMX_BUFFERHEADERTYPE
* output
)
514 omx_base_PortType
*port
= priv
->ports
[OMX_BASE_FILTER_OUTPUTPORT_INDEX
];
515 OMX_VIDEO_PORTDEFINITIONTYPE
*def
= &port
->sPortParam
.format
.video
;
517 struct pipe_sampler_view
**views
;
518 struct pipe_transfer
*transfer
;
519 struct pipe_box box
= { };
522 views
= buf
->get_sampler_view_planes(buf
);
524 dst
= output
->pBuffer
;
526 box
.width
= def
->nFrameWidth
;
527 box
.height
= def
->nFrameHeight
;
530 src
= priv
->pipe
->transfer_map(priv
->pipe
, views
[0]->texture
, 0,
531 PIPE_TRANSFER_READ
, &box
, &transfer
);
532 util_copy_rect(dst
, views
[0]->texture
->format
, def
->nStride
, 0, 0,
533 box
.width
, box
.height
, src
, transfer
->stride
, 0, 0);
534 pipe_transfer_unmap(priv
->pipe
, transfer
);
536 dst
= ((uint8_t*)output
->pBuffer
) + (def
->nStride
* box
.height
);
538 box
.width
= def
->nFrameWidth
/ 2;
539 box
.height
= def
->nFrameHeight
/ 2;
541 src
= priv
->pipe
->transfer_map(priv
->pipe
, views
[1]->texture
, 0,
542 PIPE_TRANSFER_READ
, &box
, &transfer
);
543 util_copy_rect(dst
, views
[1]->texture
->format
, def
->nStride
, 0, 0,
544 box
.width
, box
.height
, src
, transfer
->stride
, 0, 0);
545 pipe_transfer_unmap(priv
->pipe
, transfer
);
548 static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE
*comp
, OMX_BUFFERHEADERTYPE
* input
,
549 OMX_BUFFERHEADERTYPE
* output
)
551 vid_dec_PrivateType
*priv
= comp
->pComponentPrivate
;
552 bool eos
= !!(input
->nFlags
& OMX_BUFFERFLAG_EOS
);
555 if (!input
->pInputPortPrivate
) {
556 input
->pInputPortPrivate
= priv
->Flush(priv
, ×tamp
);
557 if (timestamp
!= OMX_VID_DEC_TIMESTAMP_INVALID
)
558 input
->nTimeStamp
= timestamp
;
561 if (input
->pInputPortPrivate
) {
562 if (output
->pInputPortPrivate
) {
563 struct pipe_video_buffer
*tmp
= output
->pOutputPortPrivate
;
564 output
->pOutputPortPrivate
= input
->pInputPortPrivate
;
565 input
->pInputPortPrivate
= tmp
;
567 vid_dec_FillOutput(priv
, input
->pInputPortPrivate
, output
);
569 output
->nFilledLen
= output
->nAllocLen
;
570 output
->nTimeStamp
= input
->nTimeStamp
;
573 if (eos
&& input
->pInputPortPrivate
)
574 vid_dec_FreeInputPortPrivate(input
);
576 input
->nFilledLen
= 0;