1/**************************************************************************
2 *
3 * Copyright 2013 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28#include <tizplatform.h>
29#include <tizkernel.h>
30#include <tizutils.h>
31
32#include "pipe/p_screen.h"
33#include "pipe/p_video_codec.h"
34#include "util/u_memory.h"
35
36#include "vl/vl_codec.h"
37
38#include "entrypoint.h"
39#include "h264e.h"
40#include "h264eprc.h"
41#include "vid_omx_common.h"
42#include "vid_enc_common.h"
43
44static OMX_ERRORTYPE init_port_structs(vid_enc_PrivateType * priv) {
45   const void * p_krn = NULL;
46
47   assert(priv);
48
49   /* Initialisation */
50   TIZ_INIT_OMX_PORT_STRUCT(priv->in_port_def_,
51                            OMX_VID_ENC_AVC_INPUT_PORT_INDEX);
52   TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_,
53                            OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX);
54   TIZ_INIT_OMX_PORT_STRUCT(priv->bitrate,
55                            OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX);
56   TIZ_INIT_OMX_PORT_STRUCT(priv->quant,
57                            OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX);
58   TIZ_INIT_OMX_PORT_STRUCT(priv->profile_level,
59                            OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX);
60
61   /* Get values */
62   p_krn = tiz_get_krn(handleOf(priv));
63
64   tiz_check_omx(
65      tiz_api_GetParameter(p_krn, handleOf(priv),
66                           OMX_IndexParamPortDefinition, &(priv->in_port_def_)));
67   tiz_check_omx(
68      tiz_api_GetParameter(p_krn, handleOf(priv),
69                           OMX_IndexParamPortDefinition, &(priv->out_port_def_)));
70   tiz_check_omx(
71      tiz_api_GetParameter(p_krn, handleOf(priv),
72                           OMX_IndexParamVideoBitrate, &(priv->bitrate)));
73   tiz_check_omx(
74      tiz_api_GetParameter(p_krn, handleOf(priv),
75                           OMX_IndexParamVideoQuantization, &(priv->quant)));
76   tiz_check_omx(
77      tiz_api_GetParameter(p_krn, handleOf(priv),
78                           OMX_IndexParamVideoProfileLevelCurrent, &(priv->profile_level)));
79
80   return OMX_ErrorNone;
81}
82
83static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_enc_PrivateType * priv) {
84   assert(priv);
85
86   if (priv->in_port_disabled_) {
87      return NULL;
88   }
89
90   assert(!priv->p_inhdr_); /* encode_frame expects new buffers every time */
91
92   tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)),
93                        OMX_VID_ENC_AVC_INPUT_PORT_INDEX, 0,
94                        &priv->p_inhdr_);
95   return priv->p_inhdr_;
96}
97
98static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_enc_PrivateType * priv) {
99   assert(priv);
100
101   if (priv->out_port_disabled_) {
102      return NULL;
103   }
104
105   if (!priv->p_outhdr_) {
106      tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)),
107                           OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, 0,
108                           &priv->p_outhdr_);
109   }
110   return priv->p_outhdr_;
111}
112
113static OMX_ERRORTYPE h264e_buffer_emptied(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr)
114{
115   OMX_ERRORTYPE r = OMX_ErrorNone;
116
117   assert(priv);
118   assert(priv->p_inhdr_ == p_hdr);
119
120   if (!priv->out_port_disabled_) {
121      p_hdr->nOffset = 0;
122
123      if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) {
124         priv->eos_ = true;
125      }
126
127      r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), 0, p_hdr);
128      priv->p_inhdr_ = NULL;
129   }
130
131   return r;
132}
133
134static OMX_ERRORTYPE h264e_buffer_filled(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr)
135{
136   OMX_ERRORTYPE r = OMX_ErrorNone;
137
138   assert(priv);
139   assert(priv->p_outhdr_ == p_hdr);
140   assert(p_hdr);
141
142   if (!priv->in_port_disabled_) {
143      p_hdr->nOffset = 0;
144
145      if (priv->eos_) {
146         /* EOS has been received and all the input data has been consumed
147          * already, so its time to propagate the EOS flag */
148         priv->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS;
149      }
150
151      r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)),
152                                 OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX,
153                                 p_hdr);
154      priv->p_outhdr_ = NULL;
155   }
156
157   return r;
158}
159
160
161static void release_input_header(vid_enc_PrivateType * priv) {
162   assert(!priv->in_port_disabled_);
163   if (priv->p_inhdr_) {
164      (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)),
165                             OMX_VID_ENC_AVC_INPUT_PORT_INDEX,
166                             priv->p_inhdr_);
167   }
168   priv->p_inhdr_ = NULL;
169}
170
171static void release_output_header(vid_enc_PrivateType * priv) {
172   if (priv->p_outhdr_) {
173      assert(!priv->out_port_disabled_);
174      (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)),
175                             OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX,
176                             priv->p_outhdr_);
177      priv->p_outhdr_ = NULL;
178   }
179}
180
181static OMX_ERRORTYPE h264e_release_all_headers(vid_enc_PrivateType * priv)
182{
183   assert(priv);
184
185   release_input_header(priv);
186   release_output_header(priv);
187
188   return OMX_ErrorNone;
189}
190
191static void reset_stream_parameters(vid_enc_PrivateType * priv)
192{
193   assert(priv);
194   init_port_structs(priv);
195   priv->p_inhdr_ = 0;
196   priv->p_outhdr_ = 0;
197   priv->eos_ = false;
198}
199
200/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */
201static OMX_ERRORTYPE h264e_manage_buffers(vid_enc_PrivateType* priv) {
202   OMX_BUFFERHEADERTYPE * in_buf = priv->p_inhdr_;
203   OMX_BUFFERHEADERTYPE * out_buf = priv->p_outhdr_;
204   OMX_ERRORTYPE r = OMX_ErrorNone;
205
206   if (in_buf->nFilledLen > 0) {
207      vid_enc_BufferEncoded_common(priv, in_buf, out_buf);
208   } else {
209      in_buf->nFilledLen = 0;
210   }
211
212   out_buf->nTimeStamp = in_buf->nTimeStamp;
213
214   /* Release input buffer if possible */
215   if (in_buf->nFilledLen == 0) {
216      r = h264e_buffer_emptied(priv, in_buf);
217   }
218
219   /* Realase output buffer if filled or eos */
220   if ((out_buf->nFilledLen != 0) || priv->eos_) {
221      r = h264e_buffer_filled(priv, out_buf);
222   }
223
224   return r;
225}
226
227static struct encode_task *enc_NeedTask(vid_enc_PrivateType * priv)
228{
229   OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video;
230
231   return enc_NeedTask_common(priv, def);
232}
233
234static void enc_ScaleInput(vid_enc_PrivateType * priv, struct pipe_video_buffer **vbuf, unsigned *size)
235{
236   OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video;
237   enc_ScaleInput_common(priv, def, vbuf, size);
238}
239
240static void enc_HandleTask(vid_enc_PrivateType * priv, struct encode_task *task,
241                           enum pipe_h2645_enc_picture_type picture_type)
242{
243   unsigned size = priv->out_port_def_.nBufferSize;
244   struct pipe_video_buffer *vbuf = task->buf;
245   struct pipe_h264_enc_picture_desc picture = {};
246
247   /* -------------- scale input image --------- */
248   enc_ScaleInput(priv, &vbuf, &size);
249   priv->s_pipe->flush(priv->s_pipe, NULL, 0);
250
251   /* -------------- allocate output buffer --------- */
252   task->bitstream = pipe_buffer_create(priv->s_pipe->screen,
253                                        PIPE_BIND_VERTEX_BUFFER,
254                                        PIPE_USAGE_STAGING, /* map for read */
255                                        size);
256
257   picture.picture_type = picture_type;
258   picture.pic_order_cnt = task->pic_order_cnt;
259   if (priv->restricted_b_frames && picture_type == PIPE_H2645_ENC_PICTURE_TYPE_B)
260      picture.not_referenced = true;
261   enc_ControlPicture_common(priv, &picture);
262
263   /* -------------- encode frame --------- */
264   priv->codec->begin_frame(priv->codec, vbuf, &picture.base);
265   priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback);
266   priv->codec->end_frame(priv->codec, vbuf, &picture.base);
267}
268
269static void enc_ClearBframes(vid_enc_PrivateType * priv, struct input_buf_private *inp)
270{
271   struct encode_task *task;
272
273   if (list_is_empty(&priv->b_frames))
274      return;
275
276   task = list_entry(priv->b_frames.prev, struct encode_task, list);
277   list_del(&task->list);
278
279   /* promote last from to P frame */
280   priv->ref_idx_l0 = priv->ref_idx_l1;
281   enc_HandleTask(priv, task, PIPE_H2645_ENC_PICTURE_TYPE_P);
282   list_addtail(&task->list, &inp->tasks);
283   priv->ref_idx_l1 = priv->frame_num++;
284
285   /* handle B frames */
286   LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) {
287      enc_HandleTask(priv, task, PIPE_H2645_ENC_PICTURE_TYPE_B);
288      if (!priv->restricted_b_frames)
289         priv->ref_idx_l0 = priv->frame_num;
290      priv->frame_num++;
291   }
292
293   enc_MoveTasks(&priv->b_frames, &inp->tasks);
294}
295
296static OMX_ERRORTYPE enc_LoadImage(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE *buf,
297                                   struct pipe_video_buffer *vbuf)
298{
299   OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video;
300   return enc_LoadImage_common(priv, def, buf, vbuf);
301}
302
303static OMX_ERRORTYPE encode_frame(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * in_buf)
304{
305   struct input_buf_private *inp = in_buf->pInputPortPrivate;
306   enum pipe_h2645_enc_picture_type picture_type;
307   struct encode_task *task;
308   unsigned stacked_num = 0;
309   OMX_ERRORTYPE err;
310
311   enc_MoveTasks(&inp->tasks, &priv->free_tasks);
312   task = enc_NeedTask(priv);
313   if (!task)
314      return OMX_ErrorInsufficientResources;
315
316   /* EOS */
317   if (in_buf->nFilledLen == 0) {
318      if (in_buf->nFlags & OMX_BUFFERFLAG_EOS) {
319         in_buf->nFilledLen = in_buf->nAllocLen;
320         enc_ClearBframes(priv, inp);
321         enc_MoveTasks(&priv->stacked_tasks, &inp->tasks);
322         priv->codec->flush(priv->codec);
323      }
324      return h264e_manage_buffers(priv);
325   }
326
327   if (in_buf->pOutputPortPrivate) {
328      struct pipe_video_buffer *vbuf = in_buf->pOutputPortPrivate;
329      in_buf->pOutputPortPrivate = task->buf;
330      task->buf = vbuf;
331   } else {
332      /* ------- load input image into video buffer ---- */
333      err = enc_LoadImage(priv, in_buf, task->buf);
334      if (err != OMX_ErrorNone) {
335         FREE(task);
336         return err;
337      }
338   }
339
340   /* -------------- determine picture type --------- */
341   if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) ||
342       priv->force_pic_type.IntraRefreshVOP) {
343      enc_ClearBframes(priv, inp);
344      picture_type = PIPE_H2645_ENC_PICTURE_TYPE_IDR;
345      priv->force_pic_type.IntraRefreshVOP = OMX_FALSE;
346      priv->frame_num = 0;
347   } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE ||
348              !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) ||
349              (in_buf->nFlags & OMX_BUFFERFLAG_EOS)) {
350      picture_type = PIPE_H2645_ENC_PICTURE_TYPE_P;
351   } else {
352      picture_type = PIPE_H2645_ENC_PICTURE_TYPE_B;
353   }
354
355   task->pic_order_cnt = priv->pic_order_cnt++;
356
357   if (picture_type == PIPE_H2645_ENC_PICTURE_TYPE_B) {
358      /* put frame at the tail of the queue */
359      list_addtail(&task->list, &priv->b_frames);
360   } else {
361      /* handle I or P frame */
362      priv->ref_idx_l0 = priv->ref_idx_l1;
363      enc_HandleTask(priv, task, picture_type);
364      list_addtail(&task->list, &priv->stacked_tasks);
365      LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) {
366         ++stacked_num;
367      }
368      if (stacked_num == priv->stacked_frames_num) {
369         struct encode_task *t;
370         t = list_entry(priv->stacked_tasks.next, struct encode_task, list);
371         list_del(&t->list);
372         list_addtail(&t->list, &inp->tasks);
373      }
374      priv->ref_idx_l1 = priv->frame_num++;
375
376      /* handle B frames */
377      LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) {
378         enc_HandleTask(priv, task, PIPE_H2645_ENC_PICTURE_TYPE_B);
379         if (!priv->restricted_b_frames)
380            priv->ref_idx_l0 = priv->frame_num;
381         priv->frame_num++;
382      }
383
384      enc_MoveTasks(&priv->b_frames, &inp->tasks);
385   }
386
387   if (list_is_empty(&inp->tasks)) {
388      return h264e_buffer_emptied(priv, in_buf);
389   } else {
390      return h264e_manage_buffers(priv);
391   }
392}
393
394static OMX_ERRORTYPE h264e_prc_create_encoder(void *ap_obj)
395{
396   vid_enc_PrivateType *priv = ap_obj;
397   struct pipe_screen *screen;
398
399   priv->screen = omx_get_screen();
400   if (!priv->screen)
401      return OMX_ErrorInsufficientResources;
402
403   screen = priv->screen->pscreen;
404   if (!vl_codec_supported(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, true))
405      return OMX_ErrorBadParameter;
406
407   priv->s_pipe = pipe_create_multimedia_context(screen);
408   if (!priv->s_pipe)
409      return OMX_ErrorInsufficientResources;
410
411   enc_InitCompute_common(priv);
412
413   if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) {
414      priv->s_pipe->destroy(priv->s_pipe);
415      priv->s_pipe = NULL;
416      return OMX_ErrorInsufficientResources;
417   }
418
419   if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) {
420      vl_compositor_cleanup(&priv->compositor);
421      priv->s_pipe->destroy(priv->s_pipe);
422      priv->s_pipe = NULL;
423      return OMX_ErrorInsufficientResources;
424   }
425
426   priv->t_pipe = pipe_create_multimedia_context(screen);
427   if (!priv->t_pipe)
428      return OMX_ErrorInsufficientResources;
429
430   list_inithead(&priv->free_tasks);
431   list_inithead(&priv->used_tasks);
432   list_inithead(&priv->b_frames);
433   list_inithead(&priv->stacked_tasks);
434
435   return OMX_ErrorNone;
436}
437
438static void h264e_prc_destroy_encoder(void *ap_obj)
439{
440   vid_enc_PrivateType *priv = ap_obj;
441   int i;
442
443   assert (priv);
444
445   enc_ReleaseTasks(&priv->free_tasks);
446   enc_ReleaseTasks(&priv->used_tasks);
447   enc_ReleaseTasks(&priv->b_frames);
448   enc_ReleaseTasks(&priv->stacked_tasks);
449
450   for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i)
451      if (priv->scale_buffer[i])
452      priv->scale_buffer[i]->destroy(priv->scale_buffer[i]);
453
454   if (priv->s_pipe) {
455      vl_compositor_cleanup_state(&priv->cstate);
456      vl_compositor_cleanup(&priv->compositor);
457      enc_ReleaseCompute_common(priv);
458      priv->s_pipe->destroy(priv->s_pipe);
459   }
460
461   if (priv->t_pipe)
462      priv->t_pipe->destroy(priv->t_pipe);
463
464   if (priv->screen)
465      omx_put_screen();
466}
467
468/*
469 * h264eprc
470 */
471
472static void * h264e_prc_ctor(void *ap_obj, va_list * app)
473{
474   vid_enc_PrivateType *priv = super_ctor(typeOf(ap_obj, "h264eprc"), ap_obj, app);
475   assert (priv);
476
477   if (h264e_prc_create_encoder(ap_obj) != OMX_ErrorNone)
478     return priv;
479
480   priv->p_inhdr_ = 0;
481   priv->p_outhdr_ = 0;
482   priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline;
483   priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51;
484   priv->force_pic_type.IntraRefreshVOP = OMX_FALSE;
485   priv->frame_num = 0;
486   priv->pic_order_cnt = 0;
487   priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE);
488   priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT;
489   priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT;
490   priv->in_port_disabled_   = false;
491   priv->out_port_disabled_   = false;
492   reset_stream_parameters(priv);
493
494   return priv;
495}
496
497static void * h264e_prc_dtor(void *ap_obj)
498{
499   h264e_prc_destroy_encoder(ap_obj);
500   return super_dtor(typeOf(ap_obj, "h264eprc"), ap_obj);
501}
502
503static OMX_ERRORTYPE h264e_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid)
504{
505   vid_enc_PrivateType *priv = ap_obj;
506
507   assert(priv);
508   if (!priv->screen)
509      return OMX_ErrorInsufficientResources;
510
511   return OMX_ErrorNone;
512}
513
514static OMX_ERRORTYPE h264e_prc_deallocate_resources(void *ap_obj)
515{
516   return OMX_ErrorNone;
517}
518
519static OMX_ERRORTYPE h264e_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid)
520{
521   vid_enc_PrivateType *priv = ap_obj;
522
523   assert(priv);
524
525   init_port_structs(priv);
526
527   priv->eos_ = false;
528
529   struct pipe_video_codec templat = {};
530
531   templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile);
532   templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel);
533   templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE;
534   templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
535   templat.width = priv->scale_buffer[priv->current_scale_buffer] ?
536                     priv->scale.xWidth : priv->in_port_def_.format.video.nFrameWidth;
537   templat.height = priv->scale_buffer[priv->current_scale_buffer] ?
538                      priv->scale.xHeight : priv->in_port_def_.format.video.nFrameHeight;
539
540   if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) {
541      struct pipe_screen *screen = priv->screen->pscreen;
542      templat.max_references = 1;
543      priv->stacked_frames_num =
544         screen->get_video_param(screen,
545                                 PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH,
546                                 PIPE_VIDEO_ENTRYPOINT_ENCODE,
547                                 PIPE_VIDEO_CAP_STACKED_FRAMES);
548   } else {
549      templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT;
550      priv->stacked_frames_num = 1;
551   }
552   priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat);
553
554   return OMX_ErrorNone;
555}
556
557static OMX_ERRORTYPE h264e_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid)
558{
559   return OMX_ErrorNone;
560}
561
562static OMX_ERRORTYPE h264e_prc_stop_and_return(void *ap_obj)
563{
564   vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj;
565   return h264e_release_all_headers(priv);
566}
567
568static OMX_ERRORTYPE h264e_prc_buffers_ready(const void *ap_obj)
569{
570   vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj;
571   OMX_BUFFERHEADERTYPE *in_buf = NULL;
572   OMX_BUFFERHEADERTYPE *out_buf = NULL;
573   OMX_ERRORTYPE r = OMX_ErrorNone;
574
575   assert(priv);
576
577   /* Don't get input buffer if output buffer not found */
578   while (!priv->eos_ && (out_buf = get_output_buffer(priv)) && (in_buf = get_input_buffer(priv))) {
579      if (!priv->out_port_disabled_) {
580         r = encode_frame(priv, in_buf);
581      }
582   }
583
584   return r;
585}
586
587static OMX_ERRORTYPE h264e_prc_port_flush(const void *ap_obj, OMX_U32 a_pid)
588{
589   vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj;
590   if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) {
591      release_input_header(priv);
592      reset_stream_parameters(priv);
593   }
594   if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) {
595      release_output_header(priv);
596   }
597   return OMX_ErrorNone;
598}
599
600static OMX_ERRORTYPE h264e_prc_port_disable(const void *ap_obj, OMX_U32 a_pid)
601{
602   vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj;
603   assert(priv);
604   if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) {
605      /* Release all buffers */
606      h264e_release_all_headers(priv);
607      reset_stream_parameters(priv);
608      priv->in_port_disabled_ = true;
609   }
610   if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) {
611      release_output_header(priv);
612      priv->out_port_disabled_ = true;
613   }
614   return OMX_ErrorNone;
615}
616
617static OMX_ERRORTYPE h264e_prc_port_enable(const void *ap_obj, OMX_U32 a_pid)
618{
619   vid_enc_PrivateType * priv = (vid_enc_PrivateType *) ap_obj;
620   assert(priv);
621   if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) {
622      if (priv->in_port_disabled_) {
623         reset_stream_parameters(priv);
624         priv->in_port_disabled_ = false;
625      }
626   }
627   if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) {
628      priv->out_port_disabled_ = false;
629   }
630   return OMX_ErrorNone;
631}
632
633/*
634 * h264e_prc_class
635 */
636
637static void * h264e_prc_class_ctor(void *ap_obj, va_list * app)
638{
639   /* NOTE: Class methods might be added in the future. None for now. */
640   return super_ctor(typeOf(ap_obj, "h264eprc_class"), ap_obj, app);
641}
642
643/*
644 * initialization
645 */
646
647void * h264e_prc_class_init(void * ap_tos, void * ap_hdl)
648{
649   void * tizprc = tiz_get_type(ap_hdl, "tizprc");
650   void * h264eprc_class = factory_new
651      /* TIZ_CLASS_COMMENT: class type, class name, parent, size */
652      (classOf(tizprc), "h264eprc_class", classOf(tizprc),
653       sizeof(h264e_prc_class_t),
654       /* TIZ_CLASS_COMMENT: */
655       ap_tos, ap_hdl,
656       /* TIZ_CLASS_COMMENT: class constructor */
657       ctor, h264e_prc_class_ctor,
658       /* TIZ_CLASS_COMMENT: stop value*/
659       0);
660   return h264eprc_class;
661}
662
663void * h264e_prc_init(void * ap_tos, void * ap_hdl)
664{
665   void * tizprc = tiz_get_type(ap_hdl, "tizprc");
666   void * h264eprc_class = tiz_get_type(ap_hdl, "h264eprc_class");
667   TIZ_LOG_CLASS (h264eprc_class);
668   void * h264eprc = factory_new
669      /* TIZ_CLASS_COMMENT: class type, class name, parent, size */
670      (h264eprc_class, "h264eprc", tizprc, sizeof(vid_enc_PrivateType),
671       /* TIZ_CLASS_COMMENT: */
672       ap_tos, ap_hdl,
673       /* TIZ_CLASS_COMMENT: class constructor */
674       ctor, h264e_prc_ctor,
675       /* TIZ_CLASS_COMMENT: class destructor */
676       dtor, h264e_prc_dtor,
677       /* TIZ_CLASS_COMMENT: */
678       tiz_srv_allocate_resources, h264e_prc_allocate_resources,
679       /* TIZ_CLASS_COMMENT: */
680       tiz_srv_deallocate_resources, h264e_prc_deallocate_resources,
681       /* TIZ_CLASS_COMMENT: */
682       tiz_srv_prepare_to_transfer, h264e_prc_prepare_to_transfer,
683       /* TIZ_CLASS_COMMENT: */
684       tiz_srv_transfer_and_process, h264e_prc_transfer_and_process,
685       /* TIZ_CLASS_COMMENT: */
686       tiz_srv_stop_and_return, h264e_prc_stop_and_return,
687       /* TIZ_CLASS_COMMENT: */
688       tiz_prc_buffers_ready, h264e_prc_buffers_ready,
689       /* TIZ_CLASS_COMMENT: */
690       tiz_prc_port_flush, h264e_prc_port_flush,
691       /* TIZ_CLASS_COMMENT: */
692       tiz_prc_port_disable, h264e_prc_port_disable,
693       /* TIZ_CLASS_COMMENT: */
694       tiz_prc_port_enable, h264e_prc_port_enable,
695       /* TIZ_CLASS_COMMENT: stop value*/
696       0);
697
698   return h264eprc;
699}
700