From 6d186a79f2d28dff93eddece5b0f0fdc0897301f Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Mon, 29 Aug 2016 13:09:12 -0400 Subject: [PATCH] st/omx/dec: add initial omx hevc support MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Mainly based on the h264 implementation. Signed-off-by: Leo Liu Acked-by: Christian König --- .../state_trackers/omx/Makefile.sources | 1 + src/gallium/state_trackers/omx/vid_dec.h | 11 ++ src/gallium/state_trackers/omx/vid_dec_h265.c | 148 ++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 src/gallium/state_trackers/omx/vid_dec_h265.c diff --git a/src/gallium/state_trackers/omx/Makefile.sources b/src/gallium/state_trackers/omx/Makefile.sources index d25cd2e3934..ab60ce803cb 100644 --- a/src/gallium/state_trackers/omx/Makefile.sources +++ b/src/gallium/state_trackers/omx/Makefile.sources @@ -5,5 +5,6 @@ C_SOURCES := \ vid_dec.h \ vid_dec_mpeg12.c \ vid_dec_h264.c \ + vid_dec_h265.c \ vid_enc.c \ vid_enc.h diff --git a/src/gallium/state_trackers/omx/vid_dec.h b/src/gallium/state_trackers/omx/vid_dec.h index d268925ab26..4568e6d6b9d 100644 --- a/src/gallium/state_trackers/omx/vid_dec.h +++ b/src/gallium/state_trackers/omx/vid_dec.h @@ -94,11 +94,19 @@ DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType) struct list_head dpb_list; \ unsigned dpb_num; \ } h264; \ + struct { \ + unsigned level_idc; \ + 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]; \ @@ -126,4 +134,7 @@ void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv); /* vid_dec_h264.c */ void vid_dec_h264_Init(vid_dec_PrivateType *priv); +/* vid_dec_h265.c */ +void vid_dec_h265_Init(vid_dec_PrivateType *priv); + #endif diff --git a/src/gallium/state_trackers/omx/vid_dec_h265.c b/src/gallium/state_trackers/omx/vid_dec_h265.c new file mode 100644 index 00000000000..49936b0219a --- /dev/null +++ b/src/gallium/state_trackers/omx/vid_dec_h265.c @@ -0,0 +1,148 @@ +/************************************************************************** + * + * Copyright 2016 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 "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_video.h" +#include "vl/vl_rbsp.h" + +#include "entrypoint.h" +#include "vid_dec.h" + +#define DPB_MAX_SIZE 16 + +struct dpb_list { + struct list_head list; + struct pipe_video_buffer *buffer; + unsigned poc; +}; + +static void vid_dec_h265_BeginFrame(vid_dec_PrivateType *priv) +{ + if (priv->frame_started) + return; + + vid_dec_NeedTarget(priv); + + 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.expect_chunked_decode = true; + templat.width = align(port->sPortParam.format.video.nFrameWidth, 4); + templat.height = align(port->sPortParam.format.video.nFrameHeight, 4); + templat.level = priv->codec_data.h265.level_idc; + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + } + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +static struct pipe_video_buffer *vid_dec_h265_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.h265.dpb_list, list) { + + if (result && entry->poc == 0) + break; + + if (!result || entry->poc < result->poc) + result = entry; + } + + if (!result) + return NULL; + + buf = result->buffer; + + --priv->codec_data.h265.dpb_num; + LIST_DEL(&result->list); + FREE(result); + + return buf; +} + +static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv) +{ + struct dpb_list *entry = NULL; + struct pipe_video_buffer *tmp; + + if (!priv->frame_started) + return; + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + /* add the decoded picture to the dpb list */ + entry = CALLOC_STRUCT(dpb_list); + if (!entry) + return; + + entry->buffer = priv->target; + + LIST_ADDTAIL(&entry->list, &priv->codec_data.h265.dpb_list); + ++priv->codec_data.h265.dpb_num; + priv->target = NULL; + + if (priv->codec_data.h265.dpb_num <= DPB_MAX_SIZE) + return; + + tmp = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = vid_dec_h265_Flush(priv, NULL); + priv->target = tmp; + priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; +} + +static void vid_dec_h265_Decode(vid_dec_PrivateType *priv, + struct vl_vlc *vlc, + unsigned min_bits_left) +{ + /* TODO */ + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} + +void vid_dec_h265_Init(vid_dec_PrivateType *priv) +{ + priv->picture.base.profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; + + LIST_INITHEAD(&priv->codec_data.h265.dpb_list); + + priv->Decode = vid_dec_h265_Decode; + priv->EndFrame = vid_dec_h265_EndFrame; + priv->Flush = vid_dec_h265_Flush; +} -- 2.30.2