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