• 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 "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 
init_port_structs(vid_enc_PrivateType * priv)44 static 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 
get_input_buffer(vid_enc_PrivateType * priv)83 static 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 
get_output_buffer(vid_enc_PrivateType * priv)98 static 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 
h264e_buffer_emptied(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * p_hdr)113 static 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 
h264e_buffer_filled(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * p_hdr)134 static 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 
release_input_header(vid_enc_PrivateType * priv)161 static 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 
release_output_header(vid_enc_PrivateType * priv)171 static 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 
h264e_release_all_headers(vid_enc_PrivateType * priv)181 static 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 
reset_stream_parameters(vid_enc_PrivateType * priv)191 static 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 */
h264e_manage_buffers(vid_enc_PrivateType * priv)201 static 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 
enc_NeedTask(vid_enc_PrivateType * priv)227 static 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 
enc_ScaleInput(vid_enc_PrivateType * priv,struct pipe_video_buffer ** vbuf,unsigned * size)234 static 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 
enc_HandleTask(vid_enc_PrivateType * priv,struct encode_task * task,enum pipe_h2645_enc_picture_type picture_type)240 static 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 
enc_ClearBframes(vid_enc_PrivateType * priv,struct input_buf_private * inp)269 static 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 
enc_LoadImage(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * buf,struct pipe_video_buffer * vbuf)296 static 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 
encode_frame(vid_enc_PrivateType * priv,OMX_BUFFERHEADERTYPE * in_buf)303 static 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 
h264e_prc_create_encoder(void * ap_obj)394 static 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 
h264e_prc_destroy_encoder(void * ap_obj)438 static 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 
h264e_prc_ctor(void * ap_obj,va_list * app)472 static 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 
h264e_prc_dtor(void * ap_obj)497 static 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 
h264e_prc_allocate_resources(void * ap_obj,OMX_U32 a_pid)503 static 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 
h264e_prc_deallocate_resources(void * ap_obj)514 static OMX_ERRORTYPE h264e_prc_deallocate_resources(void *ap_obj)
515 {
516    return OMX_ErrorNone;
517 }
518 
h264e_prc_prepare_to_transfer(void * ap_obj,OMX_U32 a_pid)519 static 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 
h264e_prc_transfer_and_process(void * ap_obj,OMX_U32 a_pid)557 static OMX_ERRORTYPE h264e_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid)
558 {
559    return OMX_ErrorNone;
560 }
561 
h264e_prc_stop_and_return(void * ap_obj)562 static 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 
h264e_prc_buffers_ready(const void * ap_obj)568 static 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 
h264e_prc_port_flush(const void * ap_obj,OMX_U32 a_pid)587 static 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 
h264e_prc_port_disable(const void * ap_obj,OMX_U32 a_pid)600 static 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 
h264e_prc_port_enable(const void * ap_obj,OMX_U32 a_pid)617 static 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 
h264e_prc_class_ctor(void * ap_obj,va_list * app)637 static 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 
h264e_prc_class_init(void * ap_tos,void * ap_hdl)647 void * 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 
h264e_prc_init(void * ap_tos,void * ap_hdl)663 void * 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