From b2f2236dc565dd1460f0c1d26af905955bf3a6a1 Mon Sep 17 00:00:00 2001 From: Gurkirpal Singh Date: Sat, 20 Jan 2018 07:22:33 +0530 Subject: [PATCH] st/omx/tizonia: Add H.264 encoder v2: Refactor out screen functions to st/omx Example Gstreamer pipeline : gst-launch-1.0 filesrc location=movie.mp4 ! qtdemux ! h264parse ! avdec_h264 ! videoconvert ! omxh264enc ! h264parse ! avdec_h264 ! videoconvert ! ximagesink Acked-by: Leo Liu Reviewed-by: Julien Isorce --- .../state_trackers/omx/Makefile.sources | 4 +- .../state_trackers/omx/bellagio/vid_enc.c | 355 +-------- .../state_trackers/omx/bellagio/vid_enc.h | 48 -- src/gallium/state_trackers/omx/meson.build | 7 +- .../omx/tizonia/Makefile.sources | 11 + .../state_trackers/omx/tizonia/entrypoint.c | 42 +- .../state_trackers/omx/tizonia/h264e.c | 184 +++++ .../state_trackers/omx/tizonia/h264e.h | 55 ++ .../state_trackers/omx/tizonia/h264einport.c | 216 ++++++ .../state_trackers/omx/tizonia/h264einport.h | 31 + .../omx/tizonia/h264einport_decls.h | 48 ++ .../state_trackers/omx/tizonia/h264eoutport.c | 143 ++++ .../state_trackers/omx/tizonia/h264eoutport.h | 31 + .../omx/tizonia/h264eoutport_decls.h | 48 ++ .../state_trackers/omx/tizonia/h264eprc.c | 695 ++++++++++++++++++ .../state_trackers/omx/tizonia/h264eprc.h | 31 + .../state_trackers/omx/vid_enc_common.c | 387 ++++++++++ .../state_trackers/omx/vid_enc_common.h | 173 +++++ 18 files changed, 2106 insertions(+), 403 deletions(-) create mode 100644 src/gallium/state_trackers/omx/tizonia/h264e.c create mode 100644 src/gallium/state_trackers/omx/tizonia/h264e.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264einport.c create mode 100644 src/gallium/state_trackers/omx/tizonia/h264einport.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264einport_decls.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264eoutport.c create mode 100644 src/gallium/state_trackers/omx/tizonia/h264eoutport.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264eoutport_decls.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264eprc.c create mode 100644 src/gallium/state_trackers/omx/tizonia/h264eprc.h create mode 100644 src/gallium/state_trackers/omx/vid_enc_common.c create mode 100644 src/gallium/state_trackers/omx/vid_enc_common.h diff --git a/src/gallium/state_trackers/omx/Makefile.sources b/src/gallium/state_trackers/omx/Makefile.sources index ba9b0beec99..0fb1d9a4d76 100644 --- a/src/gallium/state_trackers/omx/Makefile.sources +++ b/src/gallium/state_trackers/omx/Makefile.sources @@ -4,4 +4,6 @@ C_SOURCES := \ vid_dec_h264_common.c \ vid_dec_h264_common.h \ vid_omx_common.c \ - vid_omx_common.h + vid_omx_common.h \ + vid_enc_common.c \ + vid_enc_common.h diff --git a/src/gallium/state_trackers/omx/bellagio/vid_enc.c b/src/gallium/state_trackers/omx/bellagio/vid_enc.c index a6b09f98e25..1126c4f583d 100644 --- a/src/gallium/state_trackers/omx/bellagio/vid_enc.c +++ b/src/gallium/state_trackers/omx/bellagio/vid_enc.c @@ -49,32 +49,11 @@ #include "pipe/p_screen.h" #include "pipe/p_video_codec.h" #include "util/u_memory.h" -#include "vl/vl_video_buffer.h" #include "entrypoint.h" #include "vid_enc.h" #include "vid_omx_common.h" - -struct encode_task { - struct list_head list; - - struct pipe_video_buffer *buf; - unsigned pic_order_cnt; - struct pipe_resource *bitstream; - void *feedback; -}; - -struct input_buf_private { - struct list_head tasks; - - struct pipe_resource *resource; - struct pipe_transfer *transfer; -}; - -struct output_buf_private { - struct pipe_resource *bitstream; - struct pipe_transfer *transfer; -}; +#include "vid_enc_common.h" static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp); @@ -94,8 +73,6 @@ static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOU static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); -static void enc_ReleaseTasks(struct list_head *head); - OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp) { comp->componentVersion.s.nVersionMajor = 0; @@ -616,66 +593,6 @@ static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, return OMX_ErrorNone; } -static enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile) -{ - switch (omx_profile) { - case OMX_VIDEO_AVCProfileBaseline: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; - case OMX_VIDEO_AVCProfileMain: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; - case OMX_VIDEO_AVCProfileExtended: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED; - case OMX_VIDEO_AVCProfileHigh: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - case OMX_VIDEO_AVCProfileHigh10: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10; - case OMX_VIDEO_AVCProfileHigh422: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422; - case OMX_VIDEO_AVCProfileHigh444: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444; - default: - return PIPE_VIDEO_PROFILE_UNKNOWN; - } -} - -static unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level) -{ - switch (omx_level) { - case OMX_VIDEO_AVCLevel1: - case OMX_VIDEO_AVCLevel1b: - return 10; - case OMX_VIDEO_AVCLevel11: - return 11; - case OMX_VIDEO_AVCLevel12: - return 12; - case OMX_VIDEO_AVCLevel13: - return 13; - case OMX_VIDEO_AVCLevel2: - return 20; - case OMX_VIDEO_AVCLevel21: - return 21; - case OMX_VIDEO_AVCLevel22: - return 22; - case OMX_VIDEO_AVCLevel3: - return 30; - case OMX_VIDEO_AVCLevel31: - return 31; - case OMX_VIDEO_AVCLevel32: - return 32; - case OMX_VIDEO_AVCLevel4: - return 40; - case OMX_VIDEO_AVCLevel41: - return 41; - default: - case OMX_VIDEO_AVCLevel42: - return 42; - case OMX_VIDEO_AVCLevel5: - return 50; - case OMX_VIDEO_AVCLevel51: - return 51; - } -} - static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) { vid_enc_PrivateType* priv = comp->pComponentPrivate; @@ -834,56 +751,7 @@ static struct encode_task *enc_NeedTask(omx_base_PortType *port) OMX_COMPONENTTYPE* comp = port->standCompContainer; vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct pipe_video_buffer templat = {}; - struct encode_task *task; - - if (!LIST_IS_EMPTY(&priv->free_tasks)) { - task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list); - LIST_DEL(&task->list); - return task; - } - - /* allocate a new one */ - task = CALLOC_STRUCT(encode_task); - if (!task) - return NULL; - - templat.buffer_format = PIPE_FORMAT_NV12; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = def->nFrameWidth; - templat.height = def->nFrameHeight; - templat.interlaced = false; - - task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); - if (!task->buf) { - FREE(task); - return NULL; - } - - return task; -} - -static void enc_MoveTasks(struct list_head *from, struct list_head *to) -{ - to->prev->next = from->next; - from->next->prev = to->prev; - from->prev->next = to; - to->prev = from->prev; - LIST_INITHEAD(from); -} - -static void enc_ReleaseTasks(struct list_head *head) -{ - struct encode_task *i, *next; - - if (!head || !head->next) - return; - - LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) { - pipe_resource_reference(&i->bitstream, NULL); - i->buf->destroy(i->buf); - FREE(i); - } + return enc_NeedTask_common(priv, def); } static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf, @@ -892,80 +760,7 @@ static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE OMX_COMPONENTTYPE* comp = port->standCompContainer; vid_enc_PrivateType *priv = comp->pComponentPrivate; OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - struct pipe_box box = {}; - struct input_buf_private *inp = buf->pInputPortPrivate; - - if (!inp->resource) { - struct pipe_sampler_view **views; - void *ptr; - - views = vbuf->get_sampler_view_planes(vbuf); - if (!views) - return OMX_ErrorInsufficientResources; - - ptr = buf->pBuffer; - box.width = def->nFrameWidth; - box.height = def->nFrameHeight; - box.depth = 1; - priv->s_pipe->texture_subdata(priv->s_pipe, views[0]->texture, 0, - PIPE_TRANSFER_WRITE, &box, - ptr, def->nStride, 0); - ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height); - box.width = def->nFrameWidth / 2; - box.height = def->nFrameHeight / 2; - box.depth = 1; - priv->s_pipe->texture_subdata(priv->s_pipe, views[1]->texture, 0, - PIPE_TRANSFER_WRITE, &box, - ptr, def->nStride, 0); - } else { - struct pipe_blit_info blit; - struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf; - - pipe_transfer_unmap(priv->s_pipe, inp->transfer); - - box.width = def->nFrameWidth; - box.height = def->nFrameHeight; - box.depth = 1; - - priv->s_pipe->resource_copy_region(priv->s_pipe, - dst_buf->resources[0], - 0, 0, 0, 0, inp->resource, 0, &box); - - memset(&blit, 0, sizeof(blit)); - blit.src.resource = inp->resource; - blit.src.format = inp->resource->format; - - blit.src.box.x = 0; - blit.src.box.y = def->nFrameHeight; - blit.src.box.width = def->nFrameWidth; - blit.src.box.height = def->nFrameHeight / 2 ; - blit.src.box.depth = 1; - - blit.dst.resource = dst_buf->resources[1]; - blit.dst.format = blit.dst.resource->format; - - blit.dst.box.width = def->nFrameWidth / 2; - blit.dst.box.height = def->nFrameHeight / 2; - blit.dst.box.depth = 1; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - blit.mask = PIPE_MASK_G; - priv->s_pipe->blit(priv->s_pipe, &blit); - - blit.src.box.x = 1; - blit.mask = PIPE_MASK_R; - priv->s_pipe->blit(priv->s_pipe, &blit); - priv->s_pipe->flush(priv->s_pipe, NULL, 0); - - box.width = inp->resource->width0; - box.height = inp->resource->height0; - box.depth = inp->resource->depth0; - buf->pBuffer = priv->s_pipe->transfer_map(priv->s_pipe, inp->resource, 0, - PIPE_TRANSFER_WRITE, &box, - &inp->transfer); - } - - return OMX_ErrorNone; + return enc_LoadImage_common(priv, def, buf, vbuf); } static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **vbuf, unsigned *size) @@ -973,109 +768,14 @@ static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **v OMX_COMPONENTTYPE* comp = port->standCompContainer; vid_enc_PrivateType *priv = comp->pComponentPrivate; OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - struct pipe_video_buffer *src_buf = *vbuf; - struct vl_compositor *compositor = &priv->compositor; - struct vl_compositor_state *s = &priv->cstate; - struct pipe_sampler_view **views; - struct pipe_surface **dst_surface; - unsigned i; - - if (!priv->scale_buffer[priv->current_scale_buffer]) - return; - - views = src_buf->get_sampler_view_planes(src_buf); - dst_surface = priv->scale_buffer[priv->current_scale_buffer]->get_surfaces - (priv->scale_buffer[priv->current_scale_buffer]); - vl_compositor_clear_layers(s); - - for (i = 0; i < VL_MAX_SURFACES; ++i) { - struct u_rect src_rect; - if (!views[i] || !dst_surface[i]) - continue; - src_rect.x0 = 0; - src_rect.y0 = 0; - src_rect.x1 = def->nFrameWidth; - src_rect.y1 = def->nFrameHeight; - if (i > 0) { - src_rect.x1 /= 2; - src_rect.y1 /= 2; - } - vl_compositor_set_rgba_layer(s, compositor, 0, views[i], &src_rect, NULL, NULL); - vl_compositor_render(s, compositor, dst_surface[i], NULL, false); - } - *size = priv->scale.xWidth * priv->scale.xHeight * 2; - *vbuf = priv->scale_buffer[priv->current_scale_buffer++]; - priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS; -} - -static void enc_GetPictureParamPreset(struct pipe_h264_enc_picture_desc *picture) -{ - picture->motion_est.enc_disable_sub_mode = 0x000000fe; - picture->motion_est.enc_ime2_search_range_x = 0x00000001; - picture->motion_est.enc_ime2_search_range_y = 0x00000001; - picture->pic_ctrl.enc_constraint_set_flags = 0x00000040; + enc_ScaleInput_common(priv, def, vbuf, size); } static void enc_ControlPicture(omx_base_PortType *port, struct pipe_h264_enc_picture_desc *picture) { OMX_COMPONENTTYPE* comp = port->standCompContainer; vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct pipe_h264_enc_rate_control *rate_ctrl = &picture->rate_ctrl; - - switch (priv->bitrate.eControlRate) { - case OMX_Video_ControlRateVariable: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; - break; - case OMX_Video_ControlRateConstant: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; - break; - case OMX_Video_ControlRateVariableSkipFrames: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP; - break; - case OMX_Video_ControlRateConstantSkipFrames: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP; - break; - default: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; - break; - } - - rate_ctrl->frame_rate_den = OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT; - rate_ctrl->frame_rate_num = ((priv->frame_rate) >> 16) * rate_ctrl->frame_rate_den; - - if (rate_ctrl->rate_ctrl_method != PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE) { - if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MIN) - rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MIN; - else if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MAX) - rate_ctrl->target_bitrate = priv->bitrate.nTargetBitrate; - else - rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MAX; - rate_ctrl->peak_bitrate = rate_ctrl->target_bitrate; - if (rate_ctrl->target_bitrate < OMX_VID_ENC_BITRATE_MEDIAN) - rate_ctrl->vbv_buffer_size = MIN2((rate_ctrl->target_bitrate * 2.75), OMX_VID_ENC_BITRATE_MEDIAN); - else - rate_ctrl->vbv_buffer_size = rate_ctrl->target_bitrate; - - if (rate_ctrl->frame_rate_num) { - unsigned long long t = rate_ctrl->target_bitrate; - t *= rate_ctrl->frame_rate_den; - rate_ctrl->target_bits_picture = t / rate_ctrl->frame_rate_num; - } else { - rate_ctrl->target_bits_picture = rate_ctrl->target_bitrate; - } - rate_ctrl->peak_bits_picture_integer = rate_ctrl->target_bits_picture; - rate_ctrl->peak_bits_picture_fraction = 0; - } - - picture->quant_i_frames = priv->quant.nQpI; - picture->quant_p_frames = priv->quant.nQpP; - picture->quant_b_frames = priv->quant.nQpB; - - picture->frame_num = priv->frame_num; - picture->ref_idx_l0 = priv->ref_idx_l0; - picture->ref_idx_l1 = priv->ref_idx_l1; - picture->enable_vui = (picture->rate_ctrl.frame_rate_num != 0); - enc_GetPictureParamPreset(picture); + enc_ControlPicture_common(priv, picture); } static void enc_HandleTask(omx_base_PortType *port, struct encode_task *task, @@ -1234,48 +934,5 @@ static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEAD static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) { vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct output_buf_private *outp = output->pOutputPortPrivate; - struct input_buf_private *inp = input->pInputPortPrivate; - struct encode_task *task; - struct pipe_box box = {}; - unsigned size; - - if (!inp || LIST_IS_EMPTY(&inp->tasks)) { - input->nFilledLen = 0; /* mark buffer as empty */ - enc_MoveTasks(&priv->used_tasks, &inp->tasks); - return; - } - - task = LIST_ENTRY(struct encode_task, inp->tasks.next, list); - LIST_DEL(&task->list); - LIST_ADDTAIL(&task->list, &priv->used_tasks); - - if (!task->bitstream) - return; - - /* ------------- map result buffer ----------------- */ - - if (outp->transfer) - pipe_transfer_unmap(priv->t_pipe, outp->transfer); - - pipe_resource_reference(&outp->bitstream, task->bitstream); - pipe_resource_reference(&task->bitstream, NULL); - - box.width = outp->bitstream->width0; - box.height = outp->bitstream->height0; - box.depth = outp->bitstream->depth0; - - output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0, - PIPE_TRANSFER_READ_WRITE, - &box, &outp->transfer); - - /* ------------- get size of result ----------------- */ - - priv->codec->get_feedback(priv->codec, task->feedback, &size); - - output->nOffset = 0; - output->nFilledLen = size; /* mark buffer as full */ - - /* all output buffers contain exactly one frame */ - output->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; + vid_enc_BufferEncoded_common(priv, input, output); } diff --git a/src/gallium/state_trackers/omx/bellagio/vid_enc.h b/src/gallium/state_trackers/omx/bellagio/vid_enc.h index 0a215031c8b..4d2b867261b 100644 --- a/src/gallium/state_trackers/omx/bellagio/vid_enc.h +++ b/src/gallium/state_trackers/omx/bellagio/vid_enc.h @@ -36,61 +36,13 @@ #include #include -#include #include -#include - -#include "util/list.h" - -#include "vl/vl_defines.h" -#include "vl/vl_compositor.h" #define OMX_VID_ENC_BASE_NAME "OMX.mesa.video_encoder" #define OMX_VID_ENC_AVC_NAME "OMX.mesa.video_encoder.avc" #define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" -#define OMX_VID_ENC_BITRATE_MIN 64000 -#define OMX_VID_ENC_BITRATE_MEDIAN 2000000 -#define OMX_VID_ENC_BITRATE_MAX 240000000 -#define OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT 1001 -#define OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_SCALING_WIDTH_DEFAULT 0xffffffff -#define OMX_VID_ENC_SCALING_HEIGHT_DEFAULT 0xffffffff -#define OMX_VID_ENC_IDR_PERIOD_DEFAULT 1000 -#define OMX_VID_ENC_P_PERIOD_DEFAULT 3 - -#define OMX_VID_ENC_NUM_SCALING_BUFFERS 4 - -DERIVEDCLASS(vid_enc_PrivateType, omx_base_filter_PrivateType) -#define vid_enc_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ - struct vl_screen *screen; \ - struct pipe_context *s_pipe; \ - struct pipe_context *t_pipe; \ - struct pipe_video_codec *codec; \ - struct list_head free_tasks; \ - struct list_head used_tasks; \ - struct list_head b_frames; \ - struct list_head stacked_tasks; \ - OMX_U32 frame_rate; \ - OMX_U32 frame_num; \ - OMX_U32 pic_order_cnt; \ - OMX_U32 ref_idx_l0, ref_idx_l1; \ - OMX_BOOL restricted_b_frames; \ - OMX_VIDEO_PARAM_BITRATETYPE bitrate; \ - OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; \ - OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; \ - OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; \ - struct vl_compositor compositor; \ - struct vl_compositor_state cstate; \ - struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; \ - OMX_CONFIG_SCALEFACTORTYPE scale; \ - OMX_U32 current_scale_buffer; \ - OMX_U32 stacked_frames_num; -ENDCLASS(vid_enc_PrivateType) - OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp); #endif diff --git a/src/gallium/state_trackers/omx/meson.build b/src/gallium/state_trackers/omx/meson.build index 33e969814f5..f2daf441175 100644 --- a/src/gallium/state_trackers/omx/meson.build +++ b/src/gallium/state_trackers/omx/meson.build @@ -21,6 +21,7 @@ files_omx = files( 'vid_dec_common.c', 'vid_dec_h264_common.c', + 'vid_enc_common.c', 'vid_omx_common.c' ) @@ -38,7 +39,11 @@ files_omx += files( 'tizonia/entrypoint.c', 'tizonia/h264d.c', 'tizonia/h264dprc.c', - 'tizonia/h264dinport.c' + 'tizonia/h264dinport.c', + 'tizonia/h264e.c', + 'tizonia/h264eprc.c', + 'tizonia/h264einport.c', + 'tizonia/h264eoutport.c' ) endif diff --git a/src/gallium/state_trackers/omx/tizonia/Makefile.sources b/src/gallium/state_trackers/omx/tizonia/Makefile.sources index 41b7a3d4170..7e039d3c5ad 100644 --- a/src/gallium/state_trackers/omx/tizonia/Makefile.sources +++ b/src/gallium/state_trackers/omx/tizonia/Makefile.sources @@ -8,4 +8,15 @@ C_SOURCES := \ h264dinport.c \ h264dinport.h \ h264dinport_decls.h \ + h264e.c \ + h264e.h \ + h264eprc.c \ + h264eprc.h \ + h264einport.h \ + h264einport.c \ + h264einport_decls.h \ + h264einport.h \ + h264eoutport.c \ + h264eoutport_decls.h \ + h264eoutport.h \ names.h diff --git a/src/gallium/state_trackers/omx/tizonia/entrypoint.c b/src/gallium/state_trackers/omx/tizonia/entrypoint.c index df81ee3f517..dc81d5500ae 100644 --- a/src/gallium/state_trackers/omx/tizonia/entrypoint.c +++ b/src/gallium/state_trackers/omx/tizonia/entrypoint.c @@ -38,15 +38,27 @@ #include "h264d.h" #include "h264dprc.h" #include "h264dinport.h" +#include "h264e.h" +#include "h264eprc.h" +#include "h264einport.h" +#include "h264eoutport.h" #include "names.h" OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl) { tiz_role_factory_t h264d_role; - const tiz_role_factory_t * rf_list[] = {&h264d_role}; + tiz_role_factory_t h264e_role; + const tiz_role_factory_t * rf_list[] = {&h264d_role, &h264e_role}; tiz_type_factory_t h264dprc_type; tiz_type_factory_t h264d_inport_type; - const tiz_type_factory_t * tf_list[] = {&h264dprc_type, &h264d_inport_type}; + tiz_type_factory_t h264eprc_type; + tiz_type_factory_t h264e_inport_type; + tiz_type_factory_t h264e_outport_type; + const tiz_type_factory_t * tf_list[] = {&h264dprc_type, + &h264d_inport_type, + &h264eprc_type, + &h264e_inport_type, + &h264e_outport_type}; /* Settings for roles */ strcpy ((OMX_STRING) h264d_role.role, OMX_VID_DEC_AVC_ROLE); @@ -56,6 +68,13 @@ OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl) h264d_role.nports = 2; h264d_role.pf_proc = instantiate_h264d_processor; + strcpy ((OMX_STRING) h264e_role.role, OMX_VID_ENC_AVC_ROLE); + h264e_role.pf_cport = instantiate_h264e_config_port; + h264e_role.pf_port[0] = instantiate_h264e_input_port; + h264e_role.pf_port[1] = instantiate_h264e_output_port; + h264e_role.nports = 2; + h264e_role.pf_proc = instantiate_h264e_processor; + /* Settings for classes */ strcpy ((OMX_STRING) h264dprc_type.class_name, "h264dprc_class"); h264dprc_type.pf_class_init = h264d_prc_class_init; @@ -67,14 +86,29 @@ OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl) strcpy ((OMX_STRING) h264d_inport_type.object_name, "h264dinport"); h264d_inport_type.pf_object_init = h264d_inport_init; + strcpy ((OMX_STRING) h264eprc_type.class_name, "h264eprc_class"); + h264eprc_type.pf_class_init = h264e_prc_class_init; + strcpy ((OMX_STRING) h264eprc_type.object_name, "h264eprc"); + h264eprc_type.pf_object_init = h264e_prc_init; + + strcpy ((OMX_STRING) h264e_inport_type.class_name, "h264einport_class"); + h264e_inport_type.pf_class_init = h264e_inport_class_init; + strcpy ((OMX_STRING) h264e_inport_type.object_name, "h264einport"); + h264e_inport_type.pf_object_init = h264e_inport_init; + + strcpy ((OMX_STRING) h264e_outport_type.class_name, "h264eoutport_class"); + h264e_outport_type.pf_class_init = h264e_outport_class_init; + strcpy ((OMX_STRING) h264e_outport_type.object_name, "h264eoutport"); + h264e_outport_type.pf_object_init = h264e_outport_init; + /* Initialize the component infrastructure */ tiz_comp_init (ap_hdl, OMX_VID_COMP_NAME); /* Classes need to be registered first */ - tiz_comp_register_types (ap_hdl, tf_list, 2); + tiz_comp_register_types (ap_hdl, tf_list, 5); /* Register the component roles */ - tiz_comp_register_roles (ap_hdl, rf_list, 1); + tiz_comp_register_roles (ap_hdl, rf_list, 2); return OMX_ErrorNone; } diff --git a/src/gallium/state_trackers/omx/tizonia/h264e.c b/src/gallium/state_trackers/omx/tizonia/h264e.c new file mode 100644 index 00000000000..8ff4b14c53c --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264e.c @@ -0,0 +1,184 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "h264eprc.h" +#include "h264e.h" +#include "names.h" +#include "vid_enc_common.h" + +static OMX_VERSIONTYPE h264e_encoder_version = {{0, 0, 0, 1}}; + +OMX_PTR instantiate_h264e_input_port(OMX_HANDLETYPE ap_hdl) +{ + OMX_VIDEO_PORTDEFINITIONTYPE portdef; + OMX_VIDEO_CODINGTYPE encodings[] = { + OMX_VIDEO_CodingUnused, + OMX_VIDEO_CodingMax + }; + OMX_COLOR_FORMATTYPE formats[] = { + OMX_COLOR_FormatYUV420SemiPlanar, + OMX_COLOR_FormatMax + }; + tiz_port_options_t rawvideo_port_opts = { + OMX_PortDomainVideo, + OMX_DirInput, + OMX_VID_ENC_AVC_INPUT_PORT_MIN_BUF_COUNT, + OMX_VID_ENC_AVC_PORT_MIN_INPUT_BUF_SIZE, + OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_ENC_AVC_PORT_ALIGNMENT, + OMX_VID_ENC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_ENC_AVC_INPUT_PORT_INDEX, NULL, NULL, NULL}, + 1 /* Slave port */ + }; + + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = 15; + portdef.bFlagErrorConcealment = OMX_FALSE; + portdef.eCompressionFormat = OMX_VIDEO_CodingUnused; + portdef.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + portdef.pNativeWindow = NULL; + + return factory_new(tiz_get_type(ap_hdl, "h264einport"), + &rawvideo_port_opts, &portdef, + &encodings, &formats); +} + +OMX_PTR instantiate_h264e_output_port(OMX_HANDLETYPE ap_hdl) +{ + OMX_VIDEO_PORTDEFINITIONTYPE portdef; + OMX_VIDEO_PARAM_AVCTYPE avctype; + OMX_VIDEO_PARAM_BITRATETYPE bitrate; + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; + + OMX_VIDEO_CODINGTYPE encodings[] = { + OMX_VIDEO_CodingAVC, + OMX_VIDEO_CodingMax + }; + OMX_COLOR_FORMATTYPE formats[] = { + OMX_COLOR_FormatUnused, + OMX_COLOR_FormatMax + }; + tiz_port_options_t avc_port_opts = { + OMX_PortDomainVideo, + OMX_DirOutput, + OMX_VID_ENC_AVC_OUTPUT_PORT_MIN_BUF_COUNT, + OMX_VID_ENC_AVC_PORT_MIN_OUTPUT_BUF_SIZE, + OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_ENC_AVC_PORT_ALIGNMENT, + OMX_VID_ENC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, NULL, NULL, NULL}, + 0 /* Master port */ + }; + OMX_VIDEO_AVCLEVELTYPE levels[] = { + OMX_VIDEO_AVCLevel51, + OMX_VIDEO_AVCLevel1, + OMX_VIDEO_AVCLevel1b, + OMX_VIDEO_AVCLevel11, + OMX_VIDEO_AVCLevel12, + OMX_VIDEO_AVCLevel13, + OMX_VIDEO_AVCLevel2, + OMX_VIDEO_AVCLevel21, + OMX_VIDEO_AVCLevel22, + OMX_VIDEO_AVCLevel3, + OMX_VIDEO_AVCLevel31, + OMX_VIDEO_AVCLevel32, + OMX_VIDEO_AVCLevel4, + OMX_VIDEO_AVCLevel41, + OMX_VIDEO_AVCLevel42, + OMX_VIDEO_AVCLevel5, + OMX_VIDEO_AVCLevelMax + }; + + /* Values set from as given in specification */ + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = 15; + portdef.bFlagErrorConcealment = OMX_FALSE; + portdef.eCompressionFormat = OMX_VIDEO_CodingAVC; + portdef.eColorFormat = OMX_COLOR_FormatUnused; + portdef.pNativeWindow = NULL; + + bitrate.eControlRate = OMX_Video_ControlRateDisable; + bitrate.nTargetBitrate = 0; + + quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; + quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; + quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; + + avctype.nSize = sizeof (OMX_VIDEO_PARAM_AVCTYPE); + avctype.nVersion.nVersion = OMX_VERSION; + avctype.nPortIndex = OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX; + avctype.eProfile = OMX_VIDEO_AVCProfileBaseline; + avctype.nSliceHeaderSpacing = 0; + avctype.nPFrames = 0; + avctype.nBFrames = 0; + avctype.bUseHadamard = OMX_TRUE; + avctype.nRefFrames = 1; + avctype.nRefIdx10ActiveMinus1 = 1; + avctype.nRefIdx11ActiveMinus1 = 0; + avctype.bEnableUEP = OMX_FALSE; + avctype.bEnableFMO = OMX_FALSE; + avctype.bEnableASO = OMX_FALSE; + avctype.bEnableRS = OMX_FALSE; + avctype.eLevel = OMX_VIDEO_AVCLevel51; + avctype.nAllowedPictureTypes = 2; + avctype.bFrameMBsOnly = OMX_FALSE; + avctype.bMBAFF = OMX_FALSE; + avctype.bEntropyCodingCABAC = OMX_FALSE; + avctype.bWeightedPPrediction = OMX_FALSE; + avctype.nWeightedBipredicitonMode = 0; + avctype.bconstIpred = OMX_FALSE; + avctype.bDirect8x8Inference = OMX_FALSE; + avctype.bDirectSpatialTemporal = OMX_FALSE; + avctype.nCabacInitIdc = 0; + avctype.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; + + return factory_new(tiz_get_type(ap_hdl, "h264eoutport"), + &avc_port_opts, &portdef, + &encodings, &formats, &avctype, &levels, + &bitrate, &quant); +} + +OMX_PTR instantiate_h264e_config_port(OMX_HANDLETYPE ap_hdl) +{ + return factory_new(tiz_get_type(ap_hdl, "tizconfigport"), + NULL, /* this port does not take options */ + OMX_VID_COMP_NAME, h264e_encoder_version); +} + +OMX_PTR instantiate_h264e_processor(OMX_HANDLETYPE ap_hdl) +{ + return factory_new(tiz_get_type(ap_hdl, "h264eprc")); +} diff --git a/src/gallium/state_trackers/omx/tizonia/h264e.h b/src/gallium/state_trackers/omx/tizonia/h264e.h new file mode 100644 index 00000000000..de8316c726d --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264e.h @@ -0,0 +1,55 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264E_H +#define H264E_H + +#include +#include +#include + +#define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" + +/* With libtizonia, port indexes must start at index 0 */ +#define OMX_VID_ENC_AVC_INPUT_PORT_INDEX 0 +#define OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX 1 +#define OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH 176 +#define OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT 144 +#define OMX_VID_ENC_AVC_INPUT_PORT_MIN_BUF_COUNT 8 +#define OMX_VID_ENC_AVC_OUTPUT_PORT_MIN_BUF_COUNT 2 +#define OMX_VID_ENC_AVC_PORT_MIN_INPUT_BUF_SIZE 4 * 1024 +#define OMX_VID_ENC_AVC_PORT_MIN_OUTPUT_BUF_SIZE 345600 +#define OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS OMX_FALSE +#define OMX_VID_ENC_AVC_PORT_ALIGNMENT 0 +#define OMX_VID_ENC_AVC_PORT_SUPPLIERPREF OMX_BufferSupplyInput + +OMX_PTR instantiate_h264e_config_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264e_input_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264e_output_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264e_processor(OMX_HANDLETYPE ap_hdl); + +#endif /* H264E_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264einport.c b/src/gallium/state_trackers/omx/tizonia/h264einport.c new file mode 100644 index 00000000000..3f34e05e0b2 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264einport.c @@ -0,0 +1,216 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include +#include + +#include "vl/vl_winsys.h" + +#include "h264e.h" +#include "h264einport.h" +#include "h264einport_decls.h" +#include "vid_enc_common.h" + +static OMX_ERRORTYPE enc_AllocateBackTexture(OMX_HANDLETYPE ap_hdl, + OMX_U32 idx, + struct pipe_resource **resource, + struct pipe_transfer **transfer, + OMX_U8 **map) +{ + vid_enc_PrivateType * priv = tiz_get_prc(ap_hdl); + tiz_port_t * port = tiz_krn_get_port(tiz_get_krn(ap_hdl), idx); + struct pipe_resource buf_templ; + struct pipe_box box = {}; + OMX_U8 *ptr; + + memset(&buf_templ, 0, sizeof buf_templ); + buf_templ.target = PIPE_TEXTURE_2D; + buf_templ.format = PIPE_FORMAT_I8_UNORM; + buf_templ.bind = PIPE_BIND_LINEAR; + buf_templ.usage = PIPE_USAGE_STAGING; + buf_templ.flags = 0; + buf_templ.width0 = port->portdef_.format.video.nFrameWidth; + buf_templ.height0 = port->portdef_.format.video.nFrameHeight * 3 / 2; + buf_templ.depth0 = 1; + buf_templ.array_size = 1; + + *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); + if (!*resource) + return OMX_ErrorInsufficientResources; + + box.width = (*resource)->width0; + box.height = (*resource)->height0; + box.depth = (*resource)->depth0; + ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); + if (map) + *map = ptr; + + return OMX_ErrorNone; +} + +/* + * h264einport class + */ + +static void * h264e_inport_ctor(void * ap_obj, va_list * app) +{ + return super_ctor(typeOf(ap_obj, "h264einport"), ap_obj, app); +} + +static void * h264e_inport_dtor(void * ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264einport"), ap_obj); +} + +/* + * from tiz_api + */ + +static OMX_ERRORTYPE h264e_inport_AllocateBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_BUFFERHEADERTYPE ** buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = super_UseBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, + buf, idx, private, size, NULL); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + LIST_INITHEAD(&inp->tasks); + + r = enc_AllocateBackTexture(ap_hdl, idx, &inp->resource, &inp->transfer, &(*buf)->pBuffer); + + if (r) { + FREE(inp); + super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); + return r; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_inport_UseBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size, OMX_U8 *mem) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = super_UseBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, + buf, idx, private, size, mem); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + LIST_INITHEAD(&inp->tasks); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_inport_FreeBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + vid_enc_PrivateType *priv = tiz_get_prc(ap_hdl); + struct input_buf_private *inp = buf->pInputPortPrivate; + + if (inp) { + enc_ReleaseTasks(&inp->tasks); + if (inp->transfer) + pipe_transfer_unmap(priv->s_pipe, inp->transfer); + pipe_resource_reference(&inp->resource, NULL); + FREE(inp); + } + + return super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, buf); +} + +/* + * h264einport_class + */ + +static void * h264e_inport_class_ctor(void * ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor (typeOf (ap_obj, "h264einport_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264e_inport_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizvideoport = tiz_get_type(ap_hdl, "tizvideoport"); + void * h264einport_class + = factory_new(classOf(tizvideoport), "h264einport_class", + classOf(tizvideoport), sizeof(h264e_inport_class_t), + ap_tos, ap_hdl, ctor, h264e_inport_class_ctor, 0); + return h264einport_class; +} + +void * h264e_inport_init(void * ap_tos, void * ap_hdl) +{ + void * tizvideoport = tiz_get_type (ap_hdl, "tizvideoport"); + void * h264einport_class = tiz_get_type (ap_hdl, "h264einport_class"); + void * h264einport = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264einport_class, "h264einport", tizvideoport, + sizeof (h264e_inport_t), + /* TIZ_CLASS_COMMENT: class constructor */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_inport_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264e_inport_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_api_AllocateBuffer, h264e_inport_AllocateBuffer, + /* TIZ_CLASS_COMMENT: */ + tiz_api_UseBuffer, h264e_inport_UseBuffer, + /* TIZ_CLASS_COMMENT: */ + tiz_api_FreeBuffer, h264e_inport_FreeBuffer, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264einport; +} diff --git a/src/gallium/state_trackers/omx/tizonia/h264einport.h b/src/gallium/state_trackers/omx/tizonia/h264einport.h new file mode 100644 index 00000000000..3dd89061970 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264einport.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EINPORT_H +#define H264EINPORT_H + +void * h264e_inport_class_init(void * ap_tos, void * ap_hdl); +void * h264e_inport_init(void * ap_tos, void * ap_hdl); + +#endif /* H264EINPORT_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264einport_decls.h b/src/gallium/state_trackers/omx/tizonia/h264einport_decls.h new file mode 100644 index 00000000000..9efaf742b84 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264einport_decls.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EINPORT_DECLS_H +#define H264EINPORT_DECLS_H + +#include +#include + +#include + +typedef struct h264e_inport h264e_inport_t; +struct h264e_inport +{ + /* Object */ + const tiz_videoport_t _; +}; + +typedef struct h264e_inport_class h264e_inport_class_t; +struct h264e_inport_class +{ + /* Class */ + const tiz_videoport_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +#endif /* H264EINPORT_DECLS_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264eoutport.c b/src/gallium/state_trackers/omx/tizonia/h264eoutport.c new file mode 100644 index 00000000000..775e04278a4 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264eoutport.c @@ -0,0 +1,143 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include + +#include "vl/vl_winsys.h" + +#include "h264eoutport.h" +#include "h264eoutport_decls.h" +#include "vid_enc_common.h" + +/* + * h264eoutport class + */ + +static void * h264e_outport_ctor(void * ap_obj, va_list * app) +{ + return super_ctor(typeOf(ap_obj, "h264eoutport"), ap_obj, app); +} + +static void * h264e_outport_dtor(void * ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264eoutport"), ap_obj); +} + +/* + * from tiz_api + */ + +static OMX_ERRORTYPE h264e_outport_AllocateBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_BUFFERHEADERTYPE ** buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size) +{ + OMX_ERRORTYPE r; + + r = super_UseBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, + buf, idx, private, size, NULL); + if (r) + return r; + + (*buf)->pBuffer = NULL; + (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); + if (!(*buf)->pOutputPortPrivate) { + super_FreeBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_outport_FreeBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + vid_enc_PrivateType *priv = tiz_get_prc(ap_hdl); + struct output_buf_private *outp = buf->pOutputPortPrivate; + + if (outp) { + if (outp->transfer) + pipe_transfer_unmap(priv->t_pipe, outp->transfer); + pipe_resource_reference(&outp->bitstream, NULL); + FREE(outp); + buf->pOutputPortPrivate = NULL; + } + buf->pBuffer = NULL; + + return super_FreeBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, idx, buf); +} + +/* + * h264e_outport_class + */ + +static void * h264e_outport_class_ctor(void * ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor(typeOf(ap_obj, "h264eoutport_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264e_outport_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); + void * h264eoutport_class + = factory_new (classOf(tizavcport), "h264eoutport_class", + classOf(tizavcport), sizeof(h264e_outport_class_t), + ap_tos, ap_hdl, ctor, h264e_outport_class_ctor, 0); + return h264eoutport_class; +} + +void * h264e_outport_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); + void * h264eoutport_class = tiz_get_type(ap_hdl, "h264eoutport_class"); + void * h264eoutport = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264eoutport_class, "h264eoutport", tizavcport, + sizeof(h264e_outport_t), + /* TIZ_CLASS_COMMENT: class constructor */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_outport_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264e_outport_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_api_AllocateBuffer, h264e_outport_AllocateBuffer, + /* TIZ_CLASS_COMMENT: */ + tiz_api_FreeBuffer, h264e_outport_FreeBuffer, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264eoutport; +} diff --git a/src/gallium/state_trackers/omx/tizonia/h264eoutport.h b/src/gallium/state_trackers/omx/tizonia/h264eoutport.h new file mode 100644 index 00000000000..afbf9fed3f7 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264eoutport.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EOUTPORT_H +#define H264EOUTPORT_H + +void * h264e_outport_class_init(void * ap_tos, void * ap_hdl); +void * h264e_outport_init(void * ap_tos, void * ap_hdl); + +#endif /* H264EOUTPORT_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264eoutport_decls.h b/src/gallium/state_trackers/omx/tizonia/h264eoutport_decls.h new file mode 100644 index 00000000000..28c9e06a0f7 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264eoutport_decls.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EOUTPORT_DECLS_H +#define H264EOUTPORT_DECLS_H + +#include +#include + +#include + +typedef struct h264e_outport h264e_outport_t; +struct h264e_outport +{ + /* Object */ + const tiz_avcport_t _; +}; + +typedef struct h264e_outport_class h264e_outport_class_t; +struct h264e_outport_class +{ + /* Class */ + const tiz_avcport_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +#endif /* H264EOUTPORT_DECLS_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264eprc.c b/src/gallium/state_trackers/omx/tizonia/h264eprc.c new file mode 100644 index 00000000000..586763456f6 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264eprc.c @@ -0,0 +1,695 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" + +#include "entrypoint.h" +#include "h264e.h" +#include "h264eprc.h" +#include "vid_omx_common.h" +#include "vid_enc_common.h" + +static OMX_ERRORTYPE init_port_structs(vid_enc_PrivateType * priv) { + const void * p_krn = NULL; + + assert(priv); + + /* Initialisation */ + TIZ_INIT_OMX_PORT_STRUCT(priv->in_port_def_, + OMX_VID_ENC_AVC_INPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->bitrate, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->quant, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->profile_level, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + + /* Get values */ + p_krn = tiz_get_krn(handleOf(priv)); + + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->in_port_def_))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamVideoBitrate, &(priv->bitrate))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamVideoQuantization, &(priv->quant))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamVideoProfileLevelCurrent, &(priv->profile_level))); + + return OMX_ErrorNone; +} + +static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_enc_PrivateType * priv) { + assert(priv); + + if (priv->in_port_disabled_) { + return NULL; + } + + assert(!priv->p_inhdr_); /* encode_frame expects new buffers every time */ + + tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_INPUT_PORT_INDEX, 0, + &priv->p_inhdr_); + return priv->p_inhdr_; +} + +static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_enc_PrivateType * priv) { + assert(priv); + + if (priv->out_port_disabled_) { + return NULL; + } + + if (!priv->p_outhdr_) { + tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, 0, + &priv->p_outhdr_); + } + return priv->p_outhdr_; +} + +static OMX_ERRORTYPE h264e_buffer_emptied(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + OMX_ERRORTYPE r = OMX_ErrorNone; + + assert(priv); + assert(priv->p_inhdr_ == p_hdr); + + if (!priv->out_port_disabled_) { + p_hdr->nOffset = 0; + + if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) { + priv->eos_ = true; + } + + r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), 0, p_hdr); + priv->p_inhdr_ = NULL; + } + + return r; +} + +static OMX_ERRORTYPE h264e_buffer_filled(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + OMX_ERRORTYPE r = OMX_ErrorNone; + + assert(priv); + assert(priv->p_outhdr_ == p_hdr); + assert(p_hdr); + + if (!priv->in_port_disabled_) { + p_hdr->nOffset = 0; + + if (priv->eos_) { + /* EOS has been received and all the input data has been consumed + * already, so its time to propagate the EOS flag */ + priv->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS; + } + + r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, + p_hdr); + priv->p_outhdr_ = NULL; + } + + return r; +} + + +static void release_input_header(vid_enc_PrivateType * priv) { + assert(!priv->in_port_disabled_); + if (priv->p_inhdr_) { + (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_INPUT_PORT_INDEX, + priv->p_inhdr_); + } + priv->p_inhdr_ = NULL; +} + +static void release_output_header(vid_enc_PrivateType * priv) { + if (priv->p_outhdr_) { + assert(!priv->out_port_disabled_); + (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, + priv->p_outhdr_); + priv->p_outhdr_ = NULL; + } +} + +static OMX_ERRORTYPE h264e_release_all_headers(vid_enc_PrivateType * priv) +{ + assert(priv); + + release_input_header(priv); + release_output_header(priv); + + return OMX_ErrorNone; +} + +static void reset_stream_parameters(vid_enc_PrivateType * priv) +{ + assert(priv); + init_port_structs(priv); + priv->p_inhdr_ = 0; + priv->p_outhdr_ = 0; + priv->eos_ = false; +} + +/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */ +static OMX_ERRORTYPE h264e_manage_buffers(vid_enc_PrivateType* priv) { + OMX_BUFFERHEADERTYPE * in_buf = priv->p_inhdr_; + OMX_BUFFERHEADERTYPE * out_buf = priv->p_outhdr_; + OMX_ERRORTYPE r = OMX_ErrorNone; + + if (in_buf->nFilledLen > 0) { + vid_enc_BufferEncoded_common(priv, in_buf, out_buf); + } else { + in_buf->nFilledLen = 0; + } + + out_buf->nTimeStamp = in_buf->nTimeStamp; + + /* Release input buffer if possible */ + if (in_buf->nFilledLen == 0) { + r = h264e_buffer_emptied(priv, in_buf); + } + + /* Realase output buffer if filled or eos */ + if ((out_buf->nFilledLen != 0) || priv->eos_) { + r = h264e_buffer_filled(priv, out_buf); + } + + return r; +} + +static struct encode_task *enc_NeedTask(vid_enc_PrivateType * priv) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; + + return enc_NeedTask_common(priv, def); +} + +static void enc_ScaleInput(vid_enc_PrivateType * priv, struct pipe_video_buffer **vbuf, unsigned *size) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; + enc_ScaleInput_common(priv, def, vbuf, size); +} + +static void enc_HandleTask(vid_enc_PrivateType * priv, struct encode_task *task, + enum pipe_h264_enc_picture_type picture_type) +{ + unsigned size = priv->out_port_def_.nBufferSize; + struct pipe_video_buffer *vbuf = task->buf; + struct pipe_h264_enc_picture_desc picture = {}; + + /* -------------- scale input image --------- */ + enc_ScaleInput(priv, &vbuf, &size); + priv->s_pipe->flush(priv->s_pipe, NULL, 0); + + /* -------------- allocate output buffer --------- */ + task->bitstream = pipe_buffer_create(priv->s_pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STAGING, /* map for read */ + size); + + picture.picture_type = picture_type; + picture.pic_order_cnt = task->pic_order_cnt; + if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) + picture.not_referenced = true; + enc_ControlPicture_common(priv, &picture); + + /* -------------- encode frame --------- */ + priv->codec->begin_frame(priv->codec, vbuf, &picture.base); + priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); + priv->codec->end_frame(priv->codec, vbuf, &picture.base); +} + +static void enc_ClearBframes(vid_enc_PrivateType * priv, struct input_buf_private *inp) +{ + struct encode_task *task; + + if (LIST_IS_EMPTY(&priv->b_frames)) + return; + + task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); + LIST_DEL(&task->list); + + /* promote last from to P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_P); + LIST_ADDTAIL(&task->list, &inp->tasks); + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); +} + +static OMX_ERRORTYPE enc_LoadImage(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; + return enc_LoadImage_common(priv, def, buf, vbuf); +} + +static OMX_ERRORTYPE encode_frame(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * in_buf) +{ + struct input_buf_private *inp = in_buf->pInputPortPrivate; + enum pipe_h264_enc_picture_type picture_type; + struct encode_task *task; + unsigned stacked_num = 0; + OMX_ERRORTYPE err; + + enc_MoveTasks(&inp->tasks, &priv->free_tasks); + task = enc_NeedTask(priv); + if (!task) + return OMX_ErrorInsufficientResources; + + /* EOS */ + if (in_buf->nFilledLen == 0) { + if (in_buf->nFlags & OMX_BUFFERFLAG_EOS) { + in_buf->nFilledLen = in_buf->nAllocLen; + enc_ClearBframes(priv, inp); + enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); + priv->codec->flush(priv->codec); + } + return h264e_manage_buffers(priv); + } + + if (in_buf->pOutputPortPrivate) { + struct pipe_video_buffer *vbuf = in_buf->pOutputPortPrivate; + in_buf->pOutputPortPrivate = task->buf; + task->buf = vbuf; + } else { + /* ------- load input image into video buffer ---- */ + err = enc_LoadImage(priv, in_buf, task->buf); + if (err != OMX_ErrorNone) { + FREE(task); + return err; + } + } + + /* -------------- determine picture type --------- */ + if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || + priv->force_pic_type.IntraRefreshVOP) { + enc_ClearBframes(priv, inp); + picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || + !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || + (in_buf->nFlags & OMX_BUFFERFLAG_EOS)) { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; + } else { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; + } + + task->pic_order_cnt = priv->pic_order_cnt++; + + if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { + /* put frame at the tail of the queue */ + LIST_ADDTAIL(&task->list, &priv->b_frames); + } else { + /* handle I or P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(priv, task, picture_type); + LIST_ADDTAIL(&task->list, &priv->stacked_tasks); + LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { + ++stacked_num; + } + if (stacked_num == priv->stacked_frames_num) { + struct encode_task *t; + t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); + LIST_DEL(&t->list); + LIST_ADDTAIL(&t->list, &inp->tasks); + } + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); + } + + if (LIST_IS_EMPTY(&inp->tasks)) { + return h264e_buffer_emptied(priv, in_buf); + } else { + return h264e_manage_buffers(priv); + } +} + +static OMX_ERRORTYPE h264e_prc_create_encoder(void *ap_obj) +{ + vid_enc_PrivateType *priv = ap_obj; + struct pipe_screen *screen; + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) + return OMX_ErrorBadParameter; + + priv->s_pipe = screen->context_create(screen, NULL, 0); + if (!priv->s_pipe) + return OMX_ErrorInsufficientResources; + + if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + priv->t_pipe = screen->context_create(screen, NULL, 0); + if (!priv->t_pipe) + return OMX_ErrorInsufficientResources; + + LIST_INITHEAD(&priv->free_tasks); + LIST_INITHEAD(&priv->used_tasks); + LIST_INITHEAD(&priv->b_frames); + LIST_INITHEAD(&priv->stacked_tasks); + + return OMX_ErrorNone; +} + +static void h264e_prc_destroy_encoder(void *ap_obj) +{ + vid_enc_PrivateType *priv = ap_obj; + int i; + + assert (priv); + + enc_ReleaseTasks(&priv->free_tasks); + enc_ReleaseTasks(&priv->used_tasks); + enc_ReleaseTasks(&priv->b_frames); + enc_ReleaseTasks(&priv->stacked_tasks); + + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) + if (priv->scale_buffer[i]) + priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); + + if (priv->s_pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + priv->s_pipe->destroy(priv->s_pipe); + } + + if (priv->t_pipe) + priv->t_pipe->destroy(priv->t_pipe); + + if (priv->screen) + omx_put_screen(); +} + +/* + * h264eprc + */ + +static void * h264e_prc_ctor(void *ap_obj, va_list * app) +{ + vid_enc_PrivateType *priv = super_ctor(typeOf(ap_obj, "h264eprc"), ap_obj, app); + assert (priv); + + if (h264e_prc_create_encoder(ap_obj) != OMX_ErrorNone) + return priv; + + priv->p_inhdr_ = 0; + priv->p_outhdr_ = 0; + priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; + priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + priv->pic_order_cnt = 0; + priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); + priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + priv->in_port_disabled_ = false; + priv->out_port_disabled_ = false; + reset_stream_parameters(priv); + + return priv; +} + +static void * h264e_prc_dtor(void *ap_obj) +{ + h264e_prc_destroy_encoder(ap_obj); + return super_dtor(typeOf(ap_obj, "h264eprc"), ap_obj); +} + +static OMX_ERRORTYPE h264e_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = ap_obj; + + assert(priv); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_deallocate_resources(void *ap_obj) +{ + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = ap_obj; + + assert(priv); + + init_port_structs(priv); + + priv->eos_ = false; + + struct pipe_video_codec templat = {}; + + templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); + templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xWidth : priv->in_port_def_.format.video.nFrameWidth; + templat.height = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xHeight : priv->in_port_def_.format.video.nFrameHeight; + + if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { + struct pipe_screen *screen = priv->screen->pscreen; + templat.max_references = 1; + priv->stacked_frames_num = + screen->get_video_param(screen, + PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, + PIPE_VIDEO_CAP_STACKED_FRAMES); + } else { + templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; + priv->stacked_frames_num = 1; + } + priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid) +{ + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_stop_and_return(void *ap_obj) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + return h264e_release_all_headers(priv); +} + +static OMX_ERRORTYPE h264e_prc_buffers_ready(const void *ap_obj) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + OMX_BUFFERHEADERTYPE *in_buf = NULL; + OMX_BUFFERHEADERTYPE *out_buf = NULL; + OMX_ERRORTYPE r = OMX_ErrorNone; + + assert(priv); + + /* Don't get input buffer if output buffer not found */ + while (!priv->eos_ && (out_buf = get_output_buffer(priv)) && (in_buf = get_input_buffer(priv))) { + if (!priv->out_port_disabled_) { + r = encode_frame(priv, in_buf); + } + } + + return r; +} + +static OMX_ERRORTYPE h264e_prc_port_flush(const void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { + release_input_header(priv); + reset_stream_parameters(priv); + } + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_port_disable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { + /* Release all buffers */ + h264e_release_all_headers(priv); + reset_stream_parameters(priv); + priv->in_port_disabled_ = true; + } + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + priv->out_port_disabled_ = true; + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_port_enable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType * priv = (vid_enc_PrivateType *) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { + if (priv->in_port_disabled_) { + reset_stream_parameters(priv); + priv->in_port_disabled_ = false; + } + } + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { + priv->out_port_disabled_ = false; + } + return OMX_ErrorNone; +} + +/* + * h264e_prc_class + */ + +static void * h264e_prc_class_ctor(void *ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor(typeOf(ap_obj, "h264eprc_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264e_prc_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264eprc_class = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (classOf(tizprc), "h264eprc_class", classOf(tizprc), + sizeof(h264e_prc_class_t), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_prc_class_ctor, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + return h264eprc_class; +} + +void * h264e_prc_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264eprc_class = tiz_get_type(ap_hdl, "h264eprc_class"); + TIZ_LOG_CLASS (h264eprc_class); + void * h264eprc = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264eprc_class, "h264eprc", tizprc, sizeof(vid_enc_PrivateType), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_prc_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264e_prc_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_allocate_resources, h264e_prc_allocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_deallocate_resources, h264e_prc_deallocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_prepare_to_transfer, h264e_prc_prepare_to_transfer, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_transfer_and_process, h264e_prc_transfer_and_process, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_stop_and_return, h264e_prc_stop_and_return, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_buffers_ready, h264e_prc_buffers_ready, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_flush, h264e_prc_port_flush, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_disable, h264e_prc_port_disable, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_enable, h264e_prc_port_enable, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264eprc; +} diff --git a/src/gallium/state_trackers/omx/tizonia/h264eprc.h b/src/gallium/state_trackers/omx/tizonia/h264eprc.h new file mode 100644 index 00000000000..c5bc151a825 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264eprc.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EPRC_H +#define H264EPRC_H + +void * h264e_prc_class_init(void * ap_tos, void * ap_hdl); +void * h264e_prc_init(void * ap_tos, void * ap_hdl); + +#endif /* H264EPRC_H */ diff --git a/src/gallium/state_trackers/omx/vid_enc_common.c b/src/gallium/state_trackers/omx/vid_enc_common.c new file mode 100644 index 00000000000..874dd3a1c82 --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_enc_common.c @@ -0,0 +1,387 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vid_enc_common.h" + +#include "vl/vl_video_buffer.h" + +void enc_ReleaseTasks(struct list_head *head) +{ + struct encode_task *i, *next; + + if (!head || !head->next) + return; + + LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) { + pipe_resource_reference(&i->bitstream, NULL); + i->buf->destroy(i->buf); + FREE(i); + } +} + +void enc_MoveTasks(struct list_head *from, struct list_head *to) +{ + to->prev->next = from->next; + from->next->prev = to->prev; + from->prev->next = to; + to->prev = from->prev; + LIST_INITHEAD(from); +} + +static void enc_GetPictureParamPreset(struct pipe_h264_enc_picture_desc *picture) +{ + picture->motion_est.enc_disable_sub_mode = 0x000000fe; + picture->motion_est.enc_ime2_search_range_x = 0x00000001; + picture->motion_est.enc_ime2_search_range_y = 0x00000001; + picture->pic_ctrl.enc_constraint_set_flags = 0x00000040; +} + +enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile) +{ + switch (omx_profile) { + case OMX_VIDEO_AVCProfileBaseline: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case OMX_VIDEO_AVCProfileMain: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case OMX_VIDEO_AVCProfileExtended: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED; + case OMX_VIDEO_AVCProfileHigh: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + case OMX_VIDEO_AVCProfileHigh10: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10; + case OMX_VIDEO_AVCProfileHigh422: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422; + case OMX_VIDEO_AVCProfileHigh444: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444; + default: + return PIPE_VIDEO_PROFILE_UNKNOWN; + } +} + +unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level) +{ + switch (omx_level) { + case OMX_VIDEO_AVCLevel1: + case OMX_VIDEO_AVCLevel1b: + return 10; + case OMX_VIDEO_AVCLevel11: + return 11; + case OMX_VIDEO_AVCLevel12: + return 12; + case OMX_VIDEO_AVCLevel13: + return 13; + case OMX_VIDEO_AVCLevel2: + return 20; + case OMX_VIDEO_AVCLevel21: + return 21; + case OMX_VIDEO_AVCLevel22: + return 22; + case OMX_VIDEO_AVCLevel3: + return 30; + case OMX_VIDEO_AVCLevel31: + return 31; + case OMX_VIDEO_AVCLevel32: + return 32; + case OMX_VIDEO_AVCLevel4: + return 40; + case OMX_VIDEO_AVCLevel41: + return 41; + default: + case OMX_VIDEO_AVCLevel42: + return 42; + case OMX_VIDEO_AVCLevel5: + return 50; + case OMX_VIDEO_AVCLevel51: + return 51; + } +} + +void vid_enc_BufferEncoded_common(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) +{ + struct output_buf_private *outp = output->pOutputPortPrivate; + struct input_buf_private *inp = input->pInputPortPrivate; + struct encode_task *task; + struct pipe_box box = {}; + unsigned size; + +#if ENABLE_ST_OMX_BELLAGIO + if (!inp || LIST_IS_EMPTY(&inp->tasks)) { + input->nFilledLen = 0; /* mark buffer as empty */ + enc_MoveTasks(&priv->used_tasks, &inp->tasks); + return; + } +#endif + + task = LIST_ENTRY(struct encode_task, inp->tasks.next, list); + LIST_DEL(&task->list); + LIST_ADDTAIL(&task->list, &priv->used_tasks); + + if (!task->bitstream) + return; + + /* ------------- map result buffer ----------------- */ + + if (outp->transfer) + pipe_transfer_unmap(priv->t_pipe, outp->transfer); + + pipe_resource_reference(&outp->bitstream, task->bitstream); + pipe_resource_reference(&task->bitstream, NULL); + + box.width = outp->bitstream->width0; + box.height = outp->bitstream->height0; + box.depth = outp->bitstream->depth0; + + output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0, + PIPE_TRANSFER_READ_WRITE, + &box, &outp->transfer); + + /* ------------- get size of result ----------------- */ + + priv->codec->get_feedback(priv->codec, task->feedback, &size); + + output->nOffset = 0; + output->nFilledLen = size; /* mark buffer as full */ + + /* all output buffers contain exactly one frame */ + output->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; + +#if ENABLE_ST_OMX_TIZONIA + input->nFilledLen = 0; /* mark buffer as empty */ + enc_MoveTasks(&priv->used_tasks, &inp->tasks); +#endif +} + + +struct encode_task *enc_NeedTask_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def) +{ + struct pipe_video_buffer templat = {}; + struct encode_task *task; + + if (!LIST_IS_EMPTY(&priv->free_tasks)) { + task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list); + LIST_DEL(&task->list); + return task; + } + + /* allocate a new one */ + task = CALLOC_STRUCT(encode_task); + if (!task) + return NULL; + + templat.buffer_format = PIPE_FORMAT_NV12; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = def->nFrameWidth; + templat.height = def->nFrameHeight; + templat.interlaced = false; + + task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); + if (!task->buf) { + FREE(task); + return NULL; + } + + return task; +} + +void enc_ScaleInput_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, + struct pipe_video_buffer **vbuf, unsigned *size) +{ + struct pipe_video_buffer *src_buf = *vbuf; + struct vl_compositor *compositor = &priv->compositor; + struct vl_compositor_state *s = &priv->cstate; + struct pipe_sampler_view **views; + struct pipe_surface **dst_surface; + unsigned i; + + if (!priv->scale_buffer[priv->current_scale_buffer]) + return; + + views = src_buf->get_sampler_view_planes(src_buf); + dst_surface = priv->scale_buffer[priv->current_scale_buffer]->get_surfaces + (priv->scale_buffer[priv->current_scale_buffer]); + vl_compositor_clear_layers(s); + + for (i = 0; i < VL_MAX_SURFACES; ++i) { + struct u_rect src_rect; + if (!views[i] || !dst_surface[i]) + continue; + src_rect.x0 = 0; + src_rect.y0 = 0; + src_rect.x1 = def->nFrameWidth; + src_rect.y1 = def->nFrameHeight; + if (i > 0) { + src_rect.x1 /= 2; + src_rect.y1 /= 2; + } + vl_compositor_set_rgba_layer(s, compositor, 0, views[i], &src_rect, NULL, NULL); + vl_compositor_render(s, compositor, dst_surface[i], NULL, false); + } + *size = priv->scale.xWidth * priv->scale.xHeight * 2; + *vbuf = priv->scale_buffer[priv->current_scale_buffer++]; + priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS; +} + +void enc_ControlPicture_common(vid_enc_PrivateType * priv, struct pipe_h264_enc_picture_desc *picture) +{ + struct pipe_h264_enc_rate_control *rate_ctrl = &picture->rate_ctrl; + + /* Get bitrate from port */ + switch (priv->bitrate.eControlRate) { + case OMX_Video_ControlRateVariable: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; + break; + case OMX_Video_ControlRateConstant: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; + break; + case OMX_Video_ControlRateVariableSkipFrames: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP; + break; + case OMX_Video_ControlRateConstantSkipFrames: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP; + break; + default: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; + break; + } + + rate_ctrl->frame_rate_den = OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT; + rate_ctrl->frame_rate_num = ((priv->frame_rate) >> 16) * rate_ctrl->frame_rate_den; + + if (rate_ctrl->rate_ctrl_method != PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE) { + if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MIN) + rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MIN; + else if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MAX) + rate_ctrl->target_bitrate = priv->bitrate.nTargetBitrate; + else + rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MAX; + rate_ctrl->peak_bitrate = rate_ctrl->target_bitrate; + if (rate_ctrl->target_bitrate < OMX_VID_ENC_BITRATE_MEDIAN) + rate_ctrl->vbv_buffer_size = MIN2((rate_ctrl->target_bitrate * 2.75), OMX_VID_ENC_BITRATE_MEDIAN); + else + rate_ctrl->vbv_buffer_size = rate_ctrl->target_bitrate; + + if (rate_ctrl->frame_rate_num) { + unsigned long long t = rate_ctrl->target_bitrate; + t *= rate_ctrl->frame_rate_den; + rate_ctrl->target_bits_picture = t / rate_ctrl->frame_rate_num; + } else { + rate_ctrl->target_bits_picture = rate_ctrl->target_bitrate; + } + rate_ctrl->peak_bits_picture_integer = rate_ctrl->target_bits_picture; + rate_ctrl->peak_bits_picture_fraction = 0; + } + + picture->quant_i_frames = priv->quant.nQpI; + picture->quant_p_frames = priv->quant.nQpP; + picture->quant_b_frames = priv->quant.nQpB; + + picture->frame_num = priv->frame_num; + picture->ref_idx_l0 = priv->ref_idx_l0; + picture->ref_idx_l1 = priv->ref_idx_l1; + picture->enable_vui = (picture->rate_ctrl.frame_rate_num != 0); + enc_GetPictureParamPreset(picture); +} + +OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, + OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf) +{ + struct pipe_box box = {}; + struct input_buf_private *inp = buf->pInputPortPrivate; + + if (!inp->resource) { + struct pipe_sampler_view **views; + void *ptr; + + views = vbuf->get_sampler_view_planes(vbuf); + if (!views) + return OMX_ErrorInsufficientResources; + + ptr = buf->pBuffer; + box.width = def->nFrameWidth; + box.height = def->nFrameHeight; + box.depth = 1; + priv->s_pipe->texture_subdata(priv->s_pipe, views[0]->texture, 0, + PIPE_TRANSFER_WRITE, &box, + ptr, def->nStride, 0); + ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height); + box.width = def->nFrameWidth / 2; + box.height = def->nFrameHeight / 2; + box.depth = 1; + priv->s_pipe->texture_subdata(priv->s_pipe, views[1]->texture, 0, + PIPE_TRANSFER_WRITE, &box, + ptr, def->nStride, 0); + } else { + struct pipe_blit_info blit; + struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf; + + pipe_transfer_unmap(priv->s_pipe, inp->transfer); + + box.width = def->nFrameWidth; + box.height = def->nFrameHeight; + box.depth = 1; + + priv->s_pipe->resource_copy_region(priv->s_pipe, + dst_buf->resources[0], + 0, 0, 0, 0, inp->resource, 0, &box); + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = inp->resource; + blit.src.format = inp->resource->format; + + blit.src.box.x = 0; + blit.src.box.y = def->nFrameHeight; + blit.src.box.width = def->nFrameWidth; + blit.src.box.height = def->nFrameHeight / 2 ; + blit.src.box.depth = 1; + + blit.dst.resource = dst_buf->resources[1]; + blit.dst.format = blit.dst.resource->format; + + blit.dst.box.width = def->nFrameWidth / 2; + blit.dst.box.height = def->nFrameHeight / 2; + blit.dst.box.depth = 1; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + blit.mask = PIPE_MASK_G; + priv->s_pipe->blit(priv->s_pipe, &blit); + + blit.src.box.x = 1; + blit.mask = PIPE_MASK_R; + priv->s_pipe->blit(priv->s_pipe, &blit); + priv->s_pipe->flush(priv->s_pipe, NULL, 0); + + box.width = inp->resource->width0; + box.height = inp->resource->height0; + box.depth = inp->resource->depth0; + buf->pBuffer = priv->s_pipe->transfer_map(priv->s_pipe, inp->resource, 0, + PIPE_TRANSFER_WRITE, &box, + &inp->transfer); + } + + return OMX_ErrorNone; +} diff --git a/src/gallium/state_trackers/omx/vid_enc_common.h b/src/gallium/state_trackers/omx/vid_enc_common.h new file mode 100644 index 00000000000..bdf519db26b --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_enc_common.h @@ -0,0 +1,173 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VID_ENC_COMMON_H +#define VID_ENC_COMMON_H + +#include "util/list.h" +#include "util/u_memory.h" + +#include "vl/vl_defines.h" +#include "vl/vl_compositor.h" +#include "vl/vl_winsys.h" + +#include + +#define OMX_VID_ENC_BITRATE_MIN 64000 +#define OMX_VID_ENC_BITRATE_MEDIAN 2000000 +#define OMX_VID_ENC_BITRATE_MAX 240000000 +#define OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT 1001 +#define OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_SCALING_WIDTH_DEFAULT 0xffffffff +#define OMX_VID_ENC_SCALING_HEIGHT_DEFAULT 0xffffffff +#define OMX_VID_ENC_IDR_PERIOD_DEFAULT 1000 +#define OMX_VID_ENC_P_PERIOD_DEFAULT 3 + +#define OMX_VID_ENC_NUM_SCALING_BUFFERS 4 + +struct encode_task { + struct list_head list; + + struct pipe_video_buffer *buf; + unsigned pic_order_cnt; + struct pipe_resource *bitstream; + void *feedback; +}; + +struct input_buf_private { + struct list_head tasks; + + struct pipe_resource *resource; + struct pipe_transfer *transfer; +}; + +struct output_buf_private { + struct pipe_resource *bitstream; + struct pipe_transfer *transfer; +}; + +#if ENABLE_ST_OMX_BELLAGIO + +#include + +DERIVEDCLASS(vid_enc_PrivateType, omx_base_filter_PrivateType) +#define vid_enc_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ + struct vl_screen *screen; \ + struct pipe_context *s_pipe; \ + struct pipe_context *t_pipe; \ + struct pipe_video_codec *codec; \ + struct list_head free_tasks; \ + struct list_head used_tasks; \ + struct list_head b_frames; \ + struct list_head stacked_tasks; \ + OMX_U32 frame_rate; \ + OMX_U32 frame_num; \ + OMX_U32 pic_order_cnt; \ + OMX_U32 ref_idx_l0, ref_idx_l1; \ + OMX_BOOL restricted_b_frames; \ + OMX_VIDEO_PARAM_BITRATETYPE bitrate; \ + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; \ + OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; \ + OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; \ + struct vl_compositor compositor; \ + struct vl_compositor_state cstate; \ + struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; \ + OMX_CONFIG_SCALEFACTORTYPE scale; \ + OMX_U32 current_scale_buffer; \ + OMX_U32 stacked_frames_num; +ENDCLASS(vid_enc_PrivateType) + +#else + +#include +#include + +typedef struct h264e_prc_class h264e_prc_class_t; +struct h264e_prc_class +{ + /* Class */ + const tiz_prc_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +typedef struct h264e_prc vid_enc_PrivateType; +struct h264e_prc +{ + /* Object */ + const tiz_prc_t _; + OMX_BUFFERHEADERTYPE *p_inhdr_; + OMX_BUFFERHEADERTYPE *p_outhdr_; + OMX_PARAM_PORTDEFINITIONTYPE in_port_def_; + OMX_PARAM_PORTDEFINITIONTYPE out_port_def_; + struct vl_screen *screen; + struct pipe_context *s_pipe; + struct pipe_context *t_pipe; + struct pipe_video_codec *codec; + struct list_head free_tasks; + struct list_head used_tasks; + struct list_head b_frames; + struct list_head stacked_tasks; + OMX_U32 frame_rate; + OMX_U32 frame_num; + OMX_U32 pic_order_cnt; + OMX_U32 ref_idx_l0, ref_idx_l1; + OMX_BOOL restricted_b_frames; + OMX_VIDEO_PARAM_BITRATETYPE bitrate; + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; + OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; + OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; + struct vl_compositor compositor; + struct vl_compositor_state cstate; + struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; + OMX_CONFIG_SCALEFACTORTYPE scale; + OMX_U32 current_scale_buffer; + OMX_U32 stacked_frames_num; + bool eos_; + bool in_port_disabled_; + bool out_port_disabled_; +}; +#endif + +void enc_ReleaseTasks(struct list_head *head); +void enc_MoveTasks(struct list_head *from, struct list_head *to); +enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile); +unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level); +void vid_enc_BufferEncoded_common(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output); +struct encode_task *enc_NeedTask_common(vid_enc_PrivateType * priv, + OMX_VIDEO_PORTDEFINITIONTYPE *def); +void enc_ScaleInput_common(vid_enc_PrivateType * priv, + OMX_VIDEO_PORTDEFINITIONTYPE *def, + struct pipe_video_buffer **vbuf, unsigned *size); +void enc_ControlPicture_common(vid_enc_PrivateType * priv, + struct pipe_h264_enc_picture_desc *picture); +OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, + OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf); +#endif