d3d11decoder: Refactor decoding process
authorSeungha Yang <seungha.yang@navercorp.com>
Wed, 5 Feb 2020 12:27:23 +0000 (21:27 +0900)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 12 Feb 2020 12:34:58 +0000 (12:34 +0000)
* Move decoding process to handle_frame
* Remove GstVideoDecoder::parse implementation
* Clarify flush/drain/finish usage

In forward playback case, have_frame() call will be followed by
handle_frame() but reverse playback is not the case.
To ensure GstVideoCodecFrame, the decoding process should be placed inside
of handle_frame(), instead of parse().

Since we don't support alignment=nal, the parse() implementation is not worth.
In order to fix broken reverse playback, let's remove the parse()
implementation and revisit it when adding alignment=nal support.

sys/d3d11/gsth264decoder.c
sys/d3d11/gsth265decoder.c

index 96920fa..cc0f286 100644 (file)
@@ -95,6 +95,7 @@ struct _GstH264DecoderPrivate
 
   /* Picture currently being processed/decoded */
   GstH264Picture *current_picture;
+  GstVideoCodecFrame *current_frame;
 
   /* Slice (slice header + nalu) currently being processed/decodec */
   GstH264Slice current_slice;
@@ -127,8 +128,6 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstH264Decoder, gst_h264_decoder,
 
 static gboolean gst_h264_decoder_start (GstVideoDecoder * decoder);
 static gboolean gst_h264_decoder_stop (GstVideoDecoder * decoder);
-static GstFlowReturn gst_h264_decoder_parse (GstVideoDecoder * decoder,
-    GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
 static gboolean gst_h264_decoder_set_format (GstVideoDecoder * decoder,
     GstVideoCodecState * state);
 static GstFlowReturn gst_h264_decoder_finish (GstVideoDecoder * decoder);
@@ -141,6 +140,8 @@ static GstFlowReturn gst_h264_decoder_handle_frame (GstVideoDecoder * decoder,
 static gboolean gst_h264_decoder_process_sps (GstH264Decoder * self,
     GstH264SPS * sps);
 static gboolean gst_h264_decoder_decode_slice (GstH264Decoder * self);
+static gboolean gst_h264_decoder_decode_nal (GstH264Decoder * self,
+    GstH264NalUnit * nalu, GstClockTime pts);
 static gboolean gst_h264_decoder_fill_picture_from_slice (GstH264Decoder * self,
     const GstH264Slice * slice, GstH264Picture * picture);
 static gboolean gst_h264_decoder_calculate_poc (GstH264Decoder * self,
@@ -160,7 +161,6 @@ gst_h264_decoder_class_init (GstH264DecoderClass * klass)
 
   decoder_class->start = GST_DEBUG_FUNCPTR (gst_h264_decoder_start);
   decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h264_decoder_stop);
-  decoder_class->parse = GST_DEBUG_FUNCPTR (gst_h264_decoder_parse);
   decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_h264_decoder_set_format);
   decoder_class->finish = GST_DEBUG_FUNCPTR (gst_h264_decoder_finish);
   decoder_class->flush = GST_DEBUG_FUNCPTR (gst_h264_decoder_flush);
@@ -172,7 +172,7 @@ gst_h264_decoder_class_init (GstH264DecoderClass * klass)
 static void
 gst_h264_decoder_init (GstH264Decoder * self)
 {
-  gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), FALSE);
+  gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
 
   self->priv = gst_h264_decoder_get_instance_private (self);
 }
@@ -228,16 +228,10 @@ static gboolean
 gst_h264_decoder_flush (GstVideoDecoder * decoder)
 {
   GstH264Decoder *self = GST_H264_DECODER (decoder);
-  gboolean ret = TRUE;
-
-  gst_h264_decoder_finish_current_picture (self);
-
-  if (!gst_h264_decoder_output_all_remaining_pics (self))
-    ret = FALSE;
 
   gst_h264_decoder_clear_dpb (self);
 
-  return ret;
+  return TRUE;
 }
 
 static GstFlowReturn
@@ -246,7 +240,9 @@ gst_h264_decoder_drain (GstVideoDecoder * decoder)
   GstH264Decoder *self = GST_H264_DECODER (decoder);
   GstH264DecoderPrivate *priv = self->priv;
 
