• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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