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