-  gst_h264_decoder_flush (decoder);
+  priv->last_ret = GST_FLOW_OK;
+  gst_h264_decoder_output_all_remaining_pics (self);
+  gst_h264_decoder_clear_dpb (self);
 
   return priv->last_ret;
 }
@@ -264,26 +260,68 @@ gst_h264_decoder_handle_frame (GstVideoDecoder * decoder,
   GstH264Decoder *self = GST_H264_DECODER (decoder);
   GstH264DecoderPrivate *priv = self->priv;
   GstBuffer *in_buf = frame->input_buffer;
+  GstH264NalUnit nalu;
+  GstH264ParserResult pres;
+  GstMapInfo map;
+  gboolean decode_ret = TRUE;
 
   GST_LOG_OBJECT (self,
       "handle frame, PTS: %" GST_TIME_FORMAT ", DTS: %"
       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (in_buf)),
       GST_TIME_ARGS (GST_BUFFER_DTS (in_buf)));
 
-  if (!priv->current_picture) {
-    GST_ERROR_OBJECT (self, "No current picture");
-    gst_video_decoder_drop_frame (decoder, frame);
+  priv->current_frame = frame;
+  priv->last_ret = GST_FLOW_OK;
+
+  gst_buffer_map (in_buf, &map, GST_MAP_READ);
+  if (priv->in_format == GST_H264_DECODER_FORMAT_AVC) {
+    pres = gst_h264_parser_identify_nalu_avc (priv->parser,
+        map.data, 0, map.size, priv->nal_length_size, &nalu);
+
+    while (pres == GST_H264_PARSER_OK && decode_ret) {
+      decode_ret = gst_h264_decoder_decode_nal (self,
+          &nalu, GST_BUFFER_PTS (in_buf));
+
+      pres = gst_h264_parser_identify_nalu_avc (priv->parser,
+          map.data, nalu.offset + nalu.size, map.size, priv->nal_length_size,
+          &nalu);
+    }
+  } else {
+    pres = gst_h264_parser_identify_nalu (priv->parser,
+        map.data, 0, map.size, &nalu);
+
+    if (pres == GST_H264_PARSER_NO_NAL_END)
+      pres = GST_H264_PARSER_OK;
+
+    while (pres == GST_H264_PARSER_OK && decode_ret) {
+      decode_ret = gst_h264_decoder_decode_nal (self,
+          &nalu, GST_BUFFER_PTS (in_buf));
+
+      pres = gst_h264_parser_identify_nalu (priv->parser,
+          map.data, nalu.offset + nalu.size, map.size, &nalu);
 
-    return GST_FLOW_ERROR;
+      if (pres == GST_H264_PARSER_NO_NAL_END)
+        pres = GST_H264_PARSER_OK;
+    }
   }
 
-  gst_video_codec_frame_set_user_data (frame,
-      gst_h264_picture_ref (priv->current_picture),
-      (GDestroyNotify) gst_h264_picture_unref);
+  gst_buffer_unmap (in_buf, &map);
+  priv->current_frame = NULL;
+
+  if (!decode_ret) {
+    GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
+        ("Failed to decode data"), (NULL), priv->last_ret);
+    gst_video_decoder_drop_frame (decoder, frame);
 
+    gst_h264_picture_clear (&priv->current_picture);
+
+    return priv->last_ret;
+  }
+
+  gst_h264_decoder_finish_current_picture (self);
   gst_video_codec_frame_unref (frame);
 
-  return GST_FLOW_OK;
+  return priv->last_ret;
 }
 
 static gboolean
@@ -294,8 +332,6 @@ gst_h264_decoder_parse_sps (GstH264Decoder * self, GstH264NalUnit * nalu)
   GstH264ParserResult pres;
   gboolean ret = TRUE;
 
