1 /**
2  * @file h265/decode.c H.265 Decode
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 
7 #include <re.h>
8 #include <rem.h>
9 #include <baresip.h>
10 #include <libavutil/pixdesc.h>
11 #include <libavcodec/avcodec.h>
12 #include "h265.h"
13 
14 
15 #if LIBAVUTIL_VERSION_MAJOR < 52
16 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
17 #endif
18 
19 
20 enum {
21 	FU_HDR_SIZE = 1
22 };
23 
24 enum {
25 	DECODE_MAXSZ = 524288,
26 };
27 
28 
29 struct fu {
30 	unsigned s:1;
31 	unsigned e:1;
32 	unsigned type:6;
33 };
34 
35 struct viddec_state {
36 	AVCodecContext *ctx;
37 	AVFrame *pict;
38 	struct mbuf *mb;
39 	size_t frag_start;
40 	bool frag;
41 	uint16_t frag_seq;
42 };
43 
44 
destructor(void * arg)45 static void destructor(void *arg)
46 {
47 	struct viddec_state *vds = arg;
48 
49 	if (vds->ctx) {
50 		avcodec_close(vds->ctx);
51 		av_free(vds->ctx);
52 	}
53 
54 	if (vds->pict)
55 		av_free(vds->pict);
56 
57 	mem_deref(vds->mb);
58 }
59 
60 
h265_decode_update(struct viddec_state ** vdsp,const struct vidcodec * vc,const char * fmtp)61 int h265_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc,
62 		       const char *fmtp)
63 {
64 	struct viddec_state *vds;
65 	AVCodec *codec;
66 	int err = 0;
67 	(void)vc;
68 	(void)fmtp;
69 
70 	if (!vdsp)
71 		return EINVAL;
72 
73 	vds = *vdsp;
74 
75 	if (vds)
76 		return 0;
77 
78 	/* HEVC = H.265 */
79 	codec = avcodec_find_decoder(AV_CODEC_ID_HEVC);
80 	if (!codec) {
81 		warning("h265: could not find H265 decoder\n");
82 		return ENOSYS;
83 	}
84 
85 	vds = mem_zalloc(sizeof(*vds), destructor);
86 	if (!vds)
87 		return ENOMEM;
88 
89 	vds->mb = mbuf_alloc(1024);
90 	if (!vds->mb) {
91 		err = ENOMEM;
92 		goto out;
93 	}
94 
95 	vds->pict = av_frame_alloc();
96 	if (!vds->pict) {
97 		err = ENOMEM;
98 		goto out;
99 	}
100 
101 	vds->ctx = avcodec_alloc_context3(codec);
102 	if (!vds->ctx) {
103 		err = ENOMEM;
104 		goto out;
105 	}
106 
107 	if (avcodec_open2(vds->ctx, codec, NULL) < 0) {
108 		err = ENOMEM;
109 		goto out;
110 	}
111 
112  out:
113 	if (err)
114 		mem_deref(vds);
115 	else
116 		*vdsp = vds;
117 
118 	return err;
119 }
120 
121 
fu_decode(struct fu * fu,struct mbuf * mb)122 static inline int fu_decode(struct fu *fu, struct mbuf *mb)
123 {
124 	uint8_t v;
125 
126 	if (mbuf_get_left(mb) < 1)
127 		return EBADMSG;
128 
129 	v = mbuf_read_u8(mb);
130 
131 	fu->s    = v>>7 & 0x1;
132 	fu->e    = v>>6 & 0x1;
133 	fu->type = v>>0 & 0x3f;
134 
135 	return 0;
136 }
137 
138 
seq_diff(uint16_t x,uint16_t y)139 static inline int16_t seq_diff(uint16_t x, uint16_t y)
140 {
141 	return (int16_t)(y - x);
142 }
143 
144 
fragment_rewind(struct viddec_state * vds)145 static inline void fragment_rewind(struct viddec_state *vds)
146 {
147 	vds->mb->pos = vds->frag_start;
148 	vds->mb->end = vds->frag_start;
149 }
150 
151 
h265_decode(struct viddec_state * vds,struct vidframe * frame,bool * intra,bool marker,uint16_t seq,struct mbuf * mb)152 int h265_decode(struct viddec_state *vds, struct vidframe *frame,
153 		bool *intra, bool marker, uint16_t seq, struct mbuf *mb)
154 {
155 	static const uint8_t nal_seq[3] = {0, 0, 1};
156 	int err, ret, got_picture, i;
157 	struct h265_nal hdr;
158 	AVPacket avpkt;
159 	enum vidfmt fmt;
160 
161 	if (!vds || !frame || !intra || !mb)
162 		return EINVAL;
163 
164 	*intra = false;
165 
166 	err = h265_nal_decode(&hdr, mbuf_buf(mb));
167 	if (err)
168 		return err;
169 
170 	mbuf_advance(mb, H265_HDR_SIZE);
171 
172 #if 0
173 	debug("h265: decode: %s type=%2d  %s\n",
174 		  h265_is_keyframe(hdr.nal_unit_type) ? "<KEY>" : "     ",
175 		  hdr.nal_unit_type,
176 		  h265_nalunit_name(hdr.nal_unit_type));
177 #endif
178 
179 	if (vds->frag && hdr.nal_unit_type != H265_NAL_FU) {
180 		debug("h265: lost fragments; discarding previous NAL\n");
181 		fragment_rewind(vds);
182 		vds->frag = false;
183 	}
184 
185 	/* handle NAL types */
186 	if (0 <= hdr.nal_unit_type && hdr.nal_unit_type <= 40) {
187 
188 		if (h265_is_keyframe(hdr.nal_unit_type))
189 			*intra = true;
190 
191 		mb->pos -= H265_HDR_SIZE;
192 
193 		err  = mbuf_write_mem(vds->mb, nal_seq, 3);
194 		err |= mbuf_write_mem(vds->mb, mbuf_buf(mb),mbuf_get_left(mb));
195 		if (err)
196 			goto out;
197 	}
198 	else if (H265_NAL_FU == hdr.nal_unit_type) {
199 
200 		struct fu fu;
201 
202 		err = fu_decode(&fu, mb);
203 		if (err)
204 			return err;
205 
206 		if (fu.s) {
207 			if (h265_is_keyframe(fu.type))
208 				*intra = true;
209 
210 			if (vds->frag) {
211 				debug("h265: lost fragments; ignoring NAL\n");
212 				fragment_rewind(vds);
213 			}
214 
215 			vds->frag_start = vds->mb->pos;
216 			vds->frag = true;
217 
218 			hdr.nal_unit_type = fu.type;
219 
220 			err  = mbuf_write_mem(vds->mb, nal_seq, 3);
221 			err = h265_nal_encode_mbuf(vds->mb, &hdr);
222 			if (err)
223 				goto out;
224 		}
225 		else {
226 			if (!vds->frag) {
227 				debug("h265: ignoring fragment\n");
228 				return 0;
229 			}
230 
231 			if (seq_diff(vds->frag_seq, seq) != 1) {
232 				debug("h265: lost fragments detected\n");
233 				fragment_rewind(vds);
234 				vds->frag = false;
235 				return 0;
236 			}
237 		}
238 
239 		err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb));
240 		if (err)
241 			goto out;
242 
243 		if (fu.e)
244 			vds->frag = false;
245 
246 		vds->frag_seq = seq;
247 	}
248 	else {
249 		warning("h265: unknown NAL type %u (%s) [%zu bytes]\n",
250 			hdr.nal_unit_type,
251 			h265_nalunit_name(hdr.nal_unit_type),
252 			mbuf_get_left(mb));
253 		return EPROTO;
254 	}
255 
256 	if (!marker) {
257 
258 		if (vds->mb->end > DECODE_MAXSZ) {
259 			warning("h265: decode buffer size exceeded\n");
260 			err = ENOMEM;
261 			goto out;
262 		}
263 
264 		return 0;
265 	}
266 
267 	if (vds->frag) {
268 		err = EPROTO;
269 		goto out;
270 	}
271 
272 	av_init_packet(&avpkt);
273 	avpkt.data = vds->mb->buf;
274 	avpkt.size = (int)vds->mb->end;
275 
276 #if LIBAVCODEC_VERSION_INT >= ((57<<16)+(37<<8)+100)
277 
278 	ret = avcodec_send_packet(vds->ctx, &avpkt);
279 	if (ret < 0) {
280 		err = EBADMSG;
281 		goto out;
282 	}
283 
284 	ret = avcodec_receive_frame(vds->ctx, vds->pict);
285 	if (ret < 0) {
286 		err = EBADMSG;
287 		goto out;
288 	}
289 
290 	got_picture = true;
291 
292 #else
293 	ret = avcodec_decode_video2(vds->ctx, vds->pict, &got_picture, &avpkt);
294 	if (ret < 0) {
295 		debug("h265: decode error\n");
296 		err = EPROTO;
297 		goto out;
298 	}
299 #endif
300 
301 	if (!got_picture) {
302 		/* debug("h265: no picture\n"); */
303 		goto out;
304 	}
305 
306 	switch (vds->pict->format) {
307 
308 	case AV_PIX_FMT_YUV420P:
309 		fmt = VID_FMT_YUV420P;
310 		break;
311 
312 	case AV_PIX_FMT_YUV444P:
313 		fmt = VID_FMT_YUV444P;
314 		break;
315 
316 	default:
317 		warning("h265: decode: bad pixel format (%i) (%s)\n",
318 			vds->pict->format,
319 			av_get_pix_fmt_name(vds->pict->format));
320 		goto out;
321 	}
322 
323 	for (i=0; i<4; i++) {
324 		frame->data[i]     = vds->pict->data[i];
325 		frame->linesize[i] = vds->pict->linesize[i];
326 	}
327 
328 	frame->size.w = vds->ctx->width;
329 	frame->size.h = vds->ctx->height;
330 	frame->fmt    = fmt;
331 
332  out:
333 	mbuf_rewind(vds->mb);
334 	vds->frag = false;
335 
336 	return err;
337 }
338