1 /*
2 * GStreamer HEVC/H.265 video codec.
3 *
4 * Copyright (c) 2014 struktur AG, Joachim Bauch <bauch@struktur.de>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 /**
23 * SECTION:element-libde265dec
24 * @title: libde265dec
25 *
26 * Decodes HEVC/H.265 video.
27 *
28 * ## Example launch line
29 * |[
30 * gst-launch-1.0 filesrc location=bitstream.hevc ! 'video/x-hevc,stream-format=byte-stream,framerate=25/1' ! libde265dec ! autovideosink
31 * ]| The above pipeline decodes the HEVC/H.265 bitstream and renders it to the screen.
32 *
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include "libde265-dec.h"
43
44 /* use two decoder threads if no information about
45 * available CPU cores can be retrieved */
46 #define DEFAULT_THREAD_COUNT 2
47
48 #define parent_class gst_libde265_dec_parent_class
49 G_DEFINE_TYPE (GstLibde265Dec, gst_libde265_dec, GST_TYPE_VIDEO_DECODER);
50 GST_ELEMENT_REGISTER_DEFINE (libde265dec, "libde265dec",
51 GST_RANK_SECONDARY, GST_TYPE_LIBDE265_DEC);
52
53 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
54 GST_PAD_SINK,
55 GST_PAD_ALWAYS,
56 GST_STATIC_CAPS
57 ("video/x-h265, stream-format=(string) { hvc1, hev1, byte-stream }, "
58 "alignment=(string) { au, nal }")
59 );
60
61 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
62 GST_PAD_SRC,
63 GST_PAD_ALWAYS,
64 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420"))
65 );
66
67 enum
68 {
69 PROP_0,
70 PROP_MAX_THREADS,
71 PROP_LAST
72 };
73
74 #define DEFAULT_FORMAT GST_TYPE_LIBDE265_FORMAT_PACKETIZED
75 #define DEFAULT_MAX_THREADS 0
76
77 static void gst_libde265_dec_finalize (GObject * object);
78
79 static void gst_libde265_dec_set_property (GObject * object, guint prop_id,
80 const GValue * value, GParamSpec * pspec);
81 static void gst_libde265_dec_get_property (GObject * object, guint prop_id,
82 GValue * value, GParamSpec * pspec);
83
84 static gboolean gst_libde265_dec_start (GstVideoDecoder * decoder);
85 static gboolean gst_libde265_dec_stop (GstVideoDecoder * decoder);
86 static gboolean gst_libde265_dec_set_format (GstVideoDecoder * decoder,
87 GstVideoCodecState * state);
88 static gboolean gst_libde265_dec_flush (GstVideoDecoder * decoder);
89 static GstFlowReturn gst_libde265_dec_finish (GstVideoDecoder * decoder);
90 static GstFlowReturn _gst_libde265_return_image (GstVideoDecoder * decoder,
91 GstVideoCodecFrame * frame, const struct de265_image *img);
92 static GstFlowReturn gst_libde265_dec_handle_frame (GstVideoDecoder * decoder,
93 GstVideoCodecFrame * frame);
94 static GstFlowReturn _gst_libde265_image_available (GstVideoDecoder * decoder,
95 int width, int height);
96
97 static void
gst_libde265_dec_class_init(GstLibde265DecClass * klass)98 gst_libde265_dec_class_init (GstLibde265DecClass * klass)
99 {
100 GObjectClass *gobject_class = (GObjectClass *) klass;
101 GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
102 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
103
104 gobject_class->finalize = gst_libde265_dec_finalize;
105 gobject_class->set_property = gst_libde265_dec_set_property;
106 gobject_class->get_property = gst_libde265_dec_get_property;
107
108 g_object_class_install_property (gobject_class, PROP_MAX_THREADS,
109 g_param_spec_int ("max-threads", "Maximum decode threads",
110 "Maximum number of worker threads to spawn. (0 = auto)",
111 0, G_MAXINT, DEFAULT_MAX_THREADS,
112 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
113
114 decoder_class->start = GST_DEBUG_FUNCPTR (gst_libde265_dec_start);
115 decoder_class->stop = GST_DEBUG_FUNCPTR (gst_libde265_dec_stop);
116 decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_libde265_dec_set_format);
117 decoder_class->flush = GST_DEBUG_FUNCPTR (gst_libde265_dec_flush);
118 decoder_class->finish = GST_DEBUG_FUNCPTR (gst_libde265_dec_finish);
119 decoder_class->handle_frame =
120 GST_DEBUG_FUNCPTR (gst_libde265_dec_handle_frame);
121
122 gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
123 gst_element_class_add_static_pad_template (gstelement_class, &src_template);
124
125 gst_element_class_set_static_metadata (gstelement_class,
126 "HEVC/H.265 decoder",
127 "Codec/Decoder/Video",
128 "Decodes HEVC/H.265 video streams using libde265",
129 "struktur AG <opensource@struktur.de>");
130 }
131
132 static inline void
_gst_libde265_dec_reset_decoder(GstLibde265Dec * dec)133 _gst_libde265_dec_reset_decoder (GstLibde265Dec * dec)
134 {
135 dec->ctx = NULL;
136 dec->buffer_full = 0;
137 dec->codec_data = NULL;
138 dec->codec_data_size = 0;
139 dec->input_state = NULL;
140 dec->output_state = NULL;
141 }
142
143 static void
gst_libde265_dec_init(GstLibde265Dec * dec)144 gst_libde265_dec_init (GstLibde265Dec * dec)
145 {
146 dec->format = DEFAULT_FORMAT;
147 dec->max_threads = DEFAULT_MAX_THREADS;
148 dec->length_size = 4;
149 _gst_libde265_dec_reset_decoder (dec);
150 gst_video_decoder_set_packetized (GST_VIDEO_DECODER (dec), TRUE);
151 gst_video_decoder_set_use_default_pad_acceptcaps (GST_VIDEO_DECODER_CAST
152 (dec), TRUE);
153 GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (dec));
154 }
155
156 static inline void
_gst_libde265_dec_free_decoder(GstLibde265Dec * dec)157 _gst_libde265_dec_free_decoder (GstLibde265Dec * dec)
158 {
159 if (dec->ctx != NULL) {
160 de265_free_decoder (dec->ctx);
161 }
162 free (dec->codec_data);
163 if (dec->input_state != NULL) {
164 gst_video_codec_state_unref (dec->input_state);
165 }
166 if (dec->output_state != NULL) {
167 gst_video_codec_state_unref (dec->output_state);
168 }
169 _gst_libde265_dec_reset_decoder (dec);
170 }
171
172 static void
gst_libde265_dec_finalize(GObject * object)173 gst_libde265_dec_finalize (GObject * object)
174 {
175 GstLibde265Dec *dec = GST_LIBDE265_DEC (object);
176
177 _gst_libde265_dec_free_decoder (dec);
178
179 G_OBJECT_CLASS (parent_class)->finalize (object);
180 }
181
182 static void
gst_libde265_dec_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)183 gst_libde265_dec_set_property (GObject * object, guint prop_id,
184 const GValue * value, GParamSpec * pspec)
185 {
186 GstLibde265Dec *dec = GST_LIBDE265_DEC (object);
187
188 switch (prop_id) {
189 case PROP_MAX_THREADS:
190 dec->max_threads = g_value_get_int (value);
191 if (dec->max_threads) {
192 GST_DEBUG_OBJECT (dec, "Max. threads set to %d", dec->max_threads);
193 } else {
194 GST_DEBUG_OBJECT (dec, "Max. threads set to auto");
195 }
196 break;
197 default:
198 break;
199 }
200 }
201
202 static void
gst_libde265_dec_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)203 gst_libde265_dec_get_property (GObject * object, guint prop_id,
204 GValue * value, GParamSpec * pspec)
205 {
206 GstLibde265Dec *dec = GST_LIBDE265_DEC (object);
207
208 switch (prop_id) {
209 case PROP_MAX_THREADS:
210 g_value_set_int (value, dec->max_threads);
211 break;
212 default:
213 break;
214 }
215 }
216
217 struct GstLibde265FrameRef
218 {
219 GstVideoDecoder *decoder;
220 GstVideoCodecFrame *frame;
221 GstVideoFrame vframe;
222 GstBuffer *buffer;
223 gboolean mapped;
224 };
225
226 static void
gst_libde265_dec_release_frame_ref(struct GstLibde265FrameRef * ref)227 gst_libde265_dec_release_frame_ref (struct GstLibde265FrameRef *ref)
228 {
229 if (ref->mapped) {
230 gst_video_frame_unmap (&ref->vframe);
231 }
232 gst_video_codec_frame_unref (ref->frame);
233 gst_buffer_replace (&ref->buffer, NULL);
234 g_free (ref);
235 }
236
237 static int
gst_libde265_dec_get_buffer(de265_decoder_context * ctx,struct de265_image_spec * spec,struct de265_image * img,void * userdata)238 gst_libde265_dec_get_buffer (de265_decoder_context * ctx,
239 struct de265_image_spec *spec, struct de265_image *img, void *userdata)
240 {
241 GstVideoDecoder *base = (GstVideoDecoder *) userdata;
242 GstLibde265Dec *dec = GST_LIBDE265_DEC (base);
243 GstVideoCodecFrame *frame = NULL;
244 int i;
245 int width = spec->width;
246 int height = spec->height;
247 GstFlowReturn ret;
248 struct GstLibde265FrameRef *ref;
249 GstVideoInfo *info;
250 int frame_number;
251
252 frame_number = (uintptr_t) de265_get_image_user_data (img) - 1;
253 if (G_UNLIKELY (frame_number == -1)) {
254 /* should not happen... */
255 GST_WARNING_OBJECT (base, "Frame has no number assigned!");
256 goto fallback;
257 }
258
259 frame = gst_video_decoder_get_frame (base, frame_number);
260 if (G_UNLIKELY (frame == NULL)) {
261 /* should not happen... */
262 GST_WARNING_OBJECT (base, "Couldn't get codec frame!");
263 goto fallback;
264 }
265
266 if (width % spec->alignment) {
267 width += spec->alignment - (width % spec->alignment);
268 }
269 if (width != spec->visible_width || height != spec->visible_height) {
270 /* clipping not supported for now */
271 goto fallback;
272 }
273
274 ret = _gst_libde265_image_available (base, width, height);
275 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
276 GST_ERROR_OBJECT (dec, "Failed to notify about available image");
277 goto fallback;
278 }
279
280 ret =
281 gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER (dec), frame);
282 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
283 GST_ERROR_OBJECT (dec, "Failed to allocate output buffer");
284 goto fallback;
285 }
286
287 ref = (struct GstLibde265FrameRef *) g_malloc0 (sizeof (*ref));
288 g_assert (ref != NULL);
289 ref->decoder = base;
290 ref->frame = frame;
291
292 gst_buffer_replace (&ref->buffer, frame->output_buffer);
293 gst_buffer_replace (&frame->output_buffer, NULL);
294
295 info = &dec->output_state->info;
296 if (!gst_video_frame_map (&ref->vframe, info, ref->buffer, GST_MAP_READWRITE)) {
297 GST_ERROR_OBJECT (dec, "Failed to map frame output buffer");
298 goto error;
299 }
300
301 ref->mapped = TRUE;
302 if (GST_VIDEO_FRAME_PLANE_STRIDE (&ref->vframe,
303 0) < width * GST_VIDEO_FRAME_COMP_PSTRIDE (&ref->vframe, 0)) {
304 GST_DEBUG_OBJECT (dec, "plane 0: pitch too small (%d/%d*%d)",
305 GST_VIDEO_FRAME_PLANE_STRIDE (&ref->vframe, 0), width,
306 GST_VIDEO_FRAME_COMP_PSTRIDE (&ref->vframe, 0));
307 goto error;
308 }
309
310 if (GST_VIDEO_FRAME_COMP_HEIGHT (&ref->vframe, 0) < height) {
311 GST_DEBUG_OBJECT (dec, "plane 0: lines too few (%d/%d)",
312 GST_VIDEO_FRAME_COMP_HEIGHT (&ref->vframe, 0), height);
313 goto error;
314 }
315
316 for (i = 0; i < 3; i++) {
317 uint8_t *data;
318 int stride = GST_VIDEO_FRAME_PLANE_STRIDE (&ref->vframe, i);
319 if (stride % spec->alignment) {
320 GST_DEBUG_OBJECT (dec, "plane %d: pitch not aligned (%d%%%d)",
321 i, stride, spec->alignment);
322 goto error;
323 }
324
325 data = GST_VIDEO_FRAME_PLANE_DATA (&ref->vframe, i);
326 if ((uintptr_t) (data) % spec->alignment) {
327 GST_DEBUG_OBJECT (dec, "plane %d not aligned", i);
328 goto error;
329 }
330
331 de265_set_image_plane (img, i, data, stride, ref);
332 }
333 return 1;
334
335 error:
336 gst_libde265_dec_release_frame_ref (ref);
337 frame = NULL;
338
339 fallback:
340 if (frame != NULL) {
341 gst_video_codec_frame_unref (frame);
342 }
343 return de265_get_default_image_allocation_functions ()->get_buffer (ctx,
344 spec, img, userdata);
345 }
346
347 static void
gst_libde265_dec_release_buffer(de265_decoder_context * ctx,struct de265_image * img,void * userdata)348 gst_libde265_dec_release_buffer (de265_decoder_context * ctx,
349 struct de265_image *img, void *userdata)
350 {
351 GstVideoDecoder *base = (GstVideoDecoder *) userdata;
352 struct GstLibde265FrameRef *ref =
353 (struct GstLibde265FrameRef *) de265_get_image_plane_user_data (img, 0);
354 if (ref == NULL) {
355 de265_get_default_image_allocation_functions ()->release_buffer (ctx, img,
356 userdata);
357 return;
358 }
359 gst_libde265_dec_release_frame_ref (ref);
360 (void) base; /* unused */
361 }
362
363 static gboolean
gst_libde265_dec_start(GstVideoDecoder * decoder)364 gst_libde265_dec_start (GstVideoDecoder * decoder)
365 {
366 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
367 int threads = dec->max_threads;
368 struct de265_image_allocation allocation;
369
370 _gst_libde265_dec_free_decoder (dec);
371 dec->ctx = de265_new_decoder ();
372 if (dec->ctx == NULL) {
373 return FALSE;
374 }
375 if (threads == 0) {
376 threads = g_get_num_processors ();
377
378 /* NOTE: We start more threads than cores for now, as some threads
379 * might get blocked while waiting for dependent data. Having more
380 * threads increases decoding speed by about 10% */
381 threads *= 2;
382 }
383 if (threads > 1) {
384 if (threads > 32) {
385 /* TODO: this limit should come from the libde265 headers */
386 threads = 32;
387 }
388 de265_start_worker_threads (dec->ctx, threads);
389 }
390 GST_INFO_OBJECT (dec, "Using libde265 %s with %d worker threads",
391 de265_get_version (), threads);
392
393 allocation.get_buffer = gst_libde265_dec_get_buffer;
394 allocation.release_buffer = gst_libde265_dec_release_buffer;
395 de265_set_image_allocation_functions (dec->ctx, &allocation, decoder);
396 /* NOTE: we explicitly disable hash checks for now */
397 de265_set_parameter_bool (dec->ctx, DE265_DECODER_PARAM_BOOL_SEI_CHECK_HASH,
398 0);
399 return TRUE;
400 }
401
402 static gboolean
gst_libde265_dec_stop(GstVideoDecoder * decoder)403 gst_libde265_dec_stop (GstVideoDecoder * decoder)
404 {
405 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
406
407 _gst_libde265_dec_free_decoder (dec);
408
409 return TRUE;
410 }
411
412 static gboolean
gst_libde265_dec_flush(GstVideoDecoder * decoder)413 gst_libde265_dec_flush (GstVideoDecoder * decoder)
414 {
415 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
416
417 de265_reset (dec->ctx);
418 dec->buffer_full = 0;
419 if (dec->codec_data != NULL
420 && dec->format == GST_TYPE_LIBDE265_FORMAT_BYTESTREAM) {
421 int more;
422 de265_error err =
423 de265_push_data (dec->ctx, dec->codec_data, dec->codec_data_size, 0,
424 NULL);
425 if (!de265_isOK (err)) {
426 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
427 ("Failed to push codec data: %s (code=%d)",
428 de265_get_error_text (err), err), (NULL));
429 return FALSE;
430 }
431 de265_push_end_of_NAL (dec->ctx);
432 do {
433 err = de265_decode (dec->ctx, &more);
434 switch (err) {
435 case DE265_OK:
436 break;
437
438 case DE265_ERROR_IMAGE_BUFFER_FULL:
439 case DE265_ERROR_WAITING_FOR_INPUT_DATA:
440 /* not really an error */
441 more = 0;
442 break;
443
444 default:
445 if (!de265_isOK (err)) {
446 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
447 ("Failed to decode codec data: %s (code=%d)",
448 de265_get_error_text (err), err), (NULL));
449 return FALSE;
450 }
451 }
452 } while (more);
453 }
454
455 return TRUE;
456 }
457
458 static GstFlowReturn
gst_libde265_dec_finish(GstVideoDecoder * decoder)459 gst_libde265_dec_finish (GstVideoDecoder * decoder)
460 {
461 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
462 de265_error err;
463 const struct de265_image *img;
464 int more;
465 GstFlowReturn result;
466
467 err = de265_flush_data (dec->ctx);
468 if (!de265_isOK (err)) {
469 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
470 ("Failed to flush decoder: %s (code=%d)",
471 de265_get_error_text (err), err), (NULL));
472 return GST_FLOW_ERROR;
473 }
474
475 do {
476 err = de265_decode (dec->ctx, &more);
477 switch (err) {
478 case DE265_OK:
479 case DE265_ERROR_IMAGE_BUFFER_FULL:
480 img = de265_get_next_picture (dec->ctx);
481 if (img != NULL) {
482 result = _gst_libde265_return_image (decoder, NULL, img);
483 if (result != GST_FLOW_OK) {
484 return result;
485 }
486 }
487 break;
488
489 case DE265_ERROR_WAITING_FOR_INPUT_DATA:
490 /* not really an error */
491 more = 0;
492 break;
493
494 default:
495 if (!de265_isOK (err)) {
496 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
497 ("Failed to decode codec data: %s (code=%d)",
498 de265_get_error_text (err), err), (NULL));
499 return FALSE;
500 }
501 }
502 } while (more);
503
504 return GST_FLOW_OK;
505 }
506
507 static GstFlowReturn
_gst_libde265_image_available(GstVideoDecoder * decoder,int width,int height)508 _gst_libde265_image_available (GstVideoDecoder * decoder, int width, int height)
509 {
510 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
511
512 if (G_UNLIKELY (dec->output_state == NULL
513 || width != dec->output_state->info.width
514 || height != dec->output_state->info.height)) {
515 GstVideoCodecState *state =
516 gst_video_decoder_set_output_state (decoder, GST_VIDEO_FORMAT_I420,
517 width, height, dec->input_state);
518 if (state == NULL) {
519 GST_ERROR_OBJECT (dec, "Failed to set output state");
520 return GST_FLOW_ERROR;
521 }
522 if (!gst_video_decoder_negotiate (decoder)) {
523 GST_ERROR_OBJECT (dec, "Failed to negotiate format");
524 gst_video_codec_state_unref (state);
525 return GST_FLOW_ERROR;
526 }
527 if (dec->output_state != NULL) {
528 gst_video_codec_state_unref (dec->output_state);
529 }
530 dec->output_state = state;
531 GST_DEBUG_OBJECT (dec, "Frame dimensions are %d x %d", width, height);
532 }
533
534 return GST_FLOW_OK;
535 }
536
537 static gboolean
gst_libde265_dec_set_format(GstVideoDecoder * decoder,GstVideoCodecState * state)538 gst_libde265_dec_set_format (GstVideoDecoder * decoder,
539 GstVideoCodecState * state)
540 {
541 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
542
543 if (dec->input_state != NULL) {
544 gst_video_codec_state_unref (dec->input_state);
545 }
546 dec->input_state = state;
547 if (state != NULL) {
548 gst_video_codec_state_ref (state);
549 }
550 if (state != NULL && state->caps != NULL) {
551 GstStructure *str;
552 const GValue *value;
553 str = gst_caps_get_structure (state->caps, 0);
554 if ((value = gst_structure_get_value (str, "codec_data"))) {
555 GstMapInfo info;
556 guint8 *data;
557 gsize size;
558 GstBuffer *buf;
559 de265_error err;
560 int more;
561
562 buf = gst_value_get_buffer (value);
563 if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
564 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
565 ("Failed to map codec data"), (NULL));
566 return FALSE;
567 }
568 data = info.data;
569 size = info.size;
570 free (dec->codec_data);
571 dec->codec_data = malloc (size);
572 g_assert (dec->codec_data != NULL);
573 dec->codec_data_size = size;
574 memcpy (dec->codec_data, data, size);
575 if (size > 3 && (data[0] || data[1] || data[2] > 1)) {
576 /* encoded in "hvcC" format (assume version 0) */
577 dec->format = GST_TYPE_LIBDE265_FORMAT_PACKETIZED;
578 if (size > 22) {
579 int i;
580 int num_param_sets;
581 int pos;
582 if (data[0] != 0) {
583 GST_ELEMENT_WARNING (decoder, STREAM,
584 DECODE, ("Unsupported extra data version %d, decoding may fail",
585 data[0]), (NULL));
586 }
587 dec->length_size = (data[21] & 3) + 1;
588 num_param_sets = data[22];
589 pos = 23;
590 for (i = 0; i < num_param_sets; i++) {
591 int j;
592 int nal_count;
593 if (pos + 3 > size) {
594 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
595 ("Buffer underrun in extra header (%d >= %" G_GSIZE_FORMAT
596 ")", pos + 3, size), (NULL));
597 return FALSE;
598 }
599 /* ignore flags + NAL type (1 byte) */
600 nal_count = data[pos + 1] << 8 | data[pos + 2];
601 pos += 3;
602 for (j = 0; j < nal_count; j++) {
603 int nal_size;
604 if (pos + 2 > size) {
605 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
606 ("Buffer underrun in extra nal header (%d >= %"
607 G_GSIZE_FORMAT ")", pos + 2, size), (NULL));
608 return FALSE;
609 }
610 nal_size = data[pos] << 8 | data[pos + 1];
611 if (pos + 2 + nal_size > size) {
612 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
613 ("Buffer underrun in extra nal (%d >= %" G_GSIZE_FORMAT ")",
614 pos + 2 + nal_size, size), (NULL));
615 return FALSE;
616 }
617 err =
618 de265_push_NAL (dec->ctx, data + pos + 2, nal_size, 0, NULL);
619 if (!de265_isOK (err)) {
620 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
621 ("Failed to push data: %s (%d)", de265_get_error_text (err),
622 err), (NULL));
623 return FALSE;
624 }
625 pos += 2 + nal_size;
626 }
627 }
628 }
629 GST_DEBUG ("Assuming packetized data (%d bytes length)",
630 dec->length_size);
631 } else {
632 dec->format = GST_TYPE_LIBDE265_FORMAT_BYTESTREAM;
633 GST_DEBUG_OBJECT (dec, "Assuming non-packetized data");
634 err = de265_push_data (dec->ctx, data, size, 0, NULL);
635 if (!de265_isOK (err)) {
636 gst_buffer_unmap (buf, &info);
637 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
638 ("Failed to push codec data: %s (code=%d)",
639 de265_get_error_text (err), err), (NULL));
640 return FALSE;
641 }
642 }
643 gst_buffer_unmap (buf, &info);
644 de265_push_end_of_NAL (dec->ctx);
645 do {
646 err = de265_decode (dec->ctx, &more);
647 switch (err) {
648 case DE265_OK:
649 break;
650
651 case DE265_ERROR_IMAGE_BUFFER_FULL:
652 case DE265_ERROR_WAITING_FOR_INPUT_DATA:
653 /* not really an error */
654 more = 0;
655 break;
656
657 default:
658 if (!de265_isOK (err)) {
659 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
660 ("Failed to decode codec data: %s (code=%d)",
661 de265_get_error_text (err), err), (NULL));
662 return FALSE;
663 }
664 }
665 } while (more);
666 } else if ((value = gst_structure_get_value (str, "stream-format"))) {
667 const gchar *str = g_value_get_string (value);
668 if (strcmp (str, "byte-stream") == 0) {
669 dec->format = GST_TYPE_LIBDE265_FORMAT_BYTESTREAM;
670 GST_DEBUG_OBJECT (dec, "Assuming raw byte-stream");
671 }
672 }
673 }
674
675 return TRUE;
676 }
677
678 static GstFlowReturn
_gst_libde265_return_image(GstVideoDecoder * decoder,GstVideoCodecFrame * frame,const struct de265_image * img)679 _gst_libde265_return_image (GstVideoDecoder * decoder,
680 GstVideoCodecFrame * frame, const struct de265_image *img)
681 {
682 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
683 struct GstLibde265FrameRef *ref;
684 GstFlowReturn result;
685 GstVideoFrame outframe;
686 GstVideoCodecFrame *out_frame;
687 int frame_number;
688 int plane;
689
690 ref = (struct GstLibde265FrameRef *) de265_get_image_plane_user_data (img, 0);
691 if (ref != NULL) {
692 /* decoder is using direct rendering */
693 out_frame = gst_video_codec_frame_ref (ref->frame);
694 if (frame != NULL) {
695 gst_video_codec_frame_unref (frame);
696 }
697 gst_buffer_replace (&out_frame->output_buffer, ref->buffer);
698 gst_buffer_replace (&ref->buffer, NULL);
699 return gst_video_decoder_finish_frame (decoder, out_frame);
700 }
701
702 result =
703 _gst_libde265_image_available (decoder, de265_get_image_width (img, 0),
704 de265_get_image_height (img, 0));
705 if (result != GST_FLOW_OK) {
706 GST_ERROR_OBJECT (dec, "Failed to notify about available image");
707 return result;
708 }
709
710 frame_number = (uintptr_t) de265_get_image_user_data (img) - 1;
711 if (frame_number != -1) {
712 out_frame = gst_video_decoder_get_frame (decoder, frame_number);
713 } else {
714 out_frame = NULL;
715 }
716 if (frame != NULL) {
717 gst_video_codec_frame_unref (frame);
718 }
719
720 if (out_frame == NULL) {
721 GST_ERROR_OBJECT (dec, "No frame available to return");
722 return GST_FLOW_ERROR;
723 }
724
725 result = gst_video_decoder_allocate_output_frame (decoder, out_frame);
726 if (result != GST_FLOW_OK) {
727 GST_ERROR_OBJECT (dec, "Failed to allocate output frame");
728 return result;
729 }
730
731 g_assert (dec->output_state != NULL);
732 if (!gst_video_frame_map (&outframe, &dec->output_state->info,
733 out_frame->output_buffer, GST_MAP_WRITE)) {
734 GST_ERROR_OBJECT (dec, "Failed to map output buffer");
735 return GST_FLOW_ERROR;
736 }
737
738 for (plane = 0; plane < 3; plane++) {
739 int width = de265_get_image_width (img, plane);
740 int height = de265_get_image_height (img, plane);
741 int srcstride = width;
742 int dststride = GST_VIDEO_FRAME_COMP_STRIDE (&outframe, plane);
743 const uint8_t *src = de265_get_image_plane (img, plane, &srcstride);
744 uint8_t *dest = GST_VIDEO_FRAME_COMP_DATA (&outframe, plane);
745 if (srcstride == width && dststride == width) {
746 memcpy (dest, src, height * width);
747 } else {
748 while (height--) {
749 memcpy (dest, src, width);
750 src += srcstride;
751 dest += dststride;
752 }
753 }
754 }
755 gst_video_frame_unmap (&outframe);
756 return gst_video_decoder_finish_frame (decoder, out_frame);
757 }
758
759 static GstFlowReturn
gst_libde265_dec_handle_frame(GstVideoDecoder * decoder,GstVideoCodecFrame * frame)760 gst_libde265_dec_handle_frame (GstVideoDecoder * decoder,
761 GstVideoCodecFrame * frame)
762 {
763 GstLibde265Dec *dec = GST_LIBDE265_DEC (decoder);
764 uint8_t *frame_data;
765 uint8_t *end_data;
766 const struct de265_image *img;
767 de265_error ret = DE265_OK;
768 int more = 0;
769 GstClockTime pts;
770 gsize size;
771 GstMapInfo info;
772
773 pts = frame->pts;
774 if (pts == GST_CLOCK_TIME_NONE) {
775 pts = frame->dts;
776 }
777
778 if (!gst_buffer_map (frame->input_buffer, &info, GST_MAP_READ)) {
779 GST_ERROR_OBJECT (dec, "Failed to map input buffer");
780 return GST_FLOW_ERROR;
781 }
782
783 frame_data = info.data;
784 size = info.size;
785 end_data = frame_data + size;
786
787 if (size > 0) {
788 if (dec->format == GST_TYPE_LIBDE265_FORMAT_PACKETIZED) {
789 /* stream contains length fields and NALs */
790 uint8_t *start_data = frame_data;
791 while (start_data + dec->length_size <= end_data) {
792 int nal_size = 0;
793 int i;
794 for (i = 0; i < dec->length_size; i++) {
795 nal_size = (nal_size << 8) | start_data[i];
796 }
797 if (start_data + dec->length_size + nal_size > end_data) {
798 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
799 ("Overflow in input data, check stream format"), (NULL));
800 goto error_input;
801 }
802 ret =
803 de265_push_NAL (dec->ctx, start_data + dec->length_size, nal_size,
804 (de265_PTS) pts,
805 (void *) (uintptr_t) (frame->system_frame_number + 1));
806 if (ret != DE265_OK) {
807 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
808 ("Error while pushing data: %s (code=%d)",
809 de265_get_error_text (ret), ret), (NULL));
810 goto error_input;
811 }
812 start_data += dec->length_size + nal_size;
813 }
814 } else {
815 ret =
816 de265_push_data (dec->ctx, frame_data, size, (de265_PTS) pts,
817 (void *) (uintptr_t) (frame->system_frame_number + 1));
818 if (ret != DE265_OK) {
819 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
820 ("Error while pushing data: %s (code=%d)",
821 de265_get_error_text (ret), ret), (NULL));
822 goto error_input;
823 }
824 }
825 } else {
826 ret = de265_flush_data (dec->ctx);
827 if (ret != DE265_OK) {
828 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
829 ("Error while flushing data: %s (code=%d)",
830 de265_get_error_text (ret), ret), (NULL));
831 goto error_input;
832 }
833 }
834 gst_buffer_unmap (frame->input_buffer, &info);
835
836 /* decode as much as possible */
837 do {
838 ret = de265_decode (dec->ctx, &more);
839 } while (more && ret == DE265_OK);
840
841 switch (ret) {
842 case DE265_OK:
843 case DE265_ERROR_WAITING_FOR_INPUT_DATA:
844 break;
845
846 case DE265_ERROR_IMAGE_BUFFER_FULL:
847 dec->buffer_full = 1;
848 if ((img = de265_peek_next_picture (dec->ctx)) == NULL) {
849 return GST_FLOW_OK;
850 }
851 break;
852
853 default:
854 GST_ELEMENT_ERROR (decoder, STREAM, DECODE,
855 ("Error while decoding: %s (code=%d)", de265_get_error_text (ret),
856 ret), (NULL));
857 return GST_FLOW_ERROR;
858 }
859
860 while ((ret = de265_get_warning (dec->ctx)) != DE265_OK) {
861 GST_ELEMENT_WARNING (decoder, STREAM, DECODE,
862 ("%s (code=%d)", de265_get_error_text (ret), ret), (NULL));
863 }
864
865 img = de265_get_next_picture (dec->ctx);
866 if (img == NULL) {
867 /* need more data */
868 return GST_FLOW_OK;
869 }
870
871 return _gst_libde265_return_image (decoder, frame, img);
872
873 error_input:
874 gst_buffer_unmap (frame->input_buffer, &info);
875 return GST_FLOW_ERROR;
876 }
877