• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
init_port_structs(vid_enc_PrivateType * priv)42 static 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 
get_input_buffer(vid_enc_PrivateType * priv)81 static 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 
get_output_buffer(vid_enc_PrivateType * priv)96 static 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 
h264e_buffer_emptied(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * p_hdr)111 static 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 
h264e_buffer_filled(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * p_hdr)132 static 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 
release_input_header(vid_enc_PrivateType * priv)159 static 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 
release_output_header(vid_enc_PrivateType * priv)169 static 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 
h264e_release_all_headers(vid_enc_PrivateType * priv)179 static 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 
reset_stream_parameters(vid_enc_PrivateType * priv)189 static 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 */
h264e_manage_buffers(vid_enc_PrivateType * priv)199 static 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 
enc_NeedTask(vid_enc_PrivateType * priv)225 static 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 
enc_ScaleInput(vid_enc_PrivateType * priv,struct pipe_video_buffer ** vbuf,unsigned * size)232 static 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 
enc_HandleTask(vid_enc_PrivateType * priv,struct encode_task * task,enum pipe_h264_enc_picture_type picture_type)238 static void enc_HandleTask(vid_enc_PrivateType * priv, struct encode_task *task,
239                            enum pipe_h264_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_H264_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 
enc_ClearBframes(vid_enc_PrivateType * priv,struct input_buf_private * inp)267 static 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_H264_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_H264_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 
enc_LoadImage(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * buf,struct pipe_video_buffer * vbuf)294 static 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 
encode_frame(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * in_buf)301 static 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_h264_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_H264_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_H264_ENC_PICTURE_TYPE_P;
349    } else {
350       picture_type = PIPE_H264_ENC_PICTURE_TYPE_B;
351    }
352 
353    task->pic_order_cnt = priv->pic_order_cnt++;
354 
355    if (picture_type == PIPE_H264_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_H264_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 
h264e_prc_create_encoder(void * ap_obj)392 static 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 
h264e_prc_destroy_encoder(void * ap_obj)437 static 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 
h264e_prc_ctor(void * ap_obj,va_list * app)471 static 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 
h264e_prc_dtor(void * ap_obj)496 static 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 
h264e_prc_allocate_resources(void * ap_obj,OMX_U32 a_pid)502 static 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 
h264e_prc_deallocate_resources(void * ap_obj)513 static OMX_ERRORTYPE h264e_prc_deallocate_resources(void *ap_obj)
514 {
515    return OMX_ErrorNone;
516 }
517 
h264e_prc_prepare_to_transfer(void * ap_obj,OMX_U32 a_pid)518 static 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 
h264e_prc_transfer_and_process(void * ap_obj,OMX_U32 a_pid)556 static OMX_ERRORTYPE h264e_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid)
557 {
558    return OMX_ErrorNone;
559 }
560 
h264e_prc_stop_and_return(void * ap_obj)561 static 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 
h264e_prc_buffers_ready(const void * ap_obj)567 static 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 
h264e_prc_port_flush(const void * ap_obj,OMX_U32 a_pid)586 static 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 
h264e_prc_port_disable(const void * ap_obj,OMX_U32 a_pid)599 static 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 
h264e_prc_port_enable(const void * ap_obj,OMX_U32 a_pid)616 static 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 
h264e_prc_class_ctor(void * ap_obj,va_list * app)636 static 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 
h264e_prc_class_init(void * ap_tos,void * ap_hdl)646 void * 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 
h264e_prc_init(void * ap_tos,void * ap_hdl)662 void * 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