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