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 <leo.liu@amd.com>
Reviewed-by: Julien Isorce <julien.isorce@gmail.com>
This commit is contained in:
Gurkirpal Singh 2018-01-20 07:22:33 +05:30 committed by Julien Isorce
parent 83d4a5d5ae
commit b2f2236dc5
18 changed files with 2106 additions and 403 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -36,61 +36,13 @@
#include <OMX_Types.h>
#include <OMX_Component.h>
#include <OMX_Core.h>
#include <bellagio/st_static_component_loader.h>
#include <bellagio/omx_base_filter.h>
#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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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 <tizport_decls.h>
#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"));
}

View File

@ -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 <OMX_Core.h>
#include <OMX_Types.h>
#include <OMX_Video.h>
#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 */

View File

@ -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 <assert.h>
#include <string.h>
#include <limits.h>
#include <tizplatform.h>
#include <tizkernel.h>
#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;
}

View File

@ -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 */

View File

@ -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 <OMX_TizoniaExt.h>
#include <OMX_Types.h>
#include <tizvideoport_decls.h>
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 */

View File

@ -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 <assert.h>
#include <string.h>
#include <limits.h>
#include <tizplatform.h>
#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;
}

View File

@ -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 */

View File

@ -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 <OMX_TizoniaExt.h>
#include <OMX_Types.h>
#include <tizavcport_decls.h>
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 */

View File

@ -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 <tizplatform.h>
#include <tizkernel.h>
#include <tizutils.h>
#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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 <OMX_Core.h>
#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 <bellagio/omx_base_filter.h>
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 <tizprc_decls.h>
#include <tizport_decls.h>
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