st/omx/dec: add initial omx hevc support
[mesa.git] / src / gallium / state_trackers / omx / vid_dec_h265.c
1 /**************************************************************************
2 *
3 * Copyright 2016 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "pipe/p_video_codec.h"
29 #include "util/u_memory.h"
30 #include "util/u_video.h"
31 #include "vl/vl_rbsp.h"
32
33 #include "entrypoint.h"
34 #include "vid_dec.h"
35
36 #define DPB_MAX_SIZE 16
37
38 struct dpb_list {
39 struct list_head list;
40 struct pipe_video_buffer *buffer;
41 unsigned poc;
42 };
43
44 static void vid_dec_h265_BeginFrame(vid_dec_PrivateType *priv)
45 {
46 if (priv->frame_started)
47 return;
48
49 vid_dec_NeedTarget(priv);
50
51 if (!priv->codec) {
52 struct pipe_video_codec templat = {};
53 omx_base_video_PortType *port;
54
55 port = (omx_base_video_PortType *)
56 priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
57 templat.profile = priv->profile;
58 templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM;
59 templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
60 templat.expect_chunked_decode = true;
61 templat.width = align(port->sPortParam.format.video.nFrameWidth, 4);
62 templat.height = align(port->sPortParam.format.video.nFrameHeight, 4);
63 templat.level = priv->codec_data.h265.level_idc;
64 priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat);
65 }
66 priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base);
67 priv->frame_started = true;
68 }
69
70 static struct pipe_video_buffer *vid_dec_h265_Flush(vid_dec_PrivateType *priv,
71 OMX_TICKS *timestamp)
72 {
73 struct dpb_list *entry, *result = NULL;
74 struct pipe_video_buffer *buf;
75
76 /* search for the lowest poc and break on zeros */
77 LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) {
78
79 if (result && entry->poc == 0)
80 break;
81
82 if (!result || entry->poc < result->poc)
83 result = entry;
84 }
85
86 if (!result)
87 return NULL;
88
89 buf = result->buffer;
90
91 --priv->codec_data.h265.dpb_num;
92 LIST_DEL(&result->list);
93 FREE(result);
94
95 return buf;
96 }
97
98 static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv)
99 {
100 struct dpb_list *entry = NULL;
101 struct pipe_video_buffer *tmp;
102
103 if (!priv->frame_started)
104 return;
105
106 priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base);
107 priv->frame_started = false;
108
109 /* add the decoded picture to the dpb list */
110 entry = CALLOC_STRUCT(dpb_list);
111 if (!entry)
112 return;
113
114 entry->buffer = priv->target;
115
116 LIST_ADDTAIL(&entry->list, &priv->codec_data.h265.dpb_list);
117 ++priv->codec_data.h265.dpb_num;
118 priv->target = NULL;
119
120 if (priv->codec_data.h265.dpb_num <= DPB_MAX_SIZE)
121 return;
122
123 tmp = priv->in_buffers[0]->pInputPortPrivate;
124 priv->in_buffers[0]->pInputPortPrivate = vid_dec_h265_Flush(priv, NULL);
125 priv->target = tmp;
126 priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL;
127 }
128
129 static void vid_dec_h265_Decode(vid_dec_PrivateType *priv,
130 struct vl_vlc *vlc,
131 unsigned min_bits_left)
132 {
133 /* TODO */
134
135 /* resync to byte boundary */
136 vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8);
137 }
138
139 void vid_dec_h265_Init(vid_dec_PrivateType *priv)
140 {
141 priv->picture.base.profile = PIPE_VIDEO_PROFILE_HEVC_MAIN;
142
143 LIST_INITHEAD(&priv->codec_data.h265.dpb_list);
144
145 priv->Decode = vid_dec_h265_Decode;
146 priv->EndFrame = vid_dec_h265_EndFrame;
147 priv->Flush = vid_dec_h265_Flush;
148 }