st/omx/dec: add initial omx hevc support

Mainly based on the h264 implementation.

Signed-off-by: Leo Liu <leo.liu@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
Leo Liu
2016-08-29 13:09:12 -04:00
parent 0c374a7770
commit 6d186a79f2
3 changed files with 160 additions and 0 deletions
@@ -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
+11
View File
@@ -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
@@ -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;
}