diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2014-10-02 15:48:51 +0300 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2014-10-03 17:23:35 +0300 |
commit | 0a31814ef3bc3b72dc27d02638af014258db1c4a (patch) | |
tree | 080896c63546b1599c58cba09507c57de5bc6e9d /ext | |
parent | 10475b67936eedce5ecdd6f960a6421899d7af09 (diff) | |
download | gstreamer-plugins-bad-0a31814ef3bc3b72dc27d02638af014258db1c4a.tar.gz |
openh264dec: Properly drain codec on ::finish()
Diffstat (limited to 'ext')
-rw-r--r-- | ext/openh264/gstopenh264dec.cpp | 135 |
1 files changed, 77 insertions, 58 deletions
diff --git a/ext/openh264/gstopenh264dec.cpp b/ext/openh264/gstopenh264dec.cpp index 6494d4ae4..c81dba454 100644 --- a/ext/openh264/gstopenh264dec.cpp +++ b/ext/openh264/gstopenh264dec.cpp @@ -237,15 +237,6 @@ static gboolean gst_openh264dec_reset(GstVideoDecoder *decoder, gboolean hard) return TRUE; } -static GstFlowReturn gst_openh264dec_finish(GstVideoDecoder *decoder) -{ - GstOpenh264Dec *openh264dec = GST_OPENH264DEC(decoder); - - GST_DEBUG_OBJECT(openh264dec, "finish"); - - return GST_FLOW_OK; -} - static GstFlowReturn gst_openh264dec_handle_frame(GstVideoDecoder *decoder, GstVideoCodecFrame *frame) { GstOpenh264Dec *openh264dec = GST_OPENH264DEC(decoder); @@ -265,67 +256,81 @@ static GstFlowReturn gst_openh264dec_handle_frame(GstVideoDecoder *decoder, GstV guint8 *p; guint row_stride, component_width, component_height, src_width, row; + if (frame) { + if (!gst_buffer_map(frame->input_buffer, &map_info, GST_MAP_READ)) { + GST_ERROR_OBJECT(openh264dec, "Cannot map input buffer!"); + return GST_FLOW_ERROR; + } - if (!gst_buffer_map(frame->input_buffer, &map_info, GST_MAP_READ)) { - GST_ERROR_OBJECT(openh264dec, "Cannot map input buffer!"); - return GST_FLOW_ERROR; - } - - GST_LOG_OBJECT(openh264dec, "handle frame, %d", map_info.size > 4 ? map_info.data[4] & 0x1f : -1); - - memset (&dst_buf_info, 0, sizeof (SBufferInfo)); - while (offset < map_info.size) { + GST_LOG_OBJECT(openh264dec, "handle frame, %d", map_info.size > 4 ? map_info.data[4] & 0x1f : -1); - parser_result = gst_h264_parser_identify_nalu(openh264dec->priv->nal_parser, - map_info.data, offset, map_info.size, &nalu); - offset = nalu.offset + nalu.size; + while (offset < map_info.size) { + memset (&dst_buf_info, 0, sizeof (SBufferInfo)); + parser_result = gst_h264_parser_identify_nalu(openh264dec->priv->nal_parser, + map_info.data, offset, map_info.size, &nalu); + offset = nalu.offset + nalu.size; - if (parser_result != GST_H264_PARSER_OK && parser_result != GST_H264_PARSER_NO_NAL_END) { - GST_WARNING_OBJECT(openh264dec, "Failed to identify nalu, parser result: %u", parser_result); - break; - } - - memset (&dst_buf_info, 0, sizeof (SBufferInfo)); + if (parser_result != GST_H264_PARSER_OK && parser_result != GST_H264_PARSER_NO_NAL_END) { + GST_WARNING_OBJECT(openh264dec, "Failed to identify nalu, parser result: %u", parser_result); + break; + } - ret = openh264dec->priv->decoder->DecodeFrame2(nalu.data, nalu.size + 4, yuvdata, &dst_buf_info); + memset (&dst_buf_info, 0, sizeof (SBufferInfo)); - if (ret == dsNoParamSets) { - GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit"); - gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder), - gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0)); - } + ret = openh264dec->priv->decoder->DecodeFrame2(nalu.data, nalu.size + 4, yuvdata, &dst_buf_info); - if (ret != dsErrorFree && ret != dsNoParamSets) { - GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit"); - gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder), - gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0)); - GST_LOG_OBJECT(openh264dec, "error decoding nal, return code: %d", ret); - GST_LOG_OBJECT(openh264dec, "nal first byte: %u", (guint) nalu.data[0]); - GST_LOG_OBJECT(openh264dec, "nal size: %u", nalu.size); - } + if (ret == dsNoParamSets) { + GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit"); + gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder), + gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0)); + } - if (nalu.type == GST_H264_NAL_SPS) { - parser_result = gst_h264_parser_parse_sps(openh264dec->priv->nal_parser, &nalu, &sps, TRUE); - if (parser_result == GST_H264_PARSER_OK) { - GST_DEBUG_OBJECT(openh264dec, "Got SPS, fps_n: %u fps_d: %u", sps.fps_num, sps.fps_den); - openh264dec->priv->input_state->info.fps_n = sps.fps_num ? sps.fps_num : 30; - openh264dec->priv->input_state->info.fps_d = sps.fps_num ? sps.fps_den : 1; - } else { - GST_WARNING_OBJECT(openh264dec, "Failed to parse SPS, parser result: %u", parser_result); + if (ret != dsErrorFree && ret != dsNoParamSets) { + GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit"); + gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder), + gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0)); + GST_LOG_OBJECT(openh264dec, "error decoding nal, return code: %d", ret); + GST_LOG_OBJECT(openh264dec, "nal first byte: %u", (guint) nalu.data[0]); + GST_LOG_OBJECT(openh264dec, "nal size: %u", nalu.size); } - } else { - parser_result = gst_h264_parser_parse_nal(openh264dec->priv->nal_parser, &nalu); - if (parser_result == GST_H264_PARSER_OK) { - if (nalu.type == GST_H264_NAL_SLICE_IDR) { - GST_DEBUG_OBJECT(openh264dec, "Got an intra picture"); - GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT(frame); + + if (nalu.type == GST_H264_NAL_SPS) { + parser_result = gst_h264_parser_parse_sps(openh264dec->priv->nal_parser, &nalu, &sps, TRUE); + if (parser_result == GST_H264_PARSER_OK) { + GST_DEBUG_OBJECT(openh264dec, "Got SPS, fps_n: %u fps_d: %u", sps.fps_num, sps.fps_den); + openh264dec->priv->input_state->info.fps_n = sps.fps_num ? sps.fps_num : 30; + openh264dec->priv->input_state->info.fps_d = sps.fps_num ? sps.fps_den : 1; + } else { + GST_WARNING_OBJECT(openh264dec, "Failed to parse SPS, parser result: %u", parser_result); } } else { - GST_WARNING_OBJECT(openh264dec, "Failed to parse nal, parser result: %u", parser_result); + parser_result = gst_h264_parser_parse_nal(openh264dec->priv->nal_parser, &nalu); + if (parser_result == GST_H264_PARSER_OK) { + if (nalu.type == GST_H264_NAL_SLICE_IDR) { + GST_DEBUG_OBJECT(openh264dec, "Got an intra picture"); + GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT(frame); + } + } else { + GST_WARNING_OBJECT(openh264dec, "Failed to parse nal, parser result: %u", parser_result); + } } } + + gst_buffer_unmap(frame->input_buffer, &map_info); + gst_video_codec_frame_unref (frame); + frame = NULL; + } else { + memset (&dst_buf_info, 0, sizeof (SBufferInfo)); + ret = openh264dec->priv->decoder->DecodeFrame2(NULL, 0, yuvdata, &dst_buf_info); + if (ret != dsErrorFree) + return GST_FLOW_EOS; + } + + frame = gst_video_decoder_get_oldest_frame (decoder); + if (!frame) { + /* Can only happen in finish() */ + return GST_FLOW_EOS; } - gst_buffer_unmap(frame->input_buffer, &map_info); if (dst_buf_info.iBufferStatus != 1) { GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY(frame); @@ -382,7 +387,21 @@ static GstFlowReturn gst_openh264dec_handle_frame(GstVideoDecoder *decoder, GstV finish: - gst_video_decoder_finish_frame(decoder, frame); + return gst_video_decoder_finish_frame(decoder, frame); +} + +static GstFlowReturn gst_openh264dec_finish(GstVideoDecoder *decoder) +{ + GstOpenh264Dec *openh264dec = GST_OPENH264DEC(decoder); + + GST_DEBUG_OBJECT(openh264dec, "finish"); + + /* Decoder not negotiated yet */ + if (openh264dec->priv->width == 0) + return GST_FLOW_OK; + + /* Drain all pending frames */ + while ((gst_openh264dec_handle_frame (decoder, NULL)) == GST_FLOW_OK); return GST_FLOW_OK; } |