-  gst_h264_decoder_finish_current_picture (self);
-
   pres = gst_h264_parser_parse_sps (priv->parser, nalu, &sps);
   if (pres != GST_H264_PARSER_OK) {
     GST_WARNING_OBJECT (self, "Failed to parse SPS, result %d", pres);
@@ -319,8 +355,6 @@ gst_h264_decoder_parse_pps (GstH264Decoder * self, GstH264NalUnit * nalu)
   GstH264PPS pps;
   GstH264ParserResult pres;
 
-  gst_h264_decoder_finish_current_picture (self);
-
   pres = gst_h264_parser_parse_pps (priv->parser, nalu, &pps);
   if (pres != GST_H264_PARSER_OK) {
     GST_WARNING_OBJECT (self, "Failed to parse PPS, result %d", pres);
@@ -408,61 +442,11 @@ gst_h264_decoder_parse_codec_data (GstH264Decoder * self, const guint8 * data,
 }
 
 static gboolean
-gst_h264_decoder_is_new_au (GstH264Decoder * self, GstH264Slice * slice)
-{
-  GstH264DecoderPrivate *priv = self->priv;
-  GstH264SliceHdr *slice_hdr;
-  GstH264NalUnit *nalu;
-  GstH264Picture *current_picture;
-  const GstH264SPS *sps;
-
-  current_picture = priv->current_picture;
-  if (!current_picture)
-    return TRUE;
-
-  slice_hdr = &slice->header;
-  nalu = &slice->nalu;
-  if (slice_hdr->frame_num != current_picture->frame_num ||
-      slice_hdr->pps->id != priv->active_pps->id ||
-      nalu->ref_idc != current_picture->nal_ref_idc ||
-      (! !nalu->idr_pic_flag) != (! !current_picture->idr_pic_id) ||
-      (nalu->idr_pic_flag &&
-          (slice_hdr->idr_pic_id != current_picture->idr_pic_id ||
-              !slice_hdr->first_mb_in_slice)))
-    return TRUE;
-
-  sps = priv->active_sps;
-  if (!sps)
-    return FALSE;
-
-  if (sps->pic_order_cnt_type == current_picture->pic_order_cnt_type) {
-    if (current_picture->pic_order_cnt_type == 0) {
-      if (slice_hdr->pic_order_cnt_lsb != current_picture->pic_order_cnt_lsb ||
-          slice_hdr->delta_pic_order_cnt_bottom !=
-          current_picture->delta_pic_order_cnt_bottom)
-        return TRUE;
-    } else if (current_picture->pic_order_cnt_type == 1) {
-      if (slice_hdr->delta_pic_order_cnt[0] !=
-          current_picture->delta_pic_order_cnt0
-          || slice_hdr->delta_pic_order_cnt[1] !=
-          current_picture->delta_pic_order_cnt1)
-        return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-static gboolean
 gst_h264_decoder_preprocess_slice (GstH264Decoder * self, GstH264Slice * slice)
 {
   GstH264DecoderPrivate *priv = self->priv;
 
-  if (gst_h264_decoder_is_new_au (self, slice)) {
-    /* finish previous frame if any */
-    if (!gst_h264_decoder_finish_current_picture (self))
-      return FALSE;
-
+  if (!priv->current_picture) {
     if (slice->header.first_mb_in_slice != 0) {
       GST_ERROR_OBJECT (self, "Invalid stream, first_mb_in_slice %d",
           slice->header.first_mb_in_slice);
@@ -474,7 +458,7 @@ gst_h264_decoder_preprocess_slice (GstH264Decoder * self, GstH264Slice * slice)
       /* Output all remaining pictures, unless we are explicitly instructed
        * not to do so */
       if (!slice->header.dec_ref_pic_marking.no_output_of_prior_pics_flag)
-        gst_h264_decoder_flush (GST_VIDEO_DECODER (self));
+        gst_h264_decoder_drain (GST_VIDEO_DECODER (self));
 
       gst_h264_dpb_clear (priv->dpb);
     }
@@ -675,6 +659,9 @@ gst_h264_decoder_parse_slice (GstH264Decoder * self, GstH264NalUnit * nalu,
     }
 
     priv->current_picture = picture;
+    gst_video_codec_frame_set_user_data (priv->current_frame,
+        gst_h264_picture_ref (priv->current_picture),
+        (GDestroyNotify) gst_h264_picture_unref);
 
     if (!gst_h264_decoder_start_current_picture (self)) {
       GST_ERROR_OBJECT (self, "start picture failed");
@@ -685,62 +672,21 @@ gst_h264_decoder_parse_slice (GstH264Decoder * self, GstH264NalUnit * nalu,
   return gst_h264_decoder_decode_slice (self);
 }
 
-static GstFlowReturn
-gst_h264_decoder_parse_nal (GstH264Decoder * self, const guint8 * data,
-    gsize size, GstClockTime pts, gboolean at_eos, gsize * consumed_size)
+static gboolean
+gst_h264_decoder_decode_nal (GstH264Decoder * self, GstH264NalUnit * nalu,
+    GstClockTime pts)
 {
-  GstH264DecoderPrivate *priv = self->priv;
-  GstH264ParserResult pres;
-  GstH264NalUnit nalu;
   gboolean ret = TRUE;
 
-  *consumed_size = 0;
-
-  if (priv->in_format == GST_H264_DECODER_FORMAT_AVC) {
-    if (priv->nal_length_size < 1 || priv->nal_length_size > 4) {
-      GST_ERROR_OBJECT (self,
-          "invalid nal length size %d", priv->nal_length_size);
-      return GST_FLOW_ERROR;
-    }
-
-    pres = gst_h264_parser_identify_nalu_avc (priv->parser,
-        data, 0, size, priv->nal_length_size, &nalu);
-
-    if (pres != GST_H264_PARSER_OK) {
-      GST_WARNING_OBJECT (self, "parsing avc nal ret %d", pres);
-      return GST_FLOW_ERROR;
-    }
-  } else {
-    if (size < 5) {
-      GST_DEBUG_OBJECT (self, "Too small data");
-      return GST_VIDEO_DECODER_FLOW_NEED_DATA;
-    }
-
-    pres = gst_h264_parser_identify_nalu (priv->parser, data, 0, size, &nalu);
-
-    if (pres != GST_H264_PARSER_OK) {
-      if (pres == GST_H264_PARSER_NO_NAL_END) {
-        if (at_eos || priv->align == GST_H264_DECODER_ALIGN_AU) {
-          /* assume au boundary */
-        } else {
-          return GST_VIDEO_DECODER_FLOW_NEED_DATA;
-        }
-      } else {
-        GST_WARNING_OBJECT (self, "parser ret %d", pres);
-        return GST_FLOW_ERROR;
-      }
-    }
-  }
-
   GST_LOG_OBJECT (self, "Parsed nal type: %d, offset %d, size %d",
-      nalu.type, nalu.offset, nalu.size);
+      nalu->type, nalu->offset, nalu->size);
 
-  switch (nalu.type) {
+  switch (nalu->type) {
     case GST_H264_NAL_SPS:
-      ret = gst_h264_decoder_parse_sps (self, &nalu);
+      ret = gst_h264_decoder_parse_sps (self, nalu);
       break;
     case GST_H264_NAL_PPS:
-      ret = gst_h264_decoder_parse_pps (self, &nalu);
+      ret = gst_h264_decoder_parse_pps (self, nalu);
       break;
     case GST_H264_NAL_SLICE:
     case GST_H264_NAL_SLICE_DPA:
@@ -748,67 +694,12 @@ gst_h264_decoder_parse_nal (GstH264Decoder * self, const guint8 * data,
     case GST_H264_NAL_SLICE_DPC:
     case GST_H264_NAL_SLICE_IDR:
     case GST_H264_NAL_SLICE_EXT:
-      ret = gst_h264_decoder_parse_slice (self, &nalu, pts);
+      ret = gst_h264_decoder_parse_slice (self, nalu, pts);
       break;
     default:
       break;
   }
 
-  if (consumed_size)
-    *consumed_size = nalu.offset + nalu.size;
-
-  if (!ret)
-    return GST_FLOW_ERROR;
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_h264_decoder_parse (GstVideoDecoder * decoder, GstVideoCodecFrame * frame,
-    GstAdapter * adapter, gboolean at_eos)
-{
-  GstH264Decoder *self = GST_H264_DECODER (decoder);
-  GstH264DecoderPrivate *priv = self->priv;
-  GstFlowReturn ret = GST_FLOW_OK;
-  guint size;
-  const guint8 *data;
-  gsize consumed = 0;
-
-  /* The return from have_frame() or output_picture() */
-  priv->last_ret = GST_FLOW_OK;
-
-  size = gst_adapter_available (adapter);
-
-  data = (const guint8 *) gst_adapter_map (adapter, size);
-  ret = gst_h264_decoder_parse_nal (self, data, size,
-      gst_adapter_prev_pts (adapter, NULL), at_eos, &consumed);
-  gst_adapter_unmap (adapter);
-
-  if (consumed) {
-    GST_TRACE_OBJECT (self, "consumed size %" G_GSIZE_FORMAT, consumed);
-    gst_video_decoder_add_to_frame (decoder, consumed);
-  }
-
-  if (ret == GST_FLOW_ERROR)
-    goto error;
-
-  /* When AU alginment and has no available input data more,
-   * finish current picture if any */
-  if (priv->align == GST_H264_DECODER_ALIGN_AU &&
-      !gst_adapter_available (adapter)) {
-    gst_h264_decoder_finish_current_picture (self);
-  }
-
-  /* check last flow return again */
-  if (ret == GST_FLOW_ERROR)
-    goto error;
-
-  return priv->last_ret;
-
-error:
-  GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
-      ("Failed to decode data"), (NULL), ret);
-
   return ret;
 }
 
@@ -1240,8 +1131,6 @@ gst_h264_decoder_finish_current_picture (GstH264Decoder * self)
   if (klass->end_picture)
     ret = klass->end_picture (self, priv->current_picture);
 
-  gst_video_decoder_have_frame (GST_VIDEO_DECODER (self));
-
   /* finish picture takes ownership of the picture */
   ret = gst_h264_decoder_finish_picture (self, priv->current_picture);
   priv->current_picture = NULL;
@@ -1801,7 +1690,7 @@ gst_h264_decoder_process_sps (GstH264Decoder * self, GstH264SPS * sps)
         priv->width, priv->height, sps->width, sps->height,
         prev_max_dpb_size, max_dpb_size);
 
-    if (!gst_h264_decoder_flush (GST_VIDEO_DECODER (self)))
+    if (gst_h264_decoder_drain (GST_VIDEO_DECODER (self)) != GST_FLOW_OK)
       return FALSE;
 
     g_assert (klass->new_sequence);
index a9e8526..f847de9 100644 (file)
@@ -68,6 +68,7 @@ struct _GstH265DecoderPrivate
 
   /* Picture currently being processed/decoded */
   GstH265Picture *current_picture;
+  GstVideoCodecFrame *current_frame;
 
   /* Slice (slice header + nalu) currently being processed/decodec */
   GstH265Slice current_slice;
@@ -101,8 +102,6 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstH265Decoder, gst_h265_decoder,
 
 static gboolean gst_h265_decoder_start (GstVideoDecoder * decoder);
 static gboolean gst_h265_decoder_stop (GstVideoDecoder * decoder);
-static GstFlowReturn gst_h265_decoder_parse (GstVideoDecoder * decoder,
-    GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
 static gboolean gst_h265_decoder_set_format (GstVideoDecoder * decoder,
     GstVideoCodecState * state);
 static GstFlowReturn gst_h265_decoder_finish (GstVideoDecoder * decoder);
@@ -124,7 +123,6 @@ gst_h265_decoder_class_init (GstH265DecoderClass * klass)
 
   decoder_class->start = GST_DEBUG_FUNCPTR (gst_h265_decoder_start);
   decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h265_decoder_stop);
-  decoder_class->parse = GST_DEBUG_FUNCPTR (gst_h265_decoder_parse);
   decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_h265_decoder_set_format);
   decoder_class->finish = GST_DEBUG_FUNCPTR (gst_h265_decoder_finish);
   decoder_class->flush = GST_DEBUG_FUNCPTR (gst_h265_decoder_flush);
@@ -136,7 +134,7 @@ gst_h265_decoder_class_init (GstH265DecoderClass * klass)
 static void
 gst_h265_decoder_init (GstH265Decoder * self)
 {
-  gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), FALSE);
+  gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
 
   self->priv = gst_h265_decoder_get_instance_private (self);
 }
@@ -189,8 +187,6 @@ gst_h265_decoder_parse_vps (GstH265Decoder * self, GstH265NalUnit * nalu)
   GstH265ParserResult pres;
   gboolean ret = TRUE;
 
-  gst_h265_decoder_finish_current_picture (self);
-
   pres = gst_h265_parser_parse_vps (priv->parser, nalu, &vps);
   if (pres != GST_H265_PARSER_OK) {
     GST_WARNING_OBJECT (self, "Failed to parse VPS, result %d", pres);
@@ -277,8 +273,6 @@ gst_h265_decoder_parse_sps (GstH265Decoder * self, GstH265NalUnit * nalu)
   GstH265ParserResult pres;
   gboolean ret = TRUE;
 
-  gst_h265_decoder_finish_current_picture (self);
-
   pres = gst_h265_parser_parse_sps (priv->parser, nalu, &sps, TRUE);
   if (pres != GST_H265_PARSER_OK) {
     GST_WARNING_OBJECT (self, "Failed to parse SPS, result %d", pres);
@@ -300,8 +294,6 @@ gst_h265_decoder_parse_pps (GstH265Decoder * self, GstH265NalUnit * nalu)
   GstH265PPS pps;
   GstH265ParserResult pres;
 
-  gst_h265_decoder_finish_current_picture (self);
-
   pres = gst_h265_parser_parse_pps (priv->parser, nalu, &pps);
   if (pres != GST_H265_PARSER_OK) {
     GST_WARNING_OBJECT (self, "Failed to parse PPS, result %d", pres);
@@ -347,7 +339,7 @@ gst_h265_decoder_preprocess_slice (GstH265Decoder * self, GstH265Slice * slice)
 
   if (IS_IDR (nalu->type)) {
     GST_DEBUG_OBJECT (self, "IDR nalu, clear dpb");
-    gst_h265_decoder_flush (GST_VIDEO_DECODER (self));
+    gst_h265_decoder_drain (GST_VIDEO_DECODER (self));
   }
 
   return TRUE;
@@ -398,6 +390,9 @@ gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu,
     }
 
     priv->current_picture = picture;
+    gst_video_codec_frame_set_user_data (priv->current_frame,
+        gst_h265_picture_ref (priv->current_picture),
+        (GDestroyNotify) gst_h265_picture_unref);
 
     if (!gst_h265_decoder_start_current_picture (self)) {
       GST_ERROR_OBJECT (self, "start picture failed");
@@ -413,65 +408,24 @@ gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu,
 }
 
 static GstFlowReturn
-gst_h265_decoder_parse_nal (GstH265Decoder * self, const guint8 * data,
-    gsize size, GstClockTime pts, gboolean at_eos, gsize * consumed_size)
+gst_h265_decoder_decode_nal (GstH265Decoder * self, GstH265NalUnit * nalu,
+    GstClockTime pts)
 {
   GstH265DecoderPrivate *priv = self->priv;
-  GstH265ParserResult pres;
-  GstH265NalUnit nalu;
   gboolean ret = TRUE;
 
-  *consumed_size = 0;
-
-  if (priv->in_format == GST_H265_DECODER_FORMAT_HVC1 ||
-      priv->in_format == GST_H265_DECODER_FORMAT_HEV1) {
-    if (priv->nal_length_size < 1 || priv->nal_length_size > 4) {
-      GST_ERROR_OBJECT (self,
-          "invalid nal length size %d", priv->nal_length_size);
-      return GST_FLOW_ERROR;
-    }
-
-    pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
-        data, 0, size, priv->nal_length_size, &nalu);
-
-    if (pres != GST_H265_PARSER_OK) {
-      GST_WARNING_OBJECT (self, "parsing hevc nal ret %d", pres);
-      return GST_FLOW_ERROR;
-    }
-  } else {
-    if (size < 5) {
-      GST_DEBUG_OBJECT (self, "Too small data");
-      return GST_VIDEO_DECODER_FLOW_NEED_DATA;
-    }
-
-    pres = gst_h265_parser_identify_nalu (priv->parser, data, 0, size, &nalu);
-
-    if (pres != GST_H265_PARSER_OK) {
-      if (pres == GST_H265_PARSER_NO_NAL_END) {
-        if (at_eos || priv->align == GST_H265_DECODER_ALIGN_AU) {
-          /* assume au boundary */
-        } else {
-          return GST_VIDEO_DECODER_FLOW_NEED_DATA;
-        }
-      } else {
-        GST_WARNING_OBJECT (self, "parser ret %d", pres);
-        return GST_FLOW_ERROR;
-      }
-    }
-  }
-
   GST_LOG_OBJECT (self, "Parsed nal type: %d, offset %d, size %d",
-      nalu.type, nalu.offset, nalu.size);
+      nalu->type, nalu->offset, nalu->size);
 
-  switch (nalu.type) {
+  switch (nalu->type) {
     case GST_H265_NAL_VPS:
-      ret = gst_h265_decoder_parse_vps (self, &nalu);
+      ret = gst_h265_decoder_parse_vps (self, nalu);
       break;
     case GST_H265_NAL_SPS:
-      ret = gst_h265_decoder_parse_sps (self, &nalu);
+      ret = gst_h265_decoder_parse_sps (self, nalu);
       break;
     case GST_H265_NAL_PPS:
-      ret = gst_h265_decoder_parse_pps (self, &nalu);
+      ret = gst_h265_decoder_parse_pps (self, nalu);
       break;
     case GST_H265_NAL_SLICE_TRAIL_N:
     case GST_H265_NAL_SLICE_TRAIL_R:
@@ -489,77 +443,22 @@ gst_h265_decoder_parse_nal (GstH265Decoder * self, const guint8 * data,
     case GST_H265_NAL_SLICE_IDR_W_RADL:
     case GST_H265_NAL_SLICE_IDR_N_LP:
     case GST_H265_NAL_SLICE_CRA_NUT:
-      ret = gst_h265_decoder_parse_slice (self, &nalu, pts);
+      ret = gst_h265_decoder_parse_slice (self, nalu, pts);
       priv->new_bitstream = FALSE;
       priv->prev_nal_is_eos = FALSE;
       break;
     case GST_H265_NAL_EOB:
-      ret = gst_h265_decoder_flush (GST_VIDEO_DECODER (self));
+      gst_h265_decoder_drain (GST_VIDEO_DECODER (self));
       priv->new_bitstream = TRUE;
       break;
     case GST_H265_NAL_EOS:
-      ret = gst_h265_decoder_flush (GST_VIDEO_DECODER (self));
+      gst_h265_decoder_drain (GST_VIDEO_DECODER (self));
       priv->prev_nal_is_eos = TRUE;
       break;
     default:
       break;
   }
 
-  if (consumed_size)
-    *consumed_size = nalu.offset + nalu.size;
-
-  if (!ret)
-    return GST_FLOW_ERROR;
-
-  return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_h265_decoder_parse (GstVideoDecoder * decoder,
-    GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos)
-{
-  GstH265Decoder *self = GST_H265_DECODER (decoder);
-  GstH265DecoderPrivate *priv = self->priv;
-  GstFlowReturn ret = GST_FLOW_OK;
-  guint size;
-  const guint8 *data;
-  gsize consumed = 0;
-
-  /* The return from have_frame() or output_picture() */
-  priv->last_ret = GST_FLOW_OK;
-
-  size = gst_adapter_available (adapter);
-
-  data = (const guint8 *) gst_adapter_map (adapter, size);
-  ret = gst_h265_decoder_parse_nal (self, data, size,
-      gst_adapter_prev_pts (adapter, NULL), at_eos, &consumed);
-  gst_adapter_unmap (adapter);
-
-  if (consumed) {
-    GST_TRACE_OBJECT (self, "consumed size %" G_GSIZE_FORMAT, consumed);
-    gst_video_decoder_add_to_frame (decoder, consumed);
-  }
-
-  if (ret == GST_FLOW_ERROR)
-    goto error;
-
-  /* When AU alginment and has no available input data more,
-   * finish current picture if any */
-  if (priv->align == GST_H265_DECODER_ALIGN_AU &&
-      !gst_adapter_available (adapter)) {
-    gst_h265_decoder_finish_current_picture (self);
-  }
-
-  /* check last flow return again */
-  if (ret == GST_FLOW_ERROR)
-    goto error;
-
-  return priv->last_ret;
-
-error:
-  GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
-      ("Failed to decode data"), (NULL), ret);
-
   return ret;
 }
 
@@ -757,14 +656,10 @@ static gboolean
 gst_h265_decoder_flush (GstVideoDecoder * decoder)
 {
   GstH265Decoder *self = GST_H265_DECODER (decoder);
-  gboolean ret = TRUE;
-
-  if (!gst_h265_decoder_output_all_remaining_pics (self))
-    ret = FALSE;
 
   gst_h265_decoder_clear_dpb (self);
 
-  return ret;
+  return TRUE;
 }
 
 static GstFlowReturn
@@ -773,7 +668,9 @@ gst_h265_decoder_drain (GstVideoDecoder * decoder)
   GstH265Decoder *self = GST_H265_DECODER (decoder);
   GstH265DecoderPrivate *priv = self->priv;
 
-  gst_h265_decoder_flush (decoder);
+  priv->last_ret = GST_FLOW_OK;
+  gst_h265_decoder_output_all_remaining_pics (self);
+  gst_h265_decoder_clear_dpb (self);
 
   return priv->last_ret;
 }
@@ -1257,7 +1154,7 @@ gst_h265_decoder_dpb_init (GstH265Decoder * self, const GstH265Slice * slice,
 
     if (picture->NoOutputOfPriorPicsFlag) {
       GST_DEBUG_OBJECT (self, "Clear dpb");
-      gst_h265_decoder_flush (GST_VIDEO_DECODER (self));
+      gst_h265_decoder_drain (GST_VIDEO_DECODER (self));
     }
   }
 
@@ -1456,13 +1353,6 @@ gst_h265_decoder_finish_current_picture (GstH265Decoder * self)
   if (klass->end_picture)
     ret = klass->end_picture (self, priv->current_picture);
 
-  if (priv->current_picture->output_flag) {
-    gst_video_decoder_have_frame (GST_VIDEO_DECODER (self));
-  } else {
-    GST_DEBUG_OBJECT (self, "Skip have_frame for picture %p",
-        priv->current_picture);
-  }
-
   /* finish picture takes ownership of the picture */
   ret = gst_h265_decoder_finish_picture (self, priv->current_picture);
   priv->current_picture = NULL;
@@ -1482,24 +1372,67 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
   GstH265Decoder *self = GST_H265_DECODER (decoder);
   GstH265DecoderPrivate *priv = self->priv;
   GstBuffer *in_buf = frame->input_buffer;
+  GstH265NalUnit nalu;
+  GstH265ParserResult pres;
+  GstMapInfo map;
+  gboolean decode_ret = TRUE;
 
   GST_LOG_OBJECT (self,
       "handle frame, PTS: %" GST_TIME_FORMAT ", DTS: %"
       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (in_buf)),
       GST_TIME_ARGS (GST_BUFFER_DTS (in_buf)));
 
-  if (!priv->current_picture) {
-    GST_ERROR_OBJECT (self, "No current picture");
-    gst_video_decoder_drop_frame (decoder, frame);
+  priv->current_frame = frame;
+  priv->last_ret = GST_FLOW_OK;
+
+  gst_buffer_map (in_buf, &map, GST_MAP_READ);
+  if (priv->in_format == GST_H265_DECODER_FORMAT_HVC1 ||
+      priv->in_format == GST_H265_DECODER_FORMAT_HEV1) {
+    pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
+        map.data, 0, map.size, priv->nal_length_size, &nalu);
+
+    while (pres == GST_H265_PARSER_OK && decode_ret) {
+      decode_ret = gst_h265_decoder_decode_nal (self,
+          &nalu, GST_BUFFER_PTS (in_buf));
+
+      pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
+          map.data, nalu.offset + nalu.size, map.size, priv->nal_length_size,
+          &nalu);
+    }
+  } else {
+    pres = gst_h265_parser_identify_nalu (priv->parser,
+        map.data, 0, map.size, &nalu);
+
+    if (pres == GST_H265_PARSER_NO_NAL_END)
+      pres = GST_H265_PARSER_OK;
 
-    return GST_FLOW_ERROR;
+    while (pres == GST_H265_PARSER_OK && decode_ret) {
+      decode_ret = gst_h265_decoder_decode_nal (self,
+          &nalu, GST_BUFFER_PTS (in_buf));
+
+      pres = gst_h265_parser_identify_nalu (priv->parser,
+          map.data, nalu.offset + nalu.size, map.size, &nalu);
+
+      if (pres == GST_H265_PARSER_NO_NAL_END)
+        pres = GST_H265_PARSER_OK;
+    }
   }
 
-  gst_video_codec_frame_set_user_data (frame,
-      gst_h265_picture_ref (priv->current_picture),
-      (GDestroyNotify) gst_h265_picture_unref);
+  gst_buffer_unmap (in_buf, &map);
+  priv->current_frame = NULL;
+
+  if (!decode_ret) {
+    GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
+        ("Failed to decode data"), (NULL), priv->last_ret);
+    gst_video_decoder_drop_frame (decoder, frame);
+
+    gst_h265_picture_clear (&priv->current_picture);
+
+    return priv->last_ret;
+  }
 
+  gst_h265_decoder_finish_current_picture (self);
   gst_video_codec_frame_unref (frame);
 
-  return GST_FLOW_OK;
+  return priv->last_ret;
 }