From 83d4a5d5aea5a8a05be2eb3116d2cf3acd201876 Mon Sep 17 00:00:00 2001 From: Gurkirpal Singh Date: Sat, 20 Jan 2018 06:14:17 +0530 Subject: [PATCH] st/omx/tizonia: Add H.264 decoder v2: Refactor out screen functions to st/omx Example Gstreamer pipeline : gst-launch-1.0 filesrc location=movie.mp4 ! qtdemux ! h264parse ! omxh264dec ! videoconvert ! ximagesink Acked-by: Leo Liu Reviewed-by: Julien Isorce --- meson.build | 2 + .../state_trackers/omx/Makefile.sources | 8 +- .../state_trackers/omx/bellagio/entrypoint.c | 83 -- .../state_trackers/omx/bellagio/entrypoint.h | 3 - .../state_trackers/omx/bellagio/vid_dec.c | 142 +- .../state_trackers/omx/bellagio/vid_dec.h | 80 +- .../omx/bellagio/vid_dec_h264.c | 979 +------------- .../state_trackers/omx/bellagio/vid_enc.c | 1 + src/gallium/state_trackers/omx/meson.build | 13 +- .../omx/tizonia/Makefile.sources | 10 +- .../state_trackers/omx/tizonia/entrypoint.c | 43 + .../state_trackers/omx/tizonia/h264d.c | 176 +++ .../state_trackers/omx/tizonia/h264d.h | 40 + .../state_trackers/omx/tizonia/h264dinport.c | 147 +++ .../state_trackers/omx/tizonia/h264dinport.h | 31 + .../omx/tizonia/h264dinport_decls.h | 48 + .../state_trackers/omx/tizonia/h264dprc.c | 519 ++++++++ .../state_trackers/omx/tizonia/h264dprc.h | 31 + .../state_trackers/omx/tizonia/names.h | 30 + .../state_trackers/omx/vid_dec_common.c | 117 ++ .../state_trackers/omx/vid_dec_common.h | 194 +++ .../state_trackers/omx/vid_dec_h264_common.c | 1138 +++++++++++++++++ .../state_trackers/omx/vid_dec_h264_common.h | 99 ++ .../state_trackers/omx/vid_omx_common.c | 111 ++ .../state_trackers/omx/vid_omx_common.h | 36 + 25 files changed, 2795 insertions(+), 1286 deletions(-) create mode 100644 src/gallium/state_trackers/omx/tizonia/h264d.c create mode 100644 src/gallium/state_trackers/omx/tizonia/h264d.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264dinport.c create mode 100644 src/gallium/state_trackers/omx/tizonia/h264dinport.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h create mode 100644 src/gallium/state_trackers/omx/tizonia/h264dprc.c create mode 100644 src/gallium/state_trackers/omx/tizonia/h264dprc.h create mode 100644 src/gallium/state_trackers/omx/tizonia/names.h create mode 100644 src/gallium/state_trackers/omx/vid_dec_common.c create mode 100644 src/gallium/state_trackers/omx/vid_dec_common.h create mode 100644 src/gallium/state_trackers/omx/vid_dec_h264_common.c create mode 100644 src/gallium/state_trackers/omx/vid_dec_h264_common.h create mode 100644 src/gallium/state_trackers/omx/vid_omx_common.c create mode 100644 src/gallium/state_trackers/omx/vid_omx_common.h diff --git a/meson.build b/meson.build index 6a13e800084..dd2fa603829 100644 --- a/meson.build +++ b/meson.build @@ -487,8 +487,10 @@ gallium_omx = _omx dep_omx = [] dep_omx_other = [] if gallium_omx == 'bellagio' + pre_args += '-DENABLE_ST_OMX_BELLAGIO' dep_omx = dependency('libomxil-bellagio') elif gallium_omx == 'tizonia' + pre_args += '-DENABLE_ST_OMX_TIZONIA' dep_omx = dependency('libtizonia', version : '>= 0.10.0') dep_omx_other = [ dependency('libtizplatform'), diff --git a/src/gallium/state_trackers/omx/Makefile.sources b/src/gallium/state_trackers/omx/Makefile.sources index 9103ca899db..ba9b0beec99 100644 --- a/src/gallium/state_trackers/omx/Makefile.sources +++ b/src/gallium/state_trackers/omx/Makefile.sources @@ -1 +1,7 @@ -C_SOURCES := +C_SOURCES := \ + vid_dec_common.c \ + vid_dec_common.h \ + vid_dec_h264_common.c \ + vid_dec_h264_common.h \ + vid_omx_common.c \ + vid_omx_common.h diff --git a/src/gallium/state_trackers/omx/bellagio/entrypoint.c b/src/gallium/state_trackers/omx/bellagio/entrypoint.c index 251cc7d65d5..5c75e8dadaa 100644 --- a/src/gallium/state_trackers/omx/bellagio/entrypoint.c +++ b/src/gallium/state_trackers/omx/bellagio/entrypoint.c @@ -31,33 +31,10 @@ * */ -#include -#include -#include - -#if defined(HAVE_X11_PLATFORM) -#include -#else -#define XOpenDisplay(x) NULL -#define XCloseDisplay(x) -#define Display void -#endif - -#include "os/os_thread.h" -#include "util/u_memory.h" -#include "loader/loader.h" - #include "entrypoint.h" #include "vid_dec.h" #include "vid_enc.h" -static mtx_t omx_lock = _MTX_INITIALIZER_NP; -static Display *omx_display = NULL; -static struct vl_screen *omx_screen = NULL; -static unsigned omx_usecount = 0; -static const char *omx_render_node = NULL; -static int drm_fd; - int omx_component_library_Setup(stLoaderComponentType **stComponents) { OMX_ERRORTYPE r; @@ -78,66 +55,6 @@ int omx_component_library_Setup(stLoaderComponentType **stComponents) return 2; } -struct vl_screen *omx_get_screen(void) -{ - static bool first_time = true; - mtx_lock(&omx_lock); - - if (!omx_screen) { - if (first_time) { - omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL); - first_time = false; - } - if (omx_render_node) { - drm_fd = loader_open_device(omx_render_node); - if (drm_fd < 0) - goto error; - - omx_screen = vl_drm_screen_create(drm_fd); - if (!omx_screen) { - close(drm_fd); - goto error; - } - } else { - omx_display = XOpenDisplay(NULL); - if (!omx_display) - goto error; - - omx_screen = vl_dri3_screen_create(omx_display, 0); - if (!omx_screen) - omx_screen = vl_dri2_screen_create(omx_display, 0); - if (!omx_screen) { - XCloseDisplay(omx_display); - goto error; - } - } - } - - ++omx_usecount; - - mtx_unlock(&omx_lock); - return omx_screen; - -error: - mtx_unlock(&omx_lock); - return NULL; -} - -void omx_put_screen(void) -{ - mtx_lock(&omx_lock); - if ((--omx_usecount) == 0) { - omx_screen->destroy(omx_screen); - omx_screen = NULL; - - if (omx_render_node) - close(drm_fd); - else - XCloseDisplay(omx_display); - } - mtx_unlock(&omx_lock); -} - OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp) { omx_base_component_PrivateType* priv = (omx_base_component_PrivateType*)comp->pComponentPrivate; diff --git a/src/gallium/state_trackers/omx/bellagio/entrypoint.h b/src/gallium/state_trackers/omx/bellagio/entrypoint.h index 7625d7a5b03..d566d1eb5a3 100644 --- a/src/gallium/state_trackers/omx/bellagio/entrypoint.h +++ b/src/gallium/state_trackers/omx/bellagio/entrypoint.h @@ -40,9 +40,6 @@ PUBLIC extern int omx_component_library_Setup(stLoaderComponentType **stComponents); -struct vl_screen *omx_get_screen(void); -void omx_put_screen(void); - OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp); #endif diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec.c b/src/gallium/state_trackers/omx/bellagio/vid_dec.c index f9fe19f63f0..65e612a57fe 100644 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec.c +++ b/src/gallium/state_trackers/omx/bellagio/vid_dec.c @@ -53,6 +53,8 @@ #include "entrypoint.h" #include "vid_dec.h" +#include "vid_omx_common.h" +#include "vid_dec_h264_common.h" static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp); @@ -420,50 +422,6 @@ static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalReq return omx_base_component_MessageHandler(comp, msg); } -void vid_dec_NeedTarget(vid_dec_PrivateType *priv) -{ - struct pipe_video_buffer templat = {}; - struct vl_screen *omx_screen; - struct pipe_screen *pscreen; - - omx_screen = priv->screen; - assert(omx_screen); - - pscreen = omx_screen->pscreen; - assert(pscreen); - - if (!priv->target) { - memset(&templat, 0, sizeof(templat)); - - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = priv->codec->width; - templat.height = priv->codec->height; - templat.buffer_format = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT - ); - templat.interlaced = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERS_INTERLACED - ); - priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat); - } -} - -static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf) -{ - struct pipe_video_buffer *vbuf = buf->pInputPortPrivate; - if (!vbuf) - return; - - vbuf->destroy(vbuf); - buf->pInputPortPrivate = NULL; -} - static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) { OMX_COMPONENTTYPE* comp = port->standCompContainer; @@ -541,104 +499,10 @@ static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, return base_port_FreeBuffer(port, idx, buf); } -static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, - OMX_BUFFERHEADERTYPE* output) -{ - omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - - struct pipe_sampler_view **views; - unsigned i, j; - unsigned width, height; - - views = buf->get_sampler_view_planes(buf); - - for (i = 0; i < 2 /* NV12 */; i++) { - if (!views[i]) continue; - width = def->nFrameWidth; - height = def->nFrameHeight; - vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced); - for (j = 0; j < views[i]->texture->array_size; ++j) { - struct pipe_box box = {0, 0, j, width, height, 1}; - struct pipe_transfer *transfer; - uint8_t *map, *dst; - map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0, - PIPE_TRANSFER_READ, &box, &transfer); - if (!map) - return; - - dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride + - i * def->nFrameWidth * def->nFrameHeight; - util_copy_rect(dst, - views[i]->texture->format, - def->nStride * views[i]->texture->array_size, 0, 0, - box.width, box.height, map, transfer->stride, 0, 0); - - pipe_transfer_unmap(priv->pipe, transfer); - } - } -} - static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) { vid_dec_PrivateType *priv = comp->pComponentPrivate; - bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS); - OMX_TICKS timestamp; - - if (!input->pInputPortPrivate) { - input->pInputPortPrivate = priv->Flush(priv, ×tamp); - if (timestamp != OMX_VID_DEC_TIMESTAMP_INVALID) - input->nTimeStamp = timestamp; - } - - if (input->pInputPortPrivate) { - if (output->pInputPortPrivate && !priv->disable_tunnel) { - struct pipe_video_buffer *tmp, *vbuf, *new_vbuf; - - tmp = output->pOutputPortPrivate; - vbuf = input->pInputPortPrivate; - if (vbuf->interlaced) { - /* re-allocate the progressive buffer */ - omx_base_video_PortType *port; - struct pipe_video_buffer templat = {}; - struct u_rect src_rect, dst_rect; - - port = (omx_base_video_PortType *) - priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - memset(&templat, 0, sizeof(templat)); - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; - templat.buffer_format = PIPE_FORMAT_NV12; - templat.interlaced = false; - new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat); - - /* convert the interlaced to the progressive */ - src_rect.x0 = dst_rect.x0 = 0; - src_rect.x1 = dst_rect.x1 = templat.width; - src_rect.y0 = dst_rect.y0 = 0; - src_rect.y1 = dst_rect.y1 = templat.height; - - vl_compositor_yuv_deint_full(&priv->cstate, &priv->compositor, - input->pInputPortPrivate, new_vbuf, - &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); - - /* set the progrssive buffer for next round */ - vbuf->destroy(vbuf); - input->pInputPortPrivate = new_vbuf; - } - output->pOutputPortPrivate = input->pInputPortPrivate; - input->pInputPortPrivate = tmp; - } else { - vid_dec_FillOutput(priv, input->pInputPortPrivate, output); - } - output->nFilledLen = output->nAllocLen; - output->nTimeStamp = input->nTimeStamp; - } - if (eos && input->pInputPortPrivate) - vid_dec_FreeInputPortPrivate(input); - else - input->nFilledLen = 0; + vid_dec_FrameDecoded_common(priv, input, output); } diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec.h b/src/gallium/state_trackers/omx/bellagio/vid_dec.h index 7a10e750d91..247217810b5 100644 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec.h +++ b/src/gallium/state_trackers/omx/bellagio/vid_dec.h @@ -38,17 +38,10 @@ #include #include -#include -#include -#include -#include - -#include "pipe/p_video_state.h" #include "os/os_thread.h" -#include "util/list.h" -#include "vl/vl_compositor.h" +#include "vid_dec_common.h" #define OMX_VID_DEC_BASE_NAME "OMX.mesa.video_decoder" @@ -63,79 +56,8 @@ #define OMX_VID_DEC_TIMESTAMP_INVALID ((OMX_TICKS) -1) -struct vl_vlc; - -DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType) -#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ - enum pipe_video_profile profile; \ - struct vl_screen *screen; \ - struct pipe_context *pipe; \ - struct pipe_video_codec *codec; \ - void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \ - void (*EndFrame)(vid_dec_PrivateType *priv); \ - struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \ - struct pipe_video_buffer *target, *shadow; \ - union { \ - struct { \ - uint8_t intra_matrix[64]; \ - uint8_t non_intra_matrix[64]; \ - } mpeg12; \ - struct { \ - unsigned nal_ref_idc; \ - bool IdrPicFlag; \ - unsigned idr_pic_id; \ - unsigned pic_order_cnt_lsb; \ - unsigned pic_order_cnt_msb; \ - unsigned delta_pic_order_cnt_bottom; \ - unsigned delta_pic_order_cnt[2]; \ - unsigned prevFrameNumOffset; \ - struct pipe_h264_sps sps[32]; \ - struct pipe_h264_pps pps[256]; \ - struct list_head dpb_list; \ - unsigned dpb_num; \ - } h264; \ - struct { \ - unsigned temporal_id; \ - unsigned level_idc; \ - unsigned pic_width_in_luma_samples; \ - unsigned pic_height_in_luma_samples; \ - bool IdrPicFlag; \ - int slice_prev_poc; \ - void *ref_pic_set_list; \ - void *rps; \ - struct pipe_h265_sps sps[16]; \ - struct pipe_h265_pps pps[64]; \ - struct list_head dpb_list; \ - unsigned dpb_num; \ - } h265; \ - } codec_data; \ - union { \ - struct pipe_picture_desc base; \ - struct pipe_mpeg12_picture_desc mpeg12; \ - struct pipe_h264_picture_desc h264; \ - struct pipe_h265_picture_desc h265; \ - } picture; \ - unsigned num_in_buffers; \ - OMX_BUFFERHEADERTYPE *in_buffers[2]; \ - const void *inputs[2]; \ - unsigned sizes[2]; \ - OMX_TICKS timestamps[2]; \ - OMX_TICKS timestamp; \ - bool first_buf_in_frame; \ - bool frame_finished; \ - bool frame_started; \ - unsigned bytes_left; \ - const void *slice; \ - bool disable_tunnel; \ - struct vl_compositor compositor; \ - struct vl_compositor_state cstate; -ENDCLASS(vid_dec_PrivateType) - OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp); -/* used by MPEG12 and H264 implementation */ -void vid_dec_NeedTarget(vid_dec_PrivateType *priv); - /* vid_dec_mpeg12.c */ void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv); diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c b/src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c index 7ea71c1046b..e8f7aa5cf18 100644 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c +++ b/src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c @@ -39,51 +39,7 @@ #include "entrypoint.h" #include "vid_dec.h" - -#define DPB_MAX_SIZE 5 - -struct dpb_list { - struct list_head list; - struct pipe_video_buffer *buffer; - OMX_TICKS timestamp; - int poc; -}; - -static const uint8_t Default_4x4_Intra[16] = { - 6, 13, 20, 28, 13, 20, 28, 32, - 20, 28, 32, 37, 28, 32, 37, 42 -}; - -static const uint8_t Default_4x4_Inter[16] = { - 10, 14, 20, 24, 14, 20, 24, 27, - 20, 24, 27, 30, 24, 27, 30, 34 -}; - -static const uint8_t Default_8x8_Intra[64] = { - 6, 10, 13, 16, 18, 23, 25, 27, - 10, 11, 16, 18, 23, 25, 27, 29, - 13, 16, 18, 23, 25, 27, 29, 31, - 16, 18, 23, 25, 27, 29, 31, 33, - 18, 23, 25, 27, 29, 31, 33, 36, - 23, 25, 27, 29, 31, 33, 36, 38, - 25, 27, 29, 31, 33, 36, 38, 40, - 27, 29, 31, 33, 36, 38, 40, 42 -}; - -static const uint8_t Default_8x8_Inter[64] = { - 9, 13, 15, 17, 19, 21, 22, 24, - 13, 13, 17, 19, 21, 22, 24, 25, - 15, 17, 19, 21, 22, 24, 25, 27, - 17, 19, 21, 22, 24, 25, 27, 28, - 19, 21, 22, 24, 25, 27, 28, 30, - 21, 22, 24, 25, 27, 28, 30, 32, - 22, 24, 25, 27, 28, 30, 32, 33, - 24, 25, 27, 28, 30, 32, 33, 35 -}; - -static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); -static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv); -static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); +#include "vid_dec_h264_common.h" void vid_dec_h264_Init(vid_dec_PrivateType *priv) { @@ -97,936 +53,3 @@ void vid_dec_h264_Init(vid_dec_PrivateType *priv) priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; priv->first_buf_in_frame = true; } - -static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv) -{ - //TODO: sane buffer handling - - if (priv->frame_started) - return; - - if (!priv->codec) { - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - templat.profile = priv->profile; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.max_references = priv->picture.h264.num_ref_frames; - templat.expect_chunked_decode = true; - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; - templat.level = priv->picture.h264.pps->sps->level_idc; - - priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); - } - - vid_dec_NeedTarget(priv); - - if (priv->first_buf_in_frame) - priv->timestamp = priv->timestamps[0]; - priv->first_buf_in_frame = false; - - priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames; - - priv->picture.h264.slice_count = 0; - priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = true; -} - -static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, - OMX_TICKS *timestamp) -{ - struct dpb_list *entry, *result = NULL; - struct pipe_video_buffer *buf; - - /* search for the lowest poc and break on zeros */ - LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) { - - if (result && entry->poc == 0) - break; - - if (!result || entry->poc < result->poc) - result = entry; - } - - if (!result) - return NULL; - - buf = result->buffer; - if (timestamp) - *timestamp = result->timestamp; - - --priv->codec_data.h264.dpb_num; - LIST_DEL(&result->list); - FREE(result); - - return buf; -} - -static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv) -{ - struct dpb_list *entry; - struct pipe_video_buffer *tmp; - bool top_field_first; - OMX_TICKS timestamp; - - if (!priv->frame_started) - return; - - priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = false; - - // TODO: implement frame number handling - priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num; - priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num; - priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num; - - top_field_first = priv->picture.h264.field_order_cnt[0] < priv->picture.h264.field_order_cnt[1]; - - if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first) - return; - - /* add the decoded picture to the dpb list */ - entry = CALLOC_STRUCT(dpb_list); - if (!entry) - return; - - priv->first_buf_in_frame = true; - entry->buffer = priv->target; - entry->timestamp = priv->timestamp; - entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]); - LIST_ADDTAIL(&entry->list, &priv->codec_data.h264.dpb_list); - ++priv->codec_data.h264.dpb_num; - priv->target = NULL; - priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; - - if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE) - return; - - tmp = priv->in_buffers[0]->pInputPortPrivate; - priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); - priv->in_buffers[0]->nTimeStamp = timestamp; - priv->target = tmp; - priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; -} - -static void vui_parameters(struct vl_rbsp *rbsp) -{ - // TODO -} - -static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList, - const uint8_t *defaultList, const uint8_t *fallbackList) -{ - unsigned lastScale = 8, nextScale = 8; - const int *list; - unsigned i; - - /* (pic|seq)_scaling_list_present_flag[i] */ - if (!vl_rbsp_u(rbsp, 1)) { - if (fallbackList) - memcpy(scalingList, fallbackList, sizeOfScalingList); - return; - } - - list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal; - for (i = 0; i < sizeOfScalingList; ++i ) { - - if (nextScale != 0) { - signed delta_scale = vl_rbsp_se(rbsp); - nextScale = (lastScale + delta_scale + 256) % 256; - if (i == 0 && nextScale == 0) { - memcpy(scalingList, defaultList, sizeOfScalingList); - return; - } - } - scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale; - lastScale = scalingList[list[i]]; - } -} - -static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - if (id >= ARRAY_SIZE(priv->codec_data.h264.sps)) - return NULL; /* invalid seq_parameter_set_id */ - - return &priv->codec_data.h264.sps[id]; -} - -static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h264_sps *sps; - unsigned profile_idc, level_idc; - unsigned i; - - /* Sequence parameter set */ - profile_idc = vl_rbsp_u(rbsp, 8); - - /* constraint_set0_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set1_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set2_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set3_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set4_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set5_flag */ - vl_rbsp_u(rbsp, 1); - - /* reserved_zero_2bits */ - vl_rbsp_u(rbsp, 2); - - /* level_idc */ - level_idc = vl_rbsp_u(rbsp, 8); - - sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memset(sps, 0, sizeof(*sps)); - memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4)); - memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8)); - - sps->level_idc = level_idc; - - if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || - profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || - profile_idc == 128 || profile_idc == 138) { - - sps->chroma_format_idc = vl_rbsp_ue(rbsp); - - if (sps->chroma_format_idc == 3) - sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); - - sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); - - sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); - - /* qpprime_y_zero_transform_bypass_flag */ - vl_rbsp_u(rbsp, 1); - - sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1); - if (sps->seq_scaling_matrix_present_flag) { - - scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra); - scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]); - scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]); - scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter); - scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]); - scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]); - - scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra); - scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter); - if (sps->chroma_format_idc == 3) { - scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]); - scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]); - scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]); - scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]); - } - } - } else if (profile_idc == 183) - sps->chroma_format_idc = 0; - else - sps->chroma_format_idc = 1; - - sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp); - - sps->pic_order_cnt_type = vl_rbsp_ue(rbsp); - - if (sps->pic_order_cnt_type == 0) - sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); - else if (sps->pic_order_cnt_type == 1) { - sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1); - - sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp); - - sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp); - - sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp); - - for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) - sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp); - } - - sps->max_num_ref_frames = vl_rbsp_ue(rbsp); - - /* gaps_in_frame_num_value_allowed_flag */ - vl_rbsp_u(rbsp, 1); - - /* pic_width_in_mbs_minus1 */ - vl_rbsp_ue(rbsp); - - /* pic_height_in_map_units_minus1 */ - vl_rbsp_ue(rbsp); - - sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1); - if (!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1); - - sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1); - - /* frame_cropping_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* frame_crop_left_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_right_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_top_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_bottom_offset */ - vl_rbsp_ue(rbsp); - } - - /* vui_parameters_present_flag */ - if (vl_rbsp_u(rbsp, 1)) - vui_parameters(rbsp); -} - -static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - if (id >= ARRAY_SIZE(priv->codec_data.h264.pps)) - return NULL; /* invalid pic_parameter_set_id */ - - return &priv->codec_data.h264.pps[id]; -} - -static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h264_sps *sps; - struct pipe_h264_pps *pps; - unsigned i; - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - memset(pps, 0, sizeof(*pps)); - - sps = pps->sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4)); - memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8)); - - pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1); - - pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1); - - pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp); - if (pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = vl_rbsp_ue(rbsp); - - if (pps->slice_group_map_type == 0) { - - for (i = 0; i <= pps->num_slice_groups_minus1; ++i) - /* run_length_minus1[i] */ - vl_rbsp_ue(rbsp); - - } else if (pps->slice_group_map_type == 2) { - - for (i = 0; i <= pps->num_slice_groups_minus1; ++i) { - /* top_left[i] */ - vl_rbsp_ue(rbsp); - - /* bottom_right[i] */ - vl_rbsp_ue(rbsp); - } - - } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { - - /* slice_group_change_direction_flag */ - vl_rbsp_u(rbsp, 1); - - pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp); - - } else if (pps->slice_group_map_type == 6) { - - unsigned pic_size_in_map_units_minus1; - - pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp); - - for (i = 0; i <= pic_size_in_map_units_minus1; ++i) - /* slice_group_id[i] */ - vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1)); - } - } - - pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); - - pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); - - pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); - - pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2); - - pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp); - - /* pic_init_qs_minus26 */ - vl_rbsp_se(rbsp); - - pps->chroma_qp_index_offset = vl_rbsp_se(rbsp); - - pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); - - pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); - - pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1); - - if (vl_rbsp_more_data(rbsp)) { - pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1); - - /* pic_scaling_matrix_present_flag */ - if (vl_rbsp_u(rbsp, 1)) { - - scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra, - sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra); - scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]); - scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]); - scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter, - sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter); - scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]); - scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]); - - if (pps->transform_8x8_mode_flag) { - scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra, - sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra); - scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter, - sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Inter); - if (sps->chroma_format_idc == 3) { - scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]); - scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]); - scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]); - scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]); - } - } - } - - pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp); - } -} - -static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - // TODO - assert(0); -} - -static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - enum pipe_h264_slice_type slice_type) -{ - unsigned modification_of_pic_nums_idc; - - if (slice_type != 2 && slice_type != 4) { - /* ref_pic_list_modification_flag_l0 */ - if (vl_rbsp_u(rbsp, 1)) { - do { - modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); - if (modification_of_pic_nums_idc == 0 || - modification_of_pic_nums_idc == 1) - /* abs_diff_pic_num_minus1 */ - vl_rbsp_ue(rbsp); - else if (modification_of_pic_nums_idc == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - } while (modification_of_pic_nums_idc != 3); - } - } - - if (slice_type == 1) { - /* ref_pic_list_modification_flag_l1 */ - if (vl_rbsp_u(rbsp, 1)) { - do { - modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); - if (modification_of_pic_nums_idc == 0 || - modification_of_pic_nums_idc == 1) - /* abs_diff_pic_num_minus1 */ - vl_rbsp_ue(rbsp); - else if (modification_of_pic_nums_idc == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - } while (modification_of_pic_nums_idc != 3); - } - } -} - -static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type) -{ - unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc; - unsigned i, j; - - /* luma_log2_weight_denom */ - vl_rbsp_ue(rbsp); - - if (ChromaArrayType != 0) - /* chroma_log2_weight_denom */ - vl_rbsp_ue(rbsp); - - for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) { - /* luma_weight_l0_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* luma_weight_l0[i] */ - vl_rbsp_se(rbsp); - /* luma_offset_l0[i] */ - vl_rbsp_se(rbsp); - } - if (ChromaArrayType != 0) { - /* chroma_weight_l0_flag */ - if (vl_rbsp_u(rbsp, 1)) { - for (j = 0; j < 2; ++j) { - /* chroma_weight_l0[i][j] */ - vl_rbsp_se(rbsp); - /* chroma_offset_l0[i][j] */ - vl_rbsp_se(rbsp); - } - } - } - } - - if (slice_type == 1) { - for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) { - /* luma_weight_l1_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* luma_weight_l1[i] */ - vl_rbsp_se(rbsp); - /* luma_offset_l1[i] */ - vl_rbsp_se(rbsp); - } - if (ChromaArrayType != 0) { - /* chroma_weight_l1_flag */ - if (vl_rbsp_u(rbsp, 1)) { - for (j = 0; j < 2; ++j) { - /* chroma_weight_l1[i][j] */ - vl_rbsp_se(rbsp); - /* chroma_offset_l1[i][j] */ - vl_rbsp_se(rbsp); - } - } - } - } - } -} - -static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - bool IdrPicFlag) -{ - unsigned memory_management_control_operation; - - if (IdrPicFlag) { - /* no_output_of_prior_pics_flag */ - vl_rbsp_u(rbsp, 1); - /* long_term_reference_flag */ - vl_rbsp_u(rbsp, 1); - } else { - /* adaptive_ref_pic_marking_mode_flag */ - if (vl_rbsp_u(rbsp, 1)) { - do { - memory_management_control_operation = vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 1 || - memory_management_control_operation == 3) - /* difference_of_pic_nums_minus1 */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 3 || - memory_management_control_operation == 6) - /* long_term_frame_idx */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 4) - /* max_long_term_frame_idx_plus1 */ - vl_rbsp_ue(rbsp); - } while (memory_management_control_operation != 0); - } - } -} - -static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - unsigned nal_ref_idc, unsigned nal_unit_type) -{ - enum pipe_h264_slice_type slice_type; - struct pipe_h264_pps *pps; - struct pipe_h264_sps *sps; - unsigned frame_num, prevFrameNum; - bool IdrPicFlag = nal_unit_type == 5; - - if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.IdrPicFlag = IdrPicFlag; - - /* first_mb_in_slice */ - vl_rbsp_ue(rbsp); - - slice_type = vl_rbsp_ue(rbsp) % 5; - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - sps = pps->sps; - if (!sps) - return; - - if (pps != priv->picture.h264.pps) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.pps = pps; - - if (sps->separate_colour_plane_flag == 1 ) - /* colour_plane_id */ - vl_rbsp_u(rbsp, 2); - - frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4); - - if (frame_num != priv->picture.h264.frame_num) - vid_dec_h264_EndFrame(priv); - - prevFrameNum = priv->picture.h264.frame_num; - priv->picture.h264.frame_num = frame_num; - - priv->picture.h264.field_pic_flag = 0; - priv->picture.h264.bottom_field_flag = 0; - - if (!sps->frame_mbs_only_flag) { - unsigned field_pic_flag = vl_rbsp_u(rbsp, 1); - - if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.field_pic_flag = field_pic_flag; - - if (priv->picture.h264.field_pic_flag) { - unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1); - - if (bottom_field_flag != priv->picture.h264.bottom_field_flag) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.bottom_field_flag = bottom_field_flag; - } - } - - if (IdrPicFlag) { - unsigned idr_pic_id = vl_rbsp_ue(rbsp); - - if (idr_pic_id != priv->codec_data.h264.idr_pic_id) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.idr_pic_id = idr_pic_id; - } - - if (sps->pic_order_cnt_type == 0) { - unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4; - unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb; - int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb); - int pic_order_cnt_msb; - - if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb) - vid_dec_h264_EndFrame(priv); - - if (IdrPicFlag) { - priv->codec_data.h264.pic_order_cnt_msb = 0; - priv->codec_data.h264.pic_order_cnt_lsb = 0; - } - - if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) && - (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2)) - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb; - - else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) && - (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2)) - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb; - - else - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb; - - priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb; - priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb; - - if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { - unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; - } - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; - priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] + - priv->codec_data.h264.delta_pic_order_cnt_bottom; - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; - else - priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb; - - } else if (sps->pic_order_cnt_type == 1) { - unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); - unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt; - - if (!sps->delta_pic_order_always_zero_flag) { - unsigned delta_pic_order_cnt[2]; - - delta_pic_order_cnt[0] = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0]) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; - - if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { - delta_pic_order_cnt[1] = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1]) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1]; - } - } - - if (IdrPicFlag) - FrameNumOffset = 0; - else if (prevFrameNum > frame_num) - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; - else - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; - - priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; - - if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) - absFrameNum = FrameNumOffset + frame_num; - else - absFrameNum = 0; - - if (nal_ref_idc == 0 && absFrameNum > 0) - absFrameNum = absFrameNum - 1; - - if (absFrameNum > 0) { - unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; - unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; - signed ExpectedDeltaPerPicOrderCntCycle = 0; - unsigned i; - - for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) - ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i]; - - expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle; - for (i = 0; i <= frameNumInPicOrderCntCycle; ++i) - expectedPicOrderCnt += sps->offset_for_ref_frame[i]; - - } else - expectedPicOrderCnt = 0; - - if (nal_ref_idc == 0) - expectedPicOrderCnt += sps->offset_for_non_ref_pic; - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; - priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] + - sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1]; - - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; - else - priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field + - priv->codec_data.h264.delta_pic_order_cnt[0]; - - } else if (sps->pic_order_cnt_type == 2) { - unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); - unsigned FrameNumOffset, tempPicOrderCnt; - - if (IdrPicFlag) - FrameNumOffset = 0; - else if (prevFrameNum > frame_num) - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; - else - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; - - priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; - - if (IdrPicFlag) - tempPicOrderCnt = 0; - else if (nal_ref_idc == 0) - tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1; - else - tempPicOrderCnt = 2 * (FrameNumOffset + frame_num); - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; - priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; - - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; - else - priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; - } - - if (pps->redundant_pic_cnt_present_flag) - /* redundant_pic_cnt */ - vl_rbsp_ue(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_B) - /* direct_spatial_mv_pred_flag */ - vl_rbsp_u(rbsp, 1); - - priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; - priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; - - if (slice_type == PIPE_H264_SLICE_TYPE_P || - slice_type == PIPE_H264_SLICE_TYPE_SP || - slice_type == PIPE_H264_SLICE_TYPE_B) { - - /* num_ref_idx_active_override_flag */ - if (vl_rbsp_u(rbsp, 1)) { - priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_B) - priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp); - } - } - - if (nal_unit_type == 20 || nal_unit_type == 21) - ref_pic_list_mvc_modification(priv, rbsp); - else - ref_pic_list_modification(priv, rbsp, slice_type); - - if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) || - (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B)) - pred_weight_table(priv, rbsp, sps, slice_type); - - if (nal_ref_idc != 0) - dec_ref_pic_marking(priv, rbsp, IdrPicFlag); - - if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI) - /* cabac_init_idc */ - vl_rbsp_ue(rbsp); - - /* slice_qp_delta */ - vl_rbsp_se(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) { - if (slice_type == PIPE_H264_SLICE_TYPE_SP) - /* sp_for_switch_flag */ - vl_rbsp_u(rbsp, 1); - - /*slice_qs_delta */ - vl_rbsp_se(rbsp); - } - - if (pps->deblocking_filter_control_present_flag) { - unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp); - - if (disable_deblocking_filter_idc != 1) { - /* slice_alpha_c0_offset_div2 */ - vl_rbsp_se(rbsp); - - /* slice_beta_offset_div2 */ - vl_rbsp_se(rbsp); - } - } - - if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) - /* slice_group_change_cycle */ - vl_rbsp_u(rbsp, 2); -} - -static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) -{ - unsigned nal_ref_idc, nal_unit_type; - - if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) - return; - - if (vl_vlc_peekbits(vlc, 24) != 0x000001) { - vl_vlc_eatbits(vlc, 8); - return; - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); - ++priv->picture.h264.slice_count; - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - priv->slice = NULL; - } - - vl_vlc_eatbits(vlc, 24); - - /* forbidden_zero_bit */ - vl_vlc_eatbits(vlc, 1); - - nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2); - - if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc && - (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.nal_ref_idc = nal_ref_idc; - - nal_unit_type = vl_vlc_get_uimsbf(vlc, 5); - - if (nal_unit_type != 1 && nal_unit_type != 5) - vid_dec_h264_EndFrame(priv); - - if (nal_unit_type == 7) { - struct vl_rbsp rbsp; - vl_rbsp_init(&rbsp, vlc, ~0); - seq_parameter_set(priv, &rbsp); - - } else if (nal_unit_type == 8) { - struct vl_rbsp rbsp; - vl_rbsp_init(&rbsp, vlc, ~0); - picture_parameter_set(priv, &rbsp); - - } else if (nal_unit_type == 1 || nal_unit_type == 5) { - /* Coded slice of a non-IDR or IDR picture */ - unsigned bits = vl_vlc_valid_bits(vlc); - unsigned bytes = bits / 8 + 4; - struct vl_rbsp rbsp; - uint8_t buf[8]; - const void *ptr = buf; - unsigned i; - - buf[0] = 0x0; - buf[1] = 0x0; - buf[2] = 0x1; - buf[3] = (nal_ref_idc << 5) | nal_unit_type; - for (i = 4; i < bytes; ++i) - buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); - - priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; - priv->slice = vlc->data; - - vl_rbsp_init(&rbsp, vlc, 128); - slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type); - - vid_dec_h264_BeginFrame(priv); - - ++priv->picture.h264.slice_count; - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &ptr, &bytes); - } - - /* resync to byte boundary */ - vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); -} diff --git a/src/gallium/state_trackers/omx/bellagio/vid_enc.c b/src/gallium/state_trackers/omx/bellagio/vid_enc.c index 2a777bbb91b..a6b09f98e25 100644 --- a/src/gallium/state_trackers/omx/bellagio/vid_enc.c +++ b/src/gallium/state_trackers/omx/bellagio/vid_enc.c @@ -53,6 +53,7 @@ #include "entrypoint.h" #include "vid_enc.h" +#include "vid_omx_common.h" struct encode_task { struct list_head list; diff --git a/src/gallium/state_trackers/omx/meson.build b/src/gallium/state_trackers/omx/meson.build index f6690222190..33e969814f5 100644 --- a/src/gallium/state_trackers/omx/meson.build +++ b/src/gallium/state_trackers/omx/meson.build @@ -18,8 +18,14 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if gallium_omx == 'bellagio' files_omx = files( + 'vid_dec_common.c', + 'vid_dec_h264_common.c', + 'vid_omx_common.c' +) + +if gallium_omx == 'bellagio' +files_omx += files( 'bellagio/entrypoint.c', 'bellagio/vid_dec.c', 'bellagio/vid_dec_mpeg12.c', @@ -28,8 +34,11 @@ files_omx = files( 'bellagio/vid_enc.c' ) elif gallium_omx == 'tizonia' -files_omx = files( +files_omx += files( 'tizonia/entrypoint.c', + 'tizonia/h264d.c', + 'tizonia/h264dprc.c', + 'tizonia/h264dinport.c' ) endif diff --git a/src/gallium/state_trackers/omx/tizonia/Makefile.sources b/src/gallium/state_trackers/omx/tizonia/Makefile.sources index de6fcf926bd..41b7a3d4170 100644 --- a/src/gallium/state_trackers/omx/tizonia/Makefile.sources +++ b/src/gallium/state_trackers/omx/tizonia/Makefile.sources @@ -1,3 +1,11 @@ C_SOURCES := \ entrypoint.c \ - entrypoint.h + entrypoint.h \ + h264d.c \ + h264d.h \ + h264dprc.c \ + h264dprc.h \ + h264dinport.c \ + h264dinport.h \ + h264dinport_decls.h \ + names.h diff --git a/src/gallium/state_trackers/omx/tizonia/entrypoint.c b/src/gallium/state_trackers/omx/tizonia/entrypoint.c index c89bdfdb10a..df81ee3f517 100644 --- a/src/gallium/state_trackers/omx/tizonia/entrypoint.c +++ b/src/gallium/state_trackers/omx/tizonia/entrypoint.c @@ -28,10 +28,53 @@ #include #include #include +#include +#include +#include +#include +#include "vid_dec_h264_common.h" #include "entrypoint.h" +#include "h264d.h" +#include "h264dprc.h" +#include "h264dinport.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_type_factory_t h264dprc_type; + tiz_type_factory_t h264d_inport_type; + const tiz_type_factory_t * tf_list[] = {&h264dprc_type, &h264d_inport_type}; + + /* Settings for roles */ + strcpy ((OMX_STRING) h264d_role.role, OMX_VID_DEC_AVC_ROLE); + h264d_role.pf_cport = instantiate_h264d_config_port; + h264d_role.pf_port[0] = instantiate_h264d_input_port; + h264d_role.pf_port[1] = instantiate_h264d_output_port; + h264d_role.nports = 2; + h264d_role.pf_proc = instantiate_h264d_processor; + + /* Settings for classes */ + strcpy ((OMX_STRING) h264dprc_type.class_name, "h264dprc_class"); + h264dprc_type.pf_class_init = h264d_prc_class_init; + strcpy ((OMX_STRING) h264dprc_type.object_name, "h264dprc"); + h264dprc_type.pf_object_init = h264d_prc_init; + + strcpy ((OMX_STRING) h264d_inport_type.class_name, "h264dinport_class"); + h264d_inport_type.pf_class_init = h264d_inport_class_init; + strcpy ((OMX_STRING) h264d_inport_type.object_name, "h264dinport"); + h264d_inport_type.pf_object_init = h264d_inport_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); + + /* Register the component roles */ + tiz_comp_register_roles (ap_hdl, rf_list, 1); + return OMX_ErrorNone; } diff --git a/src/gallium/state_trackers/omx/tizonia/h264d.c b/src/gallium/state_trackers/omx/tizonia/h264d.c new file mode 100644 index 00000000000..92019a7a4bd --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264d.c @@ -0,0 +1,176 @@ +/************************************************************************** + * + * 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 "vid_dec_h264_common.h" + +#include "h264dprc.h" +#include "h264d.h" +#include "names.h" + +static OMX_VERSIONTYPE h264_decoder_version = {{0, 0, 0, 1}}; + +OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl) +{ + OMX_VIDEO_PORTDEFINITIONTYPE portdef; + OMX_VIDEO_PARAM_AVCTYPE avctype; + 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_DirInput, + OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT, + OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE, + OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_DEC_AVC_PORT_ALIGNMENT, + OMX_VID_DEC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_DEC_AVC_INPUT_PORT_INDEX, NULL, NULL, NULL}, + 1 /* slave port */ + }; + OMX_VIDEO_AVCLEVELTYPE levels[] = { + 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_AVCLevel51, + OMX_VIDEO_AVCLevelMax + }; + + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE; + portdef.bFlagErrorConcealment = OMX_FALSE; + portdef.eCompressionFormat = OMX_VIDEO_CodingAVC; + portdef.eColorFormat = OMX_COLOR_FormatUnused; + portdef.pNativeWindow = NULL; + + avctype.nSize = sizeof (OMX_VIDEO_PARAM_AVCTYPE); + avctype.nVersion.nVersion = OMX_VERSION; + avctype.nPortIndex = OMX_VID_DEC_AVC_INPUT_PORT_INDEX; + avctype.eProfile = OMX_VIDEO_AVCProfileHigh; + /* Encoder related, decide if need to initialise these */ + avctype.nSliceHeaderSpacing = 0; + avctype.nPFrames = 0; + avctype.nBFrames = 0; + avctype.bUseHadamard = OMX_FALSE; + 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, "h264dinport"), + &avc_port_opts, &portdef, + &encodings, &formats, &avctype, &levels, + NULL /* OMX_VIDEO_PARAM_BITRATETYPE */, + NULL /* OMX_VIDEO_PARAM_QUANTIZATIONTYPE */); +} + +OMX_PTR instantiate_h264d_output_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_DirOutput, + OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT, + OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE, + OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_DEC_AVC_PORT_ALIGNMENT, + OMX_VID_DEC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, NULL, NULL, NULL}, + 0 /* Master port */ + }; + + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE; + 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, "tizvideoport"), + &rawvideo_port_opts, &portdef, + &encodings, &formats); +} + +OMX_PTR instantiate_h264d_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, h264_decoder_version); +} + +OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl) +{ + return factory_new(tiz_get_type(ap_hdl, "h264dprc")); +} diff --git a/src/gallium/state_trackers/omx/tizonia/h264d.h b/src/gallium/state_trackers/omx/tizonia/h264d.h new file mode 100644 index 00000000000..1733425d45c --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264d.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * 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 H264D_H +#define H264D_H + +#include +#include +#include + +OMX_PTR instantiate_h264d_config_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264d_output_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl); + +#endif /* H264D_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport.c b/src/gallium/state_trackers/omx/tizonia/h264dinport.c new file mode 100644 index 00000000000..858ae761560 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264dinport.c @@ -0,0 +1,147 @@ +/************************************************************************** + * + * 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 "h264d.h" +#include "h264dinport.h" +#include "h264dinport_decls.h" +#include "vid_dec_common.h" + +/* + * h264dinport class + */ + +static void * h264d_inport_ctor(void * ap_obj, va_list * app) +{ + return super_ctor(typeOf(ap_obj, "h264dinport"), ap_obj, app); +} + +static void * h264d_inport_dtor(void * ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264dinport"), ap_obj); +} + +/* + * from tiz_api + */ + +static OMX_ERRORTYPE h264d_inport_SetParameter(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_INDEXTYPE a_index, OMX_PTR ap_struct) +{ + OMX_ERRORTYPE err = OMX_ErrorNone; + + assert(ap_obj); + assert(ap_hdl); + assert(ap_struct); + + if (a_index == OMX_IndexParamPortDefinition) { + vid_dec_PrivateType * p_prc = tiz_get_prc(ap_hdl); + OMX_VIDEO_PORTDEFINITIONTYPE * p_def = &(p_prc->out_port_def_.format.video); + OMX_PARAM_PORTDEFINITIONTYPE * i_def = (OMX_PARAM_PORTDEFINITIONTYPE *) ap_struct; + + /* Make changes only if there is a resolution change */ + if ((p_def->nFrameWidth == i_def->format.video.nFrameWidth) && + (p_def->nFrameHeight == i_def->format.video.nFrameHeight) && + (p_def->eCompressionFormat == i_def->format.video.eCompressionFormat)) + return err; + + /* Set some default values if not set */ + if (i_def->format.video.nStride == 0) + i_def->format.video.nStride = i_def->format.video.nFrameWidth; + if (i_def->format.video.nSliceHeight == 0) + i_def->format.video.nSliceHeight = i_def->format.video.nFrameHeight; + + err = super_SetParameter(typeOf (ap_obj, "h264dinport"), ap_obj, + ap_hdl, a_index, ap_struct); + if (err == OMX_ErrorNone) { + tiz_port_t * p_obj = (tiz_port_t *) ap_obj; + + /* Set desired buffer size that will be used when allocating input buffers */ + p_obj->portdef_.nBufferSize = i_def->format.video.nFrameWidth * i_def->format.video.nFrameHeight * 512 / (16*16); + + /* Get a locally copy of port def. Useful for the early return above */ + tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(p_prc)), handleOf(p_prc), + OMX_IndexParamPortDefinition, &(p_prc->out_port_def_))); + } + } + + return err; +} + +/* + * h264dinport_class + */ + +static void * h264d_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, "h264dinport_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264d_inport_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); + void * h264dinport_class + = factory_new(classOf(tizavcport), "h264dinport_class", + classOf(tizavcport), sizeof(h264d_inport_class_t), + ap_tos, ap_hdl, ctor, h264d_inport_class_ctor, 0); + return h264dinport_class; +} + +void * h264d_inport_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type (ap_hdl, "tizavcport"); + void * h264dinport_class = tiz_get_type (ap_hdl, "h264dinport_class"); + void * h264dinport = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264dinport_class, "h264dinport", tizavcport, + sizeof (h264d_inport_t), + /* TIZ_CLASS_COMMENT: class constructor */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264d_inport_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264d_inport_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_api_SetParameter, h264d_inport_SetParameter, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264dinport; +} diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport.h b/src/gallium/state_trackers/omx/tizonia/h264dinport.h new file mode 100644 index 00000000000..f158e4e1038 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264dinport.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 H264DINPORT_H +#define H264DINPORT_H + +void * h264d_inport_class_init(void * ap_tos, void * ap_hdl); +void * h264d_inport_init(void * ap_tos, void * ap_hdl); + +#endif /* H264DINPORT_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h b/src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h new file mode 100644 index 00000000000..0194f6e3d09 --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264dinport_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 H264DINPORT_DECLS_H +#define H264DINPORT_DECLS_H + +#include +#include + +#include + +typedef struct h264d_inport h264d_inport_t; +struct h264d_inport +{ + /* Object */ + const tiz_avcport_t _; +}; + +typedef struct h264d_inport_class h264d_inport_class_t; +struct h264d_inport_class +{ + /* Class */ + const tiz_avcport_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +#endif /* H264DINPORT_DECLS_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264dprc.c b/src/gallium/state_trackers/omx/tizonia/h264dprc.c new file mode 100644 index 00000000000..a55e3e9782b --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264dprc.c @@ -0,0 +1,519 @@ +/************************************************************************** + * + * 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 "entrypoint.h" +#include "h264d.h" +#include "h264dprc.h" +#include "vid_omx_common.h" +#include "vid_dec_common.h" +#include "vid_dec_h264_common.h" + +#include "vl/vl_video_buffer.h" +#include "vl/vl_compositor.h" +#include "util/u_surface.h" + +unsigned dec_frame_delta; + +static void release_input_headers(vid_dec_PrivateType* priv) { + int i; + for (i = 0; i < priv->num_in_buffers; i++) { + assert(!priv->in_port_disabled_); + if (priv->in_buffers[i]->pInputPortPrivate) { + vid_dec_FreeInputPortPrivate(priv->in_buffers[i]); + } + (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_INPUT_PORT_INDEX, + priv->in_buffers[i]); + priv->in_buffers[i] = NULL; + } + priv->p_inhdr_ = NULL; + priv->num_in_buffers = 0; +} + +static void release_output_header(vid_dec_PrivateType* priv) { + if (priv->p_outhdr_) { + assert(!priv->out_port_disabled_); + (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + priv->p_outhdr_); + priv->p_outhdr_ = NULL; + } +} + +static OMX_ERRORTYPE h264d_release_all_headers(vid_dec_PrivateType* priv) +{ + assert(priv); + release_input_headers(priv); + release_output_header(priv); + + return OMX_ErrorNone; +} + +static void h264d_buffer_emptied(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + assert(priv); + assert(priv->in_buffers[0] == p_hdr); + + if (!priv->out_port_disabled_) { + assert (p_hdr->nFilledLen == 0); + p_hdr->nOffset = 0; + + if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) { + priv->eos_ = true; + } + + (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), 0, p_hdr); + priv->p_inhdr_ = NULL; + priv->in_buffers[0] = NULL; + } +} + +static void h264d_buffer_filled(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + assert(priv); + assert(p_hdr); + assert(priv->p_outhdr_ == 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; + priv->eos_ = false; + } + + (void) tiz_krn_release_buffer(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + p_hdr); + priv->p_outhdr_ = NULL; + } +} + +static bool h264d_shift_buffers_left(vid_dec_PrivateType* priv) { + if (--priv->num_in_buffers) { + priv->in_buffers[0] = priv->in_buffers[1]; + priv->sizes[0] = priv->sizes[1] - dec_frame_delta; + priv->inputs[0] = priv->inputs[1] + dec_frame_delta; + priv->timestamps[0] = priv->timestamps[1]; + + return true; + } + return false; +} + +static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_dec_PrivateType* priv) { + assert(priv); + + if (priv->in_port_disabled_) { + return NULL; + } + + if (priv->num_in_buffers > 1) { + /* The input buffer wasn't cleared last time. */ + h264d_buffer_emptied(priv, priv->in_buffers[0]); + if (priv->in_buffers[0]) { + /* Failed to release buffer */ + return NULL; + } + h264d_shift_buffers_left(priv); + } + + /* Decode_frame expects new buffers each time */ + assert(priv->p_inhdr_ || priv->first_buf_in_frame); + tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_INPUT_PORT_INDEX, 0, + &priv->p_inhdr_); + return priv->p_inhdr_; +} + +static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_dec_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_DEC_AVC_OUTPUT_PORT_INDEX, 0, + &priv->p_outhdr_); + } + return priv->p_outhdr_; +} + +static void reset_stream_parameters(vid_dec_PrivateType* apriv) +{ + assert(apriv); + TIZ_INIT_OMX_PORT_STRUCT(apriv->out_port_def_, + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); + + tiz_api_GetParameter (tiz_get_krn (handleOf (apriv)), handleOf (apriv), + OMX_IndexParamPortDefinition, &(apriv->out_port_def_)); + + apriv->p_inhdr_ = 0; + apriv->num_in_buffers = 0; + apriv->first_buf_in_frame = true; + apriv->eos_ = false; + apriv->frame_finished = false; + apriv->frame_started = false; + apriv->picture.h264.field_order_cnt[0] = apriv->picture.h264.field_order_cnt[1] = INT_MAX; + apriv->slice = NULL; +} + +/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */ +static void h264d_manage_buffers(vid_dec_PrivateType* priv) { + bool next_is_eos = priv->num_in_buffers == 2 ? !!(priv->in_buffers[1]->nFlags & OMX_BUFFERFLAG_EOS) : false; + vid_dec_FrameDecoded_common(priv, priv->in_buffers[0], priv->p_outhdr_); + + priv->p_outhdr_->nTimeStamp = priv->in_buffers[0]->nTimeStamp; + + /* Realase output buffer if filled or eos + Keep if two input buffers are being decoded */ + if ((!next_is_eos) && ((priv->p_outhdr_->nFilledLen > 0) || priv->eos_)) { + h264d_buffer_filled(priv, priv->p_outhdr_); + } + + /* Release input buffer if possible */ + if (priv->in_buffers[0]->nFilledLen == 0) { + h264d_buffer_emptied(priv, priv->in_buffers[0]); + } +} + +static OMX_ERRORTYPE decode_frame(vid_dec_PrivateType*priv, + OMX_BUFFERHEADERTYPE *in_buf) +{ + unsigned i = priv->num_in_buffers++; + priv->in_buffers[i] = in_buf; + priv->sizes[i] = in_buf->nFilledLen; + priv->inputs[i] = in_buf->pBuffer; + priv->timestamps[i] = in_buf->nTimeStamp; + + while (priv->num_in_buffers > (!!(in_buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { + priv->eos_ = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); + unsigned min_bits_left = priv->eos_ ? 32 : MAX2(in_buf->nFilledLen * 8, 32); + struct vl_vlc vlc; + + vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); + + if (priv->slice) + priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; + + while (vl_vlc_bits_left (&vlc) > min_bits_left) { + vid_dec_h264_Decode(priv, &vlc, min_bits_left); + vl_vlc_fillbits(&vlc); + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; + + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + + if (priv->num_in_buffers) + priv->slice = priv->inputs[1]; + else + priv->slice = NULL; + } + + if (priv->eos_ && priv->frame_started) + vid_dec_h264_EndFrame(priv); + + if (priv->frame_finished) { + priv->frame_finished = false; + h264d_manage_buffers(priv); + } else if (priv->eos_) { + vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); + h264d_manage_buffers(priv); + } else { + priv->in_buffers[0]->nFilledLen = 0; + h264d_buffer_emptied(priv, priv->in_buffers[0]); + } + + if (priv->out_port_disabled_) { + /* In case out port is disabled, h264d_buffer_emptied will fail to release input port. + * We need to wait before shifting the buffers in that case and check in + * get_input_buffer when out port is enabled to release and shift the buffers. + * Infinite looping occurs if buffer is not released */ + if (priv->num_in_buffers == 2) { + /* Set the delta value for use in get_input_buffer before exiting */ + dec_frame_delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); + } + break; + } + + h264d_shift_buffers_left(priv); + } + + return OMX_ErrorNone; +} + +/* + * h264dprc + */ + +static void * h264d_prc_ctor(void *ap_obj, va_list * app) +{ + vid_dec_PrivateType*priv = super_ctor(typeOf (ap_obj, "h264dprc"), ap_obj, app); + assert(priv); + priv->p_inhdr_ = 0; + priv->p_outhdr_ = 0; + priv->first_buf_in_frame = true; + priv->eos_ = false; + priv->in_port_disabled_ = false; + priv->out_port_disabled_ = false; + priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + reset_stream_parameters(priv); + + return priv; +} + +static void * h264d_prc_dtor(void *ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264dprc"), ap_obj); +} + +static OMX_ERRORTYPE h264d_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = ap_obj; + struct pipe_screen *screen; + + assert (priv); + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + priv->pipe = screen->context_create(screen, priv->screen, 0); + if (!priv->pipe) + return OMX_ErrorInsufficientResources; + + if (!vl_compositor_init(&priv->compositor, priv->pipe)) { + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + LIST_INITHEAD(&priv->codec_data.h264.dpb_list); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_deallocate_resources(void *ap_obj) +{ + vid_dec_PrivateType*priv = ap_obj; + assert(priv); + + if (priv->pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + } + + if (priv->screen) + omx_put_screen(); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = ap_obj; + assert(priv); + + TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_, + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); + tiz_check_omx( + tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_))); + + priv->first_buf_in_frame = true; + priv->eos_ = false; + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid) +{ + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_stop_and_return(void *ap_obj) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + return h264d_release_all_headers (priv); +} + +static OMX_ERRORTYPE h264d_prc_buffers_ready(const void *ap_obj) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + OMX_BUFFERHEADERTYPE *in_buf = NULL; + OMX_BUFFERHEADERTYPE *out_buf = NULL; + + assert(priv); + + /* Set parameters if start of stream */ + if (!priv->eos_ && priv->first_buf_in_frame && (in_buf = get_input_buffer(priv))) { + decode_frame(priv, in_buf); + } + + /* 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_) { + decode_frame(priv, in_buf); + } + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_port_flush(const void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { + release_input_headers(priv); + reset_stream_parameters(priv); + } + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_port_disable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { + /* Release all buffers */ + h264d_release_all_headers(priv); + reset_stream_parameters(priv); + priv->in_port_disabled_ = true; + } + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + priv->out_port_disabled_ = true; + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_port_enable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType* priv = (vid_dec_PrivateType*) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_DEC_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_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { + priv->out_port_disabled_ = false; + } + return OMX_ErrorNone; +} + +/* + * h264d_prc_class + */ + +static void * h264d_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, "h264dprc_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264d_prc_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264dprc_class = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (classOf(tizprc), "h264dprc_class", classOf(tizprc), + sizeof(h264d_prc_class_t), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264d_prc_class_ctor, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + return h264dprc_class; +} + +void * h264d_prc_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264dprc_class = tiz_get_type(ap_hdl, "h264dprc_class"); + TIZ_LOG_CLASS (h264dprc_class); + void * h264dprc = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264dprc_class, "h264dprc", tizprc, sizeof(vid_dec_PrivateType), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264d_prc_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264d_prc_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_allocate_resources, h264d_prc_allocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_deallocate_resources, h264d_prc_deallocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_prepare_to_transfer, h264d_prc_prepare_to_transfer, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_transfer_and_process, h264d_prc_transfer_and_process, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_stop_and_return, h264d_prc_stop_and_return, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_buffers_ready, h264d_prc_buffers_ready, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_flush, h264d_prc_port_flush, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_disable, h264d_prc_port_disable, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_enable, h264d_prc_port_enable, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264dprc; +} diff --git a/src/gallium/state_trackers/omx/tizonia/h264dprc.h b/src/gallium/state_trackers/omx/tizonia/h264dprc.h new file mode 100644 index 00000000000..08af5491a3e --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/h264dprc.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 H264DPRC_H +#define H264DPRC_H + +void * h264d_prc_class_init(void * ap_tos, void * ap_hdl); +void * h264d_prc_init(void * ap_tos, void * ap_hdl); + +#endif /* H264DPRC_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/names.h b/src/gallium/state_trackers/omx/tizonia/names.h new file mode 100644 index 00000000000..edde7df396a --- /dev/null +++ b/src/gallium/state_trackers/omx/tizonia/names.h @@ -0,0 +1,30 @@ +/************************************************************************** + * + * 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 OMX_TIZ_NAMES_H +#define OMX_TIZ_NAMES_H + +#define OMX_VID_COMP_NAME "OMX.mesa.video.all" + +#endif diff --git a/src/gallium/state_trackers/omx/vid_dec_common.c b/src/gallium/state_trackers/omx/vid_dec_common.c new file mode 100644 index 00000000000..56010ca0aea --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_dec_common.c @@ -0,0 +1,117 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +#if ENABLE_ST_OMX_TIZONIA +#include +#endif + +#include "util/u_memory.h" +#include "vl/vl_winsys.h" +#include "vl/vl_video_buffer.h" +#include "util/u_surface.h" + +#include "vid_dec_common.h" +#include "vid_dec_h264_common.h" + +void vid_dec_NeedTarget(vid_dec_PrivateType *priv) +{ + struct pipe_video_buffer templat = {}; + struct vl_screen *omx_screen; + struct pipe_screen *pscreen; + + omx_screen = priv->screen; + assert(omx_screen); + + pscreen = omx_screen->pscreen; + assert(pscreen); + + if (!priv->target) { + memset(&templat, 0, sizeof(templat)); + + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = priv->codec->width; + templat.height = priv->codec->height; + templat.buffer_format = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT + ); + templat.interlaced = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED + ); + + priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat); + } +} + +void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, + OMX_BUFFERHEADERTYPE* output) +{ +#if ENABLE_ST_OMX_TIZONIA + tiz_port_t *out_port = tiz_krn_get_port(tiz_get_krn(handleOf(priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); + OMX_VIDEO_PORTDEFINITIONTYPE *def = &out_port->portdef_.format.video; +#else + omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; +#endif + + struct pipe_sampler_view **views; + unsigned i, j; + unsigned width, height; + + views = buf->get_sampler_view_planes(buf); + + for (i = 0; i < 2 /* NV12 */; i++) { + if (!views[i]) continue; + width = def->nFrameWidth; + height = def->nFrameHeight; + vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced); + for (j = 0; j < views[i]->texture->array_size; ++j) { + struct pipe_box box = {0, 0, j, width, height, 1}; + struct pipe_transfer *transfer; + uint8_t *map, *dst; + map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0, + PIPE_TRANSFER_READ, &box, &transfer); + if (!map) + return; + + dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride + + i * def->nFrameWidth * def->nFrameHeight; + util_copy_rect(dst, + views[i]->texture->format, + def->nStride * views[i]->texture->array_size, 0, 0, + box.width, box.height, map, transfer->stride, 0, 0); + + pipe_transfer_unmap(priv->pipe, transfer); + } + } +} diff --git a/src/gallium/state_trackers/omx/vid_dec_common.h b/src/gallium/state_trackers/omx/vid_dec_common.h new file mode 100644 index 00000000000..dea7149da86 --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_dec_common.h @@ -0,0 +1,194 @@ +/************************************************************************** + * + * 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_DEC_COMMON_H +#define VID_DEC_COMMON_H + +#include "util/list.h" + +#include "vl/vl_compositor.h" +#include "vl/vl_rbsp.h" +#include "vl/vl_zscan.h" + +#include +#include + +#if ENABLE_ST_OMX_BELLAGIO + +#include +#include +#include + +DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType) +#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ + enum pipe_video_profile profile; \ + struct vl_screen *screen; \ + struct pipe_context *pipe; \ + struct pipe_video_codec *codec; \ + void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \ + void (*EndFrame)(vid_dec_PrivateType *priv); \ + struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \ + struct pipe_video_buffer *target, *shadow; \ + union { \ + struct { \ + uint8_t intra_matrix[64]; \ + uint8_t non_intra_matrix[64]; \ + } mpeg12; \ + struct { \ + unsigned nal_ref_idc; \ + bool IdrPicFlag; \ + unsigned idr_pic_id; \ + unsigned pic_order_cnt_lsb; \ + unsigned pic_order_cnt_msb; \ + unsigned delta_pic_order_cnt_bottom; \ + unsigned delta_pic_order_cnt[2]; \ + unsigned prevFrameNumOffset; \ + struct pipe_h264_sps sps[32]; \ + struct pipe_h264_pps pps[256]; \ + struct list_head dpb_list; \ + unsigned dpb_num; \ + } h264; \ + struct { \ + unsigned temporal_id; \ + unsigned level_idc; \ + unsigned pic_width_in_luma_samples; \ + unsigned pic_height_in_luma_samples; \ + bool IdrPicFlag; \ + int slice_prev_poc; \ + void *ref_pic_set_list; \ + void *rps; \ + struct pipe_h265_sps sps[16]; \ + struct pipe_h265_pps pps[64]; \ + struct list_head dpb_list; \ + unsigned dpb_num; \ + } h265; \ + } codec_data; \ + union { \ + struct pipe_picture_desc base; \ + struct pipe_mpeg12_picture_desc mpeg12; \ + struct pipe_h264_picture_desc h264; \ + struct pipe_h265_picture_desc h265; \ + } picture; \ + unsigned num_in_buffers; \ + OMX_BUFFERHEADERTYPE *in_buffers[2]; \ + const void *inputs[2]; \ + unsigned sizes[2]; \ + OMX_TICKS timestamps[2]; \ + OMX_TICKS timestamp; \ + bool first_buf_in_frame; \ + bool frame_finished; \ + bool frame_started; \ + unsigned bytes_left; \ + const void *slice; \ + bool disable_tunnel; \ + struct vl_compositor compositor; \ + struct vl_compositor_state cstate; +ENDCLASS(vid_dec_PrivateType) + +#else + +#include +#include + +#include "util/list.h" + +#include "pipe/p_video_state.h" + +typedef struct h264d_prc_class h264d_prc_class_t; +struct h264d_prc_class +{ + /* Class */ + const tiz_prc_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +typedef struct h264d_stream_info h264d_stream_info_t; +struct h264d_stream_info +{ + unsigned int width; + unsigned int height; +}; + +typedef struct h264d_prc vid_dec_PrivateType; +struct h264d_prc +{ + /* Object */ + const tiz_prc_t _; + OMX_BUFFERHEADERTYPE *in_buffers[2]; + OMX_BUFFERHEADERTYPE *p_inhdr_; + OMX_BUFFERHEADERTYPE *p_outhdr_; + OMX_PARAM_PORTDEFINITIONTYPE out_port_def_; + const void *inputs[2]; + unsigned sizes[2]; + OMX_TICKS timestamps[2]; + OMX_TICKS timestamp; + bool eos_; + bool in_port_disabled_; + bool out_port_disabled_; + struct vl_screen *screen; + struct pipe_context *pipe; + struct pipe_video_codec *codec; + struct pipe_video_buffer *target; + enum pipe_video_profile profile; + union { + struct { + unsigned nal_ref_idc; + bool IdrPicFlag; + unsigned idr_pic_id; + unsigned pic_order_cnt_lsb; + unsigned pic_order_cnt_msb; + unsigned delta_pic_order_cnt_bottom; + unsigned delta_pic_order_cnt[2]; + unsigned prevFrameNumOffset; + struct pipe_h264_sps sps[32]; + struct pipe_h264_pps pps[256]; + struct list_head dpb_list; + unsigned dpb_num; + } h264; + } codec_data; + union { + struct pipe_picture_desc base; + struct pipe_h264_picture_desc h264; + } picture; + h264d_stream_info_t stream_info; + unsigned num_in_buffers; + bool first_buf_in_frame; + bool frame_finished; + bool frame_started; + unsigned bytes_left; + const void *slice; + bool disable_tunnel; + struct vl_compositor compositor; + struct vl_compositor_state cstate; +}; + +#endif + +void vid_dec_NeedTarget(vid_dec_PrivateType* priv); +void vid_dec_FillOutput(vid_dec_PrivateType* priv, struct pipe_video_buffer* buf, + OMX_BUFFERHEADERTYPE* output); +#endif diff --git a/src/gallium/state_trackers/omx/vid_dec_h264_common.c b/src/gallium/state_trackers/omx/vid_dec_h264_common.c new file mode 100644 index 00000000000..1965e68775c --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_dec_h264_common.c @@ -0,0 +1,1138 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +#if ENABLE_ST_OMX_TIZONIA +#include +#endif + +#include "util/u_memory.h" + +#include "vid_dec_h264_common.h" + +static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv) +{ + //TODO: sane buffer handling + + if (priv->frame_started) + return; + + if (!priv->codec) { + struct pipe_video_codec templat = {}; + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.max_references = priv->picture.h264.num_ref_frames; + templat.expect_chunked_decode = true; +#if ENABLE_ST_OMX_BELLAGIO + omx_base_video_PortType *port; + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; +#else + templat.width = priv->out_port_def_.format.video.nFrameWidth; + templat.height = priv->out_port_def_.format.video.nFrameHeight; +#endif + templat.level = priv->picture.h264.pps->sps->level_idc; + + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + } + + vid_dec_NeedTarget(priv); + + if (priv->first_buf_in_frame) + priv->timestamp = priv->timestamps[0]; + priv->first_buf_in_frame = false; + + priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames; + + priv->picture.h264.slice_count = 0; + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, + OMX_TICKS *timestamp) +{ + struct dpb_list *entry, *result = NULL; + struct pipe_video_buffer *buf; + + /* search for the lowest poc and break on zeros */ + LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) { + + if (result && entry->poc == 0) + break; + + if (!result || entry->poc < result->poc) + result = entry; + } + + if (!result) + return NULL; + + buf = result->buffer; + if (timestamp) + *timestamp = result->timestamp; + + --priv->codec_data.h264.dpb_num; + LIST_DEL(&result->list); + FREE(result); + + return buf; +} + +void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv) +{ + struct dpb_list *entry; + struct pipe_video_buffer *tmp; + bool top_field_first; + OMX_TICKS timestamp; + + if (!priv->frame_started) + return; + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + // TODO: implement frame number handling + priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num; + priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num; + priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num; + + top_field_first = priv->picture.h264.field_order_cnt[0] < priv->picture.h264.field_order_cnt[1]; + + if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first) + return; + + /* add the decoded picture to the dpb list */ + entry = CALLOC_STRUCT(dpb_list); + if (!entry) + return; + + priv->first_buf_in_frame = true; + entry->buffer = priv->target; + entry->timestamp = priv->timestamp; + entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]); + LIST_ADDTAIL(&entry->list, &priv->codec_data.h264.dpb_list); + ++priv->codec_data.h264.dpb_num; + priv->target = NULL; + priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; + + if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE) + return; + + tmp = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); + priv->in_buffers[0]->nTimeStamp = timestamp; + priv->target = tmp; + priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; +} + +static void vui_parameters(struct vl_rbsp *rbsp) +{ + // TODO +} + +static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList, + const uint8_t *defaultList, const uint8_t *fallbackList) +{ + unsigned lastScale = 8, nextScale = 8; + const int *list; + unsigned i; + + /* (pic|seq)_scaling_list_present_flag[i] */ + if (!vl_rbsp_u(rbsp, 1)) { + if (fallbackList) + memcpy(scalingList, fallbackList, sizeOfScalingList); + return; + } + + list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal; + for (i = 0; i < sizeOfScalingList; ++i ) { + + if (nextScale != 0) { + signed delta_scale = vl_rbsp_se(rbsp); + nextScale = (lastScale + delta_scale + 256) % 256; + if (i == 0 && nextScale == 0) { + memcpy(scalingList, defaultList, sizeOfScalingList); + return; + } + } + scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale; + lastScale = scalingList[list[i]]; + } +} + +static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + if (id >= ARRAY_SIZE(priv->codec_data.h264.sps)) + return NULL; /* invalid seq_parameter_set_id */ + + return &priv->codec_data.h264.sps[id]; +} + +static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h264_sps *sps; + unsigned profile_idc, level_idc; + unsigned i; + + /* Sequence parameter set */ + profile_idc = vl_rbsp_u(rbsp, 8); + + /* constraint_set0_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set1_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set2_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set3_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set4_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set5_flag */ + vl_rbsp_u(rbsp, 1); + + /* reserved_zero_2bits */ + vl_rbsp_u(rbsp, 2); + + /* level_idc */ + level_idc = vl_rbsp_u(rbsp, 8); + + sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memset(sps, 0, sizeof(*sps)); + memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4)); + memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8)); + + sps->level_idc = level_idc; + + if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || + profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || + profile_idc == 128 || profile_idc == 138) { + + sps->chroma_format_idc = vl_rbsp_ue(rbsp); + + if (sps->chroma_format_idc == 3) + sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); + + sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); + + sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); + + /* qpprime_y_zero_transform_bypass_flag */ + vl_rbsp_u(rbsp, 1); + + sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1); + if (sps->seq_scaling_matrix_present_flag) { + + scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra); + scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]); + scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]); + scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter); + scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]); + scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]); + + scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra); + scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter); + if (sps->chroma_format_idc == 3) { + scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]); + scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]); + scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]); + scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]); + } + } + } else if (profile_idc == 183) + sps->chroma_format_idc = 0; + else + sps->chroma_format_idc = 1; + + sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp); + + sps->pic_order_cnt_type = vl_rbsp_ue(rbsp); + + if (sps->pic_order_cnt_type == 0) + sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); + else if (sps->pic_order_cnt_type == 1) { + sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1); + + sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp); + + sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp); + + sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp); + + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) + sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp); + } + + sps->max_num_ref_frames = vl_rbsp_ue(rbsp); + + /* gaps_in_frame_num_value_allowed_flag */ + vl_rbsp_u(rbsp, 1); + + /* pic_width_in_mbs_minus1 */ + int pic_width_in_samplesl = (vl_rbsp_ue(rbsp) + 1) * 16; + assert(pic_width_in_samplesl); + + /* pic_height_in_map_units_minus1 */ + int pic_height_in_map_units = vl_rbsp_ue(rbsp) + 1; + assert(pic_height_in_map_units); + + sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1); + if (!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1); + + sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1); + +#if ENABLE_ST_OMX_TIZONIA + priv->stream_info.width = pic_width_in_samplesl; + + int frame_height_in_mbs = (2 - sps->frame_mbs_only_flag) * pic_height_in_map_units; + int pic_height_in_mbs = frame_height_in_mbs / ( 1 + priv->picture.h264.field_pic_flag ); + int pic_height_in_samplesl = pic_height_in_mbs * 16; + priv->stream_info.height = pic_height_in_samplesl; + + + /* frame_cropping_flag */ + if (vl_rbsp_u(rbsp, 1)) { + unsigned frame_crop_left_offset = vl_rbsp_ue(rbsp); + unsigned frame_crop_right_offset = vl_rbsp_ue(rbsp); + unsigned frame_crop_top_offset = vl_rbsp_ue(rbsp); + unsigned frame_crop_bottom_offset = vl_rbsp_ue(rbsp); + + priv->stream_info.width -= (frame_crop_left_offset + frame_crop_right_offset) * 2; + priv->stream_info.height -= (frame_crop_top_offset + frame_crop_bottom_offset) * 2; + } +#else + /* frame_cropping_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* frame_crop_left_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_right_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_top_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_bottom_offset */ + vl_rbsp_ue(rbsp); + } +#endif + + /* vui_parameters_present_flag */ + if (vl_rbsp_u(rbsp, 1)) + vui_parameters(rbsp); +} + +static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + if (id >= ARRAY_SIZE(priv->codec_data.h264.pps)) + return NULL; /* invalid pic_parameter_set_id */ + + return &priv->codec_data.h264.pps[id]; +} + +static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h264_sps *sps; + struct pipe_h264_pps *pps; + unsigned i; + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + memset(pps, 0, sizeof(*pps)); + + sps = pps->sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4)); + memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8)); + + pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1); + + pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1); + + pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp); + if (pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = vl_rbsp_ue(rbsp); + + if (pps->slice_group_map_type == 0) { + + for (i = 0; i <= pps->num_slice_groups_minus1; ++i) + /* run_length_minus1[i] */ + vl_rbsp_ue(rbsp); + + } else if (pps->slice_group_map_type == 2) { + + for (i = 0; i <= pps->num_slice_groups_minus1; ++i) { + /* top_left[i] */ + vl_rbsp_ue(rbsp); + + /* bottom_right[i] */ + vl_rbsp_ue(rbsp); + } + + } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { + + /* slice_group_change_direction_flag */ + vl_rbsp_u(rbsp, 1); + + pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp); + + } else if (pps->slice_group_map_type == 6) { + + unsigned pic_size_in_map_units_minus1; + + pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp); + + for (i = 0; i <= pic_size_in_map_units_minus1; ++i) + /* slice_group_id[i] */ + vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1)); + } + } + + pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); + + pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); + + pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); + + pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2); + + pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp); + + /* pic_init_qs_minus26 */ + vl_rbsp_se(rbsp); + + pps->chroma_qp_index_offset = vl_rbsp_se(rbsp); + + pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); + + pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); + + pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1); + + if (vl_rbsp_more_data(rbsp)) { + pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1); + + /* pic_scaling_matrix_present_flag */ + if (vl_rbsp_u(rbsp, 1)) { + + scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra, + sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra); + scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]); + scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]); + scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter, + sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter); + scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]); + scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]); + + if (pps->transform_8x8_mode_flag) { + scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra, + sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra); + scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter, + sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Inter); + if (sps->chroma_format_idc == 3) { + scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]); + scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]); + scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]); + scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]); + } + } + } + + pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp); + } +} + +static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + // TODO + assert(0); +} + +static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + enum pipe_h264_slice_type slice_type) +{ + unsigned modification_of_pic_nums_idc; + + if (slice_type != 2 && slice_type != 4) { + /* ref_pic_list_modification_flag_l0 */ + if (vl_rbsp_u(rbsp, 1)) { + do { + modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); + if (modification_of_pic_nums_idc == 0 || + modification_of_pic_nums_idc == 1) + /* abs_diff_pic_num_minus1 */ + vl_rbsp_ue(rbsp); + else if (modification_of_pic_nums_idc == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + } while (modification_of_pic_nums_idc != 3); + } + } + + if (slice_type == 1) { + /* ref_pic_list_modification_flag_l1 */ + if (vl_rbsp_u(rbsp, 1)) { + do { + modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); + if (modification_of_pic_nums_idc == 0 || + modification_of_pic_nums_idc == 1) + /* abs_diff_pic_num_minus1 */ + vl_rbsp_ue(rbsp); + else if (modification_of_pic_nums_idc == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + } while (modification_of_pic_nums_idc != 3); + } + } +} + +static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type) +{ + unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc; + unsigned i, j; + + /* luma_log2_weight_denom */ + vl_rbsp_ue(rbsp); + + if (ChromaArrayType != 0) + /* chroma_log2_weight_denom */ + vl_rbsp_ue(rbsp); + + for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) { + /* luma_weight_l0_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* luma_weight_l0[i] */ + vl_rbsp_se(rbsp); + /* luma_offset_l0[i] */ + vl_rbsp_se(rbsp); + } + if (ChromaArrayType != 0) { + /* chroma_weight_l0_flag */ + if (vl_rbsp_u(rbsp, 1)) { + for (j = 0; j < 2; ++j) { + /* chroma_weight_l0[i][j] */ + vl_rbsp_se(rbsp); + /* chroma_offset_l0[i][j] */ + vl_rbsp_se(rbsp); + } + } + } + } + + if (slice_type == 1) { + for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) { + /* luma_weight_l1_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* luma_weight_l1[i] */ + vl_rbsp_se(rbsp); + /* luma_offset_l1[i] */ + vl_rbsp_se(rbsp); + } + if (ChromaArrayType != 0) { + /* chroma_weight_l1_flag */ + if (vl_rbsp_u(rbsp, 1)) { + for (j = 0; j < 2; ++j) { + /* chroma_weight_l1[i][j] */ + vl_rbsp_se(rbsp); + /* chroma_offset_l1[i][j] */ + vl_rbsp_se(rbsp); + } + } + } + } + } +} + +static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + bool IdrPicFlag) +{ + unsigned memory_management_control_operation; + + if (IdrPicFlag) { + /* no_output_of_prior_pics_flag */ + vl_rbsp_u(rbsp, 1); + /* long_term_reference_flag */ + vl_rbsp_u(rbsp, 1); + } else { + /* adaptive_ref_pic_marking_mode_flag */ + if (vl_rbsp_u(rbsp, 1)) { + do { + memory_management_control_operation = vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 1 || + memory_management_control_operation == 3) + /* difference_of_pic_nums_minus1 */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 3 || + memory_management_control_operation == 6) + /* long_term_frame_idx */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 4) + /* max_long_term_frame_idx_plus1 */ + vl_rbsp_ue(rbsp); + } while (memory_management_control_operation != 0); + } + } +} + +static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + unsigned nal_ref_idc, unsigned nal_unit_type) +{ + enum pipe_h264_slice_type slice_type; + struct pipe_h264_pps *pps; + struct pipe_h264_sps *sps; + unsigned frame_num, prevFrameNum; + bool IdrPicFlag = nal_unit_type == 5; + + if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.IdrPicFlag = IdrPicFlag; + + /* first_mb_in_slice */ + vl_rbsp_ue(rbsp); + + slice_type = vl_rbsp_ue(rbsp) % 5; + + /* get picture parameter set */ + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + /* get sequence parameter set */ + sps = pps->sps; + if (!sps) + return; + + if (pps != priv->picture.h264.pps) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.pps = pps; + + if (sps->separate_colour_plane_flag == 1 ) + /* colour_plane_id */ + vl_rbsp_u(rbsp, 2); + + /* frame number handling */ + frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4); + + if (frame_num != priv->picture.h264.frame_num) + vid_dec_h264_EndFrame(priv); + + prevFrameNum = priv->picture.h264.frame_num; + priv->picture.h264.frame_num = frame_num; + + priv->picture.h264.field_pic_flag = 0; + priv->picture.h264.bottom_field_flag = 0; + + if (!sps->frame_mbs_only_flag) { + unsigned field_pic_flag = vl_rbsp_u(rbsp, 1); + + if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.field_pic_flag = field_pic_flag; + + if (priv->picture.h264.field_pic_flag) { + unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1); + + if (bottom_field_flag != priv->picture.h264.bottom_field_flag) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.bottom_field_flag = bottom_field_flag; + } + } + + if (IdrPicFlag) { + /* set idr_pic_id */ + unsigned idr_pic_id = vl_rbsp_ue(rbsp); + + if (idr_pic_id != priv->codec_data.h264.idr_pic_id) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.idr_pic_id = idr_pic_id; + } + + if (sps->pic_order_cnt_type == 0) { + /* pic_order_cnt_lsb */ + unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4; + unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb; + int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb); + int pic_order_cnt_msb; + + if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb) + vid_dec_h264_EndFrame(priv); + + if (IdrPicFlag) { + priv->codec_data.h264.pic_order_cnt_msb = 0; + priv->codec_data.h264.pic_order_cnt_lsb = 0; + } + + if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) && + (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2)) + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb; + + else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) && + (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2)) + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb; + + else + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb; + + priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb; + priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb; + + if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { + /* delta_pic_oreder_cnt_bottom */ + unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; + } + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; + priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] + + priv->codec_data.h264.delta_pic_order_cnt_bottom; + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; + else + priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb; + + } else if (sps->pic_order_cnt_type == 1) { + /* delta_pic_order_cnt[0] */ + unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); + unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt; + + if (!sps->delta_pic_order_always_zero_flag) { + unsigned delta_pic_order_cnt[2]; + + delta_pic_order_cnt[0] = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0]) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; + + if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { + /* delta_pic_order_cnt[1] */ + delta_pic_order_cnt[1] = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1]) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1]; + } + } + + if (IdrPicFlag) + FrameNumOffset = 0; + else if (prevFrameNum > frame_num) + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; + else + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; + + priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; + + if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) + absFrameNum = FrameNumOffset + frame_num; + else + absFrameNum = 0; + + if (nal_ref_idc == 0 && absFrameNum > 0) + absFrameNum = absFrameNum - 1; + + if (absFrameNum > 0) { + unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; + unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; + signed ExpectedDeltaPerPicOrderCntCycle = 0; + unsigned i; + + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) + ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i]; + + expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle; + for (i = 0; i <= frameNumInPicOrderCntCycle; ++i) + expectedPicOrderCnt += sps->offset_for_ref_frame[i]; + + } else + expectedPicOrderCnt = 0; + + if (nal_ref_idc == 0) + expectedPicOrderCnt += sps->offset_for_non_ref_pic; + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; + priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] + + sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1]; + + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; + else + priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field + + priv->codec_data.h264.delta_pic_order_cnt[0]; + + } else if (sps->pic_order_cnt_type == 2) { + unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); + unsigned FrameNumOffset, tempPicOrderCnt; + + if (IdrPicFlag) + FrameNumOffset = 0; + else if (prevFrameNum > frame_num) + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; + else + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; + + priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; + + if (IdrPicFlag) + tempPicOrderCnt = 0; + else if (nal_ref_idc == 0) + tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1; + else + tempPicOrderCnt = 2 * (FrameNumOffset + frame_num); + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; + priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; + + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; + else + priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; + } + + if (pps->redundant_pic_cnt_present_flag) + /* redundant_pic_cnt */ + vl_rbsp_ue(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_B) + /* direct_spatial_mv_pred_flag */ + vl_rbsp_u(rbsp, 1); + + priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; + priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; + + if (slice_type == PIPE_H264_SLICE_TYPE_P || + slice_type == PIPE_H264_SLICE_TYPE_SP || + slice_type == PIPE_H264_SLICE_TYPE_B) { + + /* num_ref_idx_active_override_flag */ + if (vl_rbsp_u(rbsp, 1)) { + priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_B) + priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp); + } + } + + if (nal_unit_type == 20 || nal_unit_type == 21) + ref_pic_list_mvc_modification(priv, rbsp); + else + ref_pic_list_modification(priv, rbsp, slice_type); + + if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) || + (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B)) + pred_weight_table(priv, rbsp, sps, slice_type); + + if (nal_ref_idc != 0) + dec_ref_pic_marking(priv, rbsp, IdrPicFlag); + + if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI) + /* cabac_init_idc */ + vl_rbsp_ue(rbsp); + + /* slice_qp_delta */ + vl_rbsp_se(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) { + if (slice_type == PIPE_H264_SLICE_TYPE_SP) + /* sp_for_switch_flag */ + vl_rbsp_u(rbsp, 1); + + /*slice_qs_delta */ + vl_rbsp_se(rbsp); + } + + if (pps->deblocking_filter_control_present_flag) { + unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp); + + if (disable_deblocking_filter_idc != 1) { + /* slice_alpha_c0_offset_div2 */ + vl_rbsp_se(rbsp); + + /* slice_beta_offset_div2 */ + vl_rbsp_se(rbsp); + } + } + + if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) + /* slice_group_change_cycle */ + vl_rbsp_u(rbsp, 2); +} + +#if ENABLE_ST_OMX_TIZONIA +static OMX_ERRORTYPE update_port_parameters(vid_dec_PrivateType* priv) { + OMX_VIDEO_PORTDEFINITIONTYPE * p_def = NULL; /* Output port info */ + h264d_stream_info_t * i_def = NULL; /* Info read from stream */ + OMX_ERRORTYPE err = OMX_ErrorNone; + + assert(priv); + + p_def = &(priv->out_port_def_.format.video); + i_def = &(priv->stream_info); + + /* Handle dynamic resolution change */ + if ((p_def->nFrameWidth == i_def->width) && p_def->nFrameHeight == i_def->height) + return err; + + p_def->nFrameWidth = i_def->width; + p_def->nFrameHeight = i_def->height; + p_def->nStride = i_def->width; + p_def->nSliceHeight = i_def->height; + + err = tiz_krn_SetParameter_internal(tiz_get_krn(handleOf(priv)), handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_)); + if (err == OMX_ErrorNone) { + tiz_port_t * p_obj = tiz_krn_get_port(tiz_get_krn(handleOf(priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX); + + /* Set desired buffer size that will be used when allocating input buffers */ + p_obj->portdef_.nBufferSize = p_def->nFrameWidth * p_def->nFrameHeight * 512 / (16*16); + + /* Get a locally copy of port def. Useful for the early return above */ + tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_))); + + tiz_srv_issue_event((OMX_PTR) priv, OMX_EventPortSettingsChanged, + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + OMX_IndexParamPortDefinition, + NULL); + } + + return err; +} +#endif + +void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) +{ + unsigned nal_ref_idc, nal_unit_type; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); + ++priv->picture.h264.slice_count; + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + + /* forbidden_zero_bit */ + vl_vlc_eatbits(vlc, 1); + + nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2); + + if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc && + (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.nal_ref_idc = nal_ref_idc; + + nal_unit_type = vl_vlc_get_uimsbf(vlc, 5); + + if (nal_unit_type != 1 && nal_unit_type != 5) + vid_dec_h264_EndFrame(priv); + + if (nal_unit_type == 7) { + struct vl_rbsp rbsp; + vl_rbsp_init(&rbsp, vlc, ~0); + seq_parameter_set(priv, &rbsp); +#if ENABLE_ST_OMX_TIZONIA + update_port_parameters(priv); +#endif + + } else if (nal_unit_type == 8) { + struct vl_rbsp rbsp; + vl_rbsp_init(&rbsp, vlc, ~0); + picture_parameter_set(priv, &rbsp); + + } else if (nal_unit_type == 1 || nal_unit_type == 5) { + /* Coded slice of a non-IDR or IDR picture */ + unsigned bits = vl_vlc_valid_bits(vlc); + unsigned bytes = bits / 8 + 4; + struct vl_rbsp rbsp; + uint8_t buf[8]; + const void *ptr = buf; + unsigned i; + + buf[0] = 0x0; + buf[1] = 0x0; + buf[2] = 0x1; + buf[3] = (nal_ref_idc << 5) | nal_unit_type; + for (i = 4; i < bytes; ++i) + buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); + + priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; + priv->slice = vlc->data; + + vl_rbsp_init(&rbsp, vlc, 128); + slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type); + + vid_dec_h264_BeginFrame(priv); + + ++priv->picture.h264.slice_count; + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &ptr, &bytes); + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} + +void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf) +{ + struct pipe_video_buffer *vbuf = buf->pInputPortPrivate; + if (!vbuf) + return; + + vbuf->destroy(vbuf); + buf->pInputPortPrivate = NULL; +} + +void vid_dec_FrameDecoded_common(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output) +{ +#if ENABLE_ST_OMX_BELLAGIO + bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS); +#else + bool eos = priv->eos_; +#endif + OMX_TICKS timestamp; + + if (!input->pInputPortPrivate) { +#if ENABLE_ST_OMX_BELLAGIO + input->pInputPortPrivate = priv->Flush(priv, ×tamp); +#else + input->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); +#endif + if (timestamp != OMX_VID_DEC_AVC_TIMESTAMP_INVALID) + input->nTimeStamp = timestamp; + } + + if (input->pInputPortPrivate) { + if (output->pInputPortPrivate && !priv->disable_tunnel) { + struct pipe_video_buffer *tmp, *vbuf, *new_vbuf; + + tmp = output->pOutputPortPrivate; + vbuf = input->pInputPortPrivate; + if (vbuf->interlaced) { + /* re-allocate the progressive buffer */ + struct pipe_video_buffer templat = {}; + struct u_rect src_rect, dst_rect; + +#if ENABLE_ST_OMX_BELLAGIO + omx_base_video_PortType *port; + port = (omx_base_video_PortType *) + priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; +#else + tiz_port_t *port; + port = tiz_krn_get_port(tiz_get_krn(handleOf (priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX); +#endif + memset(&templat, 0, sizeof(templat)); + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; +#if ENABLE_ST_OMX_BELLAGIO + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; +#else + templat.width = port->portdef_.format.video.nFrameWidth; + templat.height = port->portdef_.format.video.nFrameHeight; +#endif + templat.buffer_format = PIPE_FORMAT_NV12; + templat.interlaced = false; + new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat); + + /* convert the interlaced to the progressive */ + src_rect.x0 = dst_rect.x0 = 0; + src_rect.x1 = dst_rect.x1 = templat.width; + src_rect.y0 = dst_rect.y0 = 0; + src_rect.y1 = dst_rect.y1 = templat.height; + + vl_compositor_yuv_deint_full(&priv->cstate, &priv->compositor, + input->pInputPortPrivate, new_vbuf, + &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); + + /* set the progrssive buffer for next round */ + vbuf->destroy(vbuf); + input->pInputPortPrivate = new_vbuf; + } + output->pOutputPortPrivate = input->pInputPortPrivate; + input->pInputPortPrivate = tmp; + } else { + vid_dec_FillOutput(priv, input->pInputPortPrivate, output); + } + output->nFilledLen = output->nAllocLen; + output->nTimeStamp = input->nTimeStamp; + } + + if (eos && input->pInputPortPrivate) + vid_dec_FreeInputPortPrivate(input); + else + input->nFilledLen = 0; +} diff --git a/src/gallium/state_trackers/omx/vid_dec_h264_common.h b/src/gallium/state_trackers/omx/vid_dec_h264_common.h new file mode 100644 index 00000000000..abde53beef9 --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_dec_h264_common.h @@ -0,0 +1,99 @@ +/************************************************************************** + * + * 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_DEC_H264_COMMON_H +#define VID_DEC_H264_COMMON_H + +#include "vid_dec_common.h" + +#define OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH 176 +#define OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT 144 +#define OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE 15<<16 +#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc" +/* With libtizonia, port indexes must start at index 0 */ +#define OMX_VID_DEC_AVC_INPUT_PORT_INDEX 0 +#define OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX 1 +#define OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT 8 +#define OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT 4 +/* 38016 = (width * height) + ((width * height)/2) */ +#define OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE 38016 +#define OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE 345600 +#define OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS OMX_FALSE +#define OMX_VID_DEC_AVC_PORT_ALIGNMENT 0 +#define OMX_VID_DEC_AVC_PORT_SUPPLIERPREF OMX_BufferSupplyInput +#define OMX_VID_DEC_AVC_TIMESTAMP_INVALID ((OMX_TICKS) -1) + +#define DPB_MAX_SIZE 5 + +struct dpb_list { + struct list_head list; + struct pipe_video_buffer *buffer; + OMX_TICKS timestamp; + int poc; +}; + +static const uint8_t Default_4x4_Intra[16] = { + 6, 13, 20, 28, 13, 20, 28, 32, + 20, 28, 32, 37, 28, 32, 37, 42 +}; + +static const uint8_t Default_4x4_Inter[16] = { + 10, 14, 20, 24, 14, 20, 24, 27, + 20, 24, 27, 30, 24, 27, 30, 34 +}; + +static const uint8_t Default_8x8_Intra[64] = { + 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static const uint8_t Default_8x8_Inter[64] = { + 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 +}; + +struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, + OMX_TICKS *timestamp); +void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv); +void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); +void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf); +void vid_dec_FrameDecoded_common(vid_dec_PrivateType*priv, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output); + +#endif diff --git a/src/gallium/state_trackers/omx/vid_omx_common.c b/src/gallium/state_trackers/omx/vid_omx_common.c new file mode 100644 index 00000000000..63afa898ba1 --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_omx_common.c @@ -0,0 +1,111 @@ +/************************************************************************** + * + * 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 + +#if defined(HAVE_X11_PLATFORM) +#include +#else +#define XOpenDisplay(x) NULL +#define XCloseDisplay(x) +#define Display void +#endif + +#include "os/os_thread.h" +#include "util/u_memory.h" +#include "loader/loader.h" + +#include "vid_omx_common.h" + +static mtx_t omx_lock = _MTX_INITIALIZER_NP; +static Display *omx_display = NULL; +static struct vl_screen *omx_screen = NULL; +static unsigned omx_usecount = 0; +static const char *omx_render_node = NULL; +static int drm_fd; + +struct vl_screen *omx_get_screen(void) +{ + static bool first_time = true; + mtx_lock(&omx_lock); + + if (!omx_screen) { + if (first_time) { + omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL); + first_time = false; + } + if (omx_render_node) { + drm_fd = loader_open_device(omx_render_node); + if (drm_fd < 0) + goto error; + + omx_screen = vl_drm_screen_create(drm_fd); + if (!omx_screen) { + close(drm_fd); + goto error; + } + } else { + omx_display = XOpenDisplay(NULL); + if (!omx_display) + goto error; + + omx_screen = vl_dri3_screen_create(omx_display, 0); + if (!omx_screen) + omx_screen = vl_dri2_screen_create(omx_display, 0); + if (!omx_screen) { + XCloseDisplay(omx_display); + goto error; + } + } + } + + ++omx_usecount; + + mtx_unlock(&omx_lock); + return omx_screen; + +error: + mtx_unlock(&omx_lock); + return NULL; +} + +void omx_put_screen(void) +{ + mtx_lock(&omx_lock); + if ((--omx_usecount) == 0) { + omx_screen->destroy(omx_screen); + omx_screen = NULL; + + if (omx_render_node) + close(drm_fd); + else + XCloseDisplay(omx_display); + } + mtx_unlock(&omx_lock); +} diff --git a/src/gallium/state_trackers/omx/vid_omx_common.h b/src/gallium/state_trackers/omx/vid_omx_common.h new file mode 100644 index 00000000000..e27013d1746 --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_omx_common.h @@ -0,0 +1,36 @@ +/************************************************************************** + * + * 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_OMX_COMMON_H +#define VID_OMX_COMMON_H + +#include "vl/vl_winsys.h" + +struct vl_screen *omx_get_screen(void); +void omx_put_screen(void); + +#endif -- 2.30